Implement a simple psref leak detector
It detects leaks by counting up the number of held psref by an LWP and checking its zeroness at the end of syscalls and softint handlers. For the counter, a unused field of struct lwp is reused. The detector runs only if DIAGNOSTIC is turned on.
This commit is contained in:
parent
ad35be2d80
commit
3843688c40
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: kern_lwp.c,v 1.196 2019/03/01 09:02:03 hannken Exp $ */
|
||||
/* $NetBSD: kern_lwp.c,v 1.197 2019/04/19 01:52:55 ozaki-r Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2001, 2006, 2007, 2008, 2009 The NetBSD Foundation, Inc.
|
||||
|
@ -211,7 +211,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: kern_lwp.c,v 1.196 2019/03/01 09:02:03 hannken Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: kern_lwp.c,v 1.197 2019/04/19 01:52:55 ozaki-r Exp $");
|
||||
|
||||
#include "opt_ddb.h"
|
||||
#include "opt_lockdebug.h"
|
||||
|
@ -836,6 +836,7 @@ lwp_create(lwp_t *l1, proc_t *p2, vaddr_t uaddr, int flags,
|
|||
l2->l_flag = 0;
|
||||
l2->l_pflag = LP_MPSAFE;
|
||||
TAILQ_INIT(&l2->l_ld_locks);
|
||||
l2->l_psrefs = 0;
|
||||
|
||||
/*
|
||||
* For vfork, borrow parent's lwpctl context if it exists.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: kern_softint.c,v 1.45 2017/12/28 03:39:48 msaitoh Exp $ */
|
||||
/* $NetBSD: kern_softint.c,v 1.46 2019/04/19 01:52:55 ozaki-r Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2007, 2008 The NetBSD Foundation, Inc.
|
||||
|
@ -170,7 +170,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: kern_softint.c,v 1.45 2017/12/28 03:39:48 msaitoh Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: kern_softint.c,v 1.46 2019/04/19 01:52:55 ozaki-r Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/proc.h>
|
||||
|
@ -595,6 +595,9 @@ softint_execute(softint_t *si, lwp_t *l, int s)
|
|||
KASSERTMSG(curcpu()->ci_mtx_count == 0,
|
||||
"%s: ci_mtx_count (%d) != 0, sh_func %p\n",
|
||||
__func__, curcpu()->ci_mtx_count, sh->sh_func);
|
||||
/* Diagnostic: check that psrefs have not leaked. */
|
||||
KASSERTMSG(l->l_psrefs == 0, "%s: l_psrefs=%d, sh_func=%p\n",
|
||||
__func__, l->l_psrefs, sh->sh_func);
|
||||
|
||||
(void)splhigh();
|
||||
KASSERT((sh->sh_flags & SOFTINT_ACTIVE) != 0);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: subr_psref.c,v 1.11 2018/02/01 03:17:00 ozaki-r Exp $ */
|
||||
/* $NetBSD: subr_psref.c,v 1.12 2019/04/19 01:52:55 ozaki-r Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2016 The NetBSD Foundation, Inc.
|
||||
|
@ -64,7 +64,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: subr_psref.c,v 1.11 2018/02/01 03:17:00 ozaki-r Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: subr_psref.c,v 1.12 2019/04/19 01:52:55 ozaki-r Exp $");
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/condvar.h>
|
||||
|
@ -278,6 +278,10 @@ psref_acquire(struct psref *psref, const struct psref_target *target,
|
|||
/* Release the CPU list and restore interrupts. */
|
||||
percpu_putref(class->prc_percpu);
|
||||
splx(s);
|
||||
|
||||
#ifdef DIAGNOSTIC
|
||||
curlwp->l_psrefs++;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -332,6 +336,11 @@ psref_release(struct psref *psref, const struct psref_target *target,
|
|||
percpu_putref(class->prc_percpu);
|
||||
splx(s);
|
||||
|
||||
#ifdef DIAGNOSTIC
|
||||
KASSERT(curlwp->l_psrefs > 0);
|
||||
curlwp->l_psrefs--;
|
||||
#endif
|
||||
|
||||
/* If someone is waiting for users to drain, notify 'em. */
|
||||
if (__predict_false(target->prt_draining))
|
||||
cv_broadcast(&class->prc_cv);
|
||||
|
@ -388,6 +397,10 @@ psref_copy(struct psref *pto, const struct psref *pfrom,
|
|||
/* Release the CPU list and restore interrupts. */
|
||||
percpu_putref(class->prc_percpu);
|
||||
splx(s);
|
||||
|
||||
#ifdef DIAGNOSTIC
|
||||
curlwp->l_psrefs++;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: sysproxy.c,v 1.5 2019/04/18 08:31:44 ozaki-r Exp $ */
|
||||
/* $NetBSD: sysproxy.c,v 1.6 2019/04/19 01:52:55 ozaki-r Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2010, 2011 Antti Kantee. All Rights Reserved.
|
||||
|
@ -26,7 +26,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: sysproxy.c,v 1.5 2019/04/18 08:31:44 ozaki-r Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: sysproxy.c,v 1.6 2019/04/19 01:52:55 ozaki-r Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/filedesc.h>
|
||||
|
@ -77,6 +77,7 @@ hyp_syscall(int num, void *arg, long *retval)
|
|||
/* Sanity checks (from mi_userret) */
|
||||
LOCKDEBUG_BARRIER(NULL, 0);
|
||||
KASSERT(l->l_nopreempt == 0);
|
||||
KASSERT(l->l_psrefs == 0);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: lwp.h,v 1.181 2019/03/01 09:02:03 hannken Exp $ */
|
||||
/* $NetBSD: lwp.h,v 1.182 2019/04/19 01:52:55 ozaki-r Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2001, 2006, 2007, 2008, 2009, 2010
|
||||
|
@ -184,7 +184,7 @@ struct lwp {
|
|||
u_int l_cv_signalled; /* c: restarted by cv_signal() */
|
||||
u_short l_shlocks; /* !: lockdebug: shared locks held */
|
||||
u_short l_exlocks; /* !: lockdebug: excl. locks held */
|
||||
u_short l_unused; /* !: unused */
|
||||
u_short l_psrefs; /* !: count of psref held */
|
||||
u_short l_blcnt; /* !: count of kernel_lock held */
|
||||
int l_nopreempt; /* !: don't preempt me! */
|
||||
u_int l_dopreempt; /* s: kernel preemption pending */
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: userret.h,v 1.26 2013/04/07 07:54:53 kiyohara Exp $ */
|
||||
/* $NetBSD: userret.h,v 1.27 2019/04/19 01:52:55 ozaki-r Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1998, 2000, 2003, 2006, 2008 The NetBSD Foundation, Inc.
|
||||
|
@ -114,6 +114,7 @@ mi_userret(struct lwp *l)
|
|||
|
||||
LOCKDEBUG_BARRIER(NULL, 0);
|
||||
KASSERT(l->l_nopreempt == 0);
|
||||
KASSERT(l->l_psrefs == 0);
|
||||
}
|
||||
|
||||
#endif /* !_SYS_USERRET_H_ */
|
||||
|
|
Loading…
Reference in New Issue