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_ */