Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys allow cv_signal() immediately followed by cv_destroy().
details: https://anonhg.NetBSD.org/src/rev/14910966be0f
branches: trunk
changeset: 354214:14910966be0f
user: chs <chs%NetBSD.org@localhost>
date: Thu Jun 08 01:09:52 2017 +0000
description:
allow cv_signal() immediately followed by cv_destroy().
this sequence is used by ZFS in a couple places and by supporting it
natively we can undo our local ZFS changes that avoided it.
note that this is only legal when all of the waiters use cv_wait()
and not any of the other variations, and lockdebug will catch
any violations of this rule.
diffstat:
sys/kern/kern_condvar.c | 51 +++++++++++++++++++++++++++++++++++++++++-------
sys/sys/lwp.h | 3 +-
2 files changed, 45 insertions(+), 9 deletions(-)
diffs (132 lines):
diff -r d6ac1a89e7f4 -r 14910966be0f sys/kern/kern_condvar.c
--- a/sys/kern/kern_condvar.c Thu Jun 08 00:17:02 2017 +0000
+++ b/sys/kern/kern_condvar.c Thu Jun 08 01:09:52 2017 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: kern_condvar.c,v 1.35 2015/08/07 06:22:12 uebayasi Exp $ */
+/* $NetBSD: kern_condvar.c,v 1.36 2017/06/08 01:09:52 chs Exp $ */
/*-
* Copyright (c) 2006, 2007, 2008 The NetBSD Foundation, Inc.
@@ -34,7 +34,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_condvar.c,v 1.35 2015/08/07 06:22:12 uebayasi Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_condvar.c,v 1.36 2017/06/08 01:09:52 chs Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -65,9 +65,9 @@
#define CV_DEBUG_P(cv) (CV_WMESG(cv) != nodebug)
#define CV_RA ((uintptr_t)__builtin_return_address(0))
-static void cv_unsleep(lwp_t *, bool);
-static void cv_wakeup_one(kcondvar_t *);
-static void cv_wakeup_all(kcondvar_t *);
+static void cv_unsleep(lwp_t *, bool);
+static inline void cv_wakeup_one(kcondvar_t *);
+static inline void cv_wakeup_all(kcondvar_t *);
static syncobj_t cv_syncobj = {
SOBJ_SLEEPQ_SORTED,
@@ -86,6 +86,31 @@
static const char deadcv[] = "deadcv";
#ifdef LOCKDEBUG
static const char nodebug[] = "nodebug";
+
+#define CV_LOCKDEBUG_HANDOFF(l, cv) cv_lockdebug_handoff(l, cv)
+#define CV_LOCKDEBUG_PROCESS(l, cv) cv_lockdebug_process(l, cv)
+
+static inline void
+cv_lockdebug_handoff(lwp_t *l, kcondvar_t *cv)
+{
+
+ if (CV_DEBUG_P(cv))
+ l->l_flag |= LW_CVLOCKDEBUG;
+}
+
+static inline void
+cv_lockdebug_process(lwp_t *l, kcondvar_t *cv)
+{
+
+ if ((l->l_flag & LW_CVLOCKDEBUG) == 0)
+ return;
+
+ l->l_flag &= ~LW_CVLOCKDEBUG;
+ LOCKDEBUG_UNLOCKED(true, cv, CV_RA, 0);
+}
+#else
+#define CV_LOCKDEBUG_HANDOFF(l, cv) __nothing
+#define CV_LOCKDEBUG_PROCESS(l, cv) __nothing
#endif
/*
@@ -214,8 +239,16 @@
KASSERT(mutex_owned(mtx));
cv_enter(cv, mtx, l);
+
+ /*
+ * We can't use cv_exit() here since the cv might be destroyed before
+ * this thread gets a chance to run. Instead, hand off the lockdebug
+ * responsibility to the thread that wakes us up.
+ */
+
+ CV_LOCKDEBUG_HANDOFF(l, cv);
(void)sleepq_block(0, false);
- (void)cv_exit(cv, mtx, l, 0);
+ mutex_enter(mtx);
}
/*
@@ -302,7 +335,7 @@
cv_wakeup_one(cv);
}
-static void __noinline
+static inline void
cv_wakeup_one(kcondvar_t *cv)
{
sleepq_t *sq;
@@ -321,6 +354,7 @@
KASSERT(l->l_sleepq == sq);
KASSERT(l->l_mutex == mp);
KASSERT(l->l_wchan == cv);
+ CV_LOCKDEBUG_PROCESS(l, cv);
sleepq_remove(sq, l);
mutex_spin_exit(mp);
@@ -344,7 +378,7 @@
cv_wakeup_all(cv);
}
-static void __noinline
+static inline void
cv_wakeup_all(kcondvar_t *cv)
{
sleepq_t *sq;
@@ -360,6 +394,7 @@
KASSERT(l->l_mutex == mp);
KASSERT(l->l_wchan == cv);
next = TAILQ_NEXT(l, l_sleepchain);
+ CV_LOCKDEBUG_PROCESS(l, cv);
sleepq_remove(sq, l);
}
mutex_spin_exit(mp);
diff -r d6ac1a89e7f4 -r 14910966be0f sys/sys/lwp.h
--- a/sys/sys/lwp.h Thu Jun 08 00:17:02 2017 +0000
+++ b/sys/sys/lwp.h Thu Jun 08 01:09:52 2017 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: lwp.h,v 1.174 2017/04/21 15:10:35 christos Exp $ */
+/* $NetBSD: lwp.h,v 1.175 2017/06/08 01:09:52 chs Exp $ */
/*-
* Copyright (c) 2001, 2006, 2007, 2008, 2009, 2010
@@ -231,6 +231,7 @@
/* These flags are kept in l_flag. */
#define LW_IDLE 0x00000001 /* Idle lwp. */
#define LW_LWPCTL 0x00000002 /* Adjust lwpctl in userret */
+#define LW_CVLOCKDEBUG 0x00000004 /* Waker does lockdebug */
#define LW_SINTR 0x00000080 /* Sleep is interruptible. */
#define LW_SYSTEM 0x00000200 /* Kernel thread */
#define LW_WSUSPEND 0x00020000 /* Suspend before return to user */
Home |
Main Index |
Thread Index |
Old Index