summaryrefslogtreecommitdiffstats
path: root/sys/kern/subr_taskqueue.c
diff options
context:
space:
mode:
authorsam <sam@FreeBSD.org>2005-05-01 00:38:11 +0000
committersam <sam@FreeBSD.org>2005-05-01 00:38:11 +0000
commit17d6060ac9afc38ef9d5b09f7c28b8842a439bbd (patch)
tree5015be89917a1c9a53d2b48bf53736636c16d902 /sys/kern/subr_taskqueue.c
parenteff8f31f8b0bffb36780a423c2307f514ac22269 (diff)
downloadFreeBSD-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.c48
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);
OpenPOWER on IntegriCloud