Module Name:    src
Committed By:   chs
Date:           Thu Jun  8 01:09:52 UTC 2017

Modified Files:
        src/sys/kern: kern_condvar.c
        src/sys/sys: lwp.h

Log Message:
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.


To generate a diff of this commit:
cvs rdiff -u -r1.35 -r1.36 src/sys/kern/kern_condvar.c
cvs rdiff -u -r1.174 -r1.175 src/sys/sys/lwp.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/kern/kern_condvar.c
diff -u src/sys/kern/kern_condvar.c:1.35 src/sys/kern/kern_condvar.c:1.36
--- src/sys/kern/kern_condvar.c:1.35	Fri Aug  7 06:22:12 2015
+++ src/sys/kern/kern_condvar.c	Thu Jun  8 01:09:52 2017
@@ -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 @@ __KERNEL_RCSID(0, "$NetBSD: kern_condvar
 #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 @@ lockops_t cv_lockops = {
 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 @@ cv_wait(kcondvar_t *cv, kmutex_t *mtx)
 	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_signal(kcondvar_t *cv)
 		cv_wakeup_one(cv);
 }
 
-static void __noinline
+static inline void
 cv_wakeup_one(kcondvar_t *cv)
 {
 	sleepq_t *sq;
@@ -321,6 +354,7 @@ cv_wakeup_one(kcondvar_t *cv)
 	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_broadcast(kcondvar_t *cv)
 		cv_wakeup_all(cv);
 }
 
-static void __noinline
+static inline void
 cv_wakeup_all(kcondvar_t *cv)
 {
 	sleepq_t *sq;
@@ -360,6 +394,7 @@ cv_wakeup_all(kcondvar_t *cv)
 		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);

Index: src/sys/sys/lwp.h
diff -u src/sys/sys/lwp.h:1.174 src/sys/sys/lwp.h:1.175
--- src/sys/sys/lwp.h:1.174	Fri Apr 21 15:10:35 2017
+++ src/sys/sys/lwp.h	Thu Jun  8 01:09:52 2017
@@ -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 @@ extern int		maxlwp __read_mostly;	/* max
 /* 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 */

Reply via email to