diff --git a/sys/kern/subr_localcount.c b/sys/kern/subr_localcount.c index 064d5407f07..2948d24ed08 100644 --- a/sys/kern/subr_localcount.c +++ b/sys/kern/subr_localcount.c @@ -54,6 +54,9 @@ __KERNEL_RCSID(0, "$NetBSD: subr_localcount.c,v 1.6 2017/06/12 21:08:34 riastrad #include #include #include +#if defined(DEBUG) && defined(LOCKDEBUG) +#include +#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_uint_nv(&lc->lc_refcnt) == 0) + panic("counter overflow"); +#endif } /* @@ -253,5 +260,26 @@ localcount_release(struct localcount *lc, kcondvar_t *cv, kmutex_t *interlock) } localcount_adjust(lc, -1); +#if defined(DEBUG) && defined(LOCKDEBUG) + if (atomic_dec_uint_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 +} diff --git a/sys/sys/localcount.h b/sys/sys/localcount.h index 6a301197e95..e43a78bf80b 100644 --- a/sys/sys/localcount.h +++ b/sys/sys/localcount.h @@ -45,6 +45,7 @@ struct percpu; struct localcount { int64_t *lc_totalp; struct percpu *lc_percpu; /* int64_t */ + uint32_t lc_refcnt; /* only for debugging */ }; void localcount_init(struct localcount *); @@ -55,4 +56,7 @@ void localcount_acquire(struct localcount *); void localcount_release(struct localcount *, struct kcondvar *, struct kmutex *); +uint32_t + localcount_debug_refcnt(const struct localcount *); + #endif /* _SYS_LOCALCOUNT_H */