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