Lines Matching refs:task

18 /* $Id: task.c,v 1.107 2008/03/27 23:46:57 tbox Exp $ */
25 * XXXRTH Need to document the states a task can be in, and the rules
38 #include <isc/task.h>
48 #define XTRACE(m) fprintf(stderr, "task %p thread %lu: %s\n", \
49 task, isc_thread_self(), (m))
50 #define XTTRACE(t, m) fprintf(stderr, "task %p thread %lu: %s\n", \
83 /* Locked by task lock. */
93 /* Locked by task manager lock. */
115 /* Locked by task manager lock. */
144 task_finished(isc_task_t *task) {
145 isc_taskmgr_t *manager = task->manager;
147 REQUIRE(EMPTY(task->events));
148 REQUIRE(EMPTY(task->on_shutdown));
149 REQUIRE(task->references == 0);
150 REQUIRE(task->state == task_state_done);
155 UNLINK(manager->tasks, task, link);
160 * task manager is exiting. Wake up
169 DESTROYLOCK(&task->lock);
170 task->magic = 0;
171 isc_mem_put(manager->mctx, task, sizeof(*task));
178 isc_task_t *task;
185 task = isc_mem_get(manager->mctx, sizeof(*task));
186 if (task == NULL)
189 task->manager = manager;
190 result = isc_mutex_init(&task->lock);
192 isc_mem_put(manager->mctx, task, sizeof(*task));
195 task->state = task_state_idle;
196 task->references = 1;
197 INIT_LIST(task->events);
198 INIT_LIST(task->on_shutdown);
199 task->quantum = quantum;
200 task->flags = 0;
201 task->now = 0;
202 memset(task->name, 0, sizeof(task->name));
203 task->tag = NULL;
204 INIT_LINK(task, link);
205 INIT_LINK(task, ready_link);
210 if (task->quantum == 0)
211 task->quantum = manager->default_quantum;
212 APPEND(manager->tasks, task, link);
218 DESTROYLOCK(&task->lock);
219 isc_mem_put(manager->mctx, task, sizeof(*task));
223 task->magic = TASK_MAGIC;
224 *taskp = task;
249 task_shutdown(isc_task_t *task) {
254 * Caller must be holding the task's lock.
259 if (! TASK_SHUTTINGDOWN(task)) {
262 task->flags |= TASK_F_SHUTTINGDOWN;
263 if (task->state == task_state_idle) {
264 INSIST(EMPTY(task->events));
265 task->state = task_state_ready;
268 INSIST(task->state == task_state_ready ||
269 task->state == task_state_running);
273 for (event = TAIL(task->on_shutdown);
277 DEQUEUE(task->on_shutdown, event, ev_link);
278 ENQUEUE(task->events, event, ev_link);
286 task_ready(isc_task_t *task) {
287 isc_taskmgr_t *manager = task->manager;
290 REQUIRE(task->state == task_state_ready);
296 ENQUEUE(manager->ready_tasks, task, ready_link);
305 task_detach(isc_task_t *task) {
308 * Caller must be holding the task lock.
311 REQUIRE(task->references > 0);
315 task->references--;
316 if (task->references == 0 && task->state == task_state_idle) {
317 INSIST(EMPTY(task->events));
319 * There are no references to this task, and no
321 * either initiate shutdown or clean up the task,
323 * make the task ready and allow run() or the event
326 task->state = task_state_ready;
335 isc_task_t *task;
339 * Detach *taskp from its task.
343 task = *taskp;
344 REQUIRE(VALID_TASK(task));
348 LOCK(&task->lock);
349 was_idle = task_detach(task);
350 UNLOCK(&task->lock);
353 task_ready(task);
359 task_send(isc_task_t *task, isc_event_t **eventp) {
364 * Caller must be holding the task lock.
371 REQUIRE(task->state != task_state_done);
375 if (task->state == task_state_idle) {
377 INSIST(EMPTY(task->events));
378 task->state = task_state_ready;
380 INSIST(task->state == task_state_ready ||
381 task->state == task_state_running);
382 ENQUEUE(task->events, event, ev_link);
389 isc_task_send(isc_task_t *task, isc_event_t **eventp) {
393 * Send '*event' to 'task'.
396 REQUIRE(VALID_TASK(task));
405 LOCK(&task->lock);
406 was_idle = task_send(task, eventp);
407 UNLOCK(&task->lock);
411 * We need to add this task to the ready queue.
413 * We've waited until now to do it because making a task
415 * this while holding the task lock, we could deadlock.
418 * be trying to add this task to the ready queue. The
420 * task. It thus doesn't matter if events are added,
422 * between the time we released the task lock, and the time
423 * we add the task to the ready queue.
425 task_ready(task);
432 isc_task_t *task;
436 * task.
440 task = *taskp;
441 REQUIRE(VALID_TASK(task));
445 LOCK(&task->lock);
446 idle1 = task_send(task, eventp);
447 idle2 = task_detach(task);
448 UNLOCK(&task->lock);
452 * the task lock, and thus the task cannot switch from ready back to
458 task_ready(task);
466 dequeue_events(isc_task_t *task, void *sender, isc_eventtype_t first,
473 REQUIRE(VALID_TASK(task));
486 LOCK(&task->lock);
488 for (event = HEAD(task->events); event != NULL; event = next_event) {
494 DEQUEUE(task->events, event, ev_link);
500 UNLOCK(&task->lock);
506 isc_task_purgerange(isc_task_t *task, void *sender, isc_eventtype_t first,
514 * Purge events from a task's event queue.
521 count = dequeue_events(task, sender, first, last, tag, &events,
530 * Note that purging never changes the state of the task.
537 isc_task_purge(isc_task_t *task, void *sender, isc_eventtype_t type,
541 * Purge events from a task's event queue.
546 return (isc_task_purgerange(task, sender, type, type, tag));
550 isc_task_purgeevent(isc_task_t *task, isc_event_t *event) {
554 * Purge 'event' from a task's event queue.
559 REQUIRE(VALID_TASK(task));
562 * If 'event' is on the task's event queue, it will be purged,
564 * on the task's event queue; in fact, it can even be an invalid
565 * pointer. Purging only occurs if the event is actually on the task's
568 * Purging never changes the state of the task.
571 LOCK(&task->lock);
572 for (curr_event = HEAD(task->events);
577 DEQUEUE(task->events, curr_event, ev_link);
581 UNLOCK(&task->lock);
592 isc_task_unsendrange(isc_task_t *task, void *sender, isc_eventtype_t first,
597 * Remove events from a task's event queue.
602 return (dequeue_events(task, sender, first, last, tag, events,
607 isc_task_unsend(isc_task_t *task, void *sender, isc_eventtype_t type,
611 * Remove events from a task's event queue.
616 return (dequeue_events(task, sender, type, type, tag, events,
621 isc_task_onshutdown(isc_task_t *task, isc_taskaction_t action, const void *arg)
629 * 'task' is shutdown.
632 REQUIRE(VALID_TASK(task));
635 event = isc_event_allocate(task->manager->mctx,
644 LOCK(&task->lock);
645 if (TASK_SHUTTINGDOWN(task)) {
649 ENQUEUE(task->on_shutdown, event, ev_link);
650 UNLOCK(&task->lock);
653 isc_mem_put(task->manager->mctx, event, sizeof(*event));
659 isc_task_shutdown(isc_task_t *task) {
663 * Shutdown 'task'.
666 REQUIRE(VALID_TASK(task));
668 LOCK(&task->lock);
669 was_idle = task_shutdown(task);
670 UNLOCK(&task->lock);
673 task_ready(task);
690 isc_task_setname(isc_task_t *task, const char *name, void *tag) {
693 * Name 'task'.
696 REQUIRE(VALID_TASK(task));
698 LOCK(&task->lock);
699 memset(task->name, 0, sizeof(task->name));
700 strncpy(task->name, name, sizeof(task->name) - 1);
701 task->tag = tag;
702 UNLOCK(&task->lock);
706 isc_task_getname(isc_task_t *task) {
707 return (task->name);
711 isc_task_gettag(isc_task_t *task) {
712 return (task->tag);
716 isc_task_getcurrenttime(isc_task_t *task, isc_stdtime_t *t) {
717 REQUIRE(VALID_TASK(task));
720 LOCK(&task->lock);
722 *t = task->now;
724 UNLOCK(&task->lock);
732 isc_task_t *task;
799 * the task while only holding the manager lock, and then
800 * change the task to running state while only holding the
801 * task lock.
823 task = HEAD(manager->ready_tasks);
824 if (task != NULL) {
831 INSIST(VALID_TASK(task));
835 * have a task to do. We must reacquire the manager
836 * lock before exiting the 'if (task != NULL)' block.
838 DEQUEUE(manager->ready_tasks, task, ready_link);
842 LOCK(&task->lock);
843 INSIST(task->state == task_state_ready);
844 task->state = task_state_running;
847 isc_stdtime_get(&task->now);
849 if (!EMPTY(task->events)) {
850 event = HEAD(task->events);
851 DEQUEUE(task->events, event, ev_link);
861 UNLOCK(&task->lock);
862 (event->ev_action)(task,event);
863 LOCK(&task->lock);
871 if (task->references == 0 &&
872 EMPTY(task->events) &&
873 !TASK_SHUTTINGDOWN(task)) {
878 * pending events for this task,
888 * the "if EMPTY(task->events)" block
892 * we want the task to finish.
895 * will still want the task's
898 was_idle = task_shutdown(task);
902 if (EMPTY(task->events)) {
904 * Nothing else to do for this task
911 if (task->references == 0 &&
912 TASK_SHUTTINGDOWN(task)) {
914 * The task is done.
922 task->state = task_state_done;
924 task->state = task_state_idle;
926 } else if (dispatch_count >= task->quantum) {
941 task->state = task_state_ready;
946 UNLOCK(&task->lock);
949 task_finished(task);
966 * empty is to 'goto' the 'if (task != NULL)'
967 * block, avoiding the ENQUEUE of the task
969 * (since it is the only executable task).
980 ENQUEUE(manager->ready_tasks, task,
983 ENQUEUE(ready_tasks, task, ready_link);
1039 * Create a new task manager.
1147 isc_task_t *task;
1172 * task manager, it should ask some non-worker thread to call
1183 * task manager lock and a task lock at the same time.
1195 * Post shutdown event(s) to every task (if they haven't already been
1198 for (task = HEAD(manager->tasks);
1199 task != NULL;
1200 task = NEXT(task, link)) {
1201 LOCK(&task->lock);
1202 if (task_shutdown(task))
1203 ENQUEUE(manager->ready_tasks, task, ready_link);
1204 UNLOCK(&task->lock);
1260 isc_task_beginexclusive(isc_task_t *task) {
1262 isc_taskmgr_t *manager = task->manager;
1263 REQUIRE(task->state == task_state_running);
1275 UNUSED(task);
1281 isc_task_endexclusive(isc_task_t *task) {
1283 isc_taskmgr_t *manager = task->manager;
1284 REQUIRE(task->state == task_state_running);
1291 UNUSED(task);
1300 isc_task_t *task;
1338 task = ISC_LIST_HEAD(mgr->tasks);
1339 while (task != NULL) {
1340 LOCK(&task->lock);
1341 xmlTextWriterStartElement(writer, ISC_XMLCHAR "task");
1343 if (task->name[0] != 0) {
1346 task->name);
1351 xmlTextWriterWriteFormatString(writer, "%d", task->references);
1355 xmlTextWriterWriteFormatString(writer, "%p", task);
1360 statenames[task->state]);
1364 xmlTextWriterWriteFormatString(writer, "%d", task->quantum);
1369 UNLOCK(&task->lock);
1370 task = ISC_LIST_NEXT(task, link);