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