Lines Matching refs:task
14 * XXXRTH Need to document the states a task can be in, and the rules
31 #include <isc/task.h>
45 * when built without threads we share a single global task manager and use
46 * an integrated event loop for socket, timer, and other generic task events.
48 * we don't use either of them: an application can have multiple task managers
62 #define XTRACE(m) fprintf(stderr, "task %p thread %lu: %s\n", \
63 task, isc_thread_self(), (m))
64 #define XTTRACE(t, m) fprintf(stderr, "task %p thread %lu: %s\n", \
100 /* Locked by task lock. */
112 /* Locked by task manager lock. */
138 /* Locked by task manager lock. */
196 isc__task_purge(isc_task_t *task, void *sender, isc_eventtype_t type,
201 isc__task_unsendrange(isc_task_t *task, void *sender, isc_eventtype_t first,
205 isc__task_unsend(isc_task_t *task, void *sender, isc_eventtype_t type,
234 isc__task_beginexclusive(isc_task_t *task);
253 push_readyq(isc__taskmgr_t *manager, isc__task_t *task);
303 task_finished(isc__task_t *task) {
304 isc__taskmgr_t *manager = task->manager;
306 REQUIRE(EMPTY(task->events));
307 REQUIRE(task->nevents == 0);
308 REQUIRE(EMPTY(task->on_shutdown));
309 REQUIRE(task->references == 0);
310 REQUIRE(task->state == task_state_done);
315 UNLINK(manager->tasks, task, link);
320 * task manager is exiting. Wake up
329 DESTROYLOCK(&task->lock);
330 task->common.impmagic = 0;
331 task->common.magic = 0;
332 isc_mem_put(manager->mctx, task, sizeof(*task));
340 isc__task_t *task;
347 task = isc_mem_get(manager->mctx, sizeof(*task));
348 if (task == NULL)
351 task->manager = manager;
352 result = isc_mutex_init(&task->lock);
354 isc_mem_put(manager->mctx, task, sizeof(*task));
357 task->state = task_state_idle;
358 task->references = 1;
359 INIT_LIST(task->events);
360 INIT_LIST(task->on_shutdown);
361 task->nevents = 0;
362 task->quantum = quantum;
363 task->flags = 0;
364 task->now = 0;
365 isc_time_settoepoch(&task->tnow);
366 memset(task->name, 0, sizeof(task->name));
367 task->tag = NULL;
368 INIT_LINK(task, link);
369 INIT_LINK(task, ready_link);
370 INIT_LINK(task, ready_priority_link);
375 if (task->quantum == 0)
376 task->quantum = manager->default_quantum;
377 APPEND(manager->tasks, task, link);
383 DESTROYLOCK(&task->lock);
384 isc_mem_put(manager->mctx, task, sizeof(*task));
388 task->common.methods = (isc_taskmethods_t *)&taskmethods;
389 task->common.magic = ISCAPI_TASK_MAGIC;
390 task->common.impmagic = TASK_MAGIC;
391 *taskp = (isc_task_t *)task;
417 task_shutdown(isc__task_t *task) {
422 * Caller must be holding the task's lock.
427 if (! TASK_SHUTTINGDOWN(task)) {
430 task->flags |= TASK_F_SHUTTINGDOWN;
431 if (task->state == task_state_idle) {
432 INSIST(EMPTY(task->events));
433 task->state = task_state_ready;
436 INSIST(task->state == task_state_ready ||
437 task->state == task_state_running);
442 for (event = TAIL(task->on_shutdown);
446 DEQUEUE(task->on_shutdown, event, ev_link);
447 ENQUEUE(task->events, event, ev_link);
448 task->nevents++;
456 * Moves a task onto the appropriate run queue.
461 task_ready(isc__task_t *task) {
462 isc__taskmgr_t *manager = task->manager;
464 isc_boolean_t has_privilege = isc__task_privilege((isc_task_t *) task);
468 REQUIRE(task->state == task_state_ready);
473 push_readyq(manager, task);
482 task_detach(isc__task_t *task) {
485 * Caller must be holding the task lock.
488 REQUIRE(task->references > 0);
492 task->references--;
493 if (task->references == 0 && task->state == task_state_idle) {
494 INSIST(EMPTY(task->events));
496 * There are no references to this task, and no
498 * either initiate shutdown or clean up the task,
500 * make the task ready and allow run() or the event
503 task->state = task_state_ready;
512 isc__task_t *task;
516 * Detach *taskp from its task.
520 task = (isc__task_t *)*taskp;
521 REQUIRE(VALID_TASK(task));
525 LOCK(&task->lock);
526 was_idle = task_detach(task);
527 UNLOCK(&task->lock);
530 task_ready(task);
536 task_send(isc__task_t *task, isc_event_t **eventp) {
541 * Caller must be holding the task lock.
548 REQUIRE(task->state != task_state_done);
553 if (task->state == task_state_idle) {
555 INSIST(EMPTY(task->events));
556 task->state = task_state_ready;
558 INSIST(task->state == task_state_ready ||
559 task->state == task_state_running);
560 ENQUEUE(task->events, event, ev_link);
561 task->nevents++;
569 isc__task_t *task = (isc__task_t *)task0;
573 * Send '*event' to 'task'.
576 REQUIRE(VALID_TASK(task));
585 LOCK(&task->lock);
586 was_idle = task_send(task, eventp);
587 UNLOCK(&task->lock);
591 * We need to add this task to the ready queue.
593 * We've waited until now to do it because making a task
595 * this while holding the task lock, we could deadlock.
598 * be trying to add this task to the ready queue. The
600 * task. It thus doesn't matter if events are added,
602 * between the time we released the task lock, and the time
603 * we add the task to the ready queue.
605 task_ready(task);
612 isc__task_t *task;
616 * task.
620 task = (isc__task_t *)*taskp;
621 REQUIRE(VALID_TASK(task));
625 LOCK(&task->lock);
626 idle1 = task_send(task, eventp);
627 idle2 = task_detach(task);
628 UNLOCK(&task->lock);
632 * the task lock, and thus the task cannot switch from ready back to
638 task_ready(task);
646 dequeue_events(isc__task_t *task, void *sender, isc_eventtype_t first,
653 REQUIRE(VALID_TASK(task));
666 LOCK(&task->lock);
668 for (event = HEAD(task->events); event != NULL; event = next_event) {
674 DEQUEUE(task->events, event, ev_link);
675 task->nevents--;
681 UNLOCK(&task->lock);
690 isc__task_t *task = (isc__task_t *)task0;
696 * Purge events from a task's event queue.
703 count = dequeue_events(task, sender, first, last, tag, &events,
713 * Note that purging never changes the state of the task.
720 isc__task_purge(isc_task_t *task, void *sender, isc_eventtype_t type,
724 * Purge events from a task's event queue.
729 return (isc__task_purgerange(task, sender, type, type, tag));
734 isc__task_t *task = (isc__task_t *)task0;
738 * Purge 'event' from a task's event queue.
743 REQUIRE(VALID_TASK(task));
746 * If 'event' is on the task's event queue, it will be purged,
748 * on the task's event queue; in fact, it can even be an invalid
749 * pointer. Purging only occurs if the event is actually on the task's
752 * Purging never changes the state of the task.
755 LOCK(&task->lock);
756 for (curr_event = HEAD(task->events);
761 DEQUEUE(task->events, curr_event, ev_link);
762 task->nevents--;
766 UNLOCK(&task->lock);
777 isc__task_unsendrange(isc_task_t *task, void *sender, isc_eventtype_t first,
782 * Remove events from a task's event queue.
787 return (dequeue_events((isc__task_t *)task, sender, first,
792 isc__task_unsend(isc_task_t *task, void *sender, isc_eventtype_t type,
796 * Remove events from a task's event queue.
801 return (dequeue_events((isc__task_t *)task, sender, type,
809 isc__task_t *task = (isc__task_t *)task0;
816 * 'task' is shutdown.
819 REQUIRE(VALID_TASK(task));
822 event = isc_event_allocate(task->manager->mctx,
831 LOCK(&task->lock);
832 if (TASK_SHUTTINGDOWN(task)) {
836 ENQUEUE(task->on_shutdown, event, ev_link);
837 UNLOCK(&task->lock);
840 isc_mem_put(task->manager->mctx, event, sizeof(*event));
847 isc__task_t *task = (isc__task_t *)task0;
851 * Shutdown 'task'.
854 REQUIRE(VALID_TASK(task));
856 LOCK(&task->lock);
857 was_idle = task_shutdown(task);
858 UNLOCK(&task->lock);
861 task_ready(task);
879 isc__task_t *task = (isc__task_t *)task0;
882 * Name 'task'.
885 REQUIRE(VALID_TASK(task));
887 LOCK(&task->lock);
888 strlcpy(task->name, name, sizeof(task->name));
889 task->tag = tag;
890 UNLOCK(&task->lock);
895 isc__task_t *task = (isc__task_t *)task0;
897 REQUIRE(VALID_TASK(task));
899 return (task->name);
904 isc__task_t *task = (isc__task_t *)task0;
906 REQUIRE(VALID_TASK(task));
908 return (task->tag);
913 isc__task_t *task = (isc__task_t *)task0;
915 REQUIRE(VALID_TASK(task));
918 LOCK(&task->lock);
919 *t = task->now;
920 UNLOCK(&task->lock);
925 isc__task_t *task = (isc__task_t *)task0;
927 REQUIRE(VALID_TASK(task));
930 LOCK(&task->lock);
931 *t = task->tnow;
932 UNLOCK(&task->lock);
944 * Caller must hold the task manager lock.
959 * Dequeue and return a pointer to the first task on the current ready
961 * If the task is privileged, dequeue it from the other ready list
964 * Caller must hold the task manager lock.
968 isc__task_t *task;
971 task = HEAD(manager->ready_tasks);
973 task = HEAD(manager->ready_priority_tasks);
975 if (task != NULL) {
976 DEQUEUE(manager->ready_tasks, task, ready_link);
977 if (ISC_LINK_LINKED(task, ready_priority_link))
978 DEQUEUE(manager->ready_priority_tasks, task,
982 return (task);
986 * Push 'task' onto the ready_tasks queue. If 'task' has the privilege
989 * Caller must hold the task manager lock.
992 push_readyq(isc__taskmgr_t *manager, isc__task_t *task) {
993 ENQUEUE(manager->ready_tasks, task, ready_link);
994 if ((task->flags & TASK_F_PRIVILEGED) != 0)
995 ENQUEUE(manager->ready_priority_tasks, task,
1002 isc__task_t *task;
1073 * the task while only holding the manager lock, and then
1074 * change the task to running state while only holding the
1075 * task lock.
1099 task = pop_readyq(manager);
1100 if (task != NULL) {
1107 INSIST(VALID_TASK(task));
1111 * have a task to do. We must reacquire the manager
1112 * lock before exiting the 'if (task != NULL)' block.
1118 LOCK(&task->lock);
1119 INSIST(task->state == task_state_ready);
1120 task->state = task_state_running;
1123 TIME_NOW(&task->tnow);
1124 task->now = isc_time_seconds(&task->tnow);
1126 if (!EMPTY(task->events)) {
1127 event = HEAD(task->events);
1128 DEQUEUE(task->events, event, ev_link);
1129 task->nevents--;
1139 UNLOCK(&task->lock);
1141 (isc_task_t *)task,
1143 LOCK(&task->lock);
1151 if (task->references == 0 &&
1152 EMPTY(task->events) &&
1153 !TASK_SHUTTINGDOWN(task)) {
1158 * pending events for this task,
1168 * the "if EMPTY(task->events)" block
1172 * we want the task to finish.
1175 * will still want the task's
1178 was_idle = task_shutdown(task);
1182 if (EMPTY(task->events)) {
1184 * Nothing else to do for this task
1191 if (task->references == 0 &&
1192 TASK_SHUTTINGDOWN(task)) {
1194 * The task is done.
1202 task->state = task_state_done;
1204 task->state = task_state_idle;
1206 } else if (dispatch_count >= task->quantum) {
1221 task->state = task_state_ready;
1226 UNLOCK(&task->lock);
1229 task_finished(task);
1249 * empty is to 'goto' the 'if (task != NULL)'
1250 * block, avoiding the ENQUEUE of the task
1252 * (since it is the only executable task).
1263 push_readyq(manager, task);
1265 ENQUEUE(new_ready_tasks, task, ready_link);
1266 if ((task->flags & TASK_F_PRIVILEGED) != 0)
1267 ENQUEUE(new_priority_tasks, task,
1357 * Create a new task manager.
1495 isc__task_t *task;
1522 * task manager, it should ask some non-worker thread to call
1528 * Detach the exclusive task before acquiring the manager lock
1541 * task manager lock and a task lock at the same time.
1558 * Post shutdown event(s) to every task (if they haven't already been
1561 for (task = HEAD(manager->tasks);
1562 task != NULL;
1563 task = NEXT(task, link)) {
1564 LOCK(&task->lock);
1565 if (task_shutdown(task))
1566 push_readyq(manager, task);
1567 UNLOCK(&task->lock);
1686 isc__task_t *task = (isc__task_t *) task0;
1689 REQUIRE(VALID_TASK(task));
1718 isc__task_t *task = (isc__task_t *)task0;
1719 isc__taskmgr_t *manager = task->manager;
1721 REQUIRE(task->state == task_state_running);
1723 * TODO REQUIRE(task == task->manager->excl);
1724 * it should be here, it fails on shutdown server->task
1746 isc__task_t *task = (isc__task_t *)task0;
1747 isc__taskmgr_t *manager = task->manager;
1749 REQUIRE(task->state == task_state_running);
1762 isc__task_t *task = (isc__task_t *)task0;
1763 isc__taskmgr_t *manager = task->manager;
1766 LOCK(&task->lock);
1767 oldpriv = ISC_TF((task->flags & TASK_F_PRIVILEGED) != 0);
1769 task->flags |= TASK_F_PRIVILEGED;
1771 task->flags &= ~TASK_F_PRIVILEGED;
1772 UNLOCK(&task->lock);
1778 if (priv && ISC_LINK_LINKED(task, ready_link))
1779 ENQUEUE(manager->ready_priority_tasks, task,
1781 else if (!priv && ISC_LINK_LINKED(task, ready_priority_link))
1782 DEQUEUE(manager->ready_priority_tasks, task,
1789 isc__task_t *task = (isc__task_t *)task0;
1792 LOCK(&task->lock);
1793 priv = ISC_TF((task->flags & TASK_F_PRIVILEGED) != 0);
1794 UNLOCK(&task->lock);
1805 isc__task_t *task = (isc__task_t *)t;
1807 REQUIRE(VALID_TASK(task));
1808 return (TASK_SHUTTINGDOWN(task));
1817 isc__task_t *task = NULL;
1861 task = ISC_LIST_HEAD(mgr->tasks);
1862 while (task != NULL) {
1863 LOCK(&task->lock);
1864 TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "task"));
1866 if (task->name[0] != 0) {
1870 task->name));
1877 task->references));
1881 TRY0(xmlTextWriterWriteFormatString(writer, "%p", task));
1886 statenames[task->state]));
1891 task->quantum));
1896 task->nevents));
1901 UNLOCK(&task->lock);
1902 task = ISC_LIST_NEXT(task, link);
1907 if (task != NULL)
1908 UNLOCK(&task->lock);
1927 isc__task_t *task = NULL;
1969 for (task = ISC_LIST_HEAD(mgr->tasks);
1970 task != NULL;
1971 task = ISC_LIST_NEXT(task, link))
1975 LOCK(&task->lock);
1981 snprintf(buf, sizeof(buf), "%p", task);
1986 if (task->name[0] != 0) {
1987 obj = json_object_new_string(task->name);
1992 obj = json_object_new_int(task->references);
1996 obj = json_object_new_string(statenames[task->state]);
2000 obj = json_object_new_int(task->quantum);
2004 obj = json_object_new_int(task->nevents);
2008 UNLOCK(&task->lock);
2019 if (task != NULL)
2020 UNLOCK(&task->lock);
2165 isc_task_send(isc_task_t *task, isc_event_t **eventp) {
2166 REQUIRE(ISCAPI_TASK_VALID(task));
2170 isc__task_send(task, eventp);
2172 task->methods->send(task, eventp);
2193 isc_task_unsend(isc_task_t *task, void *sender, isc_eventtype_t type,
2196 REQUIRE(ISCAPI_TASK_VALID(task));
2199 return (isc__task_unsend(task, sender, type, tag, events));
2201 return (task->methods->unsend(task, sender, type, tag, events));
2205 isc_task_onshutdown(isc_task_t *task, isc_taskaction_t action, void *arg)
2207 REQUIRE(ISCAPI_TASK_VALID(task));
2210 return (isc__task_onshutdown(task, action, arg));
2212 return (task->methods->onshutdown(task, action, arg));
2216 isc_task_shutdown(isc_task_t *task) {
2217 REQUIRE(ISCAPI_TASK_VALID(task));
2220 isc__task_shutdown(task);
2222 task->methods->shutdown(task);
2234 isc_task_setname(isc_task_t *task, const char *name, void *tag) {
2235 REQUIRE(ISCAPI_TASK_VALID(task));
2238 isc__task_setname(task, name, tag);
2240 task->methods->setname(task, name, tag);
2244 isc_task_purge(isc_task_t *task, void *sender, isc_eventtype_t type, void *tag)
2246 REQUIRE(ISCAPI_TASK_VALID(task));
2249 return (isc__task_purge(task, sender, type, tag));
2251 return (task->methods->purgeevents(task, sender, type, tag));
2255 isc_task_beginexclusive(isc_task_t *task) {
2256 REQUIRE(ISCAPI_TASK_VALID(task));
2259 return (isc__task_beginexclusive(task));
2261 return (task->methods->beginexclusive(task));
2265 isc_task_endexclusive(isc_task_t *task) {
2266 REQUIRE(ISCAPI_TASK_VALID(task));
2269 isc__task_endexclusive(task);
2271 task->methods->endexclusive(task);
2275 isc_task_setprivilege(isc_task_t *task, isc_boolean_t priv) {
2276 REQUIRE(ISCAPI_TASK_VALID(task));
2279 isc__task_setprivilege(task, priv);
2281 task->methods->setprivilege(task, priv);
2285 isc_task_privilege(isc_task_t *task) {
2286 REQUIRE(ISCAPI_TASK_VALID(task));
2289 return (isc__task_privilege(task));
2291 return (task->methods->privilege(task));
2295 isc_task_getcurrenttime(isc_task_t *task, isc_stdtime_t *t) {
2299 isc__task_getcurrenttime(task, t);
2303 isc_task_getcurrenttimex(isc_task_t *task, isc_time_t *t) {
2307 isc__task_getcurrenttimex(task, t);
2315 isc_task_purgerange(isc_task_t *task, void *sender, isc_eventtype_t first,
2318 REQUIRE(ISCAPI_TASK_VALID(task));
2321 return (isc__task_purgerange(task, sender, first, last, tag));
2323 return (task->methods->purgerange(task, sender, first, last, tag));