]> CyberLeo.Net >> Repos - FreeBSD/releng/9.0.git/blob - contrib/bind9/lib/isc/include/isc/task.h
Copy stable/9 to releng/9.0 as part of the FreeBSD 9.0-RELEASE release
[FreeBSD/releng/9.0.git] / contrib / bind9 / lib / isc / include / isc / task.h
1 /*
2  * Copyright (C) 2004-2007, 2009-2011  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.69.14.2 2011-02-28 01:20:04 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
97 ISC_LANG_BEGINDECLS
98
99 /***
100  *** Types
101  ***/
102
103 /*% Task and task manager methods */
104 typedef struct isc_taskmgrmethods {
105         void            (*destroy)(isc_taskmgr_t **managerp);
106         isc_result_t    (*taskcreate)(isc_taskmgr_t *manager,
107                                       unsigned int quantum,
108                                       isc_task_t **taskp);
109 } isc_taskmgrmethods_t;
110
111 typedef struct isc_taskmethods {
112         void (*attach)(isc_task_t *source, isc_task_t **targetp);
113         void (*detach)(isc_task_t **taskp);
114         void (*destroy)(isc_task_t **taskp);
115         void (*send)(isc_task_t *task, isc_event_t **eventp);
116         void (*sendanddetach)(isc_task_t **taskp, isc_event_t **eventp);
117         unsigned int (*unsend)(isc_task_t *task, void *sender, isc_eventtype_t type,
118                                void *tag, isc_eventlist_t *events);
119         isc_result_t (*onshutdown)(isc_task_t *task, isc_taskaction_t action,
120                                    const void *arg);
121         void (*shutdown)(isc_task_t *task);
122         void (*setname)(isc_task_t *task, const char *name, void *tag);
123         unsigned int (*purgeevents)(isc_task_t *task, void *sender,
124                                     isc_eventtype_t type, void *tag);
125         unsigned int (*purgerange)(isc_task_t *task, void *sender,
126                                    isc_eventtype_t first, isc_eventtype_t last,
127                                    void *tag);
128         isc_result_t (*beginexclusive)(isc_task_t *task);
129         void (*endexclusive)(isc_task_t *task);
130 } isc_taskmethods_t;
131
132 /*%
133  * This structure is actually just the common prefix of a task manager
134  * object implementation's version of an isc_taskmgr_t.
135  * \brief
136  * Direct use of this structure by clients is forbidden.  task implementations
137  * may change the structure.  'magic' must be ISCAPI_TASKMGR_MAGIC for any
138  * of the isc_task_ routines to work.  task implementations must maintain
139  * all task invariants.
140  */
141 struct isc_taskmgr {
142         unsigned int            impmagic;
143         unsigned int            magic;
144         isc_taskmgrmethods_t    *methods;
145 };
146
147 #define ISCAPI_TASKMGR_MAGIC    ISC_MAGIC('A','t','m','g')
148 #define ISCAPI_TASKMGR_VALID(m) ((m) != NULL && \
149                                  (m)->magic == ISCAPI_TASKMGR_MAGIC)
150
151 /*%
152  * This is the common prefix of a task object.  The same note as
153  * that for the taskmgr structure applies.
154  */
155 struct isc_task {
156         unsigned int            impmagic;
157         unsigned int            magic;
158         isc_taskmethods_t       *methods;
159 };
160
161 #define ISCAPI_TASK_MAGIC       ISC_MAGIC('A','t','s','t')
162 #define ISCAPI_TASK_VALID(s)    ((s) != NULL && \
163                                  (s)->magic == ISCAPI_TASK_MAGIC)
164
165 isc_result_t
166 isc_task_create(isc_taskmgr_t *manager, unsigned int quantum,
167                 isc_task_t **taskp);
168 /*%<
169  * Create a task.
170  *
171  * Notes:
172  *
173  *\li   If 'quantum' is non-zero, then only that many events can be dispatched
174  *      before the task must yield to other tasks waiting to execute.  If
175  *      quantum is zero, then the default quantum of the task manager will
176  *      be used.
177  *
178  *\li   The 'quantum' option may be removed from isc_task_create() in the
179  *      future.  If this happens, isc_task_getquantum() and
180  *      isc_task_setquantum() will be provided.
181  *
182  * Requires:
183  *
184  *\li   'manager' is a valid task manager.
185  *
186  *\li   taskp != NULL && *taskp == NULL
187  *
188  * Ensures:
189  *
190  *\li   On success, '*taskp' is bound to the new task.
191  *
192  * Returns:
193  *
194  *\li   #ISC_R_SUCCESS
195  *\li   #ISC_R_NOMEMORY
196  *\li   #ISC_R_UNEXPECTED
197  *\li   #ISC_R_SHUTTINGDOWN
198  */
199
200 void
201 isc_task_attach(isc_task_t *source, isc_task_t **targetp);
202 /*%<
203  * Attach *targetp to source.
204  *
205  * Requires:
206  *
207  *\li   'source' is a valid task.
208  *
209  *\li   'targetp' points to a NULL isc_task_t *.
210  *
211  * Ensures:
212  *
213  *\li   *targetp is attached to source.
214  */
215
216 void
217 isc_task_detach(isc_task_t **taskp);
218 /*%<
219  * Detach *taskp from its task.
220  *
221  * Requires:
222  *
223  *\li   '*taskp' is a valid task.
224  *
225  * Ensures:
226  *
227  *\li   *taskp is NULL.
228  *
229  *\li   If '*taskp' is the last reference to the task, the task is idle (has
230  *      an empty event queue), and has not been shutdown, the task will be
231  *      shutdown.
232  *
233  *\li   If '*taskp' is the last reference to the task and
234  *      the task has been shutdown,
235  *              all resources used by the task will be freed.
236  */
237
238 void
239 isc_task_send(isc_task_t *task, isc_event_t **eventp);
240 /*%<
241  * Send '*event' to 'task'.
242  *
243  * Requires:
244  *
245  *\li   'task' is a valid task.
246  *\li   eventp != NULL && *eventp != NULL.
247  *
248  * Ensures:
249  *
250  *\li   *eventp == NULL.
251  */
252
253 void
254 isc_task_sendanddetach(isc_task_t **taskp, isc_event_t **eventp);
255 /*%<
256  * Send '*event' to '*taskp' and then detach '*taskp' from its
257  * task.
258  *
259  * Requires:
260  *
261  *\li   '*taskp' is a valid task.
262  *\li   eventp != NULL && *eventp != NULL.
263  *
264  * Ensures:
265  *
266  *\li   *eventp == NULL.
267  *
268  *\li   *taskp == NULL.
269  *
270  *\li   If '*taskp' is the last reference to the task, the task is
271  *      idle (has an empty event queue), and has not been shutdown,
272  *      the task will be shutdown.
273  *
274  *\li   If '*taskp' is the last reference to the task and
275  *      the task has been shutdown,
276  *              all resources used by the task will be freed.
277  */
278
279
280 unsigned int
281 isc_task_purgerange(isc_task_t *task, void *sender, isc_eventtype_t first,
282                     isc_eventtype_t last, void *tag);
283 /*%<
284  * Purge events from a task's event queue.
285  *
286  * Requires:
287  *
288  *\li   'task' is a valid task.
289  *
290  *\li   last >= first
291  *
292  * Ensures:
293  *
294  *\li   Events in the event queue of 'task' whose sender is 'sender', whose
295  *      type is >= first and <= last, and whose tag is 'tag' will be purged,
296  *      unless they are marked as unpurgable.
297  *
298  *\li   A sender of NULL will match any sender.  A NULL tag matches any
299  *      tag.
300  *
301  * Returns:
302  *
303  *\li   The number of events purged.
304  */
305
306 unsigned int
307 isc_task_purge(isc_task_t *task, void *sender, isc_eventtype_t type,
308                void *tag);
309 /*%<
310  * Purge events from a task's event queue.
311  *
312  * Notes:
313  *
314  *\li   This function is equivalent to
315  *
316  *\code
317  *              isc_task_purgerange(task, sender, type, type, tag);
318  *\endcode
319  *
320  * Requires:
321  *
322  *\li   'task' is a valid task.
323  *
324  * Ensures:
325  *
326  *\li   Events in the event queue of 'task' whose sender is 'sender', whose
327  *      type is 'type', and whose tag is 'tag' will be purged, unless they
328  *      are marked as unpurgable.
329  *
330  *\li   A sender of NULL will match any sender.  A NULL tag matches any
331  *      tag.
332  *
333  * Returns:
334  *
335  *\li   The number of events purged.
336  */
337
338 isc_boolean_t
339 isc_task_purgeevent(isc_task_t *task, isc_event_t *event);
340 /*%<
341  * Purge 'event' from a task's event queue.
342  *
343  * XXXRTH:  WARNING:  This method may be removed before beta.
344  *
345  * Notes:
346  *
347  *\li   If 'event' is on the task's event queue, it will be purged,
348  *      unless it is marked as unpurgeable.  'event' does not have to be
349  *      on the task's event queue; in fact, it can even be an invalid
350  *      pointer.  Purging only occurs if the event is actually on the task's
351  *      event queue.
352  *
353  * \li  Purging never changes the state of the task.
354  *
355  * Requires:
356  *
357  *\li   'task' is a valid task.
358  *
359  * Ensures:
360  *
361  *\li   'event' is not in the event queue for 'task'.
362  *
363  * Returns:
364  *
365  *\li   #ISC_TRUE                       The event was purged.
366  *\li   #ISC_FALSE                      The event was not in the event queue,
367  *                                      or was marked unpurgeable.
368  */
369
370 unsigned int
371 isc_task_unsendrange(isc_task_t *task, void *sender, isc_eventtype_t first,
372                      isc_eventtype_t last, void *tag, isc_eventlist_t *events);
373 /*%<
374  * Remove events from a task's event queue.
375  *
376  * Requires:
377  *
378  *\li   'task' is a valid task.
379  *
380  *\li   last >= first.
381  *
382  *\li   *events is a valid list.
383  *
384  * Ensures:
385  *
386  *\li   Events in the event queue of 'task' whose sender is 'sender', whose
387  *      type is >= first and <= last, and whose tag is 'tag' will be dequeued
388  *      and appended to *events.
389  *
390  *\li   A sender of NULL will match any sender.  A NULL tag matches any
391  *      tag.
392  *
393  * Returns:
394  *
395  *\li   The number of events unsent.
396  */
397
398 unsigned int
399 isc_task_unsend(isc_task_t *task, void *sender, isc_eventtype_t type,
400                 void *tag, isc_eventlist_t *events);
401 /*%<
402  * Remove events from a task's event queue.
403  *
404  * Notes:
405  *
406  *\li   This function is equivalent to
407  *
408  *\code
409  *              isc_task_unsendrange(task, sender, type, type, tag, events);
410  *\endcode
411  *
412  * Requires:
413  *
414  *\li   'task' is a valid task.
415  *
416  *\li   *events is a valid list.
417  *
418  * Ensures:
419  *
420  *\li   Events in the event queue of 'task' whose sender is 'sender', whose
421  *      type is 'type', and whose tag is 'tag' will be dequeued and appended
422  *      to *events.
423  *
424  * Returns:
425  *
426  *\li   The number of events unsent.
427  */
428
429 isc_result_t
430 isc_task_onshutdown(isc_task_t *task, isc_taskaction_t action,
431                     const void *arg);
432 /*%<
433  * Send a shutdown event with action 'action' and argument 'arg' when
434  * 'task' is shutdown.
435  *
436  * Notes:
437  *
438  *\li   Shutdown events are posted in LIFO order.
439  *
440  * Requires:
441  *
442  *\li   'task' is a valid task.
443  *
444  *\li   'action' is a valid task action.
445  *
446  * Ensures:
447  *
448  *\li   When the task is shutdown, shutdown events requested with
449  *      isc_task_onshutdown() will be appended to the task's event queue.
450  *
451
452  * Returns:
453  *
454  *\li   #ISC_R_SUCCESS
455  *\li   #ISC_R_NOMEMORY
456  *\li   #ISC_R_TASKSHUTTINGDOWN                 Task is shutting down.
457  */
458
459 void
460 isc_task_shutdown(isc_task_t *task);
461 /*%<
462  * Shutdown 'task'.
463  *
464  * Notes:
465  *
466  *\li   Shutting down a task causes any shutdown events requested with
467  *      isc_task_onshutdown() to be posted (in LIFO order).  The task
468  *      moves into a "shutting down" mode which prevents further calls
469  *      to isc_task_onshutdown().
470  *
471  *\li   Trying to shutdown a task that has already been shutdown has no
472  *      effect.
473  *
474  * Requires:
475  *
476  *\li   'task' is a valid task.
477  *
478  * Ensures:
479  *
480  *\li   Any shutdown events requested with isc_task_onshutdown() have been
481  *      posted (in LIFO order).
482  */
483
484 void
485 isc_task_destroy(isc_task_t **taskp);
486 /*%<
487  * Destroy '*taskp'.
488  *
489  * Notes:
490  *
491  *\li   This call is equivalent to:
492  *
493  *\code
494  *              isc_task_shutdown(*taskp);
495  *              isc_task_detach(taskp);
496  *\endcode
497  *
498  * Requires:
499  *
500  *      '*taskp' is a valid task.
501  *
502  * Ensures:
503  *
504  *\li   Any shutdown events requested with isc_task_onshutdown() have been
505  *      posted (in LIFO order).
506  *
507  *\li   *taskp == NULL
508  *
509  *\li   If '*taskp' is the last reference to the task,
510  *              all resources used by the task will be freed.
511  */
512
513 void
514 isc_task_setname(isc_task_t *task, const char *name, void *tag);
515 /*%<
516  * Name 'task'.
517  *
518  * Notes:
519  *
520  *\li   Only the first 15 characters of 'name' will be copied.
521  *
522  *\li   Naming a task is currently only useful for debugging purposes.
523  *
524  * Requires:
525  *
526  *\li   'task' is a valid task.
527  */
528
529 const char *
530 isc_task_getname(isc_task_t *task);
531 /*%<
532  * Get the name of 'task', as previously set using isc_task_setname().
533  *
534  * Notes:
535  *\li   This function is for debugging purposes only.
536  *
537  * Requires:
538  *\li   'task' is a valid task.
539  *
540  * Returns:
541  *\li   A non-NULL pointer to a null-terminated string.
542  *      If the task has not been named, the string is
543  *      empty.
544  *
545  */
546
547 void *
548 isc_task_gettag(isc_task_t *task);
549 /*%<
550  * Get the tag value for  'task', as previously set using isc_task_settag().
551  *
552  * Notes:
553  *\li   This function is for debugging purposes only.
554  *
555  * Requires:
556  *\li   'task' is a valid task.
557  */
558
559 isc_result_t
560 isc_task_beginexclusive(isc_task_t *task);
561 /*%<
562  * Request exclusive access for 'task', which must be the calling
563  * task.  Waits for any other concurrently executing tasks to finish their
564  * current event, and prevents any new events from executing in any of the
565  * tasks sharing a task manager with 'task'.
566  *
567  * The exclusive access must be relinquished by calling
568  * isc_task_endexclusive() before returning from the current event handler.
569  *
570  * Requires:
571  *\li   'task' is the calling task.
572  *
573  * Returns:
574  *\li   #ISC_R_SUCCESS          The current task now has exclusive access.
575  *\li   #ISC_R_LOCKBUSY         Another task has already requested exclusive
576  *                              access.
577  */
578
579 void
580 isc_task_endexclusive(isc_task_t *task);
581 /*%<
582  * Relinquish the exclusive access obtained by isc_task_beginexclusive(),
583  * allowing other tasks to execute.
584  *
585  * Requires:
586  *\li   'task' is the calling task, and has obtained
587  *              exclusive access by calling isc_task_spl().
588  */
589
590 void
591 isc_task_getcurrenttime(isc_task_t *task, isc_stdtime_t *t);
592 /*%<
593  * Provide the most recent timestamp on the task.  The timestamp is considered
594  * as the "current time" in the second-order granularity.
595  *
596  * Requires:
597  *\li   'task' is a valid task.
598  *\li   't' is a valid non NULL pointer.
599  *
600  * Ensures:
601  *\li   '*t' has the "current time".
602  */
603
604 isc_boolean_t
605 isc_task_exiting(isc_task_t *t);
606 /*%<
607  * Returns ISC_TRUE if the task is in the process of shutting down,
608  * ISC_FALSE otherwise.
609  *
610  * Requires:
611  *\li   'task' is a valid task.
612  */
613
614 /*****
615  ***** Task Manager.
616  *****/
617
618 isc_result_t
619 isc_taskmgr_createinctx(isc_mem_t *mctx, isc_appctx_t *actx,
620                         unsigned int workers, unsigned int default_quantum,
621                         isc_taskmgr_t **managerp);
622 isc_result_t
623 isc_taskmgr_create(isc_mem_t *mctx, unsigned int workers,
624                    unsigned int default_quantum, isc_taskmgr_t **managerp);
625 /*%<
626  * Create a new task manager.  isc_taskmgr_createinctx() also associates
627  * the new manager with the specified application context.
628  *
629  * Notes:
630  *
631  *\li   'workers' in the number of worker threads to create.  In general,
632  *      the value should be close to the number of processors in the system.
633  *      The 'workers' value is advisory only.  An attempt will be made to
634  *      create 'workers' threads, but if at least one thread creation
635  *      succeeds, isc_taskmgr_create() may return ISC_R_SUCCESS.
636  *
637  *\li   If 'default_quantum' is non-zero, then it will be used as the default
638  *      quantum value when tasks are created.  If zero, then an implementation
639  *      defined default quantum will be used.
640  *
641  * Requires:
642  *
643  *\li      'mctx' is a valid memory context.
644  *
645  *\li   workers > 0
646  *
647  *\li   managerp != NULL && *managerp == NULL
648  *
649  *\li   'actx' is a valid application context (for createinctx()).
650  *
651  * Ensures:
652  *
653  *\li   On success, '*managerp' will be attached to the newly created task
654  *      manager.
655  *
656  * Returns:
657  *
658  *\li   #ISC_R_SUCCESS
659  *\li   #ISC_R_NOMEMORY
660  *\li   #ISC_R_NOTHREADS                No threads could be created.
661  *\li   #ISC_R_UNEXPECTED               An unexpected error occurred.
662  *\li   #ISC_R_SHUTTINGDOWN             The non-threaded, shared, task
663  *                                      manager shutting down.
664  */
665
666 void
667 isc_taskmgr_destroy(isc_taskmgr_t **managerp);
668 /*%<
669  * Destroy '*managerp'.
670  *
671  * Notes:
672  *
673  *\li   Calling isc_taskmgr_destroy() will shutdown all tasks managed by
674  *      *managerp that haven't already been shutdown.  The call will block
675  *      until all tasks have entered the done state.
676  *
677  *\li   isc_taskmgr_destroy() must not be called by a task event action,
678  *      because it would block forever waiting for the event action to
679  *      complete.  An event action that wants to cause task manager shutdown
680  *      should request some non-event action thread of execution to do the
681  *      shutdown, e.g. by signaling a condition variable or using
682  *      isc_app_shutdown().
683  *
684  *\li   Task manager references are not reference counted, so the caller
685  *      must ensure that no attempt will be made to use the manager after
686  *      isc_taskmgr_destroy() returns.
687  *
688  * Requires:
689  *
690  *\li   '*managerp' is a valid task manager.
691  *
692  *\li   isc_taskmgr_destroy() has not be called previously on '*managerp'.
693  *
694  * Ensures:
695  *
696  *\li   All resources used by the task manager, and any tasks it managed,
697  *      have been freed.
698  */
699
700 #ifdef HAVE_LIBXML2
701
702 void
703 isc_taskmgr_renderxml(isc_taskmgr_t *mgr, xmlTextWriterPtr writer);
704
705 #endif
706
707 /*%<
708  * See isc_taskmgr_create() above.
709  */
710 typedef isc_result_t
711 (*isc_taskmgrcreatefunc_t)(isc_mem_t *mctx, unsigned int workers,
712                            unsigned int default_quantum,
713                            isc_taskmgr_t **managerp);
714
715 isc_result_t
716 isc_task_register(isc_taskmgrcreatefunc_t createfunc);
717 /*%<
718  * Register a new task management implementation and add it to the list of
719  * supported implementations.  This function must be called when a different
720  * event library is used than the one contained in the ISC library.
721  */
722
723 isc_result_t
724 isc__task_register(void);
725 /*%<
726  * A short cut function that specifies the task management module in the ISC
727  * library for isc_task_register().  An application that uses the ISC library
728  * usually do not have to care about this function: it would call
729  * isc_lib_register(), which internally calls this function.
730  */
731
732 ISC_LANG_ENDDECLS
733
734 #endif /* ISC_TASK_H */