Add BIND 9.2.4rc7.
[dragonfly.git] / contrib / bind-9.2.4rc7 / lib / isc / include / isc / task.h
1 /*
2  * Copyright (C) 2004  Internet Systems Consortium, Inc. ("ISC")
3  * Copyright (C) 1998-2001  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.49.2.1 2004/03/09 06:12:02 marka Exp $ */
19
20 #ifndef ISC_TASK_H
21 #define ISC_TASK_H 1
22
23 /*****
24  ***** Module Info
25  *****/
26
27 /*
28  * Task System
29  *
30  * The task system provides a lightweight execution context, which is
31  * basically an event queue.  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  * MP:
37  *      The module ensures appropriate synchronization of data structures it
38  *      creates and manipulates.
39  *
40  *      The caller must ensure that isc_taskmgr_destroy() is called only
41  *      once for a given manager.
42  *
43  * Reliability:
44  *      No anticipated impact.
45  *
46  * Resources:
47  *      <TBS>
48  *
49  * Security:
50  *      No anticipated impact.
51  *
52  * Standards:
53  *      None.
54  */
55
56
57 /***
58  *** Imports.
59  ***/
60
61 #include <isc/lang.h>
62 #include <isc/types.h>
63 #include <isc/eventclass.h>
64
65 #define ISC_TASKEVENT_FIRSTEVENT        (ISC_EVENTCLASS_TASK + 0)
66 #define ISC_TASKEVENT_SHUTDOWN          (ISC_EVENTCLASS_TASK + 1)
67 #define ISC_TASKEVENT_LASTEVENT         (ISC_EVENTCLASS_TASK + 65535)
68
69 /*****
70  ***** Tasks.
71  *****/
72
73 ISC_LANG_BEGINDECLS
74
75 isc_result_t
76 isc_task_create(isc_taskmgr_t *manager, unsigned int quantum,
77                 isc_task_t **taskp);
78 /*
79  * Create a task.
80  *
81  * Notes:
82  *
83  *      If 'quantum' is non-zero, then only that many events can be dispatched
84  *      before the task must yield to other tasks waiting to execute.  If
85  *      quantum is zero, then the default quantum of the task manager will
86  *      be used.
87  *
88  *      The 'quantum' option may be removed from isc_task_create() in the
89  *      future.  If this happens, isc_task_getquantum() and
90  *      isc_task_setquantum() will be provided.
91  *
92  * Requires:
93  *
94  *      'manager' is a valid task manager.
95  *
96  *      taskp != NULL && *taskp == NULL
97  *
98  * Ensures:
99  *
100  *      On success, '*taskp' is bound to the new task.
101  *
102  * Returns:
103  *
104  *      ISC_R_SUCCESS
105  *      ISC_R_NOMEMORY
106  *      ISC_R_UNEXPECTED
107  *      ISC_R_SHUTTINGDOWN
108  */
109
110 void
111 isc_task_attach(isc_task_t *source, isc_task_t **targetp);
112 /*
113  * Attach *targetp to source.
114  *
115  * Requires:
116  *
117  *      'source' is a valid task.
118  *
119  *      'targetp' points to a NULL isc_task_t *.
120  *
121  * Ensures:
122  *
123  *      *targetp is attached to source.
124  */
125
126 void
127 isc_task_detach(isc_task_t **taskp);
128 /*
129  * Detach *taskp from its task.
130  *
131  * Requires:
132  *
133  *      '*taskp' is a valid task.
134  *
135  * Ensures:
136  *
137  *      *taskp is NULL.
138  *
139  *      If '*taskp' is the last reference to the task, the task is idle (has
140  *      an empty event queue), and has not been shutdown, the task will be
141  *      shutdown.
142  *
143  *      If '*taskp' is the last reference to the task and
144  *      the task has been shutdown,
145  *
146  *              All resources used by the task will be freed.
147  */
148
149 void
150 isc_task_send(isc_task_t *task, isc_event_t **eventp);
151 /*
152  * Send '*event' to 'task'.
153  *
154  * Requires:
155  *
156  *      'task' is a valid task.
157  *      eventp != NULL && *eventp != NULL.
158  *
159  * Ensures:
160  *
161  *      *eventp == NULL.
162  */
163
164 void
165 isc_task_sendanddetach(isc_task_t **taskp, isc_event_t **eventp);
166 /*
167  * Send '*event' to '*taskp' and then detach '*taskp' from its
168  * task.
169  *
170  * Requires:
171  *
172  *      '*taskp' is a valid task.
173  *      eventp != NULL && *eventp != NULL.
174  *
175  * Ensures:
176  *
177  *      *eventp == NULL.
178  *
179  *      *taskp == NULL.
180  *
181  *      If '*taskp' is the last reference to the task, the task is
182  *      idle (has an empty event queue), and has not been shutdown,
183  *      the task will be shutdown.
184  *
185  *      If '*taskp' is the last reference to the task and
186  *      the task has been shutdown,
187  *
188  *              All resources used by the task will be freed.
189  */
190
191 /*
192  * Purging and Unsending
193  *
194  * Events which have been queued for a task but not delivered may be removed
195  * from the task's event queue by purging or unsending.
196  *
197  * With both types, the caller specifies a matching pattern that selects
198  * events based upon their sender, type, and tag.
199  *
200  * Purging calls isc_event_free() on the matching events.
201  *
202  * Unsending returns a list of events that matched the pattern.
203  * The caller is then responsible for them.
204  *
205  * Consumers of events should purge, not unsend.
206  *
207  * Producers of events often want to remove events when the caller indicates
208  * it is no longer interested in the object, e.g. by cancelling a timer.
209  * Sometimes this can be done by purging, but for some event types, the
210  * calls to isc_event_free() cause deadlock because the event free routine
211  * wants to acquire a lock the caller is already holding.  Unsending instead
212  * of purging solves this problem.  As a general rule, producers should only
213  * unsend events which they have sent.
214  */
215
216 unsigned int
217 isc_task_purgerange(isc_task_t *task, void *sender, isc_eventtype_t first,
218                     isc_eventtype_t last, void *tag);
219 /*
220  * Purge events from a task's event queue.
221  *
222  * Requires:
223  *
224  *      'task' is a valid task.
225  *
226  *      last >= first
227  *
228  * Ensures:
229  *
230  *      Events in the event queue of 'task' whose sender is 'sender', whose
231  *      type is >= first and <= last, and whose tag is 'tag' will be purged,
232  *      unless they are marked as unpurgable.
233  *
234  *      A sender of NULL will match any sender.  A NULL tag matches any
235  *      tag.
236  *
237  * Returns:
238  *
239  *      The number of events purged.
240  */
241
242 unsigned int
243 isc_task_purge(isc_task_t *task, void *sender, isc_eventtype_t type,
244                void *tag);
245 /*
246  * Purge events from a task's event queue.
247  *
248  * Notes:
249  *
250  *      This function is equivalent to
251  *
252  *              isc_task_purgerange(task, sender, type, type, tag);
253  *
254  * Requires:
255  *
256  *      'task' is a valid task.
257  *
258  * Ensures:
259  *
260  *      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  *      A sender of NULL will match any sender.  A NULL tag matches any
265  *      tag.
266  *
267  * Returns:
268  *
269  *      The number of events purged.
270  */
271
272 isc_boolean_t
273 isc_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  *      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  *      Purging never changes the state of the task.
288  *
289  * Requires:
290  *
291  *      'task' is a valid task.
292  *
293  * Ensures:
294  *
295  *      'event' is not in the event queue for 'task'.
296  *
297  * Returns:
298  *
299  *      ISC_TRUE                        The event was purged.
300  *      ISC_FALSE                       The event was not in the event queue,
301  *                                      or was marked unpurgeable.
302  */
303
304 unsigned int
305 isc_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  *      'task' is a valid task.
313  *
314  *      last >= first.
315  *
316  *      *events is a valid list.
317  *
318  * Ensures:
319  *
320  *      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  *      A sender of NULL will match any sender.  A NULL tag matches any
325  *      tag.
326  *
327  * Returns:
328  *
329  *      The number of events unsent.
330  */
331
332 unsigned int
333 isc_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  *      This function is equivalent to
341  *
342  *              isc_task_unsendrange(task, sender, type, type, tag, events);
343  *
344  * Requires:
345  *
346  *      'task' is a valid task.
347  *
348  *      *events is a valid list.
349  *
350  * Ensures:
351  *
352  *      Events in the event queue of 'task' whose sender is 'sender', whose
353  *      type is 'type', and whose tag is 'tag' will be dequeued and appended
354  *      to *events.
355  *
356  * Returns:
357  *
358  *      The number of events unsent.
359  */
360
361 isc_result_t
362 isc_task_onshutdown(isc_task_t *task, isc_taskaction_t action,
363                     const void *arg);
364 /*
365  * Send a shutdown event with action 'action' and argument 'arg' when
366  * 'task' is shutdown.
367  *
368  * Notes:
369  *
370  *      Shutdown events are posted in LIFO order.
371  *
372  * Requires:
373  *
374  *      'task' is a valid task.
375  *
376  *      'action' is a valid task action.
377  *
378  * Ensures:
379  *
380  *      When the task is shutdown, shutdown events requested with
381  *      isc_task_onshutdown() will be appended to the task's event queue.
382  *
383
384  * Returns:
385  *
386  *      ISC_R_SUCCESS
387  *      ISC_R_NOMEMORY
388  *      ISC_R_TASKSHUTTINGDOWN                  Task is shutting down.
389  */
390
391 void
392 isc_task_shutdown(isc_task_t *task);
393 /*
394  * Shutdown 'task'.
395  *
396  * Notes:
397  *
398  *      Shutting down a task causes any shutdown events requested with
399  *      isc_task_onshutdown() to be posted (in LIFO order).  The task
400  *      moves into a "shutting down" mode which prevents further calls
401  *      to isc_task_onshutdown().
402  *
403  *      Trying to shutdown a task that has already been shutdown has no
404  *      effect.
405  *
406  * Requires:
407  *
408  *      'task' is a valid task.
409  *
410  * Ensures:
411  *
412  *      Any shutdown events requested with isc_task_onshutdown() have been
413  *      posted (in LIFO order).
414  */
415
416 void
417 isc_task_destroy(isc_task_t **taskp);
418 /*
419  * Destroy '*taskp'.
420  *
421  * Notes:
422  *
423  *      This call is equivalent to:
424  *
425  *              isc_task_shutdown(*taskp);
426  *              isc_task_detach(taskp);
427  *
428  * Requires:
429  *
430  *      '*taskp' is a valid task.
431  *
432  * Ensures:
433  *
434  *      Any shutdown events requested with isc_task_onshutdown() have been
435  *      posted (in LIFO order).
436  *
437  *      *taskp == NULL
438  *
439  *      If '*taskp' is the last reference to the task,
440  *
441  *              All resources used by the task will be freed.
442  */
443
444 void
445 isc_task_setname(isc_task_t *task, const char *name, void *tag);
446 /*
447  * Name 'task'.
448  *
449  * Notes:
450  *
451  *      Only the first 15 characters of 'name' will be copied.
452  *
453  *      Naming a task is currently only useful for debugging purposes.
454  *
455  * Requires:
456  *
457  *      'task' is a valid task.
458  */
459
460 const char *
461 isc_task_getname(isc_task_t *task);
462 /*
463  * Get the name of 'task', as previously set using isc_task_setname().
464  *
465  * Notes:
466  *      This function is for debugging purposes only.
467  *
468  * Requires:
469  *      'task' is a valid task.
470  *
471  * Returns:
472  *      A non-NULL pointer to a null-terminated string.
473  *      If the task has not been named, the string is
474  *      empty.
475  *
476  */
477
478 void *
479 isc_task_gettag(isc_task_t *task);
480 /*
481  * Get the tag value for  'task', as previously set using isc_task_settag().
482  *
483  * Notes:
484  *      This function is for debugging purposes only.
485  *
486  * Requires:
487  *      'task' is a valid task.
488  */
489
490 isc_result_t
491 isc_task_beginexclusive(isc_task_t *task);
492 /*
493  * Request exclusive access for 'task', which must be the calling
494  * task.  Waits for any other concurrently executing tasks to finish their
495  * current event, and prevents any new events from executing in any of the
496  * tasks sharing a task manager with 'task'.
497  *
498  * The exclusive access must be relinquished by calling 
499  * isc_task_endexclusive() before returning from the current event handler.
500  *
501  * Requires:
502  *      'task' is the calling task.
503  *
504  * Returns:
505  *      ISC_R_SUCCESS           The current task now has exclusive access.
506  *      ISC_R_LOCKBUSY          Another task has already requested exclusive
507  *                              access.
508  */
509
510 void
511 isc_task_endexclusive(isc_task_t *task);
512 /*
513  * Relinquish the exclusive access obtained by isc_task_beginexclusive(), 
514  * allowing other tasks to execute.
515  *
516  * Requires:
517  *      'task' is the calling task, and has obtained
518  *              exclusive access by calling isc_task_spl().
519  */
520
521
522 /*****
523  ***** Task Manager.
524  *****/
525
526 isc_result_t
527 isc_taskmgr_create(isc_mem_t *mctx, unsigned int workers,
528                    unsigned int default_quantum, isc_taskmgr_t **managerp);
529 /*
530  * Create a new task manager.
531  *
532  * Notes:
533  *
534  *      'workers' in the number of worker threads to create.  In general,
535  *      the value should be close to the number of processors in the system.
536  *      The 'workers' value is advisory only.  An attempt will be made to
537  *      create 'workers' threads, but if at least one thread creation
538  *      succeeds, isc_taskmgr_create() may return ISC_R_SUCCESS.
539  *
540  *      If 'default_quantum' is non-zero, then it will be used as the default
541  *      quantum value when tasks are created.  If zero, then an implementation
542  *      defined default quantum will be used.
543  *
544  * Requires:
545  *
546  *      'mctx' is a valid memory context.
547  *
548  *      workers > 0
549  *
550  *      managerp != NULL && *managerp == NULL
551  *
552  * Ensures:
553  *
554  *      On success, '*managerp' will be attached to the newly created task
555  *      manager.
556  *
557  * Returns:
558  *
559  *      ISC_R_SUCCESS
560  *      ISC_R_NOMEMORY
561  *      ISC_R_NOTHREADS                 No threads could be created.
562  *      ISC_R_UNEXPECTED                An unexpected error occurred.
563  */
564
565 void
566 isc_taskmgr_destroy(isc_taskmgr_t **managerp);
567 /*
568  * Destroy '*managerp'.
569  *
570  * Notes:
571  *
572  *      Calling isc_taskmgr_destroy() will shutdown all tasks managed by
573  *      *managerp that haven't already been shutdown.  The call will block
574  *      until all tasks have entered the done state.
575  *
576  *      isc_taskmgr_destroy() must not be called by a task event action,
577  *      because it would block forever waiting for the event action to
578  *      complete.  An event action that wants to cause task manager shutdown
579  *      should request some non-event action thread of execution to do the
580  *      shutdown, e.g. by signalling a condition variable or using
581  *      isc_app_shutdown().
582  *
583  *      Task manager references are not reference counted, so the caller
584  *      must ensure that no attempt will be made to use the manager after
585  *      isc_taskmgr_destroy() returns.
586  *
587  * Requires:
588  *
589  *      '*managerp' is a valid task manager.
590  *
591  *      isc_taskmgr_destroy() has not be called previously on '*managerp'.
592  *
593  * Ensures:
594  *
595  *      All resources used by the task manager, and any tasks it managed,
596  *      have been freed.
597  */
598
599 ISC_LANG_ENDDECLS
600
601 #endif /* ISC_TASK_H */