Module Name: src Committed By: ozaki-r Date: Fri Nov 17 09:26:36 UTC 2017
Modified Files: src/sys/kern: subr_localcount.c src/sys/sys: localcount.h Log Message: Implement a debugging facility (overflow/underflow detection) for localcount We cannot get an accurate count from a localcount instance because it consists of per-cpu counters and we have no way to sum them up atomically. So we cannot detect counter overflow/underflow as we can do on a normal refcount. The facility adds an atomic counter to each localcount instance to enable the validations. The counter ups and downs in synchronization with the per-CPU counters. The counter is used iff both DEBUG and LOCKDEBUG are enabled in the kernel. Discussed on tech-kern@ To generate a diff of this commit: cvs rdiff -u -r1.6 -r1.7 src/sys/kern/subr_localcount.c cvs rdiff -u -r1.4 -r1.5 src/sys/sys/localcount.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/subr_localcount.c diff -u src/sys/kern/subr_localcount.c:1.6 src/sys/kern/subr_localcount.c:1.7 --- src/sys/kern/subr_localcount.c:1.6 Mon Jun 12 21:08:34 2017 +++ src/sys/kern/subr_localcount.c Fri Nov 17 09:26:36 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: subr_localcount.c,v 1.6 2017/06/12 21:08:34 riastradh Exp $ */ +/* $NetBSD: subr_localcount.c,v 1.7 2017/11/17 09:26:36 ozaki-r Exp $ */ /*- * Copyright (c) 2016 The NetBSD Foundation, Inc. @@ -44,7 +44,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: subr_localcount.c,v 1.6 2017/06/12 21:08:34 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: subr_localcount.c,v 1.7 2017/11/17 09:26:36 ozaki-r Exp $"); #include <sys/param.h> #include <sys/localcount.h> @@ -54,6 +54,9 @@ __KERNEL_RCSID(0, "$NetBSD: subr_localco #include <sys/mutex.h> #include <sys/percpu.h> #include <sys/xcall.h> +#if defined(DEBUG) && defined(LOCKDEBUG) +#include <sys/atomic.h> +#endif static void localcount_xc(void *, void *); @@ -209,6 +212,10 @@ localcount_acquire(struct localcount *lc KASSERT(lc->lc_totalp == NULL); localcount_adjust(lc, +1); +#if defined(DEBUG) && defined(LOCKDEBUG) + if (atomic_inc_32_nv(&lc->lc_refcnt) == 0) + panic("counter overflow"); +#endif } /* @@ -253,5 +260,26 @@ localcount_release(struct localcount *lc } localcount_adjust(lc, -1); +#if defined(DEBUG) && defined(LOCKDEBUG) + if (atomic_dec_32_nv(&lc->lc_refcnt) == UINT_MAX) + panic("counter underflow"); +#endif out: kpreempt_enable(); } + +/* + * localcount_debug_refcnt(lc) + * + * Return a total reference count of lc. It returns a correct value + * only if DEBUG and LOCKDEBUG enabled. Otherwise always return 0. + */ +uint32_t +localcount_debug_refcnt(const struct localcount *lc) +{ + +#if defined(DEBUG) && defined(LOCKDEBUG) + return lc->lc_refcnt; +#else + return 0; +#endif +} Index: src/sys/sys/localcount.h diff -u src/sys/sys/localcount.h:1.4 src/sys/sys/localcount.h:1.5 --- src/sys/sys/localcount.h:1.4 Fri Jun 2 00:32:12 2017 +++ src/sys/sys/localcount.h Fri Nov 17 09:26:36 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: localcount.h,v 1.4 2017/06/02 00:32:12 chs Exp $ */ +/* $NetBSD: localcount.h,v 1.5 2017/11/17 09:26:36 ozaki-r Exp $ */ /*- * Copyright (c) 2016 The NetBSD Foundation, Inc. @@ -43,8 +43,9 @@ struct kmutex; struct percpu; struct localcount { - int64_t *lc_totalp; - struct percpu *lc_percpu; /* int64_t */ + int64_t *lc_totalp; + struct percpu *lc_percpu; /* int64_t */ + volatile uint32_t lc_refcnt; /* only for debugging */ }; void localcount_init(struct localcount *); @@ -55,4 +56,7 @@ void localcount_acquire(struct localcoun void localcount_release(struct localcount *, struct kcondvar *, struct kmutex *); +uint32_t + localcount_debug_refcnt(const struct localcount *); + #endif /* _SYS_LOCALCOUNT_H */