diff options
author | David Gwynne <dlg@cvs.openbsd.org> | 2020-06-11 06:03:55 +0000 |
---|---|---|
committer | David Gwynne <dlg@cvs.openbsd.org> | 2020-06-11 06:03:55 +0000 |
commit | de2e25a20721e877b0e27c5b3b7dad7057686a08 (patch) | |
tree | 847bd7381c0c8ebdaa316dfbc95c26f801ff94e3 | |
parent | 1898b47e92e5453e07898b9b52c0d6b572e77f19 (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.c | 4 |
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, |