1/* 2 * Copyright (C) 2004, 2005, 2007, 2011-2013 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 56 pool->mctx = NULL; 57 isc_mem_attach(mctx, &pool->mctx); 58 pool->ntasks = ntasks; 59 pool->quantum = quantum; 60 pool->tmgr = tmgr; 61 pool->tasks = isc_mem_get(mctx, ntasks * sizeof(isc_task_t *)); 62 if (pool->tasks == NULL) { 63 isc_mem_putanddetach(&pool->mctx, pool, sizeof(*pool)); 64 return (ISC_R_NOMEMORY); 65 } 66 for (i = 0; i < ntasks; i++) 67 pool->tasks[i] = NULL; 68 69 *poolp = pool; 70 return (ISC_R_SUCCESS); 71} 72 73isc_result_t 74isc_taskpool_create(isc_taskmgr_t *tmgr, isc_mem_t *mctx, 75 unsigned int ntasks, unsigned int quantum, 76 isc_taskpool_t **poolp) 77{ 78 unsigned int i; 79 isc_taskpool_t *pool = NULL; 80 isc_result_t result; 81 82 INSIST(ntasks > 0); 83 84 /* Allocate the pool structure */ 85 result = alloc_pool(tmgr, mctx, ntasks, quantum, &pool); 86 if (result != ISC_R_SUCCESS) 87 return (result); 88 89 /* Create the tasks */ 90 for (i = 0; i < ntasks; i++) { 91 result = isc_task_create(tmgr, quantum, &pool->tasks[i]); 92 if (result != ISC_R_SUCCESS) { 93 isc_taskpool_destroy(&pool); 94 return (result); 95 } 96 isc_task_setname(pool->tasks[i], "taskpool", NULL); 97 } 98 99 *poolp = pool; 100 return (ISC_R_SUCCESS); 101} 102 103void 104isc_taskpool_gettask(isc_taskpool_t *pool, isc_task_t **targetp) { 105 isc_uint32_t i; 106 isc_random_get(&i); 107 isc_task_attach(pool->tasks[i % pool->ntasks], targetp); 108} 109 110int 111isc_taskpool_size(isc_taskpool_t *pool) { 112 REQUIRE(pool != NULL); 113 return (pool->ntasks); 114} 115 116isc_result_t 117isc_taskpool_expand(isc_taskpool_t **sourcep, unsigned int size, 118 isc_taskpool_t **targetp) 119{ 120 isc_result_t result; 121 isc_taskpool_t *pool; 122 123 REQUIRE(sourcep != NULL && *sourcep != NULL); 124 REQUIRE(targetp != NULL && *targetp == NULL); 125 126 pool = *sourcep; 127 if (size > pool->ntasks) { 128 isc_taskpool_t *newpool = NULL; 129 unsigned int i; 130 131 /* Allocate a new pool structure */ 132 result = alloc_pool(pool->tmgr, pool->mctx, size, 133 pool->quantum, &newpool); 134 if (result != ISC_R_SUCCESS) 135 return (result); 136 137 /* Copy over the tasks from the old pool */ 138 for (i = 0; i < pool->ntasks; i++) { 139 newpool->tasks[i] = pool->tasks[i]; 140 pool->tasks[i] = NULL; 141 } 142 143 /* Create new tasks */ 144 for (i = pool->ntasks; i < size; i++) { 145 result = isc_task_create(pool->tmgr, pool->quantum, 146 &newpool->tasks[i]); 147 if (result != ISC_R_SUCCESS) { 148 isc_taskpool_destroy(&newpool); 149 return (result); 150 } 151 isc_task_setname(newpool->tasks[i], "taskpool", NULL); 152 } 153 154 isc_taskpool_destroy(&pool); 155 pool = newpool; 156 } 157 158 *sourcep = NULL; 159 *targetp = pool; 160 return (ISC_R_SUCCESS); 161} 162 163void 164isc_taskpool_destroy(isc_taskpool_t **poolp) { 165 unsigned int i; 166 isc_taskpool_t *pool = *poolp; 167 for (i = 0; i < pool->ntasks; i++) { 168 if (pool->tasks[i] != NULL) 169 isc_task_detach(&pool->tasks[i]); 170 } 171 isc_mem_put(pool->mctx, pool->tasks, 172 pool->ntasks * sizeof(isc_task_t *)); 173 isc_mem_putanddetach(&pool->mctx, pool, sizeof(*pool)); 174 *poolp = NULL; 175} 176 177void 178isc_taskpool_setprivilege(isc_taskpool_t *pool, isc_boolean_t priv) { 179 unsigned int i; 180 181 REQUIRE(pool != NULL); 182 183 for (i = 0; i < pool->ntasks; i++) { 184 if (pool->tasks[i] != NULL) 185 isc_task_setprivilege(pool->tasks[i], priv); 186 } 187} 188