xref: /minix/external/bsd/bind/dist/lib/isc/taskpool.c (revision fb9c64b2)
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