xref: /freebsd/contrib/ntp/libntp/lib/isc/include/isc/task.h (revision e0c4386e)
1 /*
2  * Copyright (C) 2004-2007, 2009-2012  Internet Systems Consortium, Inc. ("ISC")
3  * Copyright (C) 1998-2001, 2003  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 #ifndef ISC_TASK_H
21 #define ISC_TASK_H 1
22 
23 /*****
24  ***** Module Info
25  *****/
26 
27 /*! \file isc/task.h
28  * \brief The task system provides a lightweight execution context, which is
29  * basically an event queue.
30 
31  * When a task's event queue is non-empty, the
32  * task is runnable.  A small work crew of threads, typically one per CPU,
33  * execute runnable tasks by dispatching the events on the tasks' event
34  * queues.  Context switching between tasks is fast.
35  *
36  * \li MP:
37  *	The module ensures appropriate synchronization of data structures it
38  *	creates and manipulates.
39  *	The caller must ensure that isc_taskmgr_destroy() is called only
40  *	once for a given manager.
41  *
42  * \li Reliability:
43  *	No anticipated impact.
44  *
45  * \li Resources:
46  *	TBS
47  *
48  * \li Security:
49  *	No anticipated impact.
50  *
51  * \li Standards:
52  *	None.
53  *
54  * \section purge Purging and Unsending
55  *
56  * Events which have been queued for a task but not delivered may be removed
57  * from the task's event queue by purging or unsending.
58  *
59  * With both types, the caller specifies a matching pattern that selects
60  * events based upon their sender, type, and tag.
61  *
62  * Purging calls isc_event_free() on the matching events.
63  *
64  * Unsending returns a list of events that matched the pattern.
65  * The caller is then responsible for them.
66  *
67  * Consumers of events should purge, not unsend.
68  *
69  * Producers of events often want to remove events when the caller indicates
70  * it is no longer interested in the object, e.g. by canceling a timer.
71  * Sometimes this can be done by purging, but for some event types, the
72  * calls to isc_event_free() cause deadlock because the event free routine
73  * wants to acquire a lock the caller is already holding.  Unsending instead
74  * of purging solves this problem.  As a general rule, producers should only
75  * unsend events which they have sent.
76  */
77 
78 
79 /***
80  *** Imports.
81  ***/
82 
83 #include <isc/eventclass.h>
84 #include <isc/lang.h>
85 #include <isc/stdtime.h>
86 #include <isc/types.h>
87 #include <isc/xml.h>
88 
89 #define ISC_TASKEVENT_FIRSTEVENT	(ISC_EVENTCLASS_TASK + 0)
90 #define ISC_TASKEVENT_SHUTDOWN		(ISC_EVENTCLASS_TASK + 1)
91 #define ISC_TASKEVENT_TEST		(ISC_EVENTCLASS_TASK + 1)
92 #define ISC_TASKEVENT_LASTEVENT		(ISC_EVENTCLASS_TASK + 65535)
93 
94 /*****
95  ***** Tasks.
96  *****/
97 
98 ISC_LANG_BEGINDECLS
99 
100 /***
101  *** Types
102  ***/
103 
104 typedef enum {
105 		isc_taskmgrmode_normal = 0,
106 		isc_taskmgrmode_privileged
107 } isc_taskmgrmode_t;
108 
109 /*% Task and task manager methods */
110 typedef struct isc_taskmgrmethods {
111 	void		(*destroy)(isc_taskmgr_t **managerp);
112 	void		(*setmode)(isc_taskmgr_t *manager,
113 				   isc_taskmgrmode_t mode);
114 	isc_taskmgrmode_t (*mode)(isc_taskmgr_t *manager);
115 	isc_result_t	(*taskcreate)(isc_taskmgr_t *manager,
116 				      unsigned int quantum,
117 				      isc_task_t **taskp);
118 } isc_taskmgrmethods_t;
119 
120 typedef struct isc_taskmethods {
121 	void (*attach)(isc_task_t *source, isc_task_t **targetp);
122 	void (*detach)(isc_task_t **taskp);
123 	void (*destroy)(isc_task_t **taskp);
124 	void (*send)(isc_task_t *task, isc_event_t **eventp);
125 	void (*sendanddetach)(isc_task_t **taskp, isc_event_t **eventp);
126 	unsigned int (*unsend)(isc_task_t *task, void *sender, isc_eventtype_t type,
127 			       void *tag, isc_eventlist_t *events);
128 	isc_result_t (*onshutdown)(isc_task_t *task, isc_taskaction_t action,
129 				   const void *arg);
130 	void (*shutdown)(isc_task_t *task);
131 	void (*setname)(isc_task_t *task, const char *name, void *tag);
132 	unsigned int (*purgeevents)(isc_task_t *task, void *sender,
133 				    isc_eventtype_t type, void *tag);
134 	unsigned int (*purgerange)(isc_task_t *task, void *sender,
135 				   isc_eventtype_t first, isc_eventtype_t last,
136 				   void *tag);
137 	isc_result_t (*beginexclusive)(isc_task_t *task);
138 	void (*endexclusive)(isc_task_t *task);
139     void (*setprivilege)(isc_task_t *task, isc_boolean_t priv);
140     isc_boolean_t (*privilege)(isc_task_t *task);
141 } isc_taskmethods_t;
142 
143 /*%
144  * This structure is actually just the common prefix of a task manager
145  * object implementation's version of an isc_taskmgr_t.
146  * \brief
147  * Direct use of this structure by clients is forbidden.  task implementations
148  * may change the structure.  'magic' must be ISCAPI_TASKMGR_MAGIC for any
149  * of the isc_task_ routines to work.  task implementations must maintain
150  * all task invariants.
151  */
152 struct isc_taskmgr {
153 	unsigned int		impmagic;
154 	unsigned int		magic;
155 	isc_taskmgrmethods_t	*methods;
156 };
157 
158 #define ISCAPI_TASKMGR_MAGIC	ISC_MAGIC('A','t','m','g')
159 #define ISCAPI_TASKMGR_VALID(m)	((m) != NULL && \
160 				 (m)->magic == ISCAPI_TASKMGR_MAGIC)
161 
162 /*%
163  * This is the common prefix of a task object.  The same note as
164  * that for the taskmgr structure applies.
165  */
166 struct isc_task {
167 	unsigned int		impmagic;
168 	unsigned int		magic;
169 	isc_taskmethods_t	*methods;
170 };
171 
172 #define ISCAPI_TASK_MAGIC	ISC_MAGIC('A','t','s','t')
173 #define ISCAPI_TASK_VALID(s)	((s) != NULL && \
174 				 (s)->magic == ISCAPI_TASK_MAGIC)
175 
176 isc_result_t
177 isc_task_create(isc_taskmgr_t *manager, unsigned int quantum,
178 		isc_task_t **taskp);
179 /*%<
180  * Create a task.
181  *
182  * Notes:
183  *
184  *\li	If 'quantum' is non-zero, then only that many events can be dispatched
185  *	before the task must yield to other tasks waiting to execute.  If
186  *	quantum is zero, then the default quantum of the task manager will
187  *	be used.
188  *
189  *\li	The 'quantum' option may be removed from isc_task_create() in the
190  *	future.  If this happens, isc_task_getquantum() and
191  *	isc_task_setquantum() will be provided.
192  *
193  * Requires:
194  *
195  *\li	'manager' is a valid task manager.
196  *
197  *\li	taskp != NULL && *taskp == NULL
198  *
199  * Ensures:
200  *
201  *\li	On success, '*taskp' is bound to the new task.
202  *
203  * Returns:
204  *
205  *\li   #ISC_R_SUCCESS
206  *\li	#ISC_R_NOMEMORY
207  *\li	#ISC_R_UNEXPECTED
208  *\li	#ISC_R_SHUTTINGDOWN
209  */
210 
211 void
212 isc_task_attach(isc_task_t *source, isc_task_t **targetp);
213 /*%<
214  * Attach *targetp to source.
215  *
216  * Requires:
217  *
218  *\li	'source' is a valid task.
219  *
220  *\li	'targetp' points to a NULL isc_task_t *.
221  *
222  * Ensures:
223  *
224  *\li	*targetp is attached to source.
225  */
226 
227 void
228 isc_task_detach(isc_task_t **taskp);
229 /*%<
230  * Detach *taskp from its task.
231  *
232  * Requires:
233  *
234  *\li	'*taskp' is a valid task.
235  *
236  * Ensures:
237  *
238  *\li	*taskp is NULL.
239  *
240  *\li	If '*taskp' is the last reference to the task, the task is idle (has
241  *	an empty event queue), and has not been shutdown, the task will be
242  *	shutdown.
243  *
244  *\li	If '*taskp' is the last reference to the task and
245  *	the task has been shutdown,
246  *		all resources used by the task will be freed.
247  */
248 
249 void
250 isc_task_send(isc_task_t *task, isc_event_t **eventp);
251 /*%<
252  * Send '*event' to 'task'.
253  *
254  * Requires:
255  *
256  *\li	'task' is a valid task.
257  *\li	eventp != NULL && *eventp != NULL.
258  *
259  * Ensures:
260  *
261  *\li	*eventp == NULL.
262  */
263 
264 void
265 isc_task_sendanddetach(isc_task_t **taskp, isc_event_t **eventp);
266 /*%<
267  * Send '*event' to '*taskp' and then detach '*taskp' from its
268  * task.
269  *
270  * Requires:
271  *
272  *\li	'*taskp' is a valid task.
273  *\li	eventp != NULL && *eventp != NULL.
274  *
275  * Ensures:
276  *
277  *\li	*eventp == NULL.
278  *
279  *\li	*taskp == NULL.
280  *
281  *\li	If '*taskp' is the last reference to the task, the task is
282  *	idle (has an empty event queue), and has not been shutdown,
283  *	the task will be shutdown.
284  *
285  *\li	If '*taskp' is the last reference to the task and
286  *	the task has been shutdown,
287  *		all resources used by the task will be freed.
288  */
289 
290 
291 unsigned int
292 isc_task_purgerange(isc_task_t *task, void *sender, isc_eventtype_t first,
293 		    isc_eventtype_t last, void *tag);
294 /*%<
295  * Purge events from a task's event queue.
296  *
297  * Requires:
298  *
299  *\li	'task' is a valid task.
300  *
301  *\li	last >= first
302  *
303  * Ensures:
304  *
305  *\li	Events in the event queue of 'task' whose sender is 'sender', whose
306  *	type is >= first and <= last, and whose tag is 'tag' will be purged,
307  *	unless they are marked as unpurgable.
308  *
309  *\li	A sender of NULL will match any sender.  A NULL tag matches any
310  *	tag.
311  *
312  * Returns:
313  *
314  *\li	The number of events purged.
315  */
316 
317 unsigned int
318 isc_task_purge(isc_task_t *task, void *sender, isc_eventtype_t type,
319 	       void *tag);
320 /*%<
321  * Purge events from a task's event queue.
322  *
323  * Notes:
324  *
325  *\li	This function is equivalent to
326  *
327  *\code
328  *		isc_task_purgerange(task, sender, type, type, tag);
329  *\endcode
330  *
331  * Requires:
332  *
333  *\li	'task' is a valid task.
334  *
335  * Ensures:
336  *
337  *\li	Events in the event queue of 'task' whose sender is 'sender', whose
338  *	type is 'type', and whose tag is 'tag' will be purged, unless they
339  *	are marked as unpurgable.
340  *
341  *\li	A sender of NULL will match any sender.  A NULL tag matches any
342  *	tag.
343  *
344  * Returns:
345  *
346  *\li	The number of events purged.
347  */
348 
349 isc_boolean_t
350 isc_task_purgeevent(isc_task_t *task, isc_event_t *event);
351 /*%<
352  * Purge 'event' from a task's event queue.
353  *
354  * XXXRTH:  WARNING:  This method may be removed before beta.
355  *
356  * Notes:
357  *
358  *\li	If 'event' is on the task's event queue, it will be purged,
359  * 	unless it is marked as unpurgeable.  'event' does not have to be
360  *	on the task's event queue; in fact, it can even be an invalid
361  *	pointer.  Purging only occurs if the event is actually on the task's
362  *	event queue.
363  *
364  * \li	Purging never changes the state of the task.
365  *
366  * Requires:
367  *
368  *\li	'task' is a valid task.
369  *
370  * Ensures:
371  *
372  *\li	'event' is not in the event queue for 'task'.
373  *
374  * Returns:
375  *
376  *\li	#ISC_TRUE			The event was purged.
377  *\li	#ISC_FALSE			The event was not in the event queue,
378  *					or was marked unpurgeable.
379  */
380 
381 unsigned int
382 isc_task_unsendrange(isc_task_t *task, void *sender, isc_eventtype_t first,
383 		     isc_eventtype_t last, void *tag, isc_eventlist_t *events);
384 /*%<
385  * Remove events from a task's event queue.
386  *
387  * Requires:
388  *
389  *\li	'task' is a valid task.
390  *
391  *\li	last >= first.
392  *
393  *\li	*events is a valid list.
394  *
395  * Ensures:
396  *
397  *\li	Events in the event queue of 'task' whose sender is 'sender', whose
398  *	type is >= first and <= last, and whose tag is 'tag' will be dequeued
399  *	and appended to *events.
400  *
401  *\li	A sender of NULL will match any sender.  A NULL tag matches any
402  *	tag.
403  *
404  * Returns:
405  *
406  *\li	The number of events unsent.
407  */
408 
409 unsigned int
410 isc_task_unsend(isc_task_t *task, void *sender, isc_eventtype_t type,
411 		void *tag, isc_eventlist_t *events);
412 /*%<
413  * Remove events from a task's event queue.
414  *
415  * Notes:
416  *
417  *\li	This function is equivalent to
418  *
419  *\code
420  *		isc_task_unsendrange(task, sender, type, type, tag, events);
421  *\endcode
422  *
423  * Requires:
424  *
425  *\li	'task' is a valid task.
426  *
427  *\li	*events is a valid list.
428  *
429  * Ensures:
430  *
431  *\li	Events in the event queue of 'task' whose sender is 'sender', whose
432  *	type is 'type', and whose tag is 'tag' will be dequeued and appended
433  *	to *events.
434  *
435  * Returns:
436  *
437  *\li	The number of events unsent.
438  */
439 
440 isc_result_t
441 isc_task_onshutdown(isc_task_t *task, isc_taskaction_t action,
442 		    const void *arg);
443 /*%<
444  * Send a shutdown event with action 'action' and argument 'arg' when
445  * 'task' is shutdown.
446  *
447  * Notes:
448  *
449  *\li	Shutdown events are posted in LIFO order.
450  *
451  * Requires:
452  *
453  *\li	'task' is a valid task.
454  *
455  *\li	'action' is a valid task action.
456  *
457  * Ensures:
458  *
459  *\li	When the task is shutdown, shutdown events requested with
460  *	isc_task_onshutdown() will be appended to the task's event queue.
461  *
462 
463  * Returns:
464  *
465  *\li	#ISC_R_SUCCESS
466  *\li	#ISC_R_NOMEMORY
467  *\li	#ISC_R_TASKSHUTTINGDOWN			Task is shutting down.
468  */
469 
470 void
471 isc_task_shutdown(isc_task_t *task);
472 /*%<
473  * Shutdown 'task'.
474  *
475  * Notes:
476  *
477  *\li	Shutting down a task causes any shutdown events requested with
478  *	isc_task_onshutdown() to be posted (in LIFO order).  The task
479  *	moves into a "shutting down" mode which prevents further calls
480  *	to isc_task_onshutdown().
481  *
482  *\li	Trying to shutdown a task that has already been shutdown has no
483  *	effect.
484  *
485  * Requires:
486  *
487  *\li	'task' is a valid task.
488  *
489  * Ensures:
490  *
491  *\li	Any shutdown events requested with isc_task_onshutdown() have been
492  *	posted (in LIFO order).
493  */
494 
495 void
496 isc_task_destroy(isc_task_t **taskp);
497 /*%<
498  * Destroy '*taskp'.
499  *
500  * Notes:
501  *
502  *\li	This call is equivalent to:
503  *
504  *\code
505  *		isc_task_shutdown(*taskp);
506  *		isc_task_detach(taskp);
507  *\endcode
508  *
509  * Requires:
510  *
511  *	'*taskp' is a valid task.
512  *
513  * Ensures:
514  *
515  *\li	Any shutdown events requested with isc_task_onshutdown() have been
516  *	posted (in LIFO order).
517  *
518  *\li	*taskp == NULL
519  *
520  *\li	If '*taskp' is the last reference to the task,
521  *		all resources used by the task will be freed.
522  */
523 
524 void
525 isc_task_setname(isc_task_t *task, const char *name, void *tag);
526 /*%<
527  * Name 'task'.
528  *
529  * Notes:
530  *
531  *\li	Only the first 15 characters of 'name' will be copied.
532  *
533  *\li	Naming a task is currently only useful for debugging purposes.
534  *
535  * Requires:
536  *
537  *\li	'task' is a valid task.
538  */
539 
540 const char *
541 isc_task_getname(isc_task_t *task);
542 /*%<
543  * Get the name of 'task', as previously set using isc_task_setname().
544  *
545  * Notes:
546  *\li	This function is for debugging purposes only.
547  *
548  * Requires:
549  *\li	'task' is a valid task.
550  *
551  * Returns:
552  *\li	A non-NULL pointer to a null-terminated string.
553  * 	If the task has not been named, the string is
554  * 	empty.
555  *
556  */
557 
558 void *
559 isc_task_gettag(isc_task_t *task);
560 /*%<
561  * Get the tag value for  'task', as previously set using isc_task_settag().
562  *
563  * Notes:
564  *\li	This function is for debugging purposes only.
565  *
566  * Requires:
567  *\li	'task' is a valid task.
568  */
569 
570 isc_result_t
571 isc_task_beginexclusive(isc_task_t *task);
572 /*%<
573  * Request exclusive access for 'task', which must be the calling
574  * task.  Waits for any other concurrently executing tasks to finish their
575  * current event, and prevents any new events from executing in any of the
576  * tasks sharing a task manager with 'task'.
577  *
578  * The exclusive access must be relinquished by calling
579  * isc_task_endexclusive() before returning from the current event handler.
580  *
581  * Requires:
582  *\li	'task' is the calling task.
583  *
584  * Returns:
585  *\li	#ISC_R_SUCCESS		The current task now has exclusive access.
586  *\li	#ISC_R_LOCKBUSY		Another task has already requested exclusive
587  *				access.
588  */
589 
590 void
591 isc_task_endexclusive(isc_task_t *task);
592 /*%<
593  * Relinquish the exclusive access obtained by isc_task_beginexclusive(),
594  * allowing other tasks to execute.
595  *
596  * Requires:
597  *\li	'task' is the calling task, and has obtained
598  *		exclusive access by calling isc_task_spl().
599  */
600 
601 void
602 isc_task_getcurrenttime(isc_task_t *task, isc_stdtime_t *t);
603 /*%<
604  * Provide the most recent timestamp on the task.  The timestamp is considered
605  * as the "current time" in the second-order granularity.
606  *
607  * Requires:
608  *\li	'task' is a valid task.
609  *\li	't' is a valid non NULL pointer.
610  *
611  * Ensures:
612  *\li	'*t' has the "current time".
613  */
614 
615 isc_boolean_t
616 isc_task_exiting(isc_task_t *t);
617 /*%<
618  * Returns ISC_TRUE if the task is in the process of shutting down,
619  * ISC_FALSE otherwise.
620  *
621  * Requires:
622  *\li	'task' is a valid task.
623  */
624 
625 void
626 isc_task_setprivilege(isc_task_t *task, isc_boolean_t priv);
627 /*%<
628  * Set or unset the task's "privileged" flag depending on the value of
629  * 'priv'.
630  *
631  * Under normal circumstances this flag has no effect on the task behavior,
632  * but when the task manager has been set to privileged exeuction mode via
633  * isc_taskmgr_setmode(), only tasks with the flag set will be executed,
634  * and all other tasks will wait until they're done.  Once all privileged
635  * tasks have finished executing, the task manager will automatically
636  * return to normal execution mode and nonprivileged task can resume.
637  *
638  * Requires:
639  *\li	'task' is a valid task.
640  */
641 
642 isc_boolean_t
643 isc_task_privilege(isc_task_t *task);
644 /*%<
645  * Returns the current value of the task's privilege flag.
646  *
647  * Requires:
648  *\li	'task' is a valid task.
649  */
650 
651 /*****
652  ***** Task Manager.
653  *****/
654 
655 isc_result_t
656 isc_taskmgr_createinctx(isc_mem_t *mctx, isc_appctx_t *actx,
657 			unsigned int workers, unsigned int default_quantum,
658 			isc_taskmgr_t **managerp);
659 isc_result_t
660 isc_taskmgr_create(isc_mem_t *mctx, unsigned int workers,
661 		   unsigned int default_quantum, isc_taskmgr_t **managerp);
662 /*%<
663  * Create a new task manager.  isc_taskmgr_createinctx() also associates
664  * the new manager with the specified application context.
665  *
666  * Notes:
667  *
668  *\li	'workers' in the number of worker threads to create.  In general,
669  *	the value should be close to the number of processors in the system.
670  *	The 'workers' value is advisory only.  An attempt will be made to
671  *	create 'workers' threads, but if at least one thread creation
672  *	succeeds, isc_taskmgr_create() may return ISC_R_SUCCESS.
673  *
674  *\li	If 'default_quantum' is non-zero, then it will be used as the default
675  *	quantum value when tasks are created.  If zero, then an implementation
676  *	defined default quantum will be used.
677  *
678  * Requires:
679  *
680  *\li      'mctx' is a valid memory context.
681  *
682  *\li	workers > 0
683  *
684  *\li	managerp != NULL && *managerp == NULL
685  *
686  *\li	'actx' is a valid application context (for createinctx()).
687  *
688  * Ensures:
689  *
690  *\li	On success, '*managerp' will be attached to the newly created task
691  *	manager.
692  *
693  * Returns:
694  *
695  *\li	#ISC_R_SUCCESS
696  *\li	#ISC_R_NOMEMORY
697  *\li	#ISC_R_NOTHREADS		No threads could be created.
698  *\li	#ISC_R_UNEXPECTED		An unexpected error occurred.
699  *\li	#ISC_R_SHUTTINGDOWN      	The non-threaded, shared, task
700  *					manager shutting down.
701  */
702 
703 void
704 isc_taskmgr_setmode(isc_taskmgr_t *manager, isc_taskmgrmode_t mode);
705 
706 isc_taskmgrmode_t
707 isc_taskmgr_mode(isc_taskmgr_t *manager);
708 /*%<
709  * Set/get the current operating mode of the task manager.  Valid modes are:
710  *
711  *\li  isc_taskmgrmode_normal
712  *\li  isc_taskmgrmode_privileged
713  *
714  * In privileged execution mode, only tasks that have had the "privilege"
715  * flag set via isc_task_setprivilege() can be executed.  When all such
716  * tasks are complete, the manager automatically returns to normal mode
717  * and proceeds with running non-privileged ready tasks.  This means it is
718  * necessary to have at least one privileged task waiting on the ready
719  * queue *before* setting the manager into privileged execution mode,
720  * which in turn means the task which calls this function should be in
721  * task-exclusive mode when it does so.
722  *
723  * Requires:
724  *
725  *\li      'manager' is a valid task manager.
726  */
727 
728 void
729 isc_taskmgr_destroy(isc_taskmgr_t **managerp);
730 /*%<
731  * Destroy '*managerp'.
732  *
733  * Notes:
734  *
735  *\li	Calling isc_taskmgr_destroy() will shutdown all tasks managed by
736  *	*managerp that haven't already been shutdown.  The call will block
737  *	until all tasks have entered the done state.
738  *
739  *\li	isc_taskmgr_destroy() must not be called by a task event action,
740  *	because it would block forever waiting for the event action to
741  *	complete.  An event action that wants to cause task manager shutdown
742  *	should request some non-event action thread of execution to do the
743  *	shutdown, e.g. by signaling a condition variable or using
744  *	isc_app_shutdown().
745  *
746  *\li	Task manager references are not reference counted, so the caller
747  *	must ensure that no attempt will be made to use the manager after
748  *	isc_taskmgr_destroy() returns.
749  *
750  * Requires:
751  *
752  *\li	'*managerp' is a valid task manager.
753  *
754  *\li	isc_taskmgr_destroy() has not be called previously on '*managerp'.
755  *
756  * Ensures:
757  *
758  *\li	All resources used by the task manager, and any tasks it managed,
759  *	have been freed.
760  */
761 
762 #ifdef HAVE_LIBXML2
763 
764 void
765 isc_taskmgr_renderxml(isc_taskmgr_t *mgr, xmlTextWriterPtr writer);
766 
767 #endif
768 
769 /*%<
770  * See isc_taskmgr_create() above.
771  */
772 typedef isc_result_t
773 (*isc_taskmgrcreatefunc_t)(isc_mem_t *mctx, unsigned int workers,
774 			   unsigned int default_quantum,
775 			   isc_taskmgr_t **managerp);
776 
777 isc_result_t
778 isc_task_register(isc_taskmgrcreatefunc_t createfunc);
779 /*%<
780  * Register a new task management implementation and add it to the list of
781  * supported implementations.  This function must be called when a different
782  * event library is used than the one contained in the ISC library.
783  */
784 
785 isc_result_t
786 isc__task_register(void);
787 /*%<
788  * A short cut function that specifies the task management module in the ISC
789  * library for isc_task_register().  An application that uses the ISC library
790  * usually do not have to care about this function: it would call
791  * isc_lib_register(), which internally calls this function.
792  */
793 
794 ISC_LANG_ENDDECLS
795 
796 #endif /* ISC_TASK_H */
797