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