1/* 2 * Copyright (C) 2004, 2005, 2007, 2011, 2012 Internet Systems Consortium, Inc. ("ISC") 3 * Copyright (C) 1999-2001 Internet Software Consortium. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 15 * PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18/* $Id$ */ 19 20/*! \file */ 21 22#include <config.h> 23 24#include <isc/mem.h> 25#include <isc/random.h> 26#include <isc/taskpool.h> 27#include <isc/util.h> 28 29/*** 30 *** Types. 31 ***/ 32 33struct isc_taskpool { 34 isc_mem_t * mctx; 35 isc_taskmgr_t * tmgr; 36 unsigned int ntasks; 37 unsigned int quantum; 38 isc_task_t ** tasks; 39}; 40 41/*** 42 *** Functions. 43 ***/ 44 45static isc_result_t 46alloc_pool(isc_taskmgr_t *tmgr, isc_mem_t *mctx, unsigned int ntasks, 47 unsigned int quantum, isc_taskpool_t **poolp) 48{ 49 isc_taskpool_t *pool; 50 unsigned int i; 51 52 pool = isc_mem_get(mctx, sizeof(*pool)); 53 if (pool == NULL) 54 return (ISC_R_NOMEMORY); 55 pool->mctx = mctx; 56 pool->ntasks = ntasks; 57 pool->quantum = quantum; 58 pool->tmgr = tmgr; 59 pool->tasks = isc_mem_get(mctx, ntasks * sizeof(isc_task_t *)); 60 if (pool->tasks == NULL) { 61 isc_mem_put(mctx, pool, sizeof(*pool)); 62 return (ISC_R_NOMEMORY); 63 } 64 for (i = 0; i < ntasks; i++) 65 pool->tasks[i] = NULL; 66 67 *poolp = pool; 68 return (ISC_R_SUCCESS); 69} 70 71isc_result_t 72isc_taskpool_create(isc_taskmgr_t *tmgr, isc_mem_t *mctx, 73 unsigned int ntasks, unsigned int quantum, 74 isc_taskpool_t **poolp) 75{ 76 unsigned int i; 77 isc_taskpool_t *pool = NULL; 78 isc_result_t result; 79 80 INSIST(ntasks > 0); 81 82 /* Allocate the pool structure */ 83 result = alloc_pool(tmgr, mctx, ntasks, quantum, &pool); 84 if (result != ISC_R_SUCCESS) 85 return (result); 86 87 /* Create the tasks */ 88 for (i = 0; i < ntasks; i++) { 89 result = isc_task_create(tmgr, quantum, &pool->tasks[i]); 90 if (result != ISC_R_SUCCESS) { 91 isc_taskpool_destroy(&pool); 92 return (result); 93 } 94 isc_task_setname(pool->tasks[i], "taskpool", NULL); 95 } 96 97 *poolp = pool; 98 return (ISC_R_SUCCESS); 99} 100 101void 102isc_taskpool_gettask(isc_taskpool_t *pool, isc_task_t **targetp) { 103 isc_uint32_t i; 104 isc_random_get(&i); 105 isc_task_attach(pool->tasks[i % pool->ntasks], targetp); 106} 107 108int 109isc_taskpool_size(isc_taskpool_t *pool) { 110 REQUIRE(pool != NULL); 111 return (pool->ntasks); 112} 113 114isc_result_t 115isc_taskpool_expand(isc_taskpool_t **sourcep, unsigned int size, 116 isc_taskpool_t **targetp) 117{ 118 isc_result_t result; 119 isc_taskpool_t *pool; 120 121 REQUIRE(sourcep != NULL && *sourcep != NULL); 122 REQUIRE(targetp != NULL && *targetp == NULL); 123 124 pool = *sourcep; 125 if (size > pool->ntasks) { 126 isc_taskpool_t *newpool = NULL; 127 unsigned int i; 128 129 /* Allocate a new pool structure */ 130 result = alloc_pool(pool->tmgr, pool->mctx, size, 131 pool->quantum, &newpool); 132 if (result != ISC_R_SUCCESS) 133 return (result); 134 135 /* Copy over the tasks from the old pool */ 136 for (i = 0; i < pool->ntasks; i++) { 137 newpool->tasks[i] = pool->tasks[i]; 138 pool->tasks[i] = NULL; 139 } 140 141 /* Create new tasks */ 142 for (i = pool->ntasks; i < size; i++) { 143 result = isc_task_create(pool->tmgr, pool->quantum, 144 &newpool->tasks[i]); 145 if (result != ISC_R_SUCCESS) { 146 isc_taskpool_destroy(&newpool); 147 return (result); 148 } 149 isc_task_setname(newpool->tasks[i], "taskpool", NULL); 150 } 151 152 isc_taskpool_destroy(&pool); 153 pool = newpool; 154 } 155 156 *sourcep = NULL; 157 *targetp = pool; 158 return (ISC_R_SUCCESS); 159} 160 161void 162isc_taskpool_destroy(isc_taskpool_t **poolp) { 163 unsigned int i; 164 isc_taskpool_t *pool = *poolp; 165 for (i = 0; i < pool->ntasks; i++) { 166 if (pool->tasks[i] != NULL) 167 isc_task_detach(&pool->tasks[i]); 168 } 169 isc_mem_put(pool->mctx, pool->tasks, 170 pool->ntasks * sizeof(isc_task_t *)); 171 isc_mem_put(pool->mctx, pool, sizeof(*pool)); 172 *poolp = NULL; 173} 174 175void 176isc_taskpool_setprivilege(isc_taskpool_t *pool, isc_boolean_t priv) { 177 unsigned int i; 178 179 REQUIRE(pool != NULL); 180 181 for (i = 0; i < pool->ntasks; i++) { 182 if (pool->tasks[i] != NULL) 183 isc_task_setprivilege(pool->tasks[i], priv); 184 } 185} 186