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