diff options
author | sam <sam@FreeBSD.org> | 2005-05-01 00:38:11 +0000 |
---|---|---|
committer | sam <sam@FreeBSD.org> | 2005-05-01 00:38:11 +0000 |
commit | 17d6060ac9afc38ef9d5b09f7c28b8842a439bbd (patch) | |
tree | 5015be89917a1c9a53d2b48bf53736636c16d902 /sys/kern/subr_taskqueue.c | |
parent | eff8f31f8b0bffb36780a423c2307f514ac22269 (diff) | |
download | FreeBSD-src-17d6060ac9afc38ef9d5b09f7c28b8842a439bbd.zip FreeBSD-src-17d6060ac9afc38ef9d5b09f7c28b8842a439bbd.tar.gz |
o enable shutdown of taskqueue threads; the thread servicing the queue checks
a new entry in the taskqueue struct each time it wakes up to see if it
should terminate
o adjust TASKQUEUE_DEFINE_THREAD & co. to record the thread/proc identity for
the shutdown rendezvous
o replace wakeup after adding a task to a queue with wakeup_one; this helps
queues where multiple threads are used to service tasks (e.g. acpi)
o remove NULL check of tq_enqueue method; it should never be NULL
Reviewed by: dfr, njl
Diffstat (limited to 'sys/kern/subr_taskqueue.c')
-rw-r--r-- | sys/kern/subr_taskqueue.c | 48 |
1 files changed, 38 insertions, 10 deletions
diff --git a/sys/kern/subr_taskqueue.c b/sys/kern/subr_taskqueue.c index 9d0ada4..9622098 100644 --- a/sys/kern/subr_taskqueue.c +++ b/sys/kern/subr_taskqueue.c @@ -36,6 +36,7 @@ __FBSDID("$FreeBSD$"); #include <sys/lock.h> #include <sys/malloc.h> #include <sys/mutex.h> +#include <sys/proc.h> #include <sys/taskqueue.h> #include <sys/unistd.h> @@ -53,6 +54,7 @@ struct taskqueue { void *tq_context; struct task *tq_running; struct mtx tq_mutex; + struct proc **tq_pproc; }; static void init_taskqueue_list(void *data); @@ -69,7 +71,8 @@ SYSINIT(taskqueue_list, SI_SUB_INTRINSIC, SI_ORDER_ANY, init_taskqueue_list, struct taskqueue * taskqueue_create(const char *name, int mflags, - taskqueue_enqueue_fn enqueue, void *context) + taskqueue_enqueue_fn enqueue, void *context, + struct proc **pp) { struct taskqueue *queue; @@ -81,6 +84,7 @@ taskqueue_create(const char *name, int mflags, queue->tq_name = name; queue->tq_enqueue = enqueue; queue->tq_context = context; + queue->tq_pproc = pp; mtx_init(&queue->tq_mutex, "taskqueue", NULL, MTX_DEF); mtx_lock(&taskqueue_queues_mutex); @@ -90,6 +94,26 @@ taskqueue_create(const char *name, int mflags, return queue; } +/* + * Signal a taskqueue thread to terminate. + */ +static void +taskqueue_terminate(struct proc **pp, struct taskqueue *tq) +{ + struct proc *p; + + p = *pp; + *pp = NULL; + if (p) { + wakeup_one(tq); + PROC_LOCK(p); /* NB: insure we don't miss wakeup */ + mtx_unlock(&tq->tq_mutex); /* let taskqueue thread run */ + msleep(p, &p->p_mtx, PWAIT, "taskqueue_destroy", 0); + PROC_UNLOCK(p); + mtx_lock(&tq->tq_mutex); + } +} + void taskqueue_free(struct taskqueue *queue) { @@ -100,6 +124,7 @@ taskqueue_free(struct taskqueue *queue) mtx_lock(&queue->tq_mutex); taskqueue_run(queue); + taskqueue_terminate(queue->tq_pproc, queue); mtx_destroy(&queue->tq_mutex); free(queue, M_TASKQUEUE); } @@ -161,8 +186,7 @@ taskqueue_enqueue(struct taskqueue *queue, struct task *task) } task->ta_pending = 1; - if (queue->tq_enqueue) - queue->tq_enqueue(queue->tq_context); + queue->tq_enqueue(queue->tq_context); mtx_unlock(&queue->tq_mutex); @@ -209,10 +233,10 @@ void taskqueue_drain(struct taskqueue *queue, struct task *task) { WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, "taskqueue_drain"); + mtx_lock(&queue->tq_mutex); - while (task->ta_pending != 0 || task == queue->tq_running) { + while (task->ta_pending != 0 || task == queue->tq_running) msleep(task, &queue->tq_mutex, PWAIT, "-", 0); - } mtx_unlock(&queue->tq_mutex); } @@ -248,10 +272,15 @@ taskqueue_thread_loop(void *arg) tqp = arg; tq = *tqp; mtx_lock(&tq->tq_mutex); - for (;;) { + do { taskqueue_run(tq); msleep(tq, &tq->tq_mutex, PWAIT, "-", 0); - } + } while (*tq->tq_pproc != NULL); + + /* rendezvous with thread that asked us to terminate */ + wakeup_one(tq); + mtx_unlock(&tq->tq_mutex); + kthread_exit(0); } void @@ -263,7 +292,7 @@ taskqueue_thread_enqueue(void *context) tq = *tqp; mtx_assert(&tq->tq_mutex, MA_OWNED); - wakeup(tq); + wakeup_one(tq); } TASKQUEUE_DEFINE(swi, taskqueue_swi_enqueue, 0, @@ -313,8 +342,7 @@ taskqueue_enqueue_fast(struct taskqueue *queue, struct task *task) } task->ta_pending = 1; - if (queue->tq_enqueue) - queue->tq_enqueue(queue->tq_context); + queue->tq_enqueue(queue->tq_context); mtx_unlock_spin(&queue->tq_mutex); |