1/* 2 * Copyright (C) 2004-2007, 2009 Internet Systems Consortium, Inc. ("ISC") 3 * Copyright (C) 1998-2001, 2003 Internet Software Consortium. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 15 * PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18/* $Id: task.h,v 1.61.332.2 2009/01/18 23:47:41 tbox Exp $ */ 19 20#ifndef ISC_TASK_H 21#define ISC_TASK_H 1 22 23/***** 24 ***** Module Info 25 *****/ 26 27/*! \file isc/task.h 28 * \brief The task system provides a lightweight execution context, which is 29 * basically an event queue. 30 31 * When a task's event queue is non-empty, the 32 * task is runnable. A small work crew of threads, typically one per CPU, 33 * execute runnable tasks by dispatching the events on the tasks' event 34 * queues. Context switching between tasks is fast. 35 * 36 * \li MP: 37 * The module ensures appropriate synchronization of data structures it 38 * creates and manipulates. 39 * The caller must ensure that isc_taskmgr_destroy() is called only 40 * once for a given manager. 41 * 42 * \li Reliability: 43 * No anticipated impact. 44 * 45 * \li Resources: 46 * TBS 47 * 48 * \li Security: 49 * No anticipated impact. 50 * 51 * \li Standards: 52 * None. 53 * 54 * \section purge Purging and Unsending 55 * 56 * Events which have been queued for a task but not delivered may be removed 57 * from the task's event queue by purging or unsending. 58 * 59 * With both types, the caller specifies a matching pattern that selects 60 * events based upon their sender, type, and tag. 61 * 62 * Purging calls isc_event_free() on the matching events. 63 * 64 * Unsending returns a list of events that matched the pattern. 65 * The caller is then responsible for them. 66 * 67 * Consumers of events should purge, not unsend. 68 * 69 * Producers of events often want to remove events when the caller indicates 70 * it is no longer interested in the object, e.g. by canceling a timer. 71 * Sometimes this can be done by purging, but for some event types, the 72 * calls to isc_event_free() cause deadlock because the event free routine 73 * wants to acquire a lock the caller is already holding. Unsending instead 74 * of purging solves this problem. As a general rule, producers should only 75 * unsend events which they have sent. 76 */ 77 78 79/*** 80 *** Imports. 81 ***/ 82 83#include <isc/eventclass.h> 84#include <isc/lang.h> 85#include <isc/stdtime.h> 86#include <isc/types.h> 87#include <isc/xml.h> 88 89#define ISC_TASKEVENT_FIRSTEVENT (ISC_EVENTCLASS_TASK + 0) 90#define ISC_TASKEVENT_SHUTDOWN (ISC_EVENTCLASS_TASK + 1) 91#define ISC_TASKEVENT_LASTEVENT (ISC_EVENTCLASS_TASK + 65535) 92 93/***** 94 ***** Tasks. 95 *****/ 96 97ISC_LANG_BEGINDECLS 98 99isc_result_t 100isc_task_create(isc_taskmgr_t *manager, unsigned int quantum, 101 isc_task_t **taskp); 102/*%< 103 * Create a task. 104 * 105 * Notes: 106 * 107 *\li If 'quantum' is non-zero, then only that many events can be dispatched 108 * before the task must yield to other tasks waiting to execute. If 109 * quantum is zero, then the default quantum of the task manager will 110 * be used. 111 * 112 *\li The 'quantum' option may be removed from isc_task_create() in the 113 * future. If this happens, isc_task_getquantum() and 114 * isc_task_setquantum() will be provided. 115 * 116 * Requires: 117 * 118 *\li 'manager' is a valid task manager. 119 * 120 *\li taskp != NULL && *taskp == NULL 121 * 122 * Ensures: 123 * 124 *\li On success, '*taskp' is bound to the new task. 125 * 126 * Returns: 127 * 128 *\li #ISC_R_SUCCESS 129 *\li #ISC_R_NOMEMORY 130 *\li #ISC_R_UNEXPECTED 131 *\li #ISC_R_SHUTTINGDOWN 132 */ 133 134void 135isc_task_attach(isc_task_t *source, isc_task_t **targetp); 136/*%< 137 * Attach *targetp to source. 138 * 139 * Requires: 140 * 141 *\li 'source' is a valid task. 142 * 143 *\li 'targetp' points to a NULL isc_task_t *. 144 * 145 * Ensures: 146 * 147 *\li *targetp is attached to source. 148 */ 149 150void 151isc_task_detach(isc_task_t **taskp); 152/*%< 153 * Detach *taskp from its task. 154 * 155 * Requires: 156 * 157 *\li '*taskp' is a valid task. 158 * 159 * Ensures: 160 * 161 *\li *taskp is NULL. 162 * 163 *\li If '*taskp' is the last reference to the task, the task is idle (has 164 * an empty event queue), and has not been shutdown, the task will be 165 * shutdown. 166 * 167 *\li If '*taskp' is the last reference to the task and 168 * the task has been shutdown, 169 * all resources used by the task will be freed. 170 */ 171 172void 173isc_task_send(isc_task_t *task, isc_event_t **eventp); 174/*%< 175 * Send '*event' to 'task'. 176 * 177 * Requires: 178 * 179 *\li 'task' is a valid task. 180 *\li eventp != NULL && *eventp != NULL. 181 * 182 * Ensures: 183 * 184 *\li *eventp == NULL. 185 */ 186 187void 188isc_task_sendanddetach(isc_task_t **taskp, isc_event_t **eventp); 189/*%< 190 * Send '*event' to '*taskp' and then detach '*taskp' from its 191 * task. 192 * 193 * Requires: 194 * 195 *\li '*taskp' is a valid task. 196 *\li eventp != NULL && *eventp != NULL. 197 * 198 * Ensures: 199 * 200 *\li *eventp == NULL. 201 * 202 *\li *taskp == NULL. 203 * 204 *\li If '*taskp' is the last reference to the task, the task is 205 * idle (has an empty event queue), and has not been shutdown, 206 * the task will be shutdown. 207 * 208 *\li If '*taskp' is the last reference to the task and 209 * the task has been shutdown, 210 * all resources used by the task will be freed. 211 */ 212 213 214unsigned int 215isc_task_purgerange(isc_task_t *task, void *sender, isc_eventtype_t first, 216 isc_eventtype_t last, void *tag); 217/*%< 218 * Purge events from a task's event queue. 219 * 220 * Requires: 221 * 222 *\li 'task' is a valid task. 223 * 224 *\li last >= first 225 * 226 * Ensures: 227 * 228 *\li Events in the event queue of 'task' whose sender is 'sender', whose 229 * type is >= first and <= last, and whose tag is 'tag' will be purged, 230 * unless they are marked as unpurgable. 231 * 232 *\li A sender of NULL will match any sender. A NULL tag matches any 233 * tag. 234 * 235 * Returns: 236 * 237 *\li The number of events purged. 238 */ 239 240unsigned int 241isc_task_purge(isc_task_t *task, void *sender, isc_eventtype_t type, 242 void *tag); 243/*%< 244 * Purge events from a task's event queue. 245 * 246 * Notes: 247 * 248 *\li This function is equivalent to 249 * 250 *\code 251 * isc_task_purgerange(task, sender, type, type, tag); 252 *\endcode 253 * 254 * Requires: 255 * 256 *\li 'task' is a valid task. 257 * 258 * Ensures: 259 * 260 *\li Events in the event queue of 'task' whose sender is 'sender', whose 261 * type is 'type', and whose tag is 'tag' will be purged, unless they 262 * are marked as unpurgable. 263 * 264 *\li A sender of NULL will match any sender. A NULL tag matches any 265 * tag. 266 * 267 * Returns: 268 * 269 *\li The number of events purged. 270 */ 271 272isc_boolean_t 273isc_task_purgeevent(isc_task_t *task, isc_event_t *event); 274/*%< 275 * Purge 'event' from a task's event queue. 276 * 277 * XXXRTH: WARNING: This method may be removed before beta. 278 * 279 * Notes: 280 * 281 *\li If 'event' is on the task's event queue, it will be purged, 282 * unless it is marked as unpurgeable. 'event' does not have to be 283 * on the task's event queue; in fact, it can even be an invalid 284 * pointer. Purging only occurs if the event is actually on the task's 285 * event queue. 286 * 287 * \li Purging never changes the state of the task. 288 * 289 * Requires: 290 * 291 *\li 'task' is a valid task. 292 * 293 * Ensures: 294 * 295 *\li 'event' is not in the event queue for 'task'. 296 * 297 * Returns: 298 * 299 *\li #ISC_TRUE The event was purged. 300 *\li #ISC_FALSE The event was not in the event queue, 301 * or was marked unpurgeable. 302 */ 303 304unsigned int 305isc_task_unsendrange(isc_task_t *task, void *sender, isc_eventtype_t first, 306 isc_eventtype_t last, void *tag, isc_eventlist_t *events); 307/*%< 308 * Remove events from a task's event queue. 309 * 310 * Requires: 311 * 312 *\li 'task' is a valid task. 313 * 314 *\li last >= first. 315 * 316 *\li *events is a valid list. 317 * 318 * Ensures: 319 * 320 *\li Events in the event queue of 'task' whose sender is 'sender', whose 321 * type is >= first and <= last, and whose tag is 'tag' will be dequeued 322 * and appended to *events. 323 * 324 *\li A sender of NULL will match any sender. A NULL tag matches any 325 * tag. 326 * 327 * Returns: 328 * 329 *\li The number of events unsent. 330 */ 331 332unsigned int 333isc_task_unsend(isc_task_t *task, void *sender, isc_eventtype_t type, 334 void *tag, isc_eventlist_t *events); 335/*%< 336 * Remove events from a task's event queue. 337 * 338 * Notes: 339 * 340 *\li This function is equivalent to 341 * 342 *\code 343 * isc_task_unsendrange(task, sender, type, type, tag, events); 344 *\endcode 345 * 346 * Requires: 347 * 348 *\li 'task' is a valid task. 349 * 350 *\li *events is a valid list. 351 * 352 * Ensures: 353 * 354 *\li Events in the event queue of 'task' whose sender is 'sender', whose 355 * type is 'type', and whose tag is 'tag' will be dequeued and appended 356 * to *events. 357 * 358 * Returns: 359 * 360 *\li The number of events unsent. 361 */ 362 363isc_result_t 364isc_task_onshutdown(isc_task_t *task, isc_taskaction_t action, 365 const void *arg); 366/*%< 367 * Send a shutdown event with action 'action' and argument 'arg' when 368 * 'task' is shutdown. 369 * 370 * Notes: 371 * 372 *\li Shutdown events are posted in LIFO order. 373 * 374 * Requires: 375 * 376 *\li 'task' is a valid task. 377 * 378 *\li 'action' is a valid task action. 379 * 380 * Ensures: 381 * 382 *\li When the task is shutdown, shutdown events requested with 383 * isc_task_onshutdown() will be appended to the task's event queue. 384 * 385 386 * Returns: 387 * 388 *\li #ISC_R_SUCCESS 389 *\li #ISC_R_NOMEMORY 390 *\li #ISC_R_TASKSHUTTINGDOWN Task is shutting down. 391 */ 392 393void 394isc_task_shutdown(isc_task_t *task); 395/*%< 396 * Shutdown 'task'. 397 * 398 * Notes: 399 * 400 *\li Shutting down a task causes any shutdown events requested with 401 * isc_task_onshutdown() to be posted (in LIFO order). The task 402 * moves into a "shutting down" mode which prevents further calls 403 * to isc_task_onshutdown(). 404 * 405 *\li Trying to shutdown a task that has already been shutdown has no 406 * effect. 407 * 408 * Requires: 409 * 410 *\li 'task' is a valid task. 411 * 412 * Ensures: 413 * 414 *\li Any shutdown events requested with isc_task_onshutdown() have been 415 * posted (in LIFO order). 416 */ 417 418void 419isc_task_destroy(isc_task_t **taskp); 420/*%< 421 * Destroy '*taskp'. 422 * 423 * Notes: 424 * 425 *\li This call is equivalent to: 426 * 427 *\code 428 * isc_task_shutdown(*taskp); 429 * isc_task_detach(taskp); 430 *\endcode 431 * 432 * Requires: 433 * 434 * '*taskp' is a valid task. 435 * 436 * Ensures: 437 * 438 *\li Any shutdown events requested with isc_task_onshutdown() have been 439 * posted (in LIFO order). 440 * 441 *\li *taskp == NULL 442 * 443 *\li If '*taskp' is the last reference to the task, 444 * all resources used by the task will be freed. 445 */ 446 447void 448isc_task_setname(isc_task_t *task, const char *name, void *tag); 449/*%< 450 * Name 'task'. 451 * 452 * Notes: 453 * 454 *\li Only the first 15 characters of 'name' will be copied. 455 * 456 *\li Naming a task is currently only useful for debugging purposes. 457 * 458 * Requires: 459 * 460 *\li 'task' is a valid task. 461 */ 462 463const char * 464isc_task_getname(isc_task_t *task); 465/*%< 466 * Get the name of 'task', as previously set using isc_task_setname(). 467 * 468 * Notes: 469 *\li This function is for debugging purposes only. 470 * 471 * Requires: 472 *\li 'task' is a valid task. 473 * 474 * Returns: 475 *\li A non-NULL pointer to a null-terminated string. 476 * If the task has not been named, the string is 477 * empty. 478 * 479 */ 480 481void * 482isc_task_gettag(isc_task_t *task); 483/*%< 484 * Get the tag value for 'task', as previously set using isc_task_settag(). 485 * 486 * Notes: 487 *\li This function is for debugging purposes only. 488 * 489 * Requires: 490 *\li 'task' is a valid task. 491 */ 492 493isc_result_t 494isc_task_beginexclusive(isc_task_t *task); 495/*%< 496 * Request exclusive access for 'task', which must be the calling 497 * task. Waits for any other concurrently executing tasks to finish their 498 * current event, and prevents any new events from executing in any of the 499 * tasks sharing a task manager with 'task'. 500 * 501 * The exclusive access must be relinquished by calling 502 * isc_task_endexclusive() before returning from the current event handler. 503 * 504 * Requires: 505 *\li 'task' is the calling task. 506 * 507 * Returns: 508 *\li #ISC_R_SUCCESS The current task now has exclusive access. 509 *\li #ISC_R_LOCKBUSY Another task has already requested exclusive 510 * access. 511 */ 512 513void 514isc_task_endexclusive(isc_task_t *task); 515/*%< 516 * Relinquish the exclusive access obtained by isc_task_beginexclusive(), 517 * allowing other tasks to execute. 518 * 519 * Requires: 520 *\li 'task' is the calling task, and has obtained 521 * exclusive access by calling isc_task_spl(). 522 */ 523 524void 525isc_task_getcurrenttime(isc_task_t *task, isc_stdtime_t *t); 526/*%< 527 * Provide the most recent timestamp on the task. The timestamp is considered 528 * as the "current time" in the second-order granularity. 529 * 530 * Requires: 531 *\li 'task' is a valid task. 532 *\li 't' is a valid non NULL pointer. 533 * 534 * Ensures: 535 *\li '*t' has the "current time". 536 */ 537 538/***** 539 ***** Task Manager. 540 *****/ 541 542isc_result_t 543isc_taskmgr_create(isc_mem_t *mctx, unsigned int workers, 544 unsigned int default_quantum, isc_taskmgr_t **managerp); 545/*%< 546 * Create a new task manager. 547 * 548 * Notes: 549 * 550 *\li 'workers' in the number of worker threads to create. In general, 551 * the value should be close to the number of processors in the system. 552 * The 'workers' value is advisory only. An attempt will be made to 553 * create 'workers' threads, but if at least one thread creation 554 * succeeds, isc_taskmgr_create() may return ISC_R_SUCCESS. 555 * 556 *\li If 'default_quantum' is non-zero, then it will be used as the default 557 * quantum value when tasks are created. If zero, then an implementation 558 * defined default quantum will be used. 559 * 560 * Requires: 561 * 562 *\li 'mctx' is a valid memory context. 563 * 564 *\li workers > 0 565 * 566 *\li managerp != NULL && *managerp == NULL 567 * 568 * Ensures: 569 * 570 *\li On success, '*managerp' will be attached to the newly created task 571 * manager. 572 * 573 * Returns: 574 * 575 *\li #ISC_R_SUCCESS 576 *\li #ISC_R_NOMEMORY 577 *\li #ISC_R_NOTHREADS No threads could be created. 578 *\li #ISC_R_UNEXPECTED An unexpected error occurred. 579 */ 580 581void 582isc_taskmgr_destroy(isc_taskmgr_t **managerp); 583/*%< 584 * Destroy '*managerp'. 585 * 586 * Notes: 587 * 588 *\li Calling isc_taskmgr_destroy() will shutdown all tasks managed by 589 * *managerp that haven't already been shutdown. The call will block 590 * until all tasks have entered the done state. 591 * 592 *\li isc_taskmgr_destroy() must not be called by a task event action, 593 * because it would block forever waiting for the event action to 594 * complete. An event action that wants to cause task manager shutdown 595 * should request some non-event action thread of execution to do the 596 * shutdown, e.g. by signaling a condition variable or using 597 * isc_app_shutdown(). 598 * 599 *\li Task manager references are not reference counted, so the caller 600 * must ensure that no attempt will be made to use the manager after 601 * isc_taskmgr_destroy() returns. 602 * 603 * Requires: 604 * 605 *\li '*managerp' is a valid task manager. 606 * 607 *\li isc_taskmgr_destroy() has not be called previously on '*managerp'. 608 * 609 * Ensures: 610 * 611 *\li All resources used by the task manager, and any tasks it managed, 612 * have been freed. 613 */ 614 615#ifdef HAVE_LIBXML2 616 617void 618isc_taskmgr_renderxml(isc_taskmgr_t *mgr, xmlTextWriterPtr writer); 619 620#endif 621 622ISC_LANG_ENDDECLS 623 624#endif /* ISC_TASK_H */ 625