taskpool.c revision 290001
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