Module Name: src
Committed By: riastradh
Date: Tue Sep 8 17:02:18 UTC 2020
Modified Files:
src/share/man/man9: workqueue.9
src/sys/kern: subr_workqueue.c
Log Message:
workqueue: Lift unnecessary restriction on workqueue_wait.
Allow multiple concurrent waits at a time, and allow enqueueing work
at the same time (as long as it's not the work we're waiting for).
This way multiple users can use a shared global workqueue and safely
wait for individual work items concurrently, while the workqueue is
still in use for other items (e.g., wg(4) peers).
This has the side effect of taking away a diagnostic measure, but I
think allowing the diagnostic's false positives instead of rejecting
them is worth it. We could cheaply add it back with some false
negatives if it's important.
To generate a diff of this commit:
cvs rdiff -u -r1.14 -r1.15 src/share/man/man9/workqueue.9
cvs rdiff -u -r1.38 -r1.39 src/sys/kern/subr_workqueue.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/share/man/man9/workqueue.9
diff -u src/share/man/man9/workqueue.9:1.14 src/share/man/man9/workqueue.9:1.15
--- src/share/man/man9/workqueue.9:1.14 Sat Aug 1 09:51:06 2020
+++ src/share/man/man9/workqueue.9 Tue Sep 8 17:02:18 2020
@@ -1,4 +1,4 @@
-.\" $NetBSD: workqueue.9,v 1.14 2020/08/01 09:51:06 wiz Exp $
+.\" $NetBSD: workqueue.9,v 1.15 2020/09/08 17:02:18 riastradh Exp $
.\"
.\" Copyright (c)2005 YAMAMOTO Takashi,
.\" All rights reserved.
@@ -133,11 +133,11 @@ waits for a specified work
on the workqueue
.Fa wq
to finish.
-The caller must ensure that no new work will be enqueued to the workqueue
-beforehand.
-Note that if the workqueue is
-.Dv WQ_PERCPU ,
-the caller can enqueue a new work to another queue other than the waiting queue.
+The caller must ensure that
+.Fa wk
+will not be enqueued to the workqueue again until after
+.Fn workqueue_wait
+returns.
.Pp
.\" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
.Fn workqueue_destroy
Index: src/sys/kern/subr_workqueue.c
diff -u src/sys/kern/subr_workqueue.c:1.38 src/sys/kern/subr_workqueue.c:1.39
--- src/sys/kern/subr_workqueue.c:1.38 Sat Aug 1 02:14:43 2020
+++ src/sys/kern/subr_workqueue.c Tue Sep 8 17:02:18 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: subr_workqueue.c,v 1.38 2020/08/01 02:14:43 riastradh Exp $ */
+/* $NetBSD: subr_workqueue.c,v 1.39 2020/09/08 17:02:18 riastradh Exp $ */
/*-
* Copyright (c)2002, 2005, 2006, 2007 YAMAMOTO Takashi,
@@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: subr_workqueue.c,v 1.38 2020/08/01 02:14:43 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: subr_workqueue.c,v 1.39 2020/09/08 17:02:18 riastradh Exp $");
#include <sys/param.h>
#include <sys/cpu.h>
@@ -52,7 +52,6 @@ struct workqueue_queue {
struct workqhead q_queue_pending;
struct workqhead q_queue_running;
lwp_t *q_worker;
- work_impl_t *q_waiter;
};
struct workqueue {
@@ -138,10 +137,8 @@ workqueue_worker(void *cookie)
mutex_enter(&q->q_mutex);
KASSERT(!SIMPLEQ_EMPTY(&q->q_queue_running));
SIMPLEQ_INIT(&q->q_queue_running);
- if (__predict_false(q->q_waiter != NULL)) {
- /* Wake up workqueue_wait */
- cv_signal(&q->q_cv);
- }
+ /* Wake up workqueue_wait */
+ cv_broadcast(&q->q_cv);
mutex_exit(&q->q_mutex);
}
if (wq->wq_flags & WQ_FPU)
@@ -211,7 +208,7 @@ workqueue_exit(struct work *wk, void *ar
KASSERT(SIMPLEQ_EMPTY(&q->q_queue_pending));
mutex_enter(&q->q_mutex);
q->q_worker = NULL;
- cv_signal(&q->q_cv);
+ cv_broadcast(&q->q_cv);
mutex_exit(&q->q_mutex);
kthread_exit(0);
}
@@ -228,7 +225,7 @@ workqueue_finiqueue(struct workqueue *wq
KASSERT(q->q_worker != NULL);
mutex_enter(&q->q_mutex);
SIMPLEQ_INSERT_TAIL(&q->q_queue_pending, &wqe.wqe_wk, wk_entry);
- cv_signal(&q->q_cv);
+ cv_broadcast(&q->q_cv);
while (q->q_worker != NULL) {
cv_wait(&q->q_cv, &q->q_mutex);
}
@@ -306,13 +303,9 @@ workqueue_q_wait(struct workqueue_queue
found:
if (wk != NULL) {
found = true;
- KASSERT(q->q_waiter == NULL);
- q->q_waiter = wk;
cv_wait(&q->q_cv, &q->q_mutex);
goto again;
}
- if (q->q_waiter != NULL)
- q->q_waiter = NULL;
out:
mutex_exit(&q->q_mutex);
@@ -386,11 +379,10 @@ workqueue_enqueue(struct workqueue *wq,
q = workqueue_queue_lookup(wq, ci);
mutex_enter(&q->q_mutex);
- KASSERT(q->q_waiter == NULL);
#ifdef DEBUG
workqueue_check_duplication(q, wk);
#endif
SIMPLEQ_INSERT_TAIL(&q->q_queue_pending, wk, wk_entry);
- cv_signal(&q->q_cv);
+ cv_broadcast(&q->q_cv);
mutex_exit(&q->q_mutex);
}