1/*
2 * Copyright (C) 2004-2007, 2009  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: task.h,v 1.61.332.2 2009/01/18 23:47:41 tbox Exp $ */
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_LASTEVENT		(ISC_EVENTCLASS_TASK + 65535)
92
93/*****
94 ***** Tasks.
95 *****/
96
97ISC_LANG_BEGINDECLS
98
99isc_result_t
100isc_task_create(isc_taskmgr_t *manager, unsigned int quantum,
101		isc_task_t **taskp);
102/*%<
103 * Create a task.
104 *
105 * Notes:
106 *
107 *\li	If 'quantum' is non-zero, then only that many events can be dispatched
108 *	before the task must yield to other tasks waiting to execute.  If
109 *	quantum is zero, then the default quantum of the task manager will
110 *	be used.
111 *
112 *\li	The 'quantum' option may be removed from isc_task_create() in the
113 *	future.  If this happens, isc_task_getquantum() and
114 *	isc_task_setquantum() will be provided.
115 *
116 * Requires:
117 *
118 *\li	'manager' is a valid task manager.
119 *
120 *\li	taskp != NULL && *taskp == NULL
121 *
122 * Ensures:
123 *
124 *\li	On success, '*taskp' is bound to the new task.
125 *
126 * Returns:
127 *
128 *\li   #ISC_R_SUCCESS
129 *\li	#ISC_R_NOMEMORY
130 *\li	#ISC_R_UNEXPECTED
131 *\li	#ISC_R_SHUTTINGDOWN
132 */
133
134void
135isc_task_attach(isc_task_t *source, isc_task_t **targetp);
136/*%<
137 * Attach *targetp to source.
138 *
139 * Requires:
140 *
141 *\li	'source' is a valid task.
142 *
143 *\li	'targetp' points to a NULL isc_task_t *.
144 *
145 * Ensures:
146 *
147 *\li	*targetp is attached to source.
148 */
149
150void
151isc_task_detach(isc_task_t **taskp);
152/*%<
153 * Detach *taskp from its task.
154 *
155 * Requires:
156 *
157 *\li	'*taskp' is a valid task.
158 *
159 * Ensures:
160 *
161 *\li	*taskp is NULL.
162 *
163 *\li	If '*taskp' is the last reference to the task, the task is idle (has
164 *	an empty event queue), and has not been shutdown, the task will be
165 *	shutdown.
166 *
167 *\li	If '*taskp' is the last reference to the task and
168 *	the task has been shutdown,
169 *		all resources used by the task will be freed.
170 */
171
172void
173isc_task_send(isc_task_t *task, isc_event_t **eventp);
174/*%<
175 * Send '*event' to 'task'.
176 *
177 * Requires:
178 *
179 *\li	'task' is a valid task.
180 *\li	eventp != NULL && *eventp != NULL.
181 *
182 * Ensures:
183 *
184 *\li	*eventp == NULL.
185 */
186
187void
188isc_task_sendanddetach(isc_task_t **taskp, isc_event_t **eventp);
189/*%<
190 * Send '*event' to '*taskp' and then detach '*taskp' from its
191 * task.
192 *
193 * Requires:
194 *
195 *\li	'*taskp' is a valid task.
196 *\li	eventp != NULL && *eventp != NULL.
197 *
198 * Ensures:
199 *
200 *\li	*eventp == NULL.
201 *
202 *\li	*taskp == NULL.
203 *
204 *\li	If '*taskp' is the last reference to the task, the task is
205 *	idle (has an empty event queue), and has not been shutdown,
206 *	the task will be shutdown.
207 *
208 *\li	If '*taskp' is the last reference to the task and
209 *	the task has been shutdown,
210 *		all resources used by the task will be freed.
211 */
212
213
214unsigned int
215isc_task_purgerange(isc_task_t *task, void *sender, isc_eventtype_t first,
216		    isc_eventtype_t last, void *tag);
217/*%<
218 * Purge events from a task's event queue.
219 *
220 * Requires:
221 *
222 *\li	'task' is a valid task.
223 *
224 *\li	last >= first
225 *
226 * Ensures:
227 *
228 *\li	Events in the event queue of 'task' whose sender is 'sender', whose
229 *	type is >= first and <= last, and whose tag is 'tag' will be purged,
230 *	unless they are marked as unpurgable.
231 *
232 *\li	A sender of NULL will match any sender.  A NULL tag matches any
233 *	tag.
234 *
235 * Returns:
236 *
237 *\li	The number of events purged.
238 */
239
240unsigned int
241isc_task_purge(isc_task_t *task, void *sender, isc_eventtype_t type,
242	       void *tag);
243/*%<
244 * Purge events from a task's event queue.
245 *
246 * Notes:
247 *
248 *\li	This function is equivalent to
249 *
250 *\code
251 *		isc_task_purgerange(task, sender, type, type, tag);
252 *\endcode
253 *
254 * Requires:
255 *
256 *\li	'task' is a valid task.
257 *
258 * Ensures:
259 *
260 *\li	Events in the event queue of 'task' whose sender is 'sender', whose
261 *	type is 'type', and whose tag is 'tag' will be purged, unless they
262 *	are marked as unpurgable.
263 *
264 *\li	A sender of NULL will match any sender.  A NULL tag matches any
265 *	tag.
266 *
267 * Returns:
268 *
269 *\li	The number of events purged.
270 */
271
272isc_boolean_t
273isc_task_purgeevent(isc_task_t *task, isc_event_t *event);
274/*%<
275 * Purge 'event' from a task's event queue.
276 *
277 * XXXRTH:  WARNING:  This method may be removed before beta.
278 *
279 * Notes:
280 *
281 *\li	If 'event' is on the task's event queue, it will be purged,
282 * 	unless it is marked as unpurgeable.  'event' does not have to be
283 *	on the task's event queue; in fact, it can even be an invalid
284 *	pointer.  Purging only occurs if the event is actually on the task's
285 *	event queue.
286 *
287 * \li	Purging never changes the state of the task.
288 *
289 * Requires:
290 *
291 *\li	'task' is a valid task.
292 *
293 * Ensures:
294 *
295 *\li	'event' is not in the event queue for 'task'.
296 *
297 * Returns:
298 *
299 *\li	#ISC_TRUE			The event was purged.
300 *\li	#ISC_FALSE			The event was not in the event queue,
301 *					or was marked unpurgeable.
302 */
303
304unsigned int
305isc_task_unsendrange(isc_task_t *task, void *sender, isc_eventtype_t first,
306		     isc_eventtype_t last, void *tag, isc_eventlist_t *events);
307/*%<
308 * Remove events from a task's event queue.
309 *
310 * Requires:
311 *
312 *\li	'task' is a valid task.
313 *
314 *\li	last >= first.
315 *
316 *\li	*events is a valid list.
317 *
318 * Ensures:
319 *
320 *\li	Events in the event queue of 'task' whose sender is 'sender', whose
321 *	type is >= first and <= last, and whose tag is 'tag' will be dequeued
322 *	and appended to *events.
323 *
324 *\li	A sender of NULL will match any sender.  A NULL tag matches any
325 *	tag.
326 *
327 * Returns:
328 *
329 *\li	The number of events unsent.
330 */
331
332unsigned int
333isc_task_unsend(isc_task_t *task, void *sender, isc_eventtype_t type,
334		void *tag, isc_eventlist_t *events);
335/*%<
336 * Remove events from a task's event queue.
337 *
338 * Notes:
339 *
340 *\li	This function is equivalent to
341 *
342 *\code
343 *		isc_task_unsendrange(task, sender, type, type, tag, events);
344 *\endcode
345 *
346 * Requires:
347 *
348 *\li	'task' is a valid task.
349 *
350 *\li	*events is a valid list.
351 *
352 * Ensures:
353 *
354 *\li	Events in the event queue of 'task' whose sender is 'sender', whose
355 *	type is 'type', and whose tag is 'tag' will be dequeued and appended
356 *	to *events.
357 *
358 * Returns:
359 *
360 *\li	The number of events unsent.
361 */
362
363isc_result_t
364isc_task_onshutdown(isc_task_t *task, isc_taskaction_t action,
365		    const void *arg);
366/*%<
367 * Send a shutdown event with action 'action' and argument 'arg' when
368 * 'task' is shutdown.
369 *
370 * Notes:
371 *
372 *\li	Shutdown events are posted in LIFO order.
373 *
374 * Requires:
375 *
376 *\li	'task' is a valid task.
377 *
378 *\li	'action' is a valid task action.
379 *
380 * Ensures:
381 *
382 *\li	When the task is shutdown, shutdown events requested with
383 *	isc_task_onshutdown() will be appended to the task's event queue.
384 *
385
386 * Returns:
387 *
388 *\li	#ISC_R_SUCCESS
389 *\li	#ISC_R_NOMEMORY
390 *\li	#ISC_R_TASKSHUTTINGDOWN			Task is shutting down.
391 */
392
393void
394isc_task_shutdown(isc_task_t *task);
395/*%<
396 * Shutdown 'task'.
397 *
398 * Notes:
399 *
400 *\li	Shutting down a task causes any shutdown events requested with
401 *	isc_task_onshutdown() to be posted (in LIFO order).  The task
402 *	moves into a "shutting down" mode which prevents further calls
403 *	to isc_task_onshutdown().
404 *
405 *\li	Trying to shutdown a task that has already been shutdown has no
406 *	effect.
407 *
408 * Requires:
409 *
410 *\li	'task' is a valid task.
411 *
412 * Ensures:
413 *
414 *\li	Any shutdown events requested with isc_task_onshutdown() have been
415 *	posted (in LIFO order).
416 */
417
418void
419isc_task_destroy(isc_task_t **taskp);
420/*%<
421 * Destroy '*taskp'.
422 *
423 * Notes:
424 *
425 *\li	This call is equivalent to:
426 *
427 *\code
428 *		isc_task_shutdown(*taskp);
429 *		isc_task_detach(taskp);
430 *\endcode
431 *
432 * Requires:
433 *
434 *	'*taskp' is a valid task.
435 *
436 * Ensures:
437 *
438 *\li	Any shutdown events requested with isc_task_onshutdown() have been
439 *	posted (in LIFO order).
440 *
441 *\li	*taskp == NULL
442 *
443 *\li	If '*taskp' is the last reference to the task,
444 *		all resources used by the task will be freed.
445 */
446
447void
448isc_task_setname(isc_task_t *task, const char *name, void *tag);
449/*%<
450 * Name 'task'.
451 *
452 * Notes:
453 *
454 *\li	Only the first 15 characters of 'name' will be copied.
455 *
456 *\li	Naming a task is currently only useful for debugging purposes.
457 *
458 * Requires:
459 *
460 *\li	'task' is a valid task.
461 */
462
463const char *
464isc_task_getname(isc_task_t *task);
465/*%<
466 * Get the name of 'task', as previously set using isc_task_setname().
467 *
468 * Notes:
469 *\li	This function is for debugging purposes only.
470 *
471 * Requires:
472 *\li	'task' is a valid task.
473 *
474 * Returns:
475 *\li	A non-NULL pointer to a null-terminated string.
476 * 	If the task has not been named, the string is
477 * 	empty.
478 *
479 */
480
481void *
482isc_task_gettag(isc_task_t *task);
483/*%<
484 * Get the tag value for  'task', as previously set using isc_task_settag().
485 *
486 * Notes:
487 *\li	This function is for debugging purposes only.
488 *
489 * Requires:
490 *\li	'task' is a valid task.
491 */
492
493isc_result_t
494isc_task_beginexclusive(isc_task_t *task);
495/*%<
496 * Request exclusive access for 'task', which must be the calling
497 * task.  Waits for any other concurrently executing tasks to finish their
498 * current event, and prevents any new events from executing in any of the
499 * tasks sharing a task manager with 'task'.
500 *
501 * The exclusive access must be relinquished by calling
502 * isc_task_endexclusive() before returning from the current event handler.
503 *
504 * Requires:
505 *\li	'task' is the calling task.
506 *
507 * Returns:
508 *\li	#ISC_R_SUCCESS		The current task now has exclusive access.
509 *\li	#ISC_R_LOCKBUSY		Another task has already requested exclusive
510 *				access.
511 */
512
513void
514isc_task_endexclusive(isc_task_t *task);
515/*%<
516 * Relinquish the exclusive access obtained by isc_task_beginexclusive(),
517 * allowing other tasks to execute.
518 *
519 * Requires:
520 *\li	'task' is the calling task, and has obtained
521 *		exclusive access by calling isc_task_spl().
522 */
523
524void
525isc_task_getcurrenttime(isc_task_t *task, isc_stdtime_t *t);
526/*%<
527 * Provide the most recent timestamp on the task.  The timestamp is considered
528 * as the "current time" in the second-order granularity.
529 *
530 * Requires:
531 *\li	'task' is a valid task.
532 *\li	't' is a valid non NULL pointer.
533 *
534 * Ensures:
535 *\li	'*t' has the "current time".
536 */
537
538/*****
539 ***** Task Manager.
540 *****/
541
542isc_result_t
543isc_taskmgr_create(isc_mem_t *mctx, unsigned int workers,
544		   unsigned int default_quantum, isc_taskmgr_t **managerp);
545/*%<
546 * Create a new task manager.
547 *
548 * Notes:
549 *
550 *\li	'workers' in the number of worker threads to create.  In general,
551 *	the value should be close to the number of processors in the system.
552 *	The 'workers' value is advisory only.  An attempt will be made to
553 *	create 'workers' threads, but if at least one thread creation
554 *	succeeds, isc_taskmgr_create() may return ISC_R_SUCCESS.
555 *
556 *\li	If 'default_quantum' is non-zero, then it will be used as the default
557 *	quantum value when tasks are created.  If zero, then an implementation
558 *	defined default quantum will be used.
559 *
560 * Requires:
561 *
562 *\li      'mctx' is a valid memory context.
563 *
564 *\li	workers > 0
565 *
566 *\li	managerp != NULL && *managerp == NULL
567 *
568 * Ensures:
569 *
570 *\li	On success, '*managerp' will be attached to the newly created task
571 *	manager.
572 *
573 * Returns:
574 *
575 *\li	#ISC_R_SUCCESS
576 *\li	#ISC_R_NOMEMORY
577 *\li	#ISC_R_NOTHREADS			No threads could be created.
578 *\li	#ISC_R_UNEXPECTED		An unexpected error occurred.
579 */
580
581void
582isc_taskmgr_destroy(isc_taskmgr_t **managerp);
583/*%<
584 * Destroy '*managerp'.
585 *
586 * Notes:
587 *
588 *\li	Calling isc_taskmgr_destroy() will shutdown all tasks managed by
589 *	*managerp that haven't already been shutdown.  The call will block
590 *	until all tasks have entered the done state.
591 *
592 *\li	isc_taskmgr_destroy() must not be called by a task event action,
593 *	because it would block forever waiting for the event action to
594 *	complete.  An event action that wants to cause task manager shutdown
595 *	should request some non-event action thread of execution to do the
596 *	shutdown, e.g. by signaling a condition variable or using
597 *	isc_app_shutdown().
598 *
599 *\li	Task manager references are not reference counted, so the caller
600 *	must ensure that no attempt will be made to use the manager after
601 *	isc_taskmgr_destroy() returns.
602 *
603 * Requires:
604 *
605 *\li	'*managerp' is a valid task manager.
606 *
607 *\li	isc_taskmgr_destroy() has not be called previously on '*managerp'.
608 *
609 * Ensures:
610 *
611 *\li	All resources used by the task manager, and any tasks it managed,
612 *	have been freed.
613 */
614
615#ifdef HAVE_LIBXML2
616
617void
618isc_taskmgr_renderxml(isc_taskmgr_t *mgr, xmlTextWriterPtr writer);
619
620#endif
621
622ISC_LANG_ENDDECLS
623
624#endif /* ISC_TASK_H */
625