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
This commit is contained in:
avg 2013-11-28 18:56:34 +00:00
parent c43b087230
commit 80c477c9b4
2 changed files with 31 additions and 0 deletions

View File

@ -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
@ -433,6 +444,25 @@ taskqueue_drain(struct taskqueue *queue, struct task *task)
TQ_UNLOCK(queue);
}
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)

View File

@ -81,6 +81,7 @@ int taskqueue_cancel_timeout(struct taskqueue *queue,
void taskqueue_drain(struct taskqueue *queue, struct task *task);
void taskqueue_drain_timeout(struct taskqueue *queue,
struct timeout_task *timeout_task);
void taskqueue_drain_all(struct taskqueue *queue);
void taskqueue_free(struct taskqueue *queue);
void taskqueue_run(struct taskqueue *queue);
void taskqueue_block(struct taskqueue *queue);