Lines Matching full:task

25  * XXXRTH  Need to document the states a task can be in, and the rules
38 #include <isc/task.h>
51 * when built without threads we share a single global task manager and use
52 * an integrated event loop for socket, timer, and other generic task events.
54 * we don't use either of them: an application can have multiple task managers
70 #define XTRACE(m) fprintf(stderr, "task %p thread %lu: %s\n", \
71 task, isc_thread_self(), (m))
72 #define XTTRACE(t, m) fprintf(stderr, "task %p thread %lu: %s\n", \
108 /* Locked by task lock. */
118 /* Locked by task manager lock. */
144 /* Locked by task manager lock. */
197 isc__task_purge(isc_task_t *task, void *sender, isc_eventtype_t type,
202 isc__task_unsendrange(isc_task_t *task, void *sender, isc_eventtype_t first,
206 isc__task_unsend(isc_task_t *task, void *sender, isc_eventtype_t type,
229 isc__task_beginexclusive(isc_task_t *task);
248 push_readyq(isc__taskmgr_t *manager, isc__task_t *task);
297 task_finished(isc__task_t *task) { in task_finished() argument
298 isc__taskmgr_t *manager = task->manager; in task_finished()
300 REQUIRE(EMPTY(task->events)); in task_finished()
301 REQUIRE(EMPTY(task->on_shutdown)); in task_finished()
302 REQUIRE(task->references == 0); in task_finished()
303 REQUIRE(task->state == task_state_done); in task_finished()
308 UNLINK(manager->tasks, task, link); in task_finished()
313 * task manager is exiting. Wake up in task_finished()
322 DESTROYLOCK(&task->lock); in task_finished()
323 task->common.impmagic = 0; in task_finished()
324 task->common.magic = 0; in task_finished()
325 isc_mem_put(manager->mctx, task, sizeof(*task)); in task_finished()
333 isc__task_t *task; in isc__task_create() local
340 task = isc_mem_get(manager->mctx, sizeof(*task)); in isc__task_create()
341 if (task == NULL) in isc__task_create()
344 result = isc_mutex_init(&task->lock); in isc__task_create()
346 isc_mem_put(manager->mctx, task, sizeof(*task)); in isc__task_create()
350 LOCK(&task->lock); /* helps coverity analysis noise ratio */ in isc__task_create()
351 task->manager = manager; in isc__task_create()
352 task->state = task_state_idle; in isc__task_create()
353 task->references = 1; in isc__task_create()
354 INIT_LIST(task->events); in isc__task_create()
355 INIT_LIST(task->on_shutdown); in isc__task_create()
356 task->quantum = quantum; in isc__task_create()
357 task->flags = 0; in isc__task_create()
358 task->now = 0; in isc__task_create()
359 memset(task->name, 0, sizeof(task->name)); in isc__task_create()
360 task->tag = NULL; in isc__task_create()
361 INIT_LINK(task, link); in isc__task_create()
362 INIT_LINK(task, ready_link); in isc__task_create()
363 INIT_LINK(task, ready_priority_link); in isc__task_create()
364 UNLOCK(&task->lock); in isc__task_create()
370 if (task->quantum == 0) in isc__task_create()
371 task->quantum = manager->default_quantum; in isc__task_create()
372 APPEND(manager->tasks, task, link); in isc__task_create()
378 DESTROYLOCK(&task->lock); in isc__task_create()
379 isc_mem_put(manager->mctx, task, sizeof(*task)); in isc__task_create()
383 task->common.methods = (isc_taskmethods_t *)&taskmethods; in isc__task_create()
384 task->common.magic = ISCAPI_TASK_MAGIC; in isc__task_create()
385 task->common.impmagic = TASK_MAGIC; in isc__task_create()
386 *taskp = (isc_task_t *)task; in isc__task_create()
412 task_shutdown(isc__task_t *task) { in task_shutdown() argument
417 * Caller must be holding the task's lock. in task_shutdown()
422 if (! TASK_SHUTTINGDOWN(task)) { in task_shutdown()
425 task->flags |= TASK_F_SHUTTINGDOWN; in task_shutdown()
426 if (task->state == task_state_idle) { in task_shutdown()
427 INSIST(EMPTY(task->events)); in task_shutdown()
428 task->state = task_state_ready; in task_shutdown()
431 INSIST(task->state == task_state_ready || in task_shutdown()
432 task->state == task_state_running); in task_shutdown()
437 for (event = TAIL(task->on_shutdown); in task_shutdown()
441 DEQUEUE(task->on_shutdown, event, ev_link); in task_shutdown()
442 ENQUEUE(task->events, event, ev_link); in task_shutdown()
450 * Moves a task onto the appropriate run queue.
455 task_ready(isc__task_t *task) { in task_ready() argument
456 isc__taskmgr_t *manager = task->manager; in task_ready()
458 isc_boolean_t has_privilege = isc__task_privilege((isc_task_t *) task); in task_ready()
462 REQUIRE(task->state == task_state_ready); in task_ready()
467 push_readyq(manager, task); in task_ready()
476 task_detach(isc__task_t *task) { in task_detach() argument
479 * Caller must be holding the task lock. in task_detach()
482 REQUIRE(task->references > 0); in task_detach()
486 task->references--; in task_detach()
487 if (task->references == 0 && task->state == task_state_idle) { in task_detach()
488 INSIST(EMPTY(task->events)); in task_detach()
490 * There are no references to this task, and no in task_detach()
492 * either initiate shutdown or clean up the task, in task_detach()
494 * make the task ready and allow run() or the event in task_detach()
497 task->state = task_state_ready; in task_detach()
506 isc__task_t *task; in isc__task_detach() local
510 * Detach *taskp from its task. in isc__task_detach()
514 task = (isc__task_t *)*taskp; in isc__task_detach()
515 REQUIRE(VALID_TASK(task)); in isc__task_detach()
519 LOCK(&task->lock); in isc__task_detach()
520 was_idle = task_detach(task); in isc__task_detach()
521 UNLOCK(&task->lock); in isc__task_detach()
524 task_ready(task); in isc__task_detach()
530 task_send(isc__task_t *task, isc_event_t **eventp) { in task_send() argument
535 * Caller must be holding the task lock. in task_send()
542 REQUIRE(task->state != task_state_done); in task_send()
546 if (task->state == task_state_idle) { in task_send()
548 INSIST(EMPTY(task->events)); in task_send()
549 task->state = task_state_ready; in task_send()
551 INSIST(task->state == task_state_ready || in task_send()
552 task->state == task_state_running); in task_send()
553 ENQUEUE(task->events, event, ev_link); in task_send()
561 isc__task_t *task = (isc__task_t *)task0; in isc__task_send() local
565 * Send '*event' to 'task'. in isc__task_send()
568 REQUIRE(VALID_TASK(task)); in isc__task_send()
577 LOCK(&task->lock); in isc__task_send()
578 was_idle = task_send(task, eventp); in isc__task_send()
579 UNLOCK(&task->lock); in isc__task_send()
583 * We need to add this task to the ready queue. in isc__task_send()
585 * We've waited until now to do it because making a task in isc__task_send()
587 * this while holding the task lock, we could deadlock. in isc__task_send()
590 * be trying to add this task to the ready queue. The in isc__task_send()
592 * task. It thus doesn't matter if events are added, in isc__task_send()
594 * between the time we released the task lock, and the time in isc__task_send()
595 * we add the task to the ready queue. in isc__task_send()
597 task_ready(task); in isc__task_send()
604 isc__task_t *task; in isc__task_sendanddetach() local
608 * task. in isc__task_sendanddetach()
612 task = (isc__task_t *)*taskp; in isc__task_sendanddetach()
613 REQUIRE(VALID_TASK(task)); in isc__task_sendanddetach()
617 LOCK(&task->lock); in isc__task_sendanddetach()
618 idle1 = task_send(task, eventp); in isc__task_sendanddetach()
619 idle2 = task_detach(task); in isc__task_sendanddetach()
620 UNLOCK(&task->lock); in isc__task_sendanddetach()
624 * the task lock, and thus the task cannot switch from ready back to in isc__task_sendanddetach()
630 task_ready(task); in isc__task_sendanddetach()
638 dequeue_events(isc__task_t *task, void *sender, isc_eventtype_t first, in dequeue_events() argument
645 REQUIRE(VALID_TASK(task)); in dequeue_events()
658 LOCK(&task->lock); in dequeue_events()
660 for (event = HEAD(task->events); event != NULL; event = next_event) { in dequeue_events()
666 DEQUEUE(task->events, event, ev_link); in dequeue_events()
672 UNLOCK(&task->lock); in dequeue_events()
681 isc__task_t *task = (isc__task_t *)task0; in isc__task_purgerange() local
687 * Purge events from a task's event queue. in isc__task_purgerange()
694 count = dequeue_events(task, sender, first, last, tag, &events, in isc__task_purgerange()
703 * Note that purging never changes the state of the task. in isc__task_purgerange()
710 isc__task_purge(isc_task_t *task, void *sender, isc_eventtype_t type, in isc__task_purge() argument
714 * Purge events from a task's event queue. in isc__task_purge()
719 return (isc__task_purgerange(task, sender, type, type, tag)); in isc__task_purge()
724 isc__task_t *task = (isc__task_t *)task0; in isc__task_purgeevent() local
728 * Purge 'event' from a task's event queue. in isc__task_purgeevent()
733 REQUIRE(VALID_TASK(task)); in isc__task_purgeevent()
736 * If 'event' is on the task's event queue, it will be purged, in isc__task_purgeevent()
738 * on the task's event queue; in fact, it can even be an invalid in isc__task_purgeevent()
739 * pointer. Purging only occurs if the event is actually on the task's in isc__task_purgeevent()
742 * Purging never changes the state of the task. in isc__task_purgeevent()
745 LOCK(&task->lock); in isc__task_purgeevent()
746 for (curr_event = HEAD(task->events); in isc__task_purgeevent()
751 DEQUEUE(task->events, curr_event, ev_link); in isc__task_purgeevent()
755 UNLOCK(&task->lock); in isc__task_purgeevent()
766 isc__task_unsendrange(isc_task_t *task, void *sender, isc_eventtype_t first, in isc__task_unsendrange() argument
771 * Remove events from a task's event queue. in isc__task_unsendrange()
776 return (dequeue_events((isc__task_t *)task, sender, first, in isc__task_unsendrange()
781 isc__task_unsend(isc_task_t *task, void *sender, isc_eventtype_t type, in isc__task_unsend() argument
785 * Remove events from a task's event queue. in isc__task_unsend()
790 return (dequeue_events((isc__task_t *)task, sender, type, in isc__task_unsend()
798 isc__task_t *task = (isc__task_t *)task0; in isc__task_onshutdown() local
805 * 'task' is shutdown. in isc__task_onshutdown()
808 REQUIRE(VALID_TASK(task)); in isc__task_onshutdown()
811 event = isc_event_allocate(task->manager->mctx, in isc__task_onshutdown()
820 LOCK(&task->lock); in isc__task_onshutdown()
821 if (TASK_SHUTTINGDOWN(task)) { in isc__task_onshutdown()
825 ENQUEUE(task->on_shutdown, event, ev_link); in isc__task_onshutdown()
826 UNLOCK(&task->lock); in isc__task_onshutdown()
829 isc_mem_put(task->manager->mctx, event, sizeof(*event)); in isc__task_onshutdown()
836 isc__task_t *task = (isc__task_t *)task0; in isc__task_shutdown() local
840 * Shutdown 'task'. in isc__task_shutdown()
843 REQUIRE(VALID_TASK(task)); in isc__task_shutdown()
845 LOCK(&task->lock); in isc__task_shutdown()
846 was_idle = task_shutdown(task); in isc__task_shutdown()
847 UNLOCK(&task->lock); in isc__task_shutdown()
850 task_ready(task); in isc__task_shutdown()
868 isc__task_t *task = (isc__task_t *)task0; in isc__task_setname() local
871 * Name 'task'. in isc__task_setname()
874 REQUIRE(VALID_TASK(task)); in isc__task_setname()
876 LOCK(&task->lock); in isc__task_setname()
877 memset(task->name, 0, sizeof(task->name)); in isc__task_setname()
878 strncpy(task->name, name, sizeof(task->name) - 1); in isc__task_setname()
879 task->tag = tag; in isc__task_setname()
880 UNLOCK(&task->lock); in isc__task_setname()
885 isc__task_t *task = (isc__task_t *)task0; in isc__task_getname() local
887 REQUIRE(VALID_TASK(task)); in isc__task_getname()
889 return (task->name); in isc__task_getname()
894 isc__task_t *task = (isc__task_t *)task0; in isc__task_gettag() local
896 REQUIRE(VALID_TASK(task)); in isc__task_gettag()
898 return (task->tag); in isc__task_gettag()
903 isc__task_t *task = (isc__task_t *)task0; in isc__task_getcurrenttime() local
905 REQUIRE(VALID_TASK(task)); in isc__task_getcurrenttime()
908 LOCK(&task->lock); in isc__task_getcurrenttime()
909 *t = task->now; in isc__task_getcurrenttime()
910 UNLOCK(&task->lock); in isc__task_getcurrenttime()
914 *** Task Manager.
922 * Caller must hold the task manager lock.
937 * Dequeue and return a pointer to the first task on the current ready
939 * If the task is privileged, dequeue it from the other ready list
942 * Caller must hold the task manager lock.
946 isc__task_t *task; in pop_readyq() local
949 task = HEAD(manager->ready_tasks); in pop_readyq()
951 task = HEAD(manager->ready_priority_tasks); in pop_readyq()
953 if (task != NULL) { in pop_readyq()
954 DEQUEUE(manager->ready_tasks, task, ready_link); in pop_readyq()
955 if (ISC_LINK_LINKED(task, ready_priority_link)) in pop_readyq()
956 DEQUEUE(manager->ready_priority_tasks, task, in pop_readyq()
960 return (task); in pop_readyq()
964 * Push 'task' onto the ready_tasks queue. If 'task' has the privilege
967 * Caller must hold the task manager lock.
970 push_readyq(isc__taskmgr_t *manager, isc__task_t *task) { in push_readyq() argument
971 ENQUEUE(manager->ready_tasks, task, ready_link); in push_readyq()
972 if ((task->flags & TASK_F_PRIVILEGED) != 0) in push_readyq()
973 ENQUEUE(manager->ready_priority_tasks, task, in push_readyq()
979 isc__task_t *task; in dispatch() local
1049 * the task while only holding the manager lock, and then in dispatch()
1050 * change the task to running state while only holding the in dispatch()
1051 * task lock. in dispatch()
1075 task = pop_readyq(manager); in dispatch()
1076 if (task != NULL) { in dispatch()
1083 INSIST(VALID_TASK(task)); in dispatch()
1087 * have a task to do. We must reacquire the manager in dispatch()
1088 * lock before exiting the 'if (task != NULL)' block. in dispatch()
1093 LOCK(&task->lock); in dispatch()
1094 INSIST(task->state == task_state_ready); in dispatch()
1095 task->state = task_state_running; in dispatch()
1098 isc_stdtime_get(&task->now); in dispatch()
1100 if (!EMPTY(task->events)) { in dispatch()
1101 event = HEAD(task->events); in dispatch()
1102 DEQUEUE(task->events, event, ev_link); in dispatch()
1112 UNLOCK(&task->lock); in dispatch()
1114 (isc_task_t *)task, in dispatch()
1116 LOCK(&task->lock); in dispatch()
1124 if (task->references == 0 && in dispatch()
1125 EMPTY(task->events) && in dispatch()
1126 !TASK_SHUTTINGDOWN(task)) { in dispatch()
1131 * pending events for this task, in dispatch()
1141 * the "if EMPTY(task->events)" block in dispatch()
1145 * we want the task to finish. in dispatch()
1148 * will still want the task's in dispatch()
1151 was_idle = task_shutdown(task); in dispatch()
1155 if (EMPTY(task->events)) { in dispatch()
1157 * Nothing else to do for this task in dispatch()
1164 if (task->references == 0 && in dispatch()
1165 TASK_SHUTTINGDOWN(task)) { in dispatch()
1167 * The task is done. in dispatch()
1175 task->state = task_state_done; in dispatch()
1177 task->state = task_state_idle; in dispatch()
1179 } else if (dispatch_count >= task->quantum) { in dispatch()
1194 task->state = task_state_ready; in dispatch()
1199 UNLOCK(&task->lock); in dispatch()
1202 task_finished(task); in dispatch()
1222 * empty is to 'goto' the 'if (task != NULL)' in dispatch()
1223 * block, avoiding the ENQUEUE of the task in dispatch()
1225 * (since it is the only executable task). in dispatch()
1236 push_readyq(manager, task); in dispatch()
1238 ENQUEUE(new_ready_tasks, task, ready_link); in dispatch()
1239 if ((task->flags & TASK_F_PRIVILEGED) != 0) in dispatch()
1240 ENQUEUE(new_priority_tasks, task, in dispatch()
1329 * Create a new task manager. in isc__taskmgr_create()
1458 isc__task_t *task; in isc__taskmgr_destroy() local
1485 * task manager, it should ask some non-worker thread to call in isc__taskmgr_destroy()
1496 * task manager lock and a task lock at the same time. in isc__taskmgr_destroy()
1513 * Post shutdown event(s) to every task (if they haven't already been in isc__taskmgr_destroy()
1516 for (task = HEAD(manager->tasks); in isc__taskmgr_destroy()
1517 task != NULL; in isc__taskmgr_destroy()
1518 task = NEXT(task, link)) { in isc__taskmgr_destroy()
1519 LOCK(&task->lock); in isc__taskmgr_destroy()
1520 if (task_shutdown(task)) in isc__taskmgr_destroy()
1521 push_readyq(manager, task); in isc__taskmgr_destroy()
1522 UNLOCK(&task->lock); in isc__taskmgr_destroy()
1643 isc__task_t *task = (isc__task_t *)task0; in isc__task_beginexclusive() local
1644 isc__taskmgr_t *manager = task->manager; in isc__task_beginexclusive()
1645 REQUIRE(task->state == task_state_running); in isc__task_beginexclusive()
1665 isc__task_t *task = (isc__task_t *)task0; in isc__task_endexclusive() local
1666 isc__taskmgr_t *manager = task->manager; in isc__task_endexclusive()
1668 REQUIRE(task->state == task_state_running); in isc__task_endexclusive()
1681 isc__task_t *task = (isc__task_t *)task0; in isc__task_setprivilege() local
1682 isc__taskmgr_t *manager = task->manager; in isc__task_setprivilege()
1685 LOCK(&task->lock); in isc__task_setprivilege()
1686 oldpriv = ISC_TF((task->flags & TASK_F_PRIVILEGED) != 0); in isc__task_setprivilege()
1688 task->flags |= TASK_F_PRIVILEGED; in isc__task_setprivilege()
1690 task->flags &= ~TASK_F_PRIVILEGED; in isc__task_setprivilege()
1691 UNLOCK(&task->lock); in isc__task_setprivilege()
1697 if (priv && ISC_LINK_LINKED(task, ready_link)) in isc__task_setprivilege()
1698 ENQUEUE(manager->ready_priority_tasks, task, in isc__task_setprivilege()
1700 else if (!priv && ISC_LINK_LINKED(task, ready_priority_link)) in isc__task_setprivilege()
1701 DEQUEUE(manager->ready_priority_tasks, task, in isc__task_setprivilege()
1708 isc__task_t *task = (isc__task_t *)task0; in isc__task_privilege() local
1711 LOCK(&task->lock); in isc__task_privilege()
1712 priv = ISC_TF((task->flags & TASK_F_PRIVILEGED) != 0); in isc__task_privilege()
1713 UNLOCK(&task->lock); in isc__task_privilege()
1726 isc__task_t *task = (isc__task_t *)t; in isc_task_exiting() local
1728 REQUIRE(VALID_TASK(task)); in isc_task_exiting()
1729 return (TASK_SHUTTINGDOWN(task)); in isc_task_exiting()
1737 isc__task_t *task; in isc_taskmgr_renderxml() local
1775 task = ISC_LIST_HEAD(mgr->tasks); in isc_taskmgr_renderxml()
1776 while (task != NULL) { in isc_taskmgr_renderxml()
1777 LOCK(&task->lock); in isc_taskmgr_renderxml()
1778 xmlTextWriterStartElement(writer, ISC_XMLCHAR "task"); in isc_taskmgr_renderxml()
1780 if (task->name[0] != 0) { in isc_taskmgr_renderxml()
1783 task->name); in isc_taskmgr_renderxml()
1788 xmlTextWriterWriteFormatString(writer, "%d", task->references); in isc_taskmgr_renderxml()
1792 xmlTextWriterWriteFormatString(writer, "%p", task); in isc_taskmgr_renderxml()
1797 statenames[task->state]); in isc_taskmgr_renderxml()
1801 xmlTextWriterWriteFormatString(writer, "%d", task->quantum); in isc_taskmgr_renderxml()
1806 UNLOCK(&task->lock); in isc_taskmgr_renderxml()
1807 task = ISC_LIST_NEXT(task, link); in isc_taskmgr_renderxml()