summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Gwynne <dlg@cvs.openbsd.org>2020-06-11 06:03:55 +0000
committerDavid Gwynne <dlg@cvs.openbsd.org>2020-06-11 06:03:55 +0000
commitde2e25a20721e877b0e27c5b3b7dad7057686a08 (patch)
tree847bd7381c0c8ebdaa316dfbc95c26f801ff94e3
parent1898b47e92e5453e07898b9b52c0d6b572e77f19 (diff)
make taskq_barrier wait for pending tasks, not just the running tasks.
I wrote taskq_barrier with the behaviour described in the manpage: taskq_barrier() guarantees that any task that was running on the tq taskq when the barrier was called has finished by the time the barrier returns. Note that it talks about the currently running task, not pending tasks. It just so happens that the original implementation just used task_add to put a condvar on the list and waited for it to run. Because task_add uses TAILQ_INSERT_TAIL, you ended up waiting for all pending to work to run too, not just the currently running task. The new implementation took advantage of already holding the lock and used TAILQ_INSERT_HEAD to put the barrier work at the front of the queue so it would run next, which is closer to the stated behaviour. Using the tail insert here restores the previous accidental behaviour. jsg@ points out the following: > The linux functions like flush_workqueue() we use this for in drm want > to wait on all scheduled work not just currently running. > > ie a comment from one of the linux functions: > > /** > * flush_workqueue - ensure that any scheduled work has run to completion. > * @wq: workqueue to flush > * > * This function sleeps until all work items which were queued on entry > * have finished execution, but it is not livelocked by new incoming ones. > */ > > our implementation of this in drm is > > void > flush_workqueue(struct workqueue_struct *wq) > { > if (cold) > return; > > taskq_barrier((struct taskq *)wq); > } I don't think it's worth complicating the taskq API, so I'm just going to make taskq_barrier wait for pending work too. tested by tb@ ok jsg@
-rw-r--r--sys/kern/kern_task.c4
1 files changed, 2 insertions, 2 deletions
diff --git a/sys/kern/kern_task.c b/sys/kern/kern_task.c
index a62fc24c7aa..448deec730a 100644
--- a/sys/kern/kern_task.c
+++ b/sys/kern/kern_task.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_task.c,v 1.28 2020/06/07 23:23:30 dlg Exp $ */
+/* $OpenBSD: kern_task.c,v 1.29 2020/06/11 06:03:54 dlg Exp $ */
/*
* Copyright (c) 2013 David Gwynne <dlg@openbsd.org>
@@ -288,7 +288,7 @@ taskq_do_barrier(struct taskq *tq)
while (tq->tq_bthreads < tq->tq_nthreads) {
/* shove the task into the queue for a worker to pick up */
SET(t.t_flags, TASK_ONQUEUE);
- TAILQ_INSERT_HEAD(&tq->tq_worklist, &t, t_entry);
+ TAILQ_INSERT_TAIL(&tq->tq_worklist, &t, t_entry);
wakeup_one(tq);
msleep_nsec(&tq->tq_bthreads, &tq->tq_mtx,