1258945Sroberto/*
2280849Scy * Copyright (C) 2004-2007, 2009-2012  Internet Systems Consortium, Inc. ("ISC")
3258945Sroberto * Copyright (C) 1998-2001, 2003  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#ifndef ISC_TASK_H
21258945Sroberto#define ISC_TASK_H 1
22258945Sroberto
23258945Sroberto/*****
24258945Sroberto ***** Module Info
25258945Sroberto *****/
26258945Sroberto
27258945Sroberto/*! \file isc/task.h
28258945Sroberto * \brief The task system provides a lightweight execution context, which is
29258945Sroberto * basically an event queue.
30258945Sroberto
31258945Sroberto * When a task's event queue is non-empty, the
32258945Sroberto * task is runnable.  A small work crew of threads, typically one per CPU,
33258945Sroberto * execute runnable tasks by dispatching the events on the tasks' event
34258945Sroberto * queues.  Context switching between tasks is fast.
35258945Sroberto *
36258945Sroberto * \li MP:
37258945Sroberto *	The module ensures appropriate synchronization of data structures it
38258945Sroberto *	creates and manipulates.
39258945Sroberto *	The caller must ensure that isc_taskmgr_destroy() is called only
40258945Sroberto *	once for a given manager.
41258945Sroberto *
42258945Sroberto * \li Reliability:
43258945Sroberto *	No anticipated impact.
44258945Sroberto *
45258945Sroberto * \li Resources:
46258945Sroberto *	TBS
47258945Sroberto *
48258945Sroberto * \li Security:
49258945Sroberto *	No anticipated impact.
50258945Sroberto *
51258945Sroberto * \li Standards:
52258945Sroberto *	None.
53258945Sroberto *
54258945Sroberto * \section purge Purging and Unsending
55258945Sroberto *
56258945Sroberto * Events which have been queued for a task but not delivered may be removed
57258945Sroberto * from the task's event queue by purging or unsending.
58258945Sroberto *
59258945Sroberto * With both types, the caller specifies a matching pattern that selects
60258945Sroberto * events based upon their sender, type, and tag.
61258945Sroberto *
62258945Sroberto * Purging calls isc_event_free() on the matching events.
63258945Sroberto *
64258945Sroberto * Unsending returns a list of events that matched the pattern.
65258945Sroberto * The caller is then responsible for them.
66258945Sroberto *
67258945Sroberto * Consumers of events should purge, not unsend.
68258945Sroberto *
69258945Sroberto * Producers of events often want to remove events when the caller indicates
70258945Sroberto * it is no longer interested in the object, e.g. by canceling a timer.
71258945Sroberto * Sometimes this can be done by purging, but for some event types, the
72258945Sroberto * calls to isc_event_free() cause deadlock because the event free routine
73258945Sroberto * wants to acquire a lock the caller is already holding.  Unsending instead
74258945Sroberto * of purging solves this problem.  As a general rule, producers should only
75258945Sroberto * unsend events which they have sent.
76258945Sroberto */
77258945Sroberto
78258945Sroberto
79258945Sroberto/***
80258945Sroberto *** Imports.
81258945Sroberto ***/
82258945Sroberto
83258945Sroberto#include <isc/eventclass.h>
84258945Sroberto#include <isc/lang.h>
85258945Sroberto#include <isc/stdtime.h>
86258945Sroberto#include <isc/types.h>
87258945Sroberto#include <isc/xml.h>
88258945Sroberto
89258945Sroberto#define ISC_TASKEVENT_FIRSTEVENT	(ISC_EVENTCLASS_TASK + 0)
90258945Sroberto#define ISC_TASKEVENT_SHUTDOWN		(ISC_EVENTCLASS_TASK + 1)
91280849Scy#define ISC_TASKEVENT_TEST		(ISC_EVENTCLASS_TASK + 1)
92258945Sroberto#define ISC_TASKEVENT_LASTEVENT		(ISC_EVENTCLASS_TASK + 65535)
93258945Sroberto
94258945Sroberto/*****
95258945Sroberto ***** Tasks.
96258945Sroberto *****/
97258945Sroberto
98258945SrobertoISC_LANG_BEGINDECLS
99258945Sroberto
100280849Scy/***
101280849Scy *** Types
102280849Scy ***/
103280849Scy
104280849Scytypedef enum {
105280849Scy		isc_taskmgrmode_normal = 0,
106280849Scy		isc_taskmgrmode_privileged
107280849Scy} isc_taskmgrmode_t;
108280849Scy
109280849Scy/*% Task and task manager methods */
110280849Scytypedef struct isc_taskmgrmethods {
111280849Scy	void		(*destroy)(isc_taskmgr_t **managerp);
112280849Scy	void		(*setmode)(isc_taskmgr_t *manager,
113280849Scy				   isc_taskmgrmode_t mode);
114280849Scy	isc_taskmgrmode_t (*mode)(isc_taskmgr_t *manager);
115280849Scy	isc_result_t	(*taskcreate)(isc_taskmgr_t *manager,
116280849Scy				      unsigned int quantum,
117280849Scy				      isc_task_t **taskp);
118280849Scy} isc_taskmgrmethods_t;
119280849Scy
120280849Scytypedef struct isc_taskmethods {
121280849Scy	void (*attach)(isc_task_t *source, isc_task_t **targetp);
122280849Scy	void (*detach)(isc_task_t **taskp);
123280849Scy	void (*destroy)(isc_task_t **taskp);
124280849Scy	void (*send)(isc_task_t *task, isc_event_t **eventp);
125280849Scy	void (*sendanddetach)(isc_task_t **taskp, isc_event_t **eventp);
126280849Scy	unsigned int (*unsend)(isc_task_t *task, void *sender, isc_eventtype_t type,
127280849Scy			       void *tag, isc_eventlist_t *events);
128280849Scy	isc_result_t (*onshutdown)(isc_task_t *task, isc_taskaction_t action,
129280849Scy				   const void *arg);
130280849Scy	void (*shutdown)(isc_task_t *task);
131280849Scy	void (*setname)(isc_task_t *task, const char *name, void *tag);
132280849Scy	unsigned int (*purgeevents)(isc_task_t *task, void *sender,
133280849Scy				    isc_eventtype_t type, void *tag);
134280849Scy	unsigned int (*purgerange)(isc_task_t *task, void *sender,
135280849Scy				   isc_eventtype_t first, isc_eventtype_t last,
136280849Scy				   void *tag);
137280849Scy	isc_result_t (*beginexclusive)(isc_task_t *task);
138280849Scy	void (*endexclusive)(isc_task_t *task);
139280849Scy    void (*setprivilege)(isc_task_t *task, isc_boolean_t priv);
140280849Scy    isc_boolean_t (*privilege)(isc_task_t *task);
141280849Scy} isc_taskmethods_t;
142280849Scy
143280849Scy/*%
144280849Scy * This structure is actually just the common prefix of a task manager
145280849Scy * object implementation's version of an isc_taskmgr_t.
146280849Scy * \brief
147280849Scy * Direct use of this structure by clients is forbidden.  task implementations
148280849Scy * may change the structure.  'magic' must be ISCAPI_TASKMGR_MAGIC for any
149280849Scy * of the isc_task_ routines to work.  task implementations must maintain
150280849Scy * all task invariants.
151280849Scy */
152280849Scystruct isc_taskmgr {
153280849Scy	unsigned int		impmagic;
154280849Scy	unsigned int		magic;
155280849Scy	isc_taskmgrmethods_t	*methods;
156280849Scy};
157280849Scy
158280849Scy#define ISCAPI_TASKMGR_MAGIC	ISC_MAGIC('A','t','m','g')
159280849Scy#define ISCAPI_TASKMGR_VALID(m)	((m) != NULL && \
160280849Scy				 (m)->magic == ISCAPI_TASKMGR_MAGIC)
161280849Scy
162280849Scy/*%
163280849Scy * This is the common prefix of a task object.  The same note as
164280849Scy * that for the taskmgr structure applies.
165280849Scy */
166280849Scystruct isc_task {
167280849Scy	unsigned int		impmagic;
168280849Scy	unsigned int		magic;
169280849Scy	isc_taskmethods_t	*methods;
170280849Scy};
171280849Scy
172280849Scy#define ISCAPI_TASK_MAGIC	ISC_MAGIC('A','t','s','t')
173280849Scy#define ISCAPI_TASK_VALID(s)	((s) != NULL && \
174280849Scy				 (s)->magic == ISCAPI_TASK_MAGIC)
175280849Scy
176258945Srobertoisc_result_t
177258945Srobertoisc_task_create(isc_taskmgr_t *manager, unsigned int quantum,
178258945Sroberto		isc_task_t **taskp);
179258945Sroberto/*%<
180258945Sroberto * Create a task.
181258945Sroberto *
182258945Sroberto * Notes:
183258945Sroberto *
184258945Sroberto *\li	If 'quantum' is non-zero, then only that many events can be dispatched
185258945Sroberto *	before the task must yield to other tasks waiting to execute.  If
186258945Sroberto *	quantum is zero, then the default quantum of the task manager will
187258945Sroberto *	be used.
188258945Sroberto *
189258945Sroberto *\li	The 'quantum' option may be removed from isc_task_create() in the
190258945Sroberto *	future.  If this happens, isc_task_getquantum() and
191258945Sroberto *	isc_task_setquantum() will be provided.
192258945Sroberto *
193258945Sroberto * Requires:
194258945Sroberto *
195258945Sroberto *\li	'manager' is a valid task manager.
196258945Sroberto *
197258945Sroberto *\li	taskp != NULL && *taskp == NULL
198258945Sroberto *
199258945Sroberto * Ensures:
200258945Sroberto *
201258945Sroberto *\li	On success, '*taskp' is bound to the new task.
202258945Sroberto *
203258945Sroberto * Returns:
204258945Sroberto *
205258945Sroberto *\li   #ISC_R_SUCCESS
206258945Sroberto *\li	#ISC_R_NOMEMORY
207258945Sroberto *\li	#ISC_R_UNEXPECTED
208258945Sroberto *\li	#ISC_R_SHUTTINGDOWN
209258945Sroberto */
210258945Sroberto
211258945Srobertovoid
212258945Srobertoisc_task_attach(isc_task_t *source, isc_task_t **targetp);
213258945Sroberto/*%<
214258945Sroberto * Attach *targetp to source.
215258945Sroberto *
216258945Sroberto * Requires:
217258945Sroberto *
218258945Sroberto *\li	'source' is a valid task.
219258945Sroberto *
220258945Sroberto *\li	'targetp' points to a NULL isc_task_t *.
221258945Sroberto *
222258945Sroberto * Ensures:
223258945Sroberto *
224258945Sroberto *\li	*targetp is attached to source.
225258945Sroberto */
226258945Sroberto
227258945Srobertovoid
228258945Srobertoisc_task_detach(isc_task_t **taskp);
229258945Sroberto/*%<
230258945Sroberto * Detach *taskp from its task.
231258945Sroberto *
232258945Sroberto * Requires:
233258945Sroberto *
234258945Sroberto *\li	'*taskp' is a valid task.
235258945Sroberto *
236258945Sroberto * Ensures:
237258945Sroberto *
238258945Sroberto *\li	*taskp is NULL.
239258945Sroberto *
240258945Sroberto *\li	If '*taskp' is the last reference to the task, the task is idle (has
241258945Sroberto *	an empty event queue), and has not been shutdown, the task will be
242258945Sroberto *	shutdown.
243258945Sroberto *
244258945Sroberto *\li	If '*taskp' is the last reference to the task and
245258945Sroberto *	the task has been shutdown,
246258945Sroberto *		all resources used by the task will be freed.
247258945Sroberto */
248258945Sroberto
249258945Srobertovoid
250258945Srobertoisc_task_send(isc_task_t *task, isc_event_t **eventp);
251258945Sroberto/*%<
252258945Sroberto * Send '*event' to 'task'.
253258945Sroberto *
254258945Sroberto * Requires:
255258945Sroberto *
256258945Sroberto *\li	'task' is a valid task.
257258945Sroberto *\li	eventp != NULL && *eventp != NULL.
258258945Sroberto *
259258945Sroberto * Ensures:
260258945Sroberto *
261258945Sroberto *\li	*eventp == NULL.
262258945Sroberto */
263258945Sroberto
264258945Srobertovoid
265258945Srobertoisc_task_sendanddetach(isc_task_t **taskp, isc_event_t **eventp);
266258945Sroberto/*%<
267258945Sroberto * Send '*event' to '*taskp' and then detach '*taskp' from its
268258945Sroberto * task.
269258945Sroberto *
270258945Sroberto * Requires:
271258945Sroberto *
272258945Sroberto *\li	'*taskp' is a valid task.
273258945Sroberto *\li	eventp != NULL && *eventp != NULL.
274258945Sroberto *
275258945Sroberto * Ensures:
276258945Sroberto *
277258945Sroberto *\li	*eventp == NULL.
278258945Sroberto *
279258945Sroberto *\li	*taskp == NULL.
280258945Sroberto *
281258945Sroberto *\li	If '*taskp' is the last reference to the task, the task is
282258945Sroberto *	idle (has an empty event queue), and has not been shutdown,
283258945Sroberto *	the task will be shutdown.
284258945Sroberto *
285258945Sroberto *\li	If '*taskp' is the last reference to the task and
286258945Sroberto *	the task has been shutdown,
287258945Sroberto *		all resources used by the task will be freed.
288258945Sroberto */
289258945Sroberto
290258945Sroberto
291258945Srobertounsigned int
292258945Srobertoisc_task_purgerange(isc_task_t *task, void *sender, isc_eventtype_t first,
293258945Sroberto		    isc_eventtype_t last, void *tag);
294258945Sroberto/*%<
295258945Sroberto * Purge events from a task's event queue.
296258945Sroberto *
297258945Sroberto * Requires:
298258945Sroberto *
299258945Sroberto *\li	'task' is a valid task.
300258945Sroberto *
301258945Sroberto *\li	last >= first
302258945Sroberto *
303258945Sroberto * Ensures:
304258945Sroberto *
305258945Sroberto *\li	Events in the event queue of 'task' whose sender is 'sender', whose
306258945Sroberto *	type is >= first and <= last, and whose tag is 'tag' will be purged,
307258945Sroberto *	unless they are marked as unpurgable.
308258945Sroberto *
309258945Sroberto *\li	A sender of NULL will match any sender.  A NULL tag matches any
310258945Sroberto *	tag.
311258945Sroberto *
312258945Sroberto * Returns:
313258945Sroberto *
314258945Sroberto *\li	The number of events purged.
315258945Sroberto */
316258945Sroberto
317258945Srobertounsigned int
318258945Srobertoisc_task_purge(isc_task_t *task, void *sender, isc_eventtype_t type,
319258945Sroberto	       void *tag);
320258945Sroberto/*%<
321258945Sroberto * Purge events from a task's event queue.
322258945Sroberto *
323258945Sroberto * Notes:
324258945Sroberto *
325258945Sroberto *\li	This function is equivalent to
326258945Sroberto *
327258945Sroberto *\code
328258945Sroberto *		isc_task_purgerange(task, sender, type, type, tag);
329258945Sroberto *\endcode
330258945Sroberto *
331258945Sroberto * Requires:
332258945Sroberto *
333258945Sroberto *\li	'task' is a valid task.
334258945Sroberto *
335258945Sroberto * Ensures:
336258945Sroberto *
337258945Sroberto *\li	Events in the event queue of 'task' whose sender is 'sender', whose
338258945Sroberto *	type is 'type', and whose tag is 'tag' will be purged, unless they
339258945Sroberto *	are marked as unpurgable.
340258945Sroberto *
341258945Sroberto *\li	A sender of NULL will match any sender.  A NULL tag matches any
342258945Sroberto *	tag.
343258945Sroberto *
344258945Sroberto * Returns:
345258945Sroberto *
346258945Sroberto *\li	The number of events purged.
347258945Sroberto */
348258945Sroberto
349258945Srobertoisc_boolean_t
350258945Srobertoisc_task_purgeevent(isc_task_t *task, isc_event_t *event);
351258945Sroberto/*%<
352258945Sroberto * Purge 'event' from a task's event queue.
353258945Sroberto *
354258945Sroberto * XXXRTH:  WARNING:  This method may be removed before beta.
355258945Sroberto *
356258945Sroberto * Notes:
357258945Sroberto *
358258945Sroberto *\li	If 'event' is on the task's event queue, it will be purged,
359258945Sroberto * 	unless it is marked as unpurgeable.  'event' does not have to be
360258945Sroberto *	on the task's event queue; in fact, it can even be an invalid
361258945Sroberto *	pointer.  Purging only occurs if the event is actually on the task's
362258945Sroberto *	event queue.
363258945Sroberto *
364258945Sroberto * \li	Purging never changes the state of the task.
365258945Sroberto *
366258945Sroberto * Requires:
367258945Sroberto *
368258945Sroberto *\li	'task' is a valid task.
369258945Sroberto *
370258945Sroberto * Ensures:
371258945Sroberto *
372258945Sroberto *\li	'event' is not in the event queue for 'task'.
373258945Sroberto *
374258945Sroberto * Returns:
375258945Sroberto *
376258945Sroberto *\li	#ISC_TRUE			The event was purged.
377258945Sroberto *\li	#ISC_FALSE			The event was not in the event queue,
378258945Sroberto *					or was marked unpurgeable.
379258945Sroberto */
380258945Sroberto
381258945Srobertounsigned int
382258945Srobertoisc_task_unsendrange(isc_task_t *task, void *sender, isc_eventtype_t first,
383258945Sroberto		     isc_eventtype_t last, void *tag, isc_eventlist_t *events);
384258945Sroberto/*%<
385258945Sroberto * Remove events from a task's event queue.
386258945Sroberto *
387258945Sroberto * Requires:
388258945Sroberto *
389258945Sroberto *\li	'task' is a valid task.
390258945Sroberto *
391258945Sroberto *\li	last >= first.
392258945Sroberto *
393258945Sroberto *\li	*events is a valid list.
394258945Sroberto *
395258945Sroberto * Ensures:
396258945Sroberto *
397258945Sroberto *\li	Events in the event queue of 'task' whose sender is 'sender', whose
398258945Sroberto *	type is >= first and <= last, and whose tag is 'tag' will be dequeued
399258945Sroberto *	and appended to *events.
400258945Sroberto *
401258945Sroberto *\li	A sender of NULL will match any sender.  A NULL tag matches any
402258945Sroberto *	tag.
403258945Sroberto *
404258945Sroberto * Returns:
405258945Sroberto *
406258945Sroberto *\li	The number of events unsent.
407258945Sroberto */
408258945Sroberto
409258945Srobertounsigned int
410258945Srobertoisc_task_unsend(isc_task_t *task, void *sender, isc_eventtype_t type,
411258945Sroberto		void *tag, isc_eventlist_t *events);
412258945Sroberto/*%<
413258945Sroberto * Remove events from a task's event queue.
414258945Sroberto *
415258945Sroberto * Notes:
416258945Sroberto *
417258945Sroberto *\li	This function is equivalent to
418258945Sroberto *
419258945Sroberto *\code
420258945Sroberto *		isc_task_unsendrange(task, sender, type, type, tag, events);
421258945Sroberto *\endcode
422258945Sroberto *
423258945Sroberto * Requires:
424258945Sroberto *
425258945Sroberto *\li	'task' is a valid task.
426258945Sroberto *
427258945Sroberto *\li	*events is a valid list.
428258945Sroberto *
429258945Sroberto * Ensures:
430258945Sroberto *
431258945Sroberto *\li	Events in the event queue of 'task' whose sender is 'sender', whose
432258945Sroberto *	type is 'type', and whose tag is 'tag' will be dequeued and appended
433258945Sroberto *	to *events.
434258945Sroberto *
435258945Sroberto * Returns:
436258945Sroberto *
437258945Sroberto *\li	The number of events unsent.
438258945Sroberto */
439258945Sroberto
440258945Srobertoisc_result_t
441258945Srobertoisc_task_onshutdown(isc_task_t *task, isc_taskaction_t action,
442258945Sroberto		    const void *arg);
443258945Sroberto/*%<
444258945Sroberto * Send a shutdown event with action 'action' and argument 'arg' when
445258945Sroberto * 'task' is shutdown.
446258945Sroberto *
447258945Sroberto * Notes:
448258945Sroberto *
449258945Sroberto *\li	Shutdown events are posted in LIFO order.
450258945Sroberto *
451258945Sroberto * Requires:
452258945Sroberto *
453258945Sroberto *\li	'task' is a valid task.
454258945Sroberto *
455258945Sroberto *\li	'action' is a valid task action.
456258945Sroberto *
457258945Sroberto * Ensures:
458258945Sroberto *
459258945Sroberto *\li	When the task is shutdown, shutdown events requested with
460258945Sroberto *	isc_task_onshutdown() will be appended to the task's event queue.
461258945Sroberto *
462258945Sroberto
463258945Sroberto * Returns:
464258945Sroberto *
465258945Sroberto *\li	#ISC_R_SUCCESS
466258945Sroberto *\li	#ISC_R_NOMEMORY
467258945Sroberto *\li	#ISC_R_TASKSHUTTINGDOWN			Task is shutting down.
468258945Sroberto */
469258945Sroberto
470258945Srobertovoid
471258945Srobertoisc_task_shutdown(isc_task_t *task);
472258945Sroberto/*%<
473258945Sroberto * Shutdown 'task'.
474258945Sroberto *
475258945Sroberto * Notes:
476258945Sroberto *
477258945Sroberto *\li	Shutting down a task causes any shutdown events requested with
478258945Sroberto *	isc_task_onshutdown() to be posted (in LIFO order).  The task
479258945Sroberto *	moves into a "shutting down" mode which prevents further calls
480258945Sroberto *	to isc_task_onshutdown().
481258945Sroberto *
482258945Sroberto *\li	Trying to shutdown a task that has already been shutdown has no
483258945Sroberto *	effect.
484258945Sroberto *
485258945Sroberto * Requires:
486258945Sroberto *
487258945Sroberto *\li	'task' is a valid task.
488258945Sroberto *
489258945Sroberto * Ensures:
490258945Sroberto *
491258945Sroberto *\li	Any shutdown events requested with isc_task_onshutdown() have been
492258945Sroberto *	posted (in LIFO order).
493258945Sroberto */
494258945Sroberto
495258945Srobertovoid
496258945Srobertoisc_task_destroy(isc_task_t **taskp);
497258945Sroberto/*%<
498258945Sroberto * Destroy '*taskp'.
499258945Sroberto *
500258945Sroberto * Notes:
501258945Sroberto *
502258945Sroberto *\li	This call is equivalent to:
503258945Sroberto *
504258945Sroberto *\code
505258945Sroberto *		isc_task_shutdown(*taskp);
506258945Sroberto *		isc_task_detach(taskp);
507258945Sroberto *\endcode
508258945Sroberto *
509258945Sroberto * Requires:
510258945Sroberto *
511258945Sroberto *	'*taskp' is a valid task.
512258945Sroberto *
513258945Sroberto * Ensures:
514258945Sroberto *
515258945Sroberto *\li	Any shutdown events requested with isc_task_onshutdown() have been
516258945Sroberto *	posted (in LIFO order).
517258945Sroberto *
518258945Sroberto *\li	*taskp == NULL
519258945Sroberto *
520258945Sroberto *\li	If '*taskp' is the last reference to the task,
521258945Sroberto *		all resources used by the task will be freed.
522258945Sroberto */
523258945Sroberto
524258945Srobertovoid
525258945Srobertoisc_task_setname(isc_task_t *task, const char *name, void *tag);
526258945Sroberto/*%<
527258945Sroberto * Name 'task'.
528258945Sroberto *
529258945Sroberto * Notes:
530258945Sroberto *
531258945Sroberto *\li	Only the first 15 characters of 'name' will be copied.
532258945Sroberto *
533258945Sroberto *\li	Naming a task is currently only useful for debugging purposes.
534258945Sroberto *
535258945Sroberto * Requires:
536258945Sroberto *
537258945Sroberto *\li	'task' is a valid task.
538258945Sroberto */
539258945Sroberto
540258945Srobertoconst char *
541258945Srobertoisc_task_getname(isc_task_t *task);
542258945Sroberto/*%<
543258945Sroberto * Get the name of 'task', as previously set using isc_task_setname().
544258945Sroberto *
545258945Sroberto * Notes:
546258945Sroberto *\li	This function is for debugging purposes only.
547258945Sroberto *
548258945Sroberto * Requires:
549258945Sroberto *\li	'task' is a valid task.
550258945Sroberto *
551258945Sroberto * Returns:
552258945Sroberto *\li	A non-NULL pointer to a null-terminated string.
553258945Sroberto * 	If the task has not been named, the string is
554258945Sroberto * 	empty.
555258945Sroberto *
556258945Sroberto */
557258945Sroberto
558258945Srobertovoid *
559258945Srobertoisc_task_gettag(isc_task_t *task);
560258945Sroberto/*%<
561258945Sroberto * Get the tag value for  'task', as previously set using isc_task_settag().
562258945Sroberto *
563258945Sroberto * Notes:
564258945Sroberto *\li	This function is for debugging purposes only.
565258945Sroberto *
566258945Sroberto * Requires:
567258945Sroberto *\li	'task' is a valid task.
568258945Sroberto */
569258945Sroberto
570258945Srobertoisc_result_t
571258945Srobertoisc_task_beginexclusive(isc_task_t *task);
572258945Sroberto/*%<
573258945Sroberto * Request exclusive access for 'task', which must be the calling
574258945Sroberto * task.  Waits for any other concurrently executing tasks to finish their
575258945Sroberto * current event, and prevents any new events from executing in any of the
576258945Sroberto * tasks sharing a task manager with 'task'.
577258945Sroberto *
578258945Sroberto * The exclusive access must be relinquished by calling
579258945Sroberto * isc_task_endexclusive() before returning from the current event handler.
580258945Sroberto *
581258945Sroberto * Requires:
582258945Sroberto *\li	'task' is the calling task.
583258945Sroberto *
584258945Sroberto * Returns:
585258945Sroberto *\li	#ISC_R_SUCCESS		The current task now has exclusive access.
586258945Sroberto *\li	#ISC_R_LOCKBUSY		Another task has already requested exclusive
587258945Sroberto *				access.
588258945Sroberto */
589258945Sroberto
590258945Srobertovoid
591258945Srobertoisc_task_endexclusive(isc_task_t *task);
592258945Sroberto/*%<
593258945Sroberto * Relinquish the exclusive access obtained by isc_task_beginexclusive(),
594258945Sroberto * allowing other tasks to execute.
595258945Sroberto *
596258945Sroberto * Requires:
597258945Sroberto *\li	'task' is the calling task, and has obtained
598258945Sroberto *		exclusive access by calling isc_task_spl().
599258945Sroberto */
600258945Sroberto
601258945Srobertovoid
602258945Srobertoisc_task_getcurrenttime(isc_task_t *task, isc_stdtime_t *t);
603258945Sroberto/*%<
604258945Sroberto * Provide the most recent timestamp on the task.  The timestamp is considered
605258945Sroberto * as the "current time" in the second-order granularity.
606258945Sroberto *
607258945Sroberto * Requires:
608258945Sroberto *\li	'task' is a valid task.
609258945Sroberto *\li	't' is a valid non NULL pointer.
610258945Sroberto *
611258945Sroberto * Ensures:
612258945Sroberto *\li	'*t' has the "current time".
613258945Sroberto */
614258945Sroberto
615280849Scyisc_boolean_t
616280849Scyisc_task_exiting(isc_task_t *t);
617280849Scy/*%<
618280849Scy * Returns ISC_TRUE if the task is in the process of shutting down,
619280849Scy * ISC_FALSE otherwise.
620280849Scy *
621280849Scy * Requires:
622280849Scy *\li	'task' is a valid task.
623280849Scy */
624280849Scy
625280849Scyvoid
626280849Scyisc_task_setprivilege(isc_task_t *task, isc_boolean_t priv);
627280849Scy/*%<
628280849Scy * Set or unset the task's "privileged" flag depending on the value of
629280849Scy * 'priv'.
630280849Scy *
631280849Scy * Under normal circumstances this flag has no effect on the task behavior,
632280849Scy * but when the task manager has been set to privileged exeuction mode via
633280849Scy * isc_taskmgr_setmode(), only tasks with the flag set will be executed,
634280849Scy * and all other tasks will wait until they're done.  Once all privileged
635280849Scy * tasks have finished executing, the task manager will automatically
636280849Scy * return to normal execution mode and nonprivileged task can resume.
637280849Scy *
638280849Scy * Requires:
639280849Scy *\li	'task' is a valid task.
640280849Scy */
641280849Scy
642280849Scyisc_boolean_t
643280849Scyisc_task_privilege(isc_task_t *task);
644280849Scy/*%<
645280849Scy * Returns the current value of the task's privilege flag.
646280849Scy *
647280849Scy * Requires:
648280849Scy *\li	'task' is a valid task.
649280849Scy */
650280849Scy
651258945Sroberto/*****
652258945Sroberto ***** Task Manager.
653258945Sroberto *****/
654258945Sroberto
655258945Srobertoisc_result_t
656280849Scyisc_taskmgr_createinctx(isc_mem_t *mctx, isc_appctx_t *actx,
657280849Scy			unsigned int workers, unsigned int default_quantum,
658280849Scy			isc_taskmgr_t **managerp);
659280849Scyisc_result_t
660258945Srobertoisc_taskmgr_create(isc_mem_t *mctx, unsigned int workers,
661258945Sroberto		   unsigned int default_quantum, isc_taskmgr_t **managerp);
662258945Sroberto/*%<
663280849Scy * Create a new task manager.  isc_taskmgr_createinctx() also associates
664280849Scy * the new manager with the specified application context.
665258945Sroberto *
666258945Sroberto * Notes:
667258945Sroberto *
668258945Sroberto *\li	'workers' in the number of worker threads to create.  In general,
669258945Sroberto *	the value should be close to the number of processors in the system.
670258945Sroberto *	The 'workers' value is advisory only.  An attempt will be made to
671258945Sroberto *	create 'workers' threads, but if at least one thread creation
672258945Sroberto *	succeeds, isc_taskmgr_create() may return ISC_R_SUCCESS.
673258945Sroberto *
674258945Sroberto *\li	If 'default_quantum' is non-zero, then it will be used as the default
675258945Sroberto *	quantum value when tasks are created.  If zero, then an implementation
676258945Sroberto *	defined default quantum will be used.
677258945Sroberto *
678258945Sroberto * Requires:
679258945Sroberto *
680258945Sroberto *\li      'mctx' is a valid memory context.
681258945Sroberto *
682258945Sroberto *\li	workers > 0
683258945Sroberto *
684258945Sroberto *\li	managerp != NULL && *managerp == NULL
685258945Sroberto *
686280849Scy *\li	'actx' is a valid application context (for createinctx()).
687280849Scy *
688258945Sroberto * Ensures:
689258945Sroberto *
690258945Sroberto *\li	On success, '*managerp' will be attached to the newly created task
691258945Sroberto *	manager.
692258945Sroberto *
693258945Sroberto * Returns:
694258945Sroberto *
695258945Sroberto *\li	#ISC_R_SUCCESS
696258945Sroberto *\li	#ISC_R_NOMEMORY
697280849Scy *\li	#ISC_R_NOTHREADS		No threads could be created.
698258945Sroberto *\li	#ISC_R_UNEXPECTED		An unexpected error occurred.
699280849Scy *\li	#ISC_R_SHUTTINGDOWN      	The non-threaded, shared, task
700280849Scy *					manager shutting down.
701258945Sroberto */
702258945Sroberto
703258945Srobertovoid
704280849Scyisc_taskmgr_setmode(isc_taskmgr_t *manager, isc_taskmgrmode_t mode);
705280849Scy
706280849Scyisc_taskmgrmode_t
707280849Scyisc_taskmgr_mode(isc_taskmgr_t *manager);
708280849Scy/*%<
709280849Scy * Set/get the current operating mode of the task manager.  Valid modes are:
710280849Scy *
711280849Scy *\li  isc_taskmgrmode_normal
712280849Scy *\li  isc_taskmgrmode_privileged
713280849Scy *
714280849Scy * In privileged execution mode, only tasks that have had the "privilege"
715280849Scy * flag set via isc_task_setprivilege() can be executed.  When all such
716280849Scy * tasks are complete, the manager automatically returns to normal mode
717280849Scy * and proceeds with running non-privileged ready tasks.  This means it is
718280849Scy * necessary to have at least one privileged task waiting on the ready
719280849Scy * queue *before* setting the manager into privileged execution mode,
720280849Scy * which in turn means the task which calls this function should be in
721280849Scy * task-exclusive mode when it does so.
722280849Scy *
723280849Scy * Requires:
724280849Scy *
725280849Scy *\li      'manager' is a valid task manager.
726280849Scy */
727280849Scy
728280849Scyvoid
729258945Srobertoisc_taskmgr_destroy(isc_taskmgr_t **managerp);
730258945Sroberto/*%<
731258945Sroberto * Destroy '*managerp'.
732258945Sroberto *
733258945Sroberto * Notes:
734258945Sroberto *
735258945Sroberto *\li	Calling isc_taskmgr_destroy() will shutdown all tasks managed by
736258945Sroberto *	*managerp that haven't already been shutdown.  The call will block
737258945Sroberto *	until all tasks have entered the done state.
738258945Sroberto *
739258945Sroberto *\li	isc_taskmgr_destroy() must not be called by a task event action,
740258945Sroberto *	because it would block forever waiting for the event action to
741258945Sroberto *	complete.  An event action that wants to cause task manager shutdown
742258945Sroberto *	should request some non-event action thread of execution to do the
743258945Sroberto *	shutdown, e.g. by signaling a condition variable or using
744258945Sroberto *	isc_app_shutdown().
745258945Sroberto *
746258945Sroberto *\li	Task manager references are not reference counted, so the caller
747258945Sroberto *	must ensure that no attempt will be made to use the manager after
748258945Sroberto *	isc_taskmgr_destroy() returns.
749258945Sroberto *
750258945Sroberto * Requires:
751258945Sroberto *
752258945Sroberto *\li	'*managerp' is a valid task manager.
753258945Sroberto *
754258945Sroberto *\li	isc_taskmgr_destroy() has not be called previously on '*managerp'.
755258945Sroberto *
756258945Sroberto * Ensures:
757258945Sroberto *
758258945Sroberto *\li	All resources used by the task manager, and any tasks it managed,
759258945Sroberto *	have been freed.
760258945Sroberto */
761258945Sroberto
762258945Sroberto#ifdef HAVE_LIBXML2
763258945Sroberto
764258945Srobertovoid
765258945Srobertoisc_taskmgr_renderxml(isc_taskmgr_t *mgr, xmlTextWriterPtr writer);
766258945Sroberto
767258945Sroberto#endif
768258945Sroberto
769280849Scy/*%<
770280849Scy * See isc_taskmgr_create() above.
771280849Scy */
772280849Scytypedef isc_result_t
773280849Scy(*isc_taskmgrcreatefunc_t)(isc_mem_t *mctx, unsigned int workers,
774280849Scy			   unsigned int default_quantum,
775280849Scy			   isc_taskmgr_t **managerp);
776280849Scy
777280849Scyisc_result_t
778280849Scyisc_task_register(isc_taskmgrcreatefunc_t createfunc);
779280849Scy/*%<
780280849Scy * Register a new task management implementation and add it to the list of
781280849Scy * supported implementations.  This function must be called when a different
782280849Scy * event library is used than the one contained in the ISC library.
783280849Scy */
784280849Scy
785280849Scyisc_result_t
786280849Scyisc__task_register(void);
787280849Scy/*%<
788280849Scy * A short cut function that specifies the task management module in the ISC
789280849Scy * library for isc_task_register().  An application that uses the ISC library
790280849Scy * usually do not have to care about this function: it would call
791280849Scy * isc_lib_register(), which internally calls this function.
792280849Scy */
793280849Scy
794258945SrobertoISC_LANG_ENDDECLS
795258945Sroberto
796258945Sroberto#endif /* ISC_TASK_H */
797