Implement an aggressive psref leak detector

It is yet another psref leak detector that enables to tell where a leak occurs
while a simpler version that is already committed just tells an occurrence of a
leak.

Investigating of psref leaks is hard because once a leak occurs a percpu list of
psref that tracks references can be corrupted.  A reference to a tracking object
is memorized in the list via an intermediate object (struct psref) that is
normally allocated on a stack of a thread.  Thus, the intermediate object can be
overwritten on a leak resulting in corruption of the list.

The tracker makes a shadow entry to an intermediate object and stores some hints
into it (currently it's a caller address of psref_acquire).  We can detect a
leak by checking the entries on certain points where any references should be
released such as the return point of syscalls and the end of each softint
handler.

The feature is expensive and enabled only if the kernel is built with
PSREF_DEBUG.

Proposed on tech-kern
This commit is contained in:
ozaki-r 2019-05-17 03:34:26 +00:00
parent 01a177fdbf
commit 7fc219a5ee
15 changed files with 229 additions and 33 deletions

View File

@ -1,4 +1,4 @@
# $NetBSD: files,v 1.1235 2019/04/26 10:11:03 jmcneill Exp $
# $NetBSD: files,v 1.1236 2019/05/17 03:34:26 ozaki-r Exp $
# @(#)files.newconf 7.5 (Berkeley) 5/10/93
version 20171118
@ -315,6 +315,7 @@ defparam opt_kgdb.h KGDB_DEV KGDB_DEVNAME KGDB_DEVPORT
defflag LOCKDEBUG
defflag SYSCALL_DEBUG
defflag opt_kstack.h KSTACK_CHECK_MAGIC
defflag PSREF_DEBUG
# memory (ram) disk options
#

View File

@ -1,4 +1,4 @@
/* $NetBSD: init_main.c,v 1.503 2019/02/20 10:07:27 hannken Exp $ */
/* $NetBSD: init_main.c,v 1.504 2019/05/17 03:34:26 ozaki-r Exp $ */
/*-
* Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
@ -97,7 +97,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: init_main.c,v 1.503 2019/02/20 10:07:27 hannken Exp $");
__KERNEL_RCSID(0, "$NetBSD: init_main.c,v 1.504 2019/05/17 03:34:26 ozaki-r Exp $");
#include "opt_ddb.h"
#include "opt_inet.h"
@ -195,6 +195,7 @@ extern void *_binary_splash_image_end;
#include <sys/kauth.h>
#include <net80211/ieee80211_netbsd.h>
#include <sys/cprng.h>
#include <sys/psref.h>
#include <sys/syscall.h>
#include <sys/syscallargs.h>
@ -393,6 +394,9 @@ main(void)
procinit();
lwpinit();
/* Must be called after lwpinit (lwpinit_specificdata) */
psref_init();
/* Initialize signal-related data structures. */
signal_init();

View File

@ -1,4 +1,4 @@
/* $NetBSD: kern_exit.c,v 1.274 2019/03/01 09:02:03 hannken Exp $ */
/* $NetBSD: kern_exit.c,v 1.275 2019/05/17 03:34:26 ozaki-r Exp $ */
/*-
* Copyright (c) 1998, 1999, 2006, 2007, 2008 The NetBSD Foundation, Inc.
@ -67,7 +67,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: kern_exit.c,v 1.274 2019/03/01 09:02:03 hannken Exp $");
__KERNEL_RCSID(0, "$NetBSD: kern_exit.c,v 1.275 2019/05/17 03:34:26 ozaki-r Exp $");
#include "opt_ktrace.h"
#include "opt_dtrace.h"
@ -105,6 +105,7 @@ __KERNEL_RCSID(0, "$NetBSD: kern_exit.c,v 1.274 2019/03/01 09:02:03 hannken Exp
#include <sys/lwpctl.h>
#include <sys/atomic.h>
#include <sys/sdt.h>
#include <sys/psref.h>
#include <uvm/uvm_extern.h>

View File

@ -1,4 +1,4 @@
/* $NetBSD: kern_lwp.c,v 1.200 2019/05/03 22:34:21 kamil Exp $ */
/* $NetBSD: kern_lwp.c,v 1.201 2019/05/17 03:34:26 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.200 2019/05/03 22:34:21 kamil Exp $");
__KERNEL_RCSID(0, "$NetBSD: kern_lwp.c,v 1.201 2019/05/17 03:34:26 ozaki-r Exp $");
#include "opt_ddb.h"
#include "opt_lockdebug.h"
@ -242,6 +242,7 @@ __KERNEL_RCSID(0, "$NetBSD: kern_lwp.c,v 1.200 2019/05/03 22:34:21 kamil Exp $")
#include <sys/xcall.h>
#include <sys/uidinfo.h>
#include <sys/sysctl.h>
#include <sys/psref.h>
#include <uvm/uvm_extern.h>
#include <uvm/uvm_object.h>
@ -878,6 +879,7 @@ lwp_create(lwp_t *l1, proc_t *p2, vaddr_t uaddr, int flags,
cv_init(&l2->l_sigcv, "sigwait");
cv_init(&l2->l_waitcv, "vfork");
l2->l_syncobj = &sched_syncobj;
PSREF_DEBUG_INIT_LWP(l2);
if (rnewlwpp != NULL)
*rnewlwpp = l2;

View File

@ -1,4 +1,4 @@
/* $NetBSD: kern_softint.c,v 1.46 2019/04/19 01:52:55 ozaki-r Exp $ */
/* $NetBSD: kern_softint.c,v 1.47 2019/05/17 03:34:26 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.46 2019/04/19 01:52:55 ozaki-r Exp $");
__KERNEL_RCSID(0, "$NetBSD: kern_softint.c,v 1.47 2019/05/17 03:34:26 ozaki-r Exp $");
#include <sys/param.h>
#include <sys/proc.h>
@ -604,6 +604,8 @@ softint_execute(softint_t *si, lwp_t *l, int s)
sh->sh_flags ^= SOFTINT_ACTIVE;
}
PSREF_DEBUG_BARRIER();
if (havelock) {
KERNEL_UNLOCK_ONE(l);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: subr_lwp_specificdata.c,v 1.3 2013/10/25 16:17:35 martin Exp $ */
/* $NetBSD: subr_lwp_specificdata.c,v 1.4 2019/05/17 03:34:26 ozaki-r Exp $ */
/*-
* Copyright (c) 2006 The NetBSD Foundation, Inc.
@ -29,7 +29,7 @@
#define _LWP_API_PRIVATE
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: subr_lwp_specificdata.c,v 1.3 2013/10/25 16:17:35 martin Exp $");
__KERNEL_RCSID(0, "$NetBSD: subr_lwp_specificdata.c,v 1.4 2019/05/17 03:34:26 ozaki-r Exp $");
#include <sys/param.h>
#include <sys/lwp.h>
@ -129,3 +129,11 @@ lwp_setspecific(specificdata_key_t key, void *data)
specificdata_setspecific(lwp_specificdata_domain,
&curlwp->l_specdataref, key, data);
}
void
lwp_setspecific_by_lwp(struct lwp *l, specificdata_key_t key, void *data)
{
specificdata_setspecific(lwp_specificdata_domain,
&l->l_specdataref, key, data);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: subr_psref.c,v 1.12 2019/04/19 01:52:55 ozaki-r Exp $ */
/* $NetBSD: subr_psref.c,v 1.13 2019/05/17 03:34:26 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.12 2019/04/19 01:52:55 ozaki-r Exp $");
__KERNEL_RCSID(0, "$NetBSD: subr_psref.c,v 1.13 2019/05/17 03:34:26 ozaki-r Exp $");
#include <sys/types.h>
#include <sys/condvar.h>
@ -77,6 +77,7 @@ __KERNEL_RCSID(0, "$NetBSD: subr_psref.c,v 1.12 2019/04/19 01:52:55 ozaki-r Exp
#include <sys/psref.h>
#include <sys/queue.h>
#include <sys/xcall.h>
#include <sys/lwp.h>
SLIST_HEAD(psref_head, psref);
@ -107,6 +108,44 @@ struct psref_cpu {
struct psref_head pcpu_head;
};
/*
* Data structures and functions for debugging.
*/
#ifndef PSREF_DEBUG_NITEMS
#define PSREF_DEBUG_NITEMS 16
#endif
struct psref_debug_item {
void *prdi_caller;
struct psref *prdi_psref;
};
struct psref_debug {
int prd_refs_peek;
struct psref_debug_item prd_items[PSREF_DEBUG_NITEMS];
};
#ifdef PSREF_DEBUG
static void psref_debug_acquire(struct psref *);
static void psref_debug_release(struct psref *);
static void psref_debug_lwp_free(void *);
static specificdata_key_t psref_debug_lwp_key;
#endif
/*
* psref_init()
*/
void
psref_init(void)
{
#ifdef PSREF_DEBUG
lwp_specific_key_create(&psref_debug_lwp_key, psref_debug_lwp_free);
#endif
}
/*
* psref_class_create(name, ipl)
*
@ -279,9 +318,12 @@ psref_acquire(struct psref *psref, const struct psref_target *target,
percpu_putref(class->prc_percpu);
splx(s);
#ifdef DIAGNOSTIC
#if defined(DIAGNOSTIC) || defined(PSREF_DEBUG)
curlwp->l_psrefs++;
#endif
#ifdef PSREF_DEBUG
psref_debug_acquire(psref);
#endif
}
/*
@ -336,10 +378,13 @@ psref_release(struct psref *psref, const struct psref_target *target,
percpu_putref(class->prc_percpu);
splx(s);
#ifdef DIAGNOSTIC
#if defined(DIAGNOSTIC) || defined(PSREF_DEBUG)
KASSERT(curlwp->l_psrefs > 0);
curlwp->l_psrefs--;
#endif
#ifdef PSREF_DEBUG
psref_debug_release(psref);
#endif
/* If someone is waiting for users to drain, notify 'em. */
if (__predict_false(target->prt_draining))
@ -398,7 +443,7 @@ psref_copy(struct psref *pto, const struct psref *pfrom,
percpu_putref(class->prc_percpu);
splx(s);
#ifdef DIAGNOSTIC
#if defined(DIAGNOSTIC) || defined(PSREF_DEBUG)
curlwp->l_psrefs++;
#endif
}
@ -565,3 +610,90 @@ psref_held(const struct psref_target *target, struct psref_class *class)
return _psref_held(target, class, false);
}
#ifdef PSREF_DEBUG
void
psref_debug_init_lwp(struct lwp *l)
{
struct psref_debug *prd;
prd = kmem_zalloc(sizeof(*prd), KM_SLEEP);
lwp_setspecific_by_lwp(l, psref_debug_lwp_key, prd);
}
static void
psref_debug_lwp_free(void *arg)
{
struct psref_debug *prd = arg;
kmem_free(prd, sizeof(*prd));
}
static void
psref_debug_acquire(struct psref *psref)
{
struct psref_debug *prd;
struct lwp *l = curlwp;
int s, i;
prd = lwp_getspecific(psref_debug_lwp_key);
if (__predict_false(prd == NULL)) {
psref->psref_debug = NULL;
return;
}
s = splserial();
if (l->l_psrefs > prd->prd_refs_peek) {
prd->prd_refs_peek = l->l_psrefs;
if (__predict_false(prd->prd_refs_peek > PSREF_DEBUG_NITEMS))
panic("exceeded PSREF_DEBUG_NITEMS");
}
for (i = 0; i < prd->prd_refs_peek; i++) {
struct psref_debug_item *prdi = &prd->prd_items[i];
if (prdi->prdi_psref != NULL)
continue;
prdi->prdi_caller = psref->psref_debug;
prdi->prdi_psref = psref;
psref->psref_debug = prdi;
break;
}
if (__predict_false(i == prd->prd_refs_peek))
panic("out of range: %d", i);
splx(s);
}
static void
psref_debug_release(struct psref *psref)
{
int s;
s = splserial();
if (__predict_true(psref->psref_debug != NULL)) {
struct psref_debug_item *prdi = psref->psref_debug;
prdi->prdi_psref = NULL;
}
splx(s);
}
void
psref_debug_barrier(void)
{
struct psref_debug *prd;
struct lwp *l = curlwp;
int s, i;
prd = lwp_getspecific(psref_debug_lwp_key);
if (__predict_false(prd == NULL))
return;
s = splserial();
for (i = 0; i < prd->prd_refs_peek; i++) {
struct psref_debug_item *prdi = &prd->prd_items[i];
if (__predict_true(prdi->prdi_psref == NULL))
continue;
panic("psref leaked: lwp(%p) acquired at %p", l, prdi->prdi_caller);
}
prd->prd_refs_peek = 0; /* Reset the counter */
splx(s);
}
#endif /* PSREF_DEBUG */

View File

@ -1,4 +1,4 @@
/* $NetBSD: if.c,v 1.452 2019/05/15 02:56:48 ozaki-r Exp $ */
/* $NetBSD: if.c,v 1.453 2019/05/17 03:34:26 ozaki-r Exp $ */
/*-
* Copyright (c) 1999, 2000, 2001, 2008 The NetBSD Foundation, Inc.
@ -90,7 +90,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: if.c,v 1.452 2019/05/15 02:56:48 ozaki-r Exp $");
__KERNEL_RCSID(0, "$NetBSD: if.c,v 1.453 2019/05/17 03:34:26 ozaki-r Exp $");
#if defined(_KERNEL_OPT)
#include "opt_inet.h"
@ -1863,6 +1863,7 @@ void
ifa_acquire(struct ifaddr *ifa, struct psref *psref)
{
PSREF_DEBUG_FILL_RETURN_ADDRESS(psref);
psref_acquire(psref, &ifa->ifa_psref, ifa_psref_class);
}
@ -2739,6 +2740,7 @@ if_get(const char *name, struct psref *psref)
if (if_is_deactivated(ifp))
continue;
if (strcmp(ifp->if_xname, name) == 0) {
PSREF_DEBUG_FILL_RETURN_ADDRESS(psref);
psref_acquire(psref, &ifp->if_psref,
ifnet_psref_class);
goto out;
@ -2802,8 +2804,10 @@ if_get_byindex(u_int idx, struct psref *psref)
s = pserialize_read_enter();
ifp = if_byindex(idx);
if (__predict_true(ifp != NULL))
if (__predict_true(ifp != NULL)) {
PSREF_DEBUG_FILL_RETURN_ADDRESS(psref);
psref_acquire(psref, &ifp->if_psref, ifnet_psref_class);
}
pserialize_read_exit(s);
return ifp;

View File

@ -1,4 +1,4 @@
/* $NetBSD: route.c,v 1.218 2019/04/29 11:57:22 roy Exp $ */
/* $NetBSD: route.c,v 1.219 2019/05/17 03:34:26 ozaki-r Exp $ */
/*-
* Copyright (c) 1998, 2008 The NetBSD Foundation, Inc.
@ -97,7 +97,7 @@
#endif
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: route.c,v 1.218 2019/04/29 11:57:22 roy Exp $");
__KERNEL_RCSID(0, "$NetBSD: route.c,v 1.219 2019/05/17 03:34:26 ozaki-r Exp $");
#include <sys/param.h>
#ifdef RTFLUSH_DEBUG
@ -2077,6 +2077,8 @@ rtcache_ref(struct rtentry *rt, struct route *ro)
#ifdef NET_MPSAFE
RTCACHE_PSREF_TRACE(rt, ro);
ro->ro_bound = curlwp_bind();
/* XXX Use a real caller's address */
PSREF_DEBUG_FILL_RETURN_ADDRESS(&ro->ro_psref);
psref_acquire(&ro->ro_psref, &rt->rt_psref, rt_psref_class);
#endif
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: sysproxy.c,v 1.6 2019/04/19 01:52:55 ozaki-r Exp $ */
/* $NetBSD: sysproxy.c,v 1.7 2019/05/17 03:34:26 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.6 2019/04/19 01:52:55 ozaki-r Exp $");
__KERNEL_RCSID(0, "$NetBSD: sysproxy.c,v 1.7 2019/05/17 03:34:26 ozaki-r Exp $");
#include <sys/param.h>
#include <sys/filedesc.h>
@ -36,6 +36,7 @@ __KERNEL_RCSID(0, "$NetBSD: sysproxy.c,v 1.6 2019/04/19 01:52:55 ozaki-r Exp $")
#include <sys/systm.h>
#include <sys/xcall.h>
#include <sys/lockdebug.h>
#include <sys/psref.h>
#define _RUMP_SYSPROXY
#include <rump/rumpuser.h>
@ -77,6 +78,7 @@ hyp_syscall(int num, void *arg, long *retval)
/* Sanity checks (from mi_userret) */
LOCKDEBUG_BARRIER(NULL, 0);
KASSERT(l->l_nopreempt == 0);
PSREF_DEBUG_BARRIER();
KASSERT(l->l_psrefs == 0);
return rv;

View File

@ -1,4 +1,4 @@
/* $NetBSD: lwproc.c,v 1.41 2019/03/09 09:02:38 hannken Exp $ */
/* $NetBSD: lwproc.c,v 1.42 2019/05/17 03:34:26 ozaki-r Exp $ */
/*
* Copyright (c) 2010, 2011 Antti Kantee. All Rights Reserved.
@ -28,7 +28,7 @@
#define RUMP__CURLWP_PRIVATE
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: lwproc.c,v 1.41 2019/03/09 09:02:38 hannken Exp $");
__KERNEL_RCSID(0, "$NetBSD: lwproc.c,v 1.42 2019/05/17 03:34:26 ozaki-r Exp $");
#include <sys/param.h>
#include <sys/atomic.h>
@ -43,6 +43,7 @@ __KERNEL_RCSID(0, "$NetBSD: lwproc.c,v 1.41 2019/03/09 09:02:38 hannken Exp $");
#include <sys/queue.h>
#include <sys/resourcevar.h>
#include <sys/uidinfo.h>
#include <sys/psref.h>
#include <rump-sys/kern.h>
@ -372,6 +373,7 @@ lwproc_makelwp(struct proc *p, struct lwp *l, bool doswitch, bool procmake)
lwp_update_creds(l);
lwp_initspecific(l);
PSREF_DEBUG_INIT_LWP(l);
membar_enter();
lwproc_curlwpop(RUMPUSER_LWP_CREATE, l);

View File

@ -1,4 +1,4 @@
/* $NetBSD: rump.c,v 1.333 2019/03/29 02:09:14 christos Exp $ */
/* $NetBSD: rump.c,v 1.334 2019/05/17 03:34:26 ozaki-r 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.333 2019/03/29 02:09:14 christos Exp $");
__KERNEL_RCSID(0, "$NetBSD: rump.c,v 1.334 2019/05/17 03:34:26 ozaki-r Exp $");
#include <sys/systm.h>
#define ELFSIZE ARCH_ELFSIZE
@ -74,6 +74,7 @@ __KERNEL_RCSID(0, "$NetBSD: rump.c,v 1.333 2019/03/29 02:09:14 christos Exp $");
#include <sys/cprng.h>
#include <sys/rnd.h>
#include <sys/ktrace.h>
#include <sys/psref.h>
#include <rump-sys/kern.h>
#include <rump-sys/dev.h>
@ -344,6 +345,9 @@ rump_init(void)
lwpinit_specificdata();
lwp_initspecific(&lwp0);
/* Must be called after lwpinit_specificdata */
psref_init();
threadpools_init();
loginit();

View File

@ -1,4 +1,4 @@
/* $NetBSD: lwp.h,v 1.182 2019/04/19 01:52:55 ozaki-r Exp $ */
/* $NetBSD: lwp.h,v 1.183 2019/05/17 03:34:26 ozaki-r Exp $ */
/*
* Copyright (c) 2001, 2006, 2007, 2008, 2009, 2010
@ -357,6 +357,7 @@ void *lwp_getspecific(specificdata_key_t);
void *_lwp_getspecific_by_lwp(lwp_t *, specificdata_key_t);
#endif
void lwp_setspecific(specificdata_key_t, void *);
void lwp_setspecific_by_lwp(lwp_t *, specificdata_key_t, void *);
/* Syscalls. */
int lwp_park(clockid_t, int, struct timespec *, const void *);

View File

@ -1,4 +1,4 @@
/* $NetBSD: psref.h,v 1.3 2017/12/11 02:33:17 knakahara Exp $ */
/* $NetBSD: psref.h,v 1.4 2019/05/17 03:34:27 ozaki-r Exp $ */
/*-
* Copyright (c) 2016 The NetBSD Foundation, Inc.
@ -32,6 +32,10 @@
#ifndef _SYS_PSREF_H
#define _SYS_PSREF_H
#ifdef _KERNEL_OPT
#include "opt_psref_debug.h"
#endif
#include <sys/types.h>
#include <sys/queue.h>
@ -70,14 +74,15 @@ struct psref_target {
*/
struct psref {
SLIST_ENTRY(psref) psref_entry;
/* To keep ABI with LIST_ENTRY(psref) version. */
void *psref_unused0;
void *psref_debug; /* For debugging */
const struct psref_target *psref_target;
struct lwp *psref_lwp;
struct cpu_info *psref_cpu;
};
#ifdef _KERNEL
void psref_init(void);
struct psref_class *
psref_class_create(const char *, int);
void psref_class_destroy(struct psref_class *);
@ -94,6 +99,30 @@ void psref_copy(struct psref *, const struct psref *,
/* For use only in assertions. */
bool psref_held(const struct psref_target *, struct psref_class *);
#endif
#ifdef PSREF_DEBUG
void psref_debug_barrier(void);
void psref_debug_init_lwp(struct lwp *);
#define PSREF_DEBUG_BARRIER() psref_debug_barrier()
#define PSREF_DEBUG_INIT_LWP(l) psref_debug_init_lwp((l))
#define PSREF_DEBUG_FILL_RETURN_ADDRESS0(psref, addr) do { \
(psref)->psref_debug = (addr); \
} while (0)
#define PSREF_DEBUG_FILL_RETURN_ADDRESS(psref) do { \
PSREF_DEBUG_FILL_RETURN_ADDRESS0(psref, __builtin_return_address(0));\
} while (0)
#else
#define PSREF_DEBUG_BARRIER() __nothing
#define PSREF_DEBUG_INIT_LWP(l) __nothing
#define PSREF_DEBUG_FILL_RETURN_ADDRESS0(psref, addr) __nothing
#define PSREF_DEBUG_FILL_RETURN_ADDRESS(psref) __nothing
#endif /* PSREF_DEBUG */
#endif /* _KERNEL */
#endif /* _SYS_PSREF_H */

View File

@ -1,4 +1,4 @@
/* $NetBSD: userret.h,v 1.27 2019/04/19 01:52:55 ozaki-r Exp $ */
/* $NetBSD: userret.h,v 1.28 2019/05/17 03:34:27 ozaki-r Exp $ */
/*-
* Copyright (c) 1998, 2000, 2003, 2006, 2008 The NetBSD Foundation, Inc.
@ -67,6 +67,7 @@
#include <sys/lockdebug.h>
#include <sys/intr.h>
#include <sys/psref.h>
/*
* Define the MI code needed before returning to user mode, for
@ -114,6 +115,7 @@ mi_userret(struct lwp *l)
LOCKDEBUG_BARRIER(NULL, 0);
KASSERT(l->l_nopreempt == 0);
PSREF_DEBUG_BARRIER();
KASSERT(l->l_psrefs == 0);
}