Module Name:    src
Committed By:   ozaki-r
Date:           Tue Nov 21 08:49:15 UTC 2017

Modified Files:
        src/sys/kern: kern_lock.c subr_pserialize.c
        src/sys/rump/librump/rumpkern: emul.c rump.c
        src/sys/sys: pserialize.h

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


To generate a diff of this commit:
cvs rdiff -u -r1.159 -r1.160 src/sys/kern/kern_lock.c
cvs rdiff -u -r1.8 -r1.9 src/sys/kern/subr_pserialize.c
cvs rdiff -u -r1.183 -r1.184 src/sys/rump/librump/rumpkern/emul.c
cvs rdiff -u -r1.329 -r1.330 src/sys/rump/librump/rumpkern/rump.c
cvs rdiff -u -r1.1 -r1.2 src/sys/sys/pserialize.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_lock.c
diff -u src/sys/kern/kern_lock.c:1.159 src/sys/kern/kern_lock.c:1.160
--- src/sys/kern/kern_lock.c:1.159	Sat Sep 16 23:55:33 2017
+++ src/sys/kern/kern_lock.c	Tue Nov 21 08:49:14 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: kern_lock.c,v 1.159 2017/09/16 23:55:33 christos Exp $	*/
+/*	$NetBSD: kern_lock.c,v 1.160 2017/11/21 08:49:14 ozaki-r 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.159 2017/09/16 23:55:33 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_lock.c,v 1.160 2017/11/21 08:49:14 ozaki-r Exp $");
 
 #include <sys/param.h>
 #include <sys/proc.h>
@@ -43,6 +43,7 @@ __KERNEL_RCSID(0, "$NetBSD: kern_lock.c,
 #include <sys/syslog.h>
 #include <sys/atomic.h>
 #include <sys/lwp.h>
+#include <sys/pserialize.h>
 
 #include <machine/lock.h>
 
@@ -88,6 +89,9 @@ assert_sleepable(void)
 	if (cpu_softintr_p()) {
 		reason = "softint";
 	}
+	if (!pserialize_not_in_read_section()) {
+		reason = "pserialize";
+	}
 
 	if (reason) {
 		panic("%s: %s caller=%p", __func__, reason,

Index: src/sys/kern/subr_pserialize.c
diff -u src/sys/kern/subr_pserialize.c:1.8 src/sys/kern/subr_pserialize.c:1.9
--- src/sys/kern/subr_pserialize.c:1.8	Fri Jun 12 19:18:30 2015
+++ src/sys/kern/subr_pserialize.c	Tue Nov 21 08:49:14 2017
@@ -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.9 2017/11/21 08:49:14 ozaki-r 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.9 2017/11/21 08:49:14 ozaki-r Exp $");
 
 #include <sys/param.h>
 
@@ -73,6 +73,12 @@ static TAILQ_HEAD(, pserialize)	psz_queu
 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 @@ pserialize_init(void)
 	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 @@ pserialize_perform(pserialize_t psz)
 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_switchpoint(void)
 	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
@@ -261,3 +295,61 @@ pserialize_switchpoint(void)
 	}
 	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
+}

Index: src/sys/rump/librump/rumpkern/emul.c
diff -u src/sys/rump/librump/rumpkern/emul.c:1.183 src/sys/rump/librump/rumpkern/emul.c:1.184
--- src/sys/rump/librump/rumpkern/emul.c:1.183	Thu Nov  9 12:46:55 2017
+++ src/sys/rump/librump/rumpkern/emul.c	Tue Nov 21 08:49:14 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: emul.c,v 1.183 2017/11/09 12:46:55 christos Exp $	*/
+/*	$NetBSD: emul.c,v 1.184 2017/11/21 08:49:14 ozaki-r 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.183 2017/11/09 12:46:55 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: emul.c,v 1.184 2017/11/21 08:49:14 ozaki-r Exp $");
 
 #include <sys/param.h>
 #include <sys/cprng.h>
@@ -166,11 +166,23 @@ calc_cache_size(vsize_t vasz, int pct, i
 	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

Index: src/sys/rump/librump/rumpkern/rump.c
diff -u src/sys/rump/librump/rumpkern/rump.c:1.329 src/sys/rump/librump/rumpkern/rump.c:1.330
--- src/sys/rump/librump/rumpkern/rump.c:1.329	Tue Mar  8 14:30:48 2016
+++ src/sys/rump/librump/rumpkern/rump.c	Tue Nov 21 08:49:14 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: rump.c,v 1.329 2016/03/08 14:30:48 joerg Exp $	*/
+/*	$NetBSD: rump.c,v 1.330 2017/11/21 08:49:14 ozaki-r 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.330 2017/11/21 08:49:14 ozaki-r Exp $");
 
 #include <sys/systm.h>
 #define ELFSIZE ARCH_ELFSIZE
@@ -301,6 +301,7 @@ rump_init(void)
 	callout_startup();
 
 	kprintf_init();
+	percpu_init();
 	pserialize_init();
 
 	kauth_init();
@@ -351,7 +352,6 @@ rump_init(void)
 	rump_schedule();
 	bootlwp = curlwp;
 
-	percpu_init();
 	inittimecounter();
 	ntp_init();
 

Index: src/sys/sys/pserialize.h
diff -u src/sys/sys/pserialize.h:1.1 src/sys/sys/pserialize.h:1.2
--- src/sys/sys/pserialize.h:1.1	Sat Jul 30 17:01:04 2011
+++ src/sys/sys/pserialize.h	Tue Nov 21 08:49:15 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: pserialize.h,v 1.1 2011/07/30 17:01:04 christos Exp $	*/
+/*	$NetBSD: pserialize.h,v 1.2 2017/11/21 08:49:15 ozaki-r Exp $	*/
 
 /*-
  * Copyright (c) 2010, 2011 The NetBSD Foundation, Inc.
@@ -44,6 +44,8 @@ void		pserialize_perform(pserialize_t);
 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_ */

Reply via email to