1224090Sdougb/*
2254897Serwin * Copyright (C) 2009-2012  Internet Systems Consortium, Inc. ("ISC")
3224090Sdougb *
4224090Sdougb * Permission to use, copy, modify, and/or distribute this software for any
5224090Sdougb * purpose with or without fee is hereby granted, provided that the above
6224090Sdougb * copyright notice and this permission notice appear in all copies.
7224090Sdougb *
8224090Sdougb * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
9224090Sdougb * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
10224090Sdougb * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
11224090Sdougb * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
12224090Sdougb * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
13224090Sdougb * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14224090Sdougb * PERFORMANCE OF THIS SOFTWARE.
15224090Sdougb */
16224090Sdougb
17234010Sdougb/* $Id$ */
18224090Sdougb
19224090Sdougb#include <config.h>
20224090Sdougb
21224090Sdougb#include <unistd.h>
22224090Sdougb
23224090Sdougb#include <isc/app.h>
24224090Sdougb#include <isc/magic.h>
25224090Sdougb#include <isc/mutex.h>
26224090Sdougb#include <isc/once.h>
27224090Sdougb#include <isc/task.h>
28224090Sdougb#include <isc/util.h>
29224090Sdougb
30224090Sdougbstatic isc_mutex_t createlock;
31224090Sdougbstatic isc_once_t once = ISC_ONCE_INIT;
32224090Sdougbstatic isc_taskmgrcreatefunc_t taskmgr_createfunc = NULL;
33224090Sdougb
34224090Sdougbstatic void
35224090Sdougbinitialize(void) {
36224090Sdougb	RUNTIME_CHECK(isc_mutex_init(&createlock) == ISC_R_SUCCESS);
37224090Sdougb}
38224090Sdougb
39224090Sdougbisc_result_t
40224090Sdougbisc_task_register(isc_taskmgrcreatefunc_t createfunc) {
41224090Sdougb	isc_result_t result = ISC_R_SUCCESS;
42224090Sdougb
43224090Sdougb	RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS);
44224090Sdougb
45224090Sdougb	LOCK(&createlock);
46224090Sdougb	if (taskmgr_createfunc == NULL)
47224090Sdougb		taskmgr_createfunc = createfunc;
48224090Sdougb	else
49224090Sdougb		result = ISC_R_EXISTS;
50224090Sdougb	UNLOCK(&createlock);
51224090Sdougb
52224090Sdougb	return (result);
53224090Sdougb}
54224090Sdougb
55224090Sdougbisc_result_t
56224090Sdougbisc_taskmgr_createinctx(isc_mem_t *mctx, isc_appctx_t *actx,
57224090Sdougb			unsigned int workers, unsigned int default_quantum,
58224090Sdougb			isc_taskmgr_t **managerp)
59224090Sdougb{
60224090Sdougb	isc_result_t result;
61224090Sdougb
62224090Sdougb	LOCK(&createlock);
63224090Sdougb
64224090Sdougb	REQUIRE(taskmgr_createfunc != NULL);
65224090Sdougb	result = (*taskmgr_createfunc)(mctx, workers, default_quantum,
66224090Sdougb				       managerp);
67224090Sdougb
68224090Sdougb	UNLOCK(&createlock);
69224090Sdougb
70224090Sdougb	if (result == ISC_R_SUCCESS)
71224090Sdougb		isc_appctx_settaskmgr(actx, *managerp);
72224090Sdougb
73224090Sdougb	return (result);
74224090Sdougb}
75224090Sdougb
76224090Sdougbisc_result_t
77224090Sdougbisc_taskmgr_create(isc_mem_t *mctx, unsigned int workers,
78224090Sdougb		   unsigned int default_quantum, isc_taskmgr_t **managerp)
79224090Sdougb{
80224090Sdougb	isc_result_t result;
81224090Sdougb
82224090Sdougb	LOCK(&createlock);
83224090Sdougb
84224090Sdougb	REQUIRE(taskmgr_createfunc != NULL);
85224090Sdougb	result = (*taskmgr_createfunc)(mctx, workers, default_quantum,
86224090Sdougb				       managerp);
87224090Sdougb
88224090Sdougb	UNLOCK(&createlock);
89224090Sdougb
90224090Sdougb	return (result);
91224090Sdougb}
92224090Sdougb
93224090Sdougbvoid
94224090Sdougbisc_taskmgr_destroy(isc_taskmgr_t **managerp) {
95224090Sdougb	REQUIRE(managerp != NULL && ISCAPI_TASKMGR_VALID(*managerp));
96224090Sdougb
97224090Sdougb	(*managerp)->methods->destroy(managerp);
98224090Sdougb
99224090Sdougb	ENSURE(*managerp == NULL);
100224090Sdougb}
101224090Sdougb
102254897Serwinvoid
103254897Serwinisc_taskmgr_setmode(isc_taskmgr_t *manager, isc_taskmgrmode_t mode) {
104254897Serwin	REQUIRE(ISCAPI_TASKMGR_VALID(manager));
105254897Serwin
106254897Serwin	manager->methods->setmode(manager, mode);
107254897Serwin}
108254897Serwin
109254897Serwinisc_taskmgrmode_t
110254897Serwinisc_taskmgr_mode(isc_taskmgr_t *manager) {
111254897Serwin	REQUIRE(ISCAPI_TASKMGR_VALID(manager));
112254897Serwin
113254897Serwin	return (manager->methods->mode(manager));
114254897Serwin}
115254897Serwin
116224090Sdougbisc_result_t
117224090Sdougbisc_task_create(isc_taskmgr_t *manager, unsigned int quantum,
118224090Sdougb		isc_task_t **taskp)
119224090Sdougb{
120224090Sdougb	REQUIRE(ISCAPI_TASKMGR_VALID(manager));
121224090Sdougb	REQUIRE(taskp != NULL && *taskp == NULL);
122224090Sdougb
123224090Sdougb	return (manager->methods->taskcreate(manager, quantum, taskp));
124224090Sdougb}
125224090Sdougb
126224090Sdougbvoid
127224090Sdougbisc_task_attach(isc_task_t *source, isc_task_t **targetp) {
128224090Sdougb	REQUIRE(ISCAPI_TASK_VALID(source));
129224090Sdougb	REQUIRE(targetp != NULL && *targetp == NULL);
130224090Sdougb
131224090Sdougb	source->methods->attach(source, targetp);
132224090Sdougb
133224090Sdougb	ENSURE(*targetp == source);
134224090Sdougb}
135224090Sdougb
136224090Sdougbvoid
137224090Sdougbisc_task_detach(isc_task_t **taskp) {
138224090Sdougb	REQUIRE(taskp != NULL && ISCAPI_TASK_VALID(*taskp));
139224090Sdougb
140224090Sdougb	(*taskp)->methods->detach(taskp);
141224090Sdougb
142224090Sdougb	ENSURE(*taskp == NULL);
143224090Sdougb}
144224090Sdougb
145224090Sdougbvoid
146224090Sdougbisc_task_send(isc_task_t *task, isc_event_t **eventp) {
147224090Sdougb	REQUIRE(ISCAPI_TASK_VALID(task));
148224090Sdougb	REQUIRE(eventp != NULL && *eventp != NULL);
149224090Sdougb
150224090Sdougb	task->methods->send(task, eventp);
151224090Sdougb
152224090Sdougb	ENSURE(*eventp == NULL);
153224090Sdougb}
154224090Sdougb
155224090Sdougbvoid
156224090Sdougbisc_task_sendanddetach(isc_task_t **taskp, isc_event_t **eventp) {
157224090Sdougb	REQUIRE(taskp != NULL && ISCAPI_TASK_VALID(*taskp));
158224090Sdougb	REQUIRE(eventp != NULL && *eventp != NULL);
159224090Sdougb
160224090Sdougb	(*taskp)->methods->sendanddetach(taskp, eventp);
161224090Sdougb
162224090Sdougb	ENSURE(*taskp == NULL && *eventp == NULL);
163224090Sdougb}
164224090Sdougb
165224090Sdougbunsigned int
166224090Sdougbisc_task_unsend(isc_task_t *task, void *sender, isc_eventtype_t type,
167224090Sdougb		void *tag, isc_eventlist_t *events)
168224090Sdougb{
169224090Sdougb	REQUIRE(ISCAPI_TASK_VALID(task));
170224090Sdougb
171224090Sdougb	return (task->methods->unsend(task, sender, type, tag, events));
172224090Sdougb}
173224090Sdougb
174224090Sdougbisc_result_t
175224090Sdougbisc_task_onshutdown(isc_task_t *task, isc_taskaction_t action, const void *arg)
176224090Sdougb{
177224090Sdougb	REQUIRE(ISCAPI_TASK_VALID(task));
178224090Sdougb
179224090Sdougb	return (task->methods->onshutdown(task, action, arg));
180224090Sdougb}
181224090Sdougb
182224090Sdougbvoid
183224090Sdougbisc_task_shutdown(isc_task_t *task) {
184224090Sdougb	REQUIRE(ISCAPI_TASK_VALID(task));
185224090Sdougb
186224090Sdougb	task->methods->shutdown(task);
187224090Sdougb}
188224090Sdougb
189224090Sdougbvoid
190224090Sdougbisc_task_setname(isc_task_t *task, const char *name, void *tag) {
191224090Sdougb	REQUIRE(ISCAPI_TASK_VALID(task));
192224090Sdougb
193224090Sdougb	task->methods->setname(task, name, tag);
194224090Sdougb}
195224090Sdougb
196224090Sdougbunsigned int
197224090Sdougbisc_task_purge(isc_task_t *task, void *sender, isc_eventtype_t type, void *tag)
198224090Sdougb{
199224090Sdougb	REQUIRE(ISCAPI_TASK_VALID(task));
200224090Sdougb
201224090Sdougb	return (task->methods->purgeevents(task, sender, type, tag));
202224090Sdougb}
203224090Sdougb
204245163Serwinvoid
205245163Serwinisc_taskmgr_setexcltask(isc_taskmgr_t *mgr, isc_task_t *task) {
206245163Serwin	REQUIRE(ISCAPI_TASK_VALID(task));
207245163Serwin	return (mgr->methods->setexcltask(mgr, task));
208245163Serwin}
209245163Serwin
210224090Sdougbisc_result_t
211245163Serwinisc_taskmgr_excltask(isc_taskmgr_t *mgr, isc_task_t **taskp) {
212245163Serwin	return (mgr->methods->excltask(mgr, taskp));
213245163Serwin}
214245163Serwin
215245163Serwinisc_result_t
216224090Sdougbisc_task_beginexclusive(isc_task_t *task) {
217224090Sdougb	REQUIRE(ISCAPI_TASK_VALID(task));
218224090Sdougb
219224090Sdougb	return (task->methods->beginexclusive(task));
220224090Sdougb}
221224090Sdougb
222224090Sdougbvoid
223224090Sdougbisc_task_endexclusive(isc_task_t *task) {
224224090Sdougb	REQUIRE(ISCAPI_TASK_VALID(task));
225224090Sdougb
226224090Sdougb	task->methods->endexclusive(task);
227224090Sdougb}
228224090Sdougb
229254897Serwinvoid
230254897Serwinisc_task_setprivilege(isc_task_t *task, isc_boolean_t priv) {
231254897Serwin	REQUIRE(ISCAPI_TASK_VALID(task));
232224090Sdougb
233254897Serwin	task->methods->setprivilege(task, priv);
234254897Serwin}
235254897Serwin
236254897Serwinisc_boolean_t
237254897Serwinisc_task_privilege(isc_task_t *task) {
238254897Serwin	REQUIRE(ISCAPI_TASK_VALID(task));
239254897Serwin
240254897Serwin	return (task->methods->privilege(task));
241254897Serwin}
242254897Serwin
243254897Serwin
244224090Sdougb/*%
245224090Sdougb * This is necessary for libisc's internal timer implementation.  Other
246224090Sdougb * implementation might skip implementing this.
247224090Sdougb */
248224090Sdougbunsigned int
249224090Sdougbisc_task_purgerange(isc_task_t *task, void *sender, isc_eventtype_t first,
250224090Sdougb		    isc_eventtype_t last, void *tag)
251224090Sdougb{
252224090Sdougb	REQUIRE(ISCAPI_TASK_VALID(task));
253224090Sdougb
254224090Sdougb	return (task->methods->purgerange(task, sender, first, last, tag));
255224090Sdougb}
256