Thu Nov 30 14:40:46 2017 UTC ()
Pull up following revision(s) (requested by ozaki-r in ticket #405):
	sys/sys/pserialize.h: revision 1.2
	sys/kern/kern_lock.c: revision 1.160
	sys/kern/subr_pserialize.c: revision 1.9
	sys/rump/librump/rumpkern/emul.c: revision 1.184
	sys/rump/librump/rumpkern/emul.c: revision 1.185
	sys/rump/librump/rumpkern/rump.c: revision 1.330
Implement debugging feature for pserialize(9)
The debugging feature detects violations of pserialize constraints.
It causes a panic:
- if a context switch happens in a read section, or
- if a sleepable function is called in a read section.
The feature is enabled only if LOCKDEBUG is on.
Discussed on tech-kern@
Add missing inclusion of pserialize.h (fix build)


(martin)
diff -r1.158 -r1.158.6.1 src/sys/kern/kern_lock.c
diff -r1.8 -r1.8.10.1 src/sys/kern/subr_pserialize.c
diff -r1.181.6.1 -r1.181.6.2 src/sys/rump/librump/rumpkern/emul.c
diff -r1.329 -r1.329.10.1 src/sys/rump/librump/rumpkern/rump.c
diff -r1.1 -r1.1.46.1 src/sys/sys/pserialize.h

cvs diff -r1.158 -r1.158.6.1 src/sys/kern/kern_lock.c (expand / switch to context diff)
--- src/sys/kern/kern_lock.c 2017/01/26 04:11:56 1.158
+++ src/sys/kern/kern_lock.c 2017/11/30 14:40:46 1.158.6.1
@@ -1,4 +1,4 @@
-/*	$NetBSD: kern_lock.c,v 1.158 2017/01/26 04:11:56 christos Exp $	*/
+/*	$NetBSD: kern_lock.c,v 1.158.6.1 2017/11/30 14:40:46 martin Exp $	*/
 
 /*-
  * Copyright (c) 2002, 2006, 2007, 2008, 2009 The NetBSD Foundation, Inc.
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_lock.c,v 1.158 2017/01/26 04:11:56 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_lock.c,v 1.158.6.1 2017/11/30 14:40:46 martin Exp $");
 
 #include <sys/param.h>
 #include <sys/proc.h>
@@ -43,6 +43,7 @@
 #include <sys/syslog.h>
 #include <sys/atomic.h>
 #include <sys/lwp.h>
+#include <sys/pserialize.h>
 
 #include <machine/lock.h>
 
@@ -87,6 +88,9 @@
 	}
 	if (cpu_softintr_p()) {
 		reason = "softint";
+	}
+	if (!pserialize_not_in_read_section()) {
+		reason = "pserialize";
 	}
 
 	if (reason) {

cvs diff -r1.8 -r1.8.10.1 src/sys/kern/subr_pserialize.c (expand / switch to context diff)
--- src/sys/kern/subr_pserialize.c 2015/06/12 19:18:30 1.8
+++ src/sys/kern/subr_pserialize.c 2017/11/30 14:40:46 1.8.10.1
@@ -1,4 +1,4 @@
-/*	$NetBSD: subr_pserialize.c,v 1.8 2015/06/12 19:18:30 dholland Exp $	*/
+/*	$NetBSD: subr_pserialize.c,v 1.8.10.1 2017/11/30 14:40:46 martin Exp $	*/
 
 /*-
  * Copyright (c) 2010, 2011 The NetBSD Foundation, Inc.
@@ -38,7 +38,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: subr_pserialize.c,v 1.8 2015/06/12 19:18:30 dholland Exp $");
+__KERNEL_RCSID(0, "$NetBSD: subr_pserialize.c,v 1.8.10.1 2017/11/30 14:40:46 martin Exp $");
 
 #include <sys/param.h>
 
@@ -73,6 +73,12 @@
 static TAILQ_HEAD(, pserialize)	psz_queue1	__cacheline_aligned;
 static TAILQ_HEAD(, pserialize)	psz_queue2	__cacheline_aligned;
 
+#ifdef LOCKDEBUG
+#include <sys/percpu.h>
+
+static percpu_t		*psz_debug_nreads	__cacheline_aligned;
+#endif
+
 /*
  * pserialize_init:
  *
@@ -89,6 +95,9 @@
 	mutex_init(&psz_lock, MUTEX_DEFAULT, IPL_SCHED);
 	evcnt_attach_dynamic(&psz_ev_excl, EVCNT_TYPE_MISC, NULL,
 	    "pserialize", "exclusive access");
+#ifdef LOCKDEBUG
+	psz_debug_nreads = percpu_alloc(sizeof(uint32_t));
+#endif
 }
 
 /*
@@ -185,15 +194,37 @@
 int
 pserialize_read_enter(void)
 {
+	int s;
 
 	KASSERT(!cpu_intr_p());
-	return splsoftserial();
+	s = splsoftserial();
+#ifdef LOCKDEBUG
+	{
+		uint32_t *nreads;
+		nreads = percpu_getref(psz_debug_nreads);
+		(*nreads)++;
+		if (*nreads == 0)
+			panic("nreads overflow");
+		percpu_putref(psz_debug_nreads);
+	}
+#endif
+	return s;
 }
 
 void
 pserialize_read_exit(int s)
 {
 
+#ifdef LOCKDEBUG
+	{
+		uint32_t *nreads;
+		nreads = percpu_getref(psz_debug_nreads);
+		(*nreads)--;
+		if (*nreads == UINT_MAX)
+			panic("nreads underflow");
+		percpu_putref(psz_debug_nreads);
+	}
+#endif
 	splx(s);
 }
 
@@ -209,6 +240,9 @@
 	pserialize_t psz, next;
 	cpuid_t cid;
 
+	/* We must to ensure not to come here from inside a read section. */
+	KASSERT(pserialize_not_in_read_section());
+
 	/*
 	 * If no updates pending, bail out.  No need to lock in order to
 	 * test psz_work_todo; the only ill effect of missing an update
@@ -260,4 +294,62 @@
 		psz_work_todo--;
 	}
 	mutex_spin_exit(&psz_lock);
+}
+
+/*
+ * pserialize_in_read_section:
+ *
+ *   True if the caller is in a pserialize read section.  To be used only
+ *   for diagnostic assertions where we want to guarantee the condition like:
+ *
+ *     KASSERT(pserialize_in_read_section());
+ */
+bool
+pserialize_in_read_section(void)
+{
+#ifdef LOCKDEBUG
+	uint32_t *nreads;
+	bool in;
+
+	/* Not initialized yet */
+	if (__predict_false(psz_debug_nreads == NULL))
+		return true;
+
+	nreads = percpu_getref(psz_debug_nreads);
+	in = *nreads != 0;
+	percpu_putref(psz_debug_nreads);
+
+	return in;
+#else
+	return true;
+#endif
+}
+
+/*
+ * pserialize_not_in_read_section:
+ *
+ *   True if the caller is not in a pserialize read section.  To be used only
+ *   for diagnostic assertions where we want to guarantee the condition like:
+ *
+ *     KASSERT(pserialize_not_in_read_section());
+ */
+bool
+pserialize_not_in_read_section(void)
+{
+#ifdef LOCKDEBUG
+	uint32_t *nreads;
+	bool notin;
+
+	/* Not initialized yet */
+	if (__predict_false(psz_debug_nreads == NULL))
+		return true;
+
+	nreads = percpu_getref(psz_debug_nreads);
+	notin = *nreads == 0;
+	percpu_putref(psz_debug_nreads);
+
+	return notin;
+#else
+	return true;
+#endif
 }

cvs diff -r1.181.6.1 -r1.181.6.2 src/sys/rump/librump/rumpkern/emul.c (expand / switch to context diff)
--- src/sys/rump/librump/rumpkern/emul.c 2017/06/04 20:35:01 1.181.6.1
+++ src/sys/rump/librump/rumpkern/emul.c 2017/11/30 14:40:46 1.181.6.2
@@ -1,4 +1,4 @@
-/*	$NetBSD: emul.c,v 1.181.6.1 2017/06/04 20:35:01 bouyer Exp $	*/
+/*	$NetBSD: emul.c,v 1.181.6.2 2017/11/30 14:40:46 martin Exp $	*/
 
 /*
  * Copyright (c) 2007-2011 Antti Kantee.  All Rights Reserved.
@@ -26,7 +26,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: emul.c,v 1.181.6.1 2017/06/04 20:35:01 bouyer Exp $");
+__KERNEL_RCSID(0, "$NetBSD: emul.c,v 1.181.6.2 2017/11/30 14:40:46 martin Exp $");
 
 #include <sys/param.h>
 #include <sys/cprng.h>
@@ -36,6 +36,7 @@
 #include <sys/module.h>
 #include <sys/reboot.h>
 #include <sys/syscall.h>
+#include <sys/pserialize.h>
 #ifdef LOCKDEBUG
 #include <sys/sleepq.h>
 #endif
@@ -165,11 +166,23 @@
 	return t;
 }
 
+#define	RETURN_ADDRESS	(uintptr_t)__builtin_return_address(0)
+
 void
 assert_sleepable(void)
 {
+	const char *reason = NULL;
 
 	/* always sleepable, although we should improve this */
+
+	if (!pserialize_not_in_read_section()) {
+		reason = "pserialize";
+	}
+
+	if (reason) {
+		panic("%s: %s caller=%p", __func__, reason,
+		    (void *)RETURN_ADDRESS);
+	}
 }
 
 void

cvs diff -r1.329 -r1.329.10.1 src/sys/rump/librump/rumpkern/rump.c (expand / switch to context diff)
--- src/sys/rump/librump/rumpkern/rump.c 2016/03/08 14:30:48 1.329
+++ src/sys/rump/librump/rumpkern/rump.c 2017/11/30 14:40:46 1.329.10.1
@@ -1,4 +1,4 @@
-/*	$NetBSD: rump.c,v 1.329 2016/03/08 14:30:48 joerg Exp $	*/
+/*	$NetBSD: rump.c,v 1.329.10.1 2017/11/30 14:40:46 martin Exp $	*/
 
 /*
  * Copyright (c) 2007-2011 Antti Kantee.  All Rights Reserved.
@@ -26,7 +26,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: rump.c,v 1.329 2016/03/08 14:30:48 joerg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: rump.c,v 1.329.10.1 2017/11/30 14:40:46 martin Exp $");
 
 #include <sys/systm.h>
 #define ELFSIZE ARCH_ELFSIZE
@@ -301,6 +301,7 @@
 	callout_startup();
 
 	kprintf_init();
+	percpu_init();
 	pserialize_init();
 
 	kauth_init();
@@ -351,7 +352,6 @@
 	rump_schedule();
 	bootlwp = curlwp;
 
-	percpu_init();
 	inittimecounter();
 	ntp_init();
 

cvs diff -r1.1 -r1.1.46.1 src/sys/sys/pserialize.h (expand / switch to context diff)
--- src/sys/sys/pserialize.h 2011/07/30 17:01:04 1.1
+++ src/sys/sys/pserialize.h 2017/11/30 14:40:46 1.1.46.1
@@ -1,4 +1,4 @@
-/*	$NetBSD: pserialize.h,v 1.1 2011/07/30 17:01:04 christos Exp $	*/
+/*	$NetBSD: pserialize.h,v 1.1.46.1 2017/11/30 14:40:46 martin Exp $	*/
 
 /*-
  * Copyright (c) 2010, 2011 The NetBSD Foundation, Inc.
@@ -44,6 +44,8 @@
 int		pserialize_read_enter(void);
 void		pserialize_read_exit(int);
 
+bool		pserialize_in_read_section(void);
+bool		pserialize_not_in_read_section(void);
 #endif	/* _KERNEL */
 
 #endif	/* _SYS_PSERIALIZE_H_ */