1/* 2 * Copyright (C) 2004-2007, 2009-2012 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$ */ 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 97ISC_LANG_BEGINDECLS 98 99/*** 100 *** Types 101 ***/ 102 103/*% Task and task manager methods */ 104typedef 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 111typedef 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 */ 141struct 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 */ 155struct 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 165isc_result_t 166isc_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 200void 201isc_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 216void 217isc_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 238void 239isc_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 253void 254isc_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 280unsigned int 281isc_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 306unsigned int 307isc_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 338isc_boolean_t 339isc_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 370unsigned int 371isc_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 398unsigned int 399isc_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 429isc_result_t 430isc_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 459void 460isc_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 484void 485isc_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 513void 514isc_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 529const char * 530isc_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 547void * 548isc_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 559isc_result_t 560isc_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 579void 580isc_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 590void 591isc_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 604isc_boolean_t 605isc_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 618isc_result_t 619isc_taskmgr_createinctx(isc_mem_t *mctx, isc_appctx_t *actx, 620 unsigned int workers, unsigned int default_quantum, 621 isc_taskmgr_t **managerp); 622isc_result_t 623isc_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 666void 667isc_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 702void 703isc_taskmgr_renderxml(isc_taskmgr_t *mgr, xmlTextWriterPtr writer); 704 705#endif 706 707/*%< 708 * See isc_taskmgr_create() above. 709 */ 710typedef 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 715isc_result_t 716isc_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 723isc_result_t 724isc__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 732ISC_LANG_ENDDECLS 733 734#endif /* ISC_TASK_H */ 735