Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/external/bsd/common/linux Exercise greater care in acqui...
details: https://anonhg.NetBSD.org/src/rev/245f51950118
branches: trunk
changeset: 366347:245f51950118
user: riastradh <riastradh%NetBSD.org@localhost>
date: Mon Aug 27 14:59:20 2018 +0000
description:
Exercise greater care in acquiring and releasing work.
diffstat:
sys/external/bsd/common/linux/linux_work.c | 47 ++++++++++++++++++++++++-----
1 files changed, 39 insertions(+), 8 deletions(-)
diffs (110 lines):
diff -r 3241359926c8 -r 245f51950118 sys/external/bsd/common/linux/linux_work.c
--- a/sys/external/bsd/common/linux/linux_work.c Mon Aug 27 14:59:04 2018 +0000
+++ b/sys/external/bsd/common/linux/linux_work.c Mon Aug 27 14:59:20 2018 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: linux_work.c,v 1.16 2018/08/27 14:58:57 riastradh Exp $ */
+/* $NetBSD: linux_work.c,v 1.17 2018/08/27 14:59:20 riastradh Exp $ */
/*-
* Copyright (c) 2018 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: linux_work.c,v 1.16 2018/08/27 14:58:57 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: linux_work.c,v 1.17 2018/08/27 14:59:20 riastradh Exp $");
#include <sys/types.h>
#include <sys/atomic.h>
@@ -60,6 +60,11 @@
static void __dead linux_workqueue_thread(void *);
static void linux_workqueue_timeout(void *);
+static struct workqueue_struct *
+ acquire_work(struct work_struct *,
+ struct workqueue_struct *);
+static void release_work(struct work_struct *,
+ struct workqueue_struct *);
static void queue_delayed_work_anew(struct workqueue_struct *,
struct delayed_work *, unsigned long);
@@ -238,7 +243,7 @@
if (wq->wq_requeued)
wq->wq_requeued = false;
else
- work->work_queue = NULL;
+ release_work(work, wq);
wq->wq_current_work = NULL;
cv_broadcast(&wq->wq_cv);
}
@@ -278,6 +283,7 @@
dw->dw_state = DELAYED_WORK_IDLE;
callout_destroy(&dw->dw_callout);
TAILQ_REMOVE(&wq->wq_delayed, dw, dw_entry);
+ release_work(&dw->work, wq);
break;
default:
panic("delayed work callout in bad state: %p", dw);
@@ -316,6 +322,33 @@
work->func = fn;
}
+static struct workqueue_struct *
+acquire_work(struct work_struct *work, struct workqueue_struct *wq)
+{
+ struct workqueue_struct *wq0;
+
+ KASSERT(mutex_owned(&wq->wq_lock));
+
+ wq0 = atomic_cas_ptr(&work->work_queue, NULL, wq);
+ if (wq0 == NULL) {
+ membar_enter();
+ KASSERT(work->work_queue == wq);
+ }
+
+ return wq0;
+}
+
+static void
+release_work(struct work_struct *work, struct workqueue_struct *wq)
+{
+
+ KASSERT(work->work_queue == wq);
+ KASSERT(mutex_owned(&wq->wq_lock));
+
+ membar_exit();
+ work->work_queue = NULL;
+}
+
bool
schedule_work(struct work_struct *work)
{
@@ -332,8 +365,7 @@
KASSERT(wq != NULL);
mutex_enter(&wq->wq_lock);
- if (__predict_true((wq0 = atomic_cas_ptr(&work->work_queue, NULL, wq))
- == NULL)) {
+ if (__predict_true((wq0 = acquire_work(work, wq)) == NULL)) {
TAILQ_INSERT_TAIL(&wq->wq_queue, work, work_entry);
newly_queued = true;
} else {
@@ -462,8 +494,7 @@
bool newly_queued;
mutex_enter(&wq->wq_lock);
- if (__predict_true((wq0 = atomic_cas_ptr(&dw->work.work_queue, NULL,
- wq)) == NULL)) {
+ if (__predict_true((wq0 = acquire_work(&dw->work, wq)) == NULL)) {
KASSERT(dw->dw_state == DELAYED_WORK_IDLE);
queue_delayed_work_anew(wq, dw, ticks);
newly_queued = true;
@@ -484,7 +515,7 @@
bool timer_modified;
mutex_enter(&wq->wq_lock);
- if ((wq0 = atomic_cas_ptr(&dw->work.work_queue, NULL, wq)) == NULL) {
+ if ((wq0 = acquire_work(&dw->work, wq)) == NULL) {
KASSERT(dw->dw_state == DELAYED_WORK_IDLE);
queue_delayed_work_anew(wq, dw, ticks);
timer_modified = false;
Home |
Main Index |
Thread Index |
Old Index