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
alloc_pool(isc_taskmgr_t * tmgr,isc_mem_t * mctx,unsigned int ntasks,unsigned int quantum,isc_taskpool_t ** poolp)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
isc_taskpool_create(isc_taskmgr_t * tmgr,isc_mem_t * mctx,unsigned int ntasks,unsigned int quantum,isc_taskpool_t ** poolp)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
isc_taskpool_gettask(isc_taskpool_t * pool,isc_task_t ** targetp)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
isc_taskpool_size(isc_taskpool_t * pool)113 isc_taskpool_size(isc_taskpool_t *pool) {
114 REQUIRE(pool != NULL);
115 return (pool->ntasks);
116 }
117
118 isc_result_t
isc_taskpool_expand(isc_taskpool_t ** sourcep,unsigned int size,isc_taskpool_t ** targetp)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
isc_taskpool_destroy(isc_taskpool_t ** poolp)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
isc_taskpool_setprivilege(isc_taskpool_t * pool,isc_boolean_t priv)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