aboutsummaryrefslogtreecommitdiff
path: root/sys/kern
diff options
context:
space:
mode:
authorAndriy Gapon <avg@FreeBSD.org>2013-11-28 18:56:34 +0000
committerAndriy Gapon <avg@FreeBSD.org>2013-11-28 18:56:34 +0000
commit73f82099ea1313da843f5423e73f00304991dc7f (patch)
treee3cdfe8d1f244a8c7fceece93f7bb436667058b2 /sys/kern
parent729f64d6ae27142cfc8f2bcc0e69330a9499e480 (diff)
downloadsrc-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.c30
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)
{