diff options
author | Andriy Gapon <avg@FreeBSD.org> | 2013-11-28 18:56:34 +0000 |
---|---|---|
committer | Andriy Gapon <avg@FreeBSD.org> | 2013-11-28 18:56:34 +0000 |
commit | 73f82099ea1313da843f5423e73f00304991dc7f (patch) | |
tree | e3cdfe8d1f244a8c7fceece93f7bb436667058b2 /sys/kern | |
parent | 729f64d6ae27142cfc8f2bcc0e69330a9499e480 (diff) | |
download | src-73f82099ea1313da843f5423e73f00304991dc7f.tar.gz src-73f82099ea1313da843f5423e73f00304991dc7f.zip |
add taskqueue_drain_all
This API has semantics similar to that of taskqueue_drain but acts on
all tasks that might be queued or running on a taskqueue.
A caller must ensure that no new tasks are being enqueued otherwise this
call would be totally meaningless. For example, if the tasks are
enqueued by an interrupt filter then its interrupt must be disabled.
MFC after: 10 days
Notes
Notes:
svn path=/head/; revision=258713
Diffstat (limited to 'sys/kern')
-rw-r--r-- | sys/kern/subr_taskqueue.c | 30 |
1 files changed, 30 insertions, 0 deletions
diff --git a/sys/kern/subr_taskqueue.c b/sys/kern/subr_taskqueue.c index cbe80deb3428..bfc941ee3326 100644 --- a/sys/kern/subr_taskqueue.c +++ b/sys/kern/subr_taskqueue.c @@ -300,6 +300,15 @@ taskqueue_enqueue_timeout(struct taskqueue *queue, return (res); } +static void +taskqueue_drain_running(struct taskqueue *queue) +{ + + while (!TAILQ_EMPTY(&queue->tq_active)) + TQ_SLEEP(queue, &queue->tq_active, &queue->tq_mutex, + PWAIT, "-", 0); +} + void taskqueue_block(struct taskqueue *queue) { @@ -350,6 +359,8 @@ taskqueue_run_locked(struct taskqueue *queue) wakeup(task); } TAILQ_REMOVE(&queue->tq_active, &tb, tb_link); + if (TAILQ_EMPTY(&queue->tq_active)) + wakeup(&queue->tq_active); } void @@ -434,6 +445,25 @@ taskqueue_drain(struct taskqueue *queue, struct task *task) } void +taskqueue_drain_all(struct taskqueue *queue) +{ + struct task *task; + + if (!queue->tq_spin) + WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, __func__); + + TQ_LOCK(queue); + task = STAILQ_LAST(&queue->tq_queue, task, ta_link); + if (task != NULL) + while (task->ta_pending != 0) + TQ_SLEEP(queue, task, &queue->tq_mutex, PWAIT, "-", 0); + taskqueue_drain_running(queue); + KASSERT(STAILQ_EMPTY(&queue->tq_queue), + ("taskqueue queue is not empty after draining")); + TQ_UNLOCK(queue); +} + +void taskqueue_drain_timeout(struct taskqueue *queue, struct timeout_task *timeout_task) { |