1258945Sroberto/*
2280849Scy * Copyright (C) 2004, 2005, 2007, 2011, 2012  Internet Systems Consortium, Inc. ("ISC")
3258945Sroberto * Copyright (C) 1999-2001  Internet Software Consortium.
4258945Sroberto *
5258945Sroberto * Permission to use, copy, modify, and/or distribute this software for any
6258945Sroberto * purpose with or without fee is hereby granted, provided that the above
7258945Sroberto * copyright notice and this permission notice appear in all copies.
8258945Sroberto *
9258945Sroberto * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10258945Sroberto * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11258945Sroberto * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12258945Sroberto * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13258945Sroberto * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14258945Sroberto * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15258945Sroberto * PERFORMANCE OF THIS SOFTWARE.
16258945Sroberto */
17258945Sroberto
18280849Scy/* $Id$ */
19258945Sroberto
20258945Sroberto/*! \file */
21258945Sroberto
22258945Sroberto#include <config.h>
23258945Sroberto
24258945Sroberto#include <isc/mem.h>
25280849Scy#include <isc/random.h>
26258945Sroberto#include <isc/taskpool.h>
27258945Sroberto#include <isc/util.h>
28258945Sroberto
29258945Sroberto/***
30258945Sroberto *** Types.
31258945Sroberto ***/
32258945Sroberto
33258945Srobertostruct isc_taskpool {
34258945Sroberto	isc_mem_t *			mctx;
35280849Scy	isc_taskmgr_t *			tmgr;
36258945Sroberto	unsigned int			ntasks;
37280849Scy	unsigned int			quantum;
38258945Sroberto	isc_task_t **			tasks;
39258945Sroberto};
40280849Scy
41258945Sroberto/***
42258945Sroberto *** Functions.
43258945Sroberto ***/
44258945Sroberto
45280849Scystatic isc_result_t
46280849Scyalloc_pool(isc_taskmgr_t *tmgr, isc_mem_t *mctx, unsigned int ntasks,
47280849Scy	   unsigned int quantum, isc_taskpool_t **poolp)
48258945Sroberto{
49280849Scy	isc_taskpool_t *pool;
50258945Sroberto	unsigned int i;
51258945Sroberto
52258945Sroberto	pool = isc_mem_get(mctx, sizeof(*pool));
53258945Sroberto	if (pool == NULL)
54258945Sroberto		return (ISC_R_NOMEMORY);
55258945Sroberto	pool->mctx = mctx;
56258945Sroberto	pool->ntasks = ntasks;
57280849Scy	pool->quantum = quantum;
58280849Scy	pool->tmgr = tmgr;
59258945Sroberto	pool->tasks = isc_mem_get(mctx, ntasks * sizeof(isc_task_t *));
60258945Sroberto	if (pool->tasks == NULL) {
61258945Sroberto		isc_mem_put(mctx, pool, sizeof(*pool));
62258945Sroberto		return (ISC_R_NOMEMORY);
63258945Sroberto	}
64258945Sroberto	for (i = 0; i < ntasks; i++)
65258945Sroberto		pool->tasks[i] = NULL;
66280849Scy
67280849Scy	*poolp = pool;
68280849Scy	return (ISC_R_SUCCESS);
69280849Scy}
70280849Scy
71280849Scyisc_result_t
72280849Scyisc_taskpool_create(isc_taskmgr_t *tmgr, isc_mem_t *mctx,
73280849Scy		    unsigned int ntasks, unsigned int quantum,
74280849Scy		    isc_taskpool_t **poolp)
75280849Scy{
76280849Scy	unsigned int i;
77280849Scy	isc_taskpool_t *pool = NULL;
78280849Scy	isc_result_t result;
79280849Scy
80280849Scy	INSIST(ntasks > 0);
81280849Scy
82280849Scy	/* Allocate the pool structure */
83280849Scy	result = alloc_pool(tmgr, mctx, ntasks, quantum, &pool);
84280849Scy	if (result != ISC_R_SUCCESS)
85280849Scy		return (result);
86280849Scy
87280849Scy	/* Create the tasks */
88258945Sroberto	for (i = 0; i < ntasks; i++) {
89258945Sroberto		result = isc_task_create(tmgr, quantum, &pool->tasks[i]);
90258945Sroberto		if (result != ISC_R_SUCCESS) {
91258945Sroberto			isc_taskpool_destroy(&pool);
92258945Sroberto			return (result);
93258945Sroberto		}
94258945Sroberto		isc_task_setname(pool->tasks[i], "taskpool", NULL);
95258945Sroberto	}
96280849Scy
97258945Sroberto	*poolp = pool;
98258945Sroberto	return (ISC_R_SUCCESS);
99258945Sroberto}
100258945Sroberto
101280849Scyvoid
102280849Scyisc_taskpool_gettask(isc_taskpool_t *pool, isc_task_t **targetp) {
103280849Scy	isc_uint32_t i;
104280849Scy	isc_random_get(&i);
105280849Scy	isc_task_attach(pool->tasks[i % pool->ntasks], targetp);
106280849Scy}
107280849Scy
108280849Scyint
109280849Scyisc_taskpool_size(isc_taskpool_t *pool) {
110280849Scy	REQUIRE(pool != NULL);
111280849Scy	return (pool->ntasks);
112280849Scy}
113280849Scy
114280849Scyisc_result_t
115280849Scyisc_taskpool_expand(isc_taskpool_t **sourcep, unsigned int size,
116280849Scy		    isc_taskpool_t **targetp)
117258945Sroberto{
118280849Scy	isc_result_t result;
119280849Scy	isc_taskpool_t *pool;
120280849Scy
121280849Scy	REQUIRE(sourcep != NULL && *sourcep != NULL);
122280849Scy	REQUIRE(targetp != NULL && *targetp == NULL);
123280849Scy
124280849Scy	pool = *sourcep;
125280849Scy	if (size > pool->ntasks) {
126280849Scy		isc_taskpool_t *newpool = NULL;
127280849Scy		unsigned int i;
128280849Scy
129280849Scy		/* Allocate a new pool structure */
130280849Scy		result = alloc_pool(pool->tmgr, pool->mctx, size,
131280849Scy				    pool->quantum, &newpool);
132280849Scy		if (result != ISC_R_SUCCESS)
133280849Scy			return (result);
134280849Scy
135280849Scy		/* Copy over the tasks from the old pool */
136280849Scy		for (i = 0; i < pool->ntasks; i++) {
137280849Scy			newpool->tasks[i] = pool->tasks[i];
138280849Scy			pool->tasks[i] = NULL;
139280849Scy		}
140280849Scy
141280849Scy		/* Create new tasks */
142280849Scy		for (i = pool->ntasks; i < size; i++) {
143280849Scy			result = isc_task_create(pool->tmgr, pool->quantum,
144280849Scy						 &newpool->tasks[i]);
145280849Scy			if (result != ISC_R_SUCCESS) {
146280849Scy				isc_taskpool_destroy(&newpool);
147280849Scy				return (result);
148280849Scy			}
149280849Scy			isc_task_setname(newpool->tasks[i], "taskpool", NULL);
150280849Scy		}
151280849Scy
152280849Scy		isc_taskpool_destroy(&pool);
153280849Scy		pool = newpool;
154280849Scy	}
155280849Scy
156280849Scy	*sourcep = NULL;
157280849Scy	*targetp = pool;
158280849Scy	return (ISC_R_SUCCESS);
159258945Sroberto}
160258945Sroberto
161258945Srobertovoid
162258945Srobertoisc_taskpool_destroy(isc_taskpool_t **poolp) {
163258945Sroberto	unsigned int i;
164258945Sroberto	isc_taskpool_t *pool = *poolp;
165258945Sroberto	for (i = 0; i < pool->ntasks; i++) {
166280849Scy		if (pool->tasks[i] != NULL)
167258945Sroberto			isc_task_detach(&pool->tasks[i]);
168258945Sroberto	}
169258945Sroberto	isc_mem_put(pool->mctx, pool->tasks,
170258945Sroberto		    pool->ntasks * sizeof(isc_task_t *));
171258945Sroberto	isc_mem_put(pool->mctx, pool, sizeof(*pool));
172258945Sroberto	*poolp = NULL;
173258945Sroberto}
174258945Sroberto
175280849Scyvoid
176280849Scyisc_taskpool_setprivilege(isc_taskpool_t *pool, isc_boolean_t priv) {
177280849Scy	unsigned int i;
178258945Sroberto
179280849Scy	REQUIRE(pool != NULL);
180280849Scy
181280849Scy	for (i = 0; i < pool->ntasks; i++) {
182280849Scy		if (pool->tasks[i] != NULL)
183280849Scy			isc_task_setprivilege(pool->tasks[i], priv);
184280849Scy	}
185280849Scy}
186