1258945Sroberto/* 2280849Scy * Copyright (C) 2004-2007, 2009-2012 Internet Systems Consortium, Inc. ("ISC") 3258945Sroberto * Copyright (C) 1998-2001, 2003 Internet Software Consortium. 4258945Sroberto * 5258945Sroberto * Permission to use, copy, modify, and/or distribute this software for any 6258945Sroberto * purpose with or without fee is hereby granted, provided that the above 7258945Sroberto * copyright notice and this permission notice appear in all copies. 8258945Sroberto * 9258945Sroberto * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 10258945Sroberto * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 11258945Sroberto * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 12258945Sroberto * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 13258945Sroberto * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 14258945Sroberto * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 15258945Sroberto * PERFORMANCE OF THIS SOFTWARE. 16258945Sroberto */ 17258945Sroberto 18280849Scy/* $Id$ */ 19258945Sroberto 20258945Sroberto#ifndef ISC_TASK_H 21258945Sroberto#define ISC_TASK_H 1 22258945Sroberto 23258945Sroberto/***** 24258945Sroberto ***** Module Info 25258945Sroberto *****/ 26258945Sroberto 27258945Sroberto/*! \file isc/task.h 28258945Sroberto * \brief The task system provides a lightweight execution context, which is 29258945Sroberto * basically an event queue. 30258945Sroberto 31258945Sroberto * When a task's event queue is non-empty, the 32258945Sroberto * task is runnable. A small work crew of threads, typically one per CPU, 33258945Sroberto * execute runnable tasks by dispatching the events on the tasks' event 34258945Sroberto * queues. Context switching between tasks is fast. 35258945Sroberto * 36258945Sroberto * \li MP: 37258945Sroberto * The module ensures appropriate synchronization of data structures it 38258945Sroberto * creates and manipulates. 39258945Sroberto * The caller must ensure that isc_taskmgr_destroy() is called only 40258945Sroberto * once for a given manager. 41258945Sroberto * 42258945Sroberto * \li Reliability: 43258945Sroberto * No anticipated impact. 44258945Sroberto * 45258945Sroberto * \li Resources: 46258945Sroberto * TBS 47258945Sroberto * 48258945Sroberto * \li Security: 49258945Sroberto * No anticipated impact. 50258945Sroberto * 51258945Sroberto * \li Standards: 52258945Sroberto * None. 53258945Sroberto * 54258945Sroberto * \section purge Purging and Unsending 55258945Sroberto * 56258945Sroberto * Events which have been queued for a task but not delivered may be removed 57258945Sroberto * from the task's event queue by purging or unsending. 58258945Sroberto * 59258945Sroberto * With both types, the caller specifies a matching pattern that selects 60258945Sroberto * events based upon their sender, type, and tag. 61258945Sroberto * 62258945Sroberto * Purging calls isc_event_free() on the matching events. 63258945Sroberto * 64258945Sroberto * Unsending returns a list of events that matched the pattern. 65258945Sroberto * The caller is then responsible for them. 66258945Sroberto * 67258945Sroberto * Consumers of events should purge, not unsend. 68258945Sroberto * 69258945Sroberto * Producers of events often want to remove events when the caller indicates 70258945Sroberto * it is no longer interested in the object, e.g. by canceling a timer. 71258945Sroberto * Sometimes this can be done by purging, but for some event types, the 72258945Sroberto * calls to isc_event_free() cause deadlock because the event free routine 73258945Sroberto * wants to acquire a lock the caller is already holding. Unsending instead 74258945Sroberto * of purging solves this problem. As a general rule, producers should only 75258945Sroberto * unsend events which they have sent. 76258945Sroberto */ 77258945Sroberto 78258945Sroberto 79258945Sroberto/*** 80258945Sroberto *** Imports. 81258945Sroberto ***/ 82258945Sroberto 83258945Sroberto#include <isc/eventclass.h> 84258945Sroberto#include <isc/lang.h> 85258945Sroberto#include <isc/stdtime.h> 86258945Sroberto#include <isc/types.h> 87258945Sroberto#include <isc/xml.h> 88258945Sroberto 89258945Sroberto#define ISC_TASKEVENT_FIRSTEVENT (ISC_EVENTCLASS_TASK + 0) 90258945Sroberto#define ISC_TASKEVENT_SHUTDOWN (ISC_EVENTCLASS_TASK + 1) 91280849Scy#define ISC_TASKEVENT_TEST (ISC_EVENTCLASS_TASK + 1) 92258945Sroberto#define ISC_TASKEVENT_LASTEVENT (ISC_EVENTCLASS_TASK + 65535) 93258945Sroberto 94258945Sroberto/***** 95258945Sroberto ***** Tasks. 96258945Sroberto *****/ 97258945Sroberto 98258945SrobertoISC_LANG_BEGINDECLS 99258945Sroberto 100280849Scy/*** 101280849Scy *** Types 102280849Scy ***/ 103280849Scy 104280849Scytypedef enum { 105280849Scy isc_taskmgrmode_normal = 0, 106280849Scy isc_taskmgrmode_privileged 107280849Scy} isc_taskmgrmode_t; 108280849Scy 109280849Scy/*% Task and task manager methods */ 110280849Scytypedef struct isc_taskmgrmethods { 111280849Scy void (*destroy)(isc_taskmgr_t **managerp); 112280849Scy void (*setmode)(isc_taskmgr_t *manager, 113280849Scy isc_taskmgrmode_t mode); 114280849Scy isc_taskmgrmode_t (*mode)(isc_taskmgr_t *manager); 115280849Scy isc_result_t (*taskcreate)(isc_taskmgr_t *manager, 116280849Scy unsigned int quantum, 117280849Scy isc_task_t **taskp); 118280849Scy} isc_taskmgrmethods_t; 119280849Scy 120280849Scytypedef struct isc_taskmethods { 121280849Scy void (*attach)(isc_task_t *source, isc_task_t **targetp); 122280849Scy void (*detach)(isc_task_t **taskp); 123280849Scy void (*destroy)(isc_task_t **taskp); 124280849Scy void (*send)(isc_task_t *task, isc_event_t **eventp); 125280849Scy void (*sendanddetach)(isc_task_t **taskp, isc_event_t **eventp); 126280849Scy unsigned int (*unsend)(isc_task_t *task, void *sender, isc_eventtype_t type, 127280849Scy void *tag, isc_eventlist_t *events); 128280849Scy isc_result_t (*onshutdown)(isc_task_t *task, isc_taskaction_t action, 129280849Scy const void *arg); 130280849Scy void (*shutdown)(isc_task_t *task); 131280849Scy void (*setname)(isc_task_t *task, const char *name, void *tag); 132280849Scy unsigned int (*purgeevents)(isc_task_t *task, void *sender, 133280849Scy isc_eventtype_t type, void *tag); 134280849Scy unsigned int (*purgerange)(isc_task_t *task, void *sender, 135280849Scy isc_eventtype_t first, isc_eventtype_t last, 136280849Scy void *tag); 137280849Scy isc_result_t (*beginexclusive)(isc_task_t *task); 138280849Scy void (*endexclusive)(isc_task_t *task); 139280849Scy void (*setprivilege)(isc_task_t *task, isc_boolean_t priv); 140280849Scy isc_boolean_t (*privilege)(isc_task_t *task); 141280849Scy} isc_taskmethods_t; 142280849Scy 143280849Scy/*% 144280849Scy * This structure is actually just the common prefix of a task manager 145280849Scy * object implementation's version of an isc_taskmgr_t. 146280849Scy * \brief 147280849Scy * Direct use of this structure by clients is forbidden. task implementations 148280849Scy * may change the structure. 'magic' must be ISCAPI_TASKMGR_MAGIC for any 149280849Scy * of the isc_task_ routines to work. task implementations must maintain 150280849Scy * all task invariants. 151280849Scy */ 152280849Scystruct isc_taskmgr { 153280849Scy unsigned int impmagic; 154280849Scy unsigned int magic; 155280849Scy isc_taskmgrmethods_t *methods; 156280849Scy}; 157280849Scy 158280849Scy#define ISCAPI_TASKMGR_MAGIC ISC_MAGIC('A','t','m','g') 159280849Scy#define ISCAPI_TASKMGR_VALID(m) ((m) != NULL && \ 160280849Scy (m)->magic == ISCAPI_TASKMGR_MAGIC) 161280849Scy 162280849Scy/*% 163280849Scy * This is the common prefix of a task object. The same note as 164280849Scy * that for the taskmgr structure applies. 165280849Scy */ 166280849Scystruct isc_task { 167280849Scy unsigned int impmagic; 168280849Scy unsigned int magic; 169280849Scy isc_taskmethods_t *methods; 170280849Scy}; 171280849Scy 172280849Scy#define ISCAPI_TASK_MAGIC ISC_MAGIC('A','t','s','t') 173280849Scy#define ISCAPI_TASK_VALID(s) ((s) != NULL && \ 174280849Scy (s)->magic == ISCAPI_TASK_MAGIC) 175280849Scy 176258945Srobertoisc_result_t 177258945Srobertoisc_task_create(isc_taskmgr_t *manager, unsigned int quantum, 178258945Sroberto isc_task_t **taskp); 179258945Sroberto/*%< 180258945Sroberto * Create a task. 181258945Sroberto * 182258945Sroberto * Notes: 183258945Sroberto * 184258945Sroberto *\li If 'quantum' is non-zero, then only that many events can be dispatched 185258945Sroberto * before the task must yield to other tasks waiting to execute. If 186258945Sroberto * quantum is zero, then the default quantum of the task manager will 187258945Sroberto * be used. 188258945Sroberto * 189258945Sroberto *\li The 'quantum' option may be removed from isc_task_create() in the 190258945Sroberto * future. If this happens, isc_task_getquantum() and 191258945Sroberto * isc_task_setquantum() will be provided. 192258945Sroberto * 193258945Sroberto * Requires: 194258945Sroberto * 195258945Sroberto *\li 'manager' is a valid task manager. 196258945Sroberto * 197258945Sroberto *\li taskp != NULL && *taskp == NULL 198258945Sroberto * 199258945Sroberto * Ensures: 200258945Sroberto * 201258945Sroberto *\li On success, '*taskp' is bound to the new task. 202258945Sroberto * 203258945Sroberto * Returns: 204258945Sroberto * 205258945Sroberto *\li #ISC_R_SUCCESS 206258945Sroberto *\li #ISC_R_NOMEMORY 207258945Sroberto *\li #ISC_R_UNEXPECTED 208258945Sroberto *\li #ISC_R_SHUTTINGDOWN 209258945Sroberto */ 210258945Sroberto 211258945Srobertovoid 212258945Srobertoisc_task_attach(isc_task_t *source, isc_task_t **targetp); 213258945Sroberto/*%< 214258945Sroberto * Attach *targetp to source. 215258945Sroberto * 216258945Sroberto * Requires: 217258945Sroberto * 218258945Sroberto *\li 'source' is a valid task. 219258945Sroberto * 220258945Sroberto *\li 'targetp' points to a NULL isc_task_t *. 221258945Sroberto * 222258945Sroberto * Ensures: 223258945Sroberto * 224258945Sroberto *\li *targetp is attached to source. 225258945Sroberto */ 226258945Sroberto 227258945Srobertovoid 228258945Srobertoisc_task_detach(isc_task_t **taskp); 229258945Sroberto/*%< 230258945Sroberto * Detach *taskp from its task. 231258945Sroberto * 232258945Sroberto * Requires: 233258945Sroberto * 234258945Sroberto *\li '*taskp' is a valid task. 235258945Sroberto * 236258945Sroberto * Ensures: 237258945Sroberto * 238258945Sroberto *\li *taskp is NULL. 239258945Sroberto * 240258945Sroberto *\li If '*taskp' is the last reference to the task, the task is idle (has 241258945Sroberto * an empty event queue), and has not been shutdown, the task will be 242258945Sroberto * shutdown. 243258945Sroberto * 244258945Sroberto *\li If '*taskp' is the last reference to the task and 245258945Sroberto * the task has been shutdown, 246258945Sroberto * all resources used by the task will be freed. 247258945Sroberto */ 248258945Sroberto 249258945Srobertovoid 250258945Srobertoisc_task_send(isc_task_t *task, isc_event_t **eventp); 251258945Sroberto/*%< 252258945Sroberto * Send '*event' to 'task'. 253258945Sroberto * 254258945Sroberto * Requires: 255258945Sroberto * 256258945Sroberto *\li 'task' is a valid task. 257258945Sroberto *\li eventp != NULL && *eventp != NULL. 258258945Sroberto * 259258945Sroberto * Ensures: 260258945Sroberto * 261258945Sroberto *\li *eventp == NULL. 262258945Sroberto */ 263258945Sroberto 264258945Srobertovoid 265258945Srobertoisc_task_sendanddetach(isc_task_t **taskp, isc_event_t **eventp); 266258945Sroberto/*%< 267258945Sroberto * Send '*event' to '*taskp' and then detach '*taskp' from its 268258945Sroberto * task. 269258945Sroberto * 270258945Sroberto * Requires: 271258945Sroberto * 272258945Sroberto *\li '*taskp' is a valid task. 273258945Sroberto *\li eventp != NULL && *eventp != NULL. 274258945Sroberto * 275258945Sroberto * Ensures: 276258945Sroberto * 277258945Sroberto *\li *eventp == NULL. 278258945Sroberto * 279258945Sroberto *\li *taskp == NULL. 280258945Sroberto * 281258945Sroberto *\li If '*taskp' is the last reference to the task, the task is 282258945Sroberto * idle (has an empty event queue), and has not been shutdown, 283258945Sroberto * the task will be shutdown. 284258945Sroberto * 285258945Sroberto *\li If '*taskp' is the last reference to the task and 286258945Sroberto * the task has been shutdown, 287258945Sroberto * all resources used by the task will be freed. 288258945Sroberto */ 289258945Sroberto 290258945Sroberto 291258945Srobertounsigned int 292258945Srobertoisc_task_purgerange(isc_task_t *task, void *sender, isc_eventtype_t first, 293258945Sroberto isc_eventtype_t last, void *tag); 294258945Sroberto/*%< 295258945Sroberto * Purge events from a task's event queue. 296258945Sroberto * 297258945Sroberto * Requires: 298258945Sroberto * 299258945Sroberto *\li 'task' is a valid task. 300258945Sroberto * 301258945Sroberto *\li last >= first 302258945Sroberto * 303258945Sroberto * Ensures: 304258945Sroberto * 305258945Sroberto *\li Events in the event queue of 'task' whose sender is 'sender', whose 306258945Sroberto * type is >= first and <= last, and whose tag is 'tag' will be purged, 307258945Sroberto * unless they are marked as unpurgable. 308258945Sroberto * 309258945Sroberto *\li A sender of NULL will match any sender. A NULL tag matches any 310258945Sroberto * tag. 311258945Sroberto * 312258945Sroberto * Returns: 313258945Sroberto * 314258945Sroberto *\li The number of events purged. 315258945Sroberto */ 316258945Sroberto 317258945Srobertounsigned int 318258945Srobertoisc_task_purge(isc_task_t *task, void *sender, isc_eventtype_t type, 319258945Sroberto void *tag); 320258945Sroberto/*%< 321258945Sroberto * Purge events from a task's event queue. 322258945Sroberto * 323258945Sroberto * Notes: 324258945Sroberto * 325258945Sroberto *\li This function is equivalent to 326258945Sroberto * 327258945Sroberto *\code 328258945Sroberto * isc_task_purgerange(task, sender, type, type, tag); 329258945Sroberto *\endcode 330258945Sroberto * 331258945Sroberto * Requires: 332258945Sroberto * 333258945Sroberto *\li 'task' is a valid task. 334258945Sroberto * 335258945Sroberto * Ensures: 336258945Sroberto * 337258945Sroberto *\li Events in the event queue of 'task' whose sender is 'sender', whose 338258945Sroberto * type is 'type', and whose tag is 'tag' will be purged, unless they 339258945Sroberto * are marked as unpurgable. 340258945Sroberto * 341258945Sroberto *\li A sender of NULL will match any sender. A NULL tag matches any 342258945Sroberto * tag. 343258945Sroberto * 344258945Sroberto * Returns: 345258945Sroberto * 346258945Sroberto *\li The number of events purged. 347258945Sroberto */ 348258945Sroberto 349258945Srobertoisc_boolean_t 350258945Srobertoisc_task_purgeevent(isc_task_t *task, isc_event_t *event); 351258945Sroberto/*%< 352258945Sroberto * Purge 'event' from a task's event queue. 353258945Sroberto * 354258945Sroberto * XXXRTH: WARNING: This method may be removed before beta. 355258945Sroberto * 356258945Sroberto * Notes: 357258945Sroberto * 358258945Sroberto *\li If 'event' is on the task's event queue, it will be purged, 359258945Sroberto * unless it is marked as unpurgeable. 'event' does not have to be 360258945Sroberto * on the task's event queue; in fact, it can even be an invalid 361258945Sroberto * pointer. Purging only occurs if the event is actually on the task's 362258945Sroberto * event queue. 363258945Sroberto * 364258945Sroberto * \li Purging never changes the state of the task. 365258945Sroberto * 366258945Sroberto * Requires: 367258945Sroberto * 368258945Sroberto *\li 'task' is a valid task. 369258945Sroberto * 370258945Sroberto * Ensures: 371258945Sroberto * 372258945Sroberto *\li 'event' is not in the event queue for 'task'. 373258945Sroberto * 374258945Sroberto * Returns: 375258945Sroberto * 376258945Sroberto *\li #ISC_TRUE The event was purged. 377258945Sroberto *\li #ISC_FALSE The event was not in the event queue, 378258945Sroberto * or was marked unpurgeable. 379258945Sroberto */ 380258945Sroberto 381258945Srobertounsigned int 382258945Srobertoisc_task_unsendrange(isc_task_t *task, void *sender, isc_eventtype_t first, 383258945Sroberto isc_eventtype_t last, void *tag, isc_eventlist_t *events); 384258945Sroberto/*%< 385258945Sroberto * Remove events from a task's event queue. 386258945Sroberto * 387258945Sroberto * Requires: 388258945Sroberto * 389258945Sroberto *\li 'task' is a valid task. 390258945Sroberto * 391258945Sroberto *\li last >= first. 392258945Sroberto * 393258945Sroberto *\li *events is a valid list. 394258945Sroberto * 395258945Sroberto * Ensures: 396258945Sroberto * 397258945Sroberto *\li Events in the event queue of 'task' whose sender is 'sender', whose 398258945Sroberto * type is >= first and <= last, and whose tag is 'tag' will be dequeued 399258945Sroberto * and appended to *events. 400258945Sroberto * 401258945Sroberto *\li A sender of NULL will match any sender. A NULL tag matches any 402258945Sroberto * tag. 403258945Sroberto * 404258945Sroberto * Returns: 405258945Sroberto * 406258945Sroberto *\li The number of events unsent. 407258945Sroberto */ 408258945Sroberto 409258945Srobertounsigned int 410258945Srobertoisc_task_unsend(isc_task_t *task, void *sender, isc_eventtype_t type, 411258945Sroberto void *tag, isc_eventlist_t *events); 412258945Sroberto/*%< 413258945Sroberto * Remove events from a task's event queue. 414258945Sroberto * 415258945Sroberto * Notes: 416258945Sroberto * 417258945Sroberto *\li This function is equivalent to 418258945Sroberto * 419258945Sroberto *\code 420258945Sroberto * isc_task_unsendrange(task, sender, type, type, tag, events); 421258945Sroberto *\endcode 422258945Sroberto * 423258945Sroberto * Requires: 424258945Sroberto * 425258945Sroberto *\li 'task' is a valid task. 426258945Sroberto * 427258945Sroberto *\li *events is a valid list. 428258945Sroberto * 429258945Sroberto * Ensures: 430258945Sroberto * 431258945Sroberto *\li Events in the event queue of 'task' whose sender is 'sender', whose 432258945Sroberto * type is 'type', and whose tag is 'tag' will be dequeued and appended 433258945Sroberto * to *events. 434258945Sroberto * 435258945Sroberto * Returns: 436258945Sroberto * 437258945Sroberto *\li The number of events unsent. 438258945Sroberto */ 439258945Sroberto 440258945Srobertoisc_result_t 441258945Srobertoisc_task_onshutdown(isc_task_t *task, isc_taskaction_t action, 442258945Sroberto const void *arg); 443258945Sroberto/*%< 444258945Sroberto * Send a shutdown event with action 'action' and argument 'arg' when 445258945Sroberto * 'task' is shutdown. 446258945Sroberto * 447258945Sroberto * Notes: 448258945Sroberto * 449258945Sroberto *\li Shutdown events are posted in LIFO order. 450258945Sroberto * 451258945Sroberto * Requires: 452258945Sroberto * 453258945Sroberto *\li 'task' is a valid task. 454258945Sroberto * 455258945Sroberto *\li 'action' is a valid task action. 456258945Sroberto * 457258945Sroberto * Ensures: 458258945Sroberto * 459258945Sroberto *\li When the task is shutdown, shutdown events requested with 460258945Sroberto * isc_task_onshutdown() will be appended to the task's event queue. 461258945Sroberto * 462258945Sroberto 463258945Sroberto * Returns: 464258945Sroberto * 465258945Sroberto *\li #ISC_R_SUCCESS 466258945Sroberto *\li #ISC_R_NOMEMORY 467258945Sroberto *\li #ISC_R_TASKSHUTTINGDOWN Task is shutting down. 468258945Sroberto */ 469258945Sroberto 470258945Srobertovoid 471258945Srobertoisc_task_shutdown(isc_task_t *task); 472258945Sroberto/*%< 473258945Sroberto * Shutdown 'task'. 474258945Sroberto * 475258945Sroberto * Notes: 476258945Sroberto * 477258945Sroberto *\li Shutting down a task causes any shutdown events requested with 478258945Sroberto * isc_task_onshutdown() to be posted (in LIFO order). The task 479258945Sroberto * moves into a "shutting down" mode which prevents further calls 480258945Sroberto * to isc_task_onshutdown(). 481258945Sroberto * 482258945Sroberto *\li Trying to shutdown a task that has already been shutdown has no 483258945Sroberto * effect. 484258945Sroberto * 485258945Sroberto * Requires: 486258945Sroberto * 487258945Sroberto *\li 'task' is a valid task. 488258945Sroberto * 489258945Sroberto * Ensures: 490258945Sroberto * 491258945Sroberto *\li Any shutdown events requested with isc_task_onshutdown() have been 492258945Sroberto * posted (in LIFO order). 493258945Sroberto */ 494258945Sroberto 495258945Srobertovoid 496258945Srobertoisc_task_destroy(isc_task_t **taskp); 497258945Sroberto/*%< 498258945Sroberto * Destroy '*taskp'. 499258945Sroberto * 500258945Sroberto * Notes: 501258945Sroberto * 502258945Sroberto *\li This call is equivalent to: 503258945Sroberto * 504258945Sroberto *\code 505258945Sroberto * isc_task_shutdown(*taskp); 506258945Sroberto * isc_task_detach(taskp); 507258945Sroberto *\endcode 508258945Sroberto * 509258945Sroberto * Requires: 510258945Sroberto * 511258945Sroberto * '*taskp' is a valid task. 512258945Sroberto * 513258945Sroberto * Ensures: 514258945Sroberto * 515258945Sroberto *\li Any shutdown events requested with isc_task_onshutdown() have been 516258945Sroberto * posted (in LIFO order). 517258945Sroberto * 518258945Sroberto *\li *taskp == NULL 519258945Sroberto * 520258945Sroberto *\li If '*taskp' is the last reference to the task, 521258945Sroberto * all resources used by the task will be freed. 522258945Sroberto */ 523258945Sroberto 524258945Srobertovoid 525258945Srobertoisc_task_setname(isc_task_t *task, const char *name, void *tag); 526258945Sroberto/*%< 527258945Sroberto * Name 'task'. 528258945Sroberto * 529258945Sroberto * Notes: 530258945Sroberto * 531258945Sroberto *\li Only the first 15 characters of 'name' will be copied. 532258945Sroberto * 533258945Sroberto *\li Naming a task is currently only useful for debugging purposes. 534258945Sroberto * 535258945Sroberto * Requires: 536258945Sroberto * 537258945Sroberto *\li 'task' is a valid task. 538258945Sroberto */ 539258945Sroberto 540258945Srobertoconst char * 541258945Srobertoisc_task_getname(isc_task_t *task); 542258945Sroberto/*%< 543258945Sroberto * Get the name of 'task', as previously set using isc_task_setname(). 544258945Sroberto * 545258945Sroberto * Notes: 546258945Sroberto *\li This function is for debugging purposes only. 547258945Sroberto * 548258945Sroberto * Requires: 549258945Sroberto *\li 'task' is a valid task. 550258945Sroberto * 551258945Sroberto * Returns: 552258945Sroberto *\li A non-NULL pointer to a null-terminated string. 553258945Sroberto * If the task has not been named, the string is 554258945Sroberto * empty. 555258945Sroberto * 556258945Sroberto */ 557258945Sroberto 558258945Srobertovoid * 559258945Srobertoisc_task_gettag(isc_task_t *task); 560258945Sroberto/*%< 561258945Sroberto * Get the tag value for 'task', as previously set using isc_task_settag(). 562258945Sroberto * 563258945Sroberto * Notes: 564258945Sroberto *\li This function is for debugging purposes only. 565258945Sroberto * 566258945Sroberto * Requires: 567258945Sroberto *\li 'task' is a valid task. 568258945Sroberto */ 569258945Sroberto 570258945Srobertoisc_result_t 571258945Srobertoisc_task_beginexclusive(isc_task_t *task); 572258945Sroberto/*%< 573258945Sroberto * Request exclusive access for 'task', which must be the calling 574258945Sroberto * task. Waits for any other concurrently executing tasks to finish their 575258945Sroberto * current event, and prevents any new events from executing in any of the 576258945Sroberto * tasks sharing a task manager with 'task'. 577258945Sroberto * 578258945Sroberto * The exclusive access must be relinquished by calling 579258945Sroberto * isc_task_endexclusive() before returning from the current event handler. 580258945Sroberto * 581258945Sroberto * Requires: 582258945Sroberto *\li 'task' is the calling task. 583258945Sroberto * 584258945Sroberto * Returns: 585258945Sroberto *\li #ISC_R_SUCCESS The current task now has exclusive access. 586258945Sroberto *\li #ISC_R_LOCKBUSY Another task has already requested exclusive 587258945Sroberto * access. 588258945Sroberto */ 589258945Sroberto 590258945Srobertovoid 591258945Srobertoisc_task_endexclusive(isc_task_t *task); 592258945Sroberto/*%< 593258945Sroberto * Relinquish the exclusive access obtained by isc_task_beginexclusive(), 594258945Sroberto * allowing other tasks to execute. 595258945Sroberto * 596258945Sroberto * Requires: 597258945Sroberto *\li 'task' is the calling task, and has obtained 598258945Sroberto * exclusive access by calling isc_task_spl(). 599258945Sroberto */ 600258945Sroberto 601258945Srobertovoid 602258945Srobertoisc_task_getcurrenttime(isc_task_t *task, isc_stdtime_t *t); 603258945Sroberto/*%< 604258945Sroberto * Provide the most recent timestamp on the task. The timestamp is considered 605258945Sroberto * as the "current time" in the second-order granularity. 606258945Sroberto * 607258945Sroberto * Requires: 608258945Sroberto *\li 'task' is a valid task. 609258945Sroberto *\li 't' is a valid non NULL pointer. 610258945Sroberto * 611258945Sroberto * Ensures: 612258945Sroberto *\li '*t' has the "current time". 613258945Sroberto */ 614258945Sroberto 615280849Scyisc_boolean_t 616280849Scyisc_task_exiting(isc_task_t *t); 617280849Scy/*%< 618280849Scy * Returns ISC_TRUE if the task is in the process of shutting down, 619280849Scy * ISC_FALSE otherwise. 620280849Scy * 621280849Scy * Requires: 622280849Scy *\li 'task' is a valid task. 623280849Scy */ 624280849Scy 625280849Scyvoid 626280849Scyisc_task_setprivilege(isc_task_t *task, isc_boolean_t priv); 627280849Scy/*%< 628280849Scy * Set or unset the task's "privileged" flag depending on the value of 629280849Scy * 'priv'. 630280849Scy * 631280849Scy * Under normal circumstances this flag has no effect on the task behavior, 632280849Scy * but when the task manager has been set to privileged exeuction mode via 633280849Scy * isc_taskmgr_setmode(), only tasks with the flag set will be executed, 634280849Scy * and all other tasks will wait until they're done. Once all privileged 635280849Scy * tasks have finished executing, the task manager will automatically 636280849Scy * return to normal execution mode and nonprivileged task can resume. 637280849Scy * 638280849Scy * Requires: 639280849Scy *\li 'task' is a valid task. 640280849Scy */ 641280849Scy 642280849Scyisc_boolean_t 643280849Scyisc_task_privilege(isc_task_t *task); 644280849Scy/*%< 645280849Scy * Returns the current value of the task's privilege flag. 646280849Scy * 647280849Scy * Requires: 648280849Scy *\li 'task' is a valid task. 649280849Scy */ 650280849Scy 651258945Sroberto/***** 652258945Sroberto ***** Task Manager. 653258945Sroberto *****/ 654258945Sroberto 655258945Srobertoisc_result_t 656280849Scyisc_taskmgr_createinctx(isc_mem_t *mctx, isc_appctx_t *actx, 657280849Scy unsigned int workers, unsigned int default_quantum, 658280849Scy isc_taskmgr_t **managerp); 659280849Scyisc_result_t 660258945Srobertoisc_taskmgr_create(isc_mem_t *mctx, unsigned int workers, 661258945Sroberto unsigned int default_quantum, isc_taskmgr_t **managerp); 662258945Sroberto/*%< 663280849Scy * Create a new task manager. isc_taskmgr_createinctx() also associates 664280849Scy * the new manager with the specified application context. 665258945Sroberto * 666258945Sroberto * Notes: 667258945Sroberto * 668258945Sroberto *\li 'workers' in the number of worker threads to create. In general, 669258945Sroberto * the value should be close to the number of processors in the system. 670258945Sroberto * The 'workers' value is advisory only. An attempt will be made to 671258945Sroberto * create 'workers' threads, but if at least one thread creation 672258945Sroberto * succeeds, isc_taskmgr_create() may return ISC_R_SUCCESS. 673258945Sroberto * 674258945Sroberto *\li If 'default_quantum' is non-zero, then it will be used as the default 675258945Sroberto * quantum value when tasks are created. If zero, then an implementation 676258945Sroberto * defined default quantum will be used. 677258945Sroberto * 678258945Sroberto * Requires: 679258945Sroberto * 680258945Sroberto *\li 'mctx' is a valid memory context. 681258945Sroberto * 682258945Sroberto *\li workers > 0 683258945Sroberto * 684258945Sroberto *\li managerp != NULL && *managerp == NULL 685258945Sroberto * 686280849Scy *\li 'actx' is a valid application context (for createinctx()). 687280849Scy * 688258945Sroberto * Ensures: 689258945Sroberto * 690258945Sroberto *\li On success, '*managerp' will be attached to the newly created task 691258945Sroberto * manager. 692258945Sroberto * 693258945Sroberto * Returns: 694258945Sroberto * 695258945Sroberto *\li #ISC_R_SUCCESS 696258945Sroberto *\li #ISC_R_NOMEMORY 697280849Scy *\li #ISC_R_NOTHREADS No threads could be created. 698258945Sroberto *\li #ISC_R_UNEXPECTED An unexpected error occurred. 699280849Scy *\li #ISC_R_SHUTTINGDOWN The non-threaded, shared, task 700280849Scy * manager shutting down. 701258945Sroberto */ 702258945Sroberto 703258945Srobertovoid 704280849Scyisc_taskmgr_setmode(isc_taskmgr_t *manager, isc_taskmgrmode_t mode); 705280849Scy 706280849Scyisc_taskmgrmode_t 707280849Scyisc_taskmgr_mode(isc_taskmgr_t *manager); 708280849Scy/*%< 709280849Scy * Set/get the current operating mode of the task manager. Valid modes are: 710280849Scy * 711280849Scy *\li isc_taskmgrmode_normal 712280849Scy *\li isc_taskmgrmode_privileged 713280849Scy * 714280849Scy * In privileged execution mode, only tasks that have had the "privilege" 715280849Scy * flag set via isc_task_setprivilege() can be executed. When all such 716280849Scy * tasks are complete, the manager automatically returns to normal mode 717280849Scy * and proceeds with running non-privileged ready tasks. This means it is 718280849Scy * necessary to have at least one privileged task waiting on the ready 719280849Scy * queue *before* setting the manager into privileged execution mode, 720280849Scy * which in turn means the task which calls this function should be in 721280849Scy * task-exclusive mode when it does so. 722280849Scy * 723280849Scy * Requires: 724280849Scy * 725280849Scy *\li 'manager' is a valid task manager. 726280849Scy */ 727280849Scy 728280849Scyvoid 729258945Srobertoisc_taskmgr_destroy(isc_taskmgr_t **managerp); 730258945Sroberto/*%< 731258945Sroberto * Destroy '*managerp'. 732258945Sroberto * 733258945Sroberto * Notes: 734258945Sroberto * 735258945Sroberto *\li Calling isc_taskmgr_destroy() will shutdown all tasks managed by 736258945Sroberto * *managerp that haven't already been shutdown. The call will block 737258945Sroberto * until all tasks have entered the done state. 738258945Sroberto * 739258945Sroberto *\li isc_taskmgr_destroy() must not be called by a task event action, 740258945Sroberto * because it would block forever waiting for the event action to 741258945Sroberto * complete. An event action that wants to cause task manager shutdown 742258945Sroberto * should request some non-event action thread of execution to do the 743258945Sroberto * shutdown, e.g. by signaling a condition variable or using 744258945Sroberto * isc_app_shutdown(). 745258945Sroberto * 746258945Sroberto *\li Task manager references are not reference counted, so the caller 747258945Sroberto * must ensure that no attempt will be made to use the manager after 748258945Sroberto * isc_taskmgr_destroy() returns. 749258945Sroberto * 750258945Sroberto * Requires: 751258945Sroberto * 752258945Sroberto *\li '*managerp' is a valid task manager. 753258945Sroberto * 754258945Sroberto *\li isc_taskmgr_destroy() has not be called previously on '*managerp'. 755258945Sroberto * 756258945Sroberto * Ensures: 757258945Sroberto * 758258945Sroberto *\li All resources used by the task manager, and any tasks it managed, 759258945Sroberto * have been freed. 760258945Sroberto */ 761258945Sroberto 762258945Sroberto#ifdef HAVE_LIBXML2 763258945Sroberto 764258945Srobertovoid 765258945Srobertoisc_taskmgr_renderxml(isc_taskmgr_t *mgr, xmlTextWriterPtr writer); 766258945Sroberto 767258945Sroberto#endif 768258945Sroberto 769280849Scy/*%< 770280849Scy * See isc_taskmgr_create() above. 771280849Scy */ 772280849Scytypedef isc_result_t 773280849Scy(*isc_taskmgrcreatefunc_t)(isc_mem_t *mctx, unsigned int workers, 774280849Scy unsigned int default_quantum, 775280849Scy isc_taskmgr_t **managerp); 776280849Scy 777280849Scyisc_result_t 778280849Scyisc_task_register(isc_taskmgrcreatefunc_t createfunc); 779280849Scy/*%< 780280849Scy * Register a new task management implementation and add it to the list of 781280849Scy * supported implementations. This function must be called when a different 782280849Scy * event library is used than the one contained in the ISC library. 783280849Scy */ 784280849Scy 785280849Scyisc_result_t 786280849Scyisc__task_register(void); 787280849Scy/*%< 788280849Scy * A short cut function that specifies the task management module in the ISC 789280849Scy * library for isc_task_register(). An application that uses the ISC library 790280849Scy * usually do not have to care about this function: it would call 791280849Scy * isc_lib_register(), which internally calls this function. 792280849Scy */ 793280849Scy 794258945SrobertoISC_LANG_ENDDECLS 795258945Sroberto 796258945Sroberto#endif /* ISC_TASK_H */ 797