Module Name: src
Committed By: martin
Date: Thu Nov 30 14:40:46 UTC 2017
Modified Files:
src/sys/kern [netbsd-8]: kern_lock.c subr_pserialize.c
src/sys/rump/librump/rumpkern [netbsd-8]: emul.c rump.c
src/sys/sys [netbsd-8]: pserialize.h
Log Message:
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)
To generate a diff of this commit:
cvs rdiff -u -r1.158 -r1.158.6.1 src/sys/kern/kern_lock.c
cvs rdiff -u -r1.8 -r1.8.10.1 src/sys/kern/subr_pserialize.c
cvs rdiff -u -r1.181.6.1 -r1.181.6.2 src/sys/rump/librump/rumpkern/emul.c
cvs rdiff -u -r1.329 -r1.329.10.1 src/sys/rump/librump/rumpkern/rump.c
cvs rdiff -u -r1.1 -r1.1.46.1 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.158 src/sys/kern/kern_lock.c:1.158.6.1
--- src/sys/kern/kern_lock.c:1.158 Thu Jan 26 04:11:56 2017
+++ src/sys/kern/kern_lock.c Thu Nov 30 14:40:46 2017
@@ -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 @@ __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.8.10.1
--- src/sys/kern/subr_pserialize.c:1.8 Fri Jun 12 19:18:30 2015
+++ src/sys/kern/subr_pserialize.c Thu Nov 30 14:40:46 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.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_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.181.6.1 src/sys/rump/librump/rumpkern/emul.c:1.181.6.2
--- src/sys/rump/librump/rumpkern/emul.c:1.181.6.1 Sun Jun 4 20:35:01 2017
+++ src/sys/rump/librump/rumpkern/emul.c Thu Nov 30 14:40:46 2017
@@ -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 @@ __KERNEL_RCSID(0, "$NetBSD: emul.c,v 1.1
#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 @@ 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.329.10.1
--- src/sys/rump/librump/rumpkern/rump.c:1.329 Tue Mar 8 14:30:48 2016
+++ src/sys/rump/librump/rumpkern/rump.c Thu Nov 30 14:40:46 2017
@@ -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 @@ 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.1.46.1
--- src/sys/sys/pserialize.h:1.1 Sat Jul 30 17:01:04 2011
+++ src/sys/sys/pserialize.h Thu Nov 30 14:40:46 2017
@@ -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 @@ 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_ */