diff --git a/sys/kern/kern_ktrace.c b/sys/kern/kern_ktrace.c index a377001760b9..30ba715dbed7 100644 --- a/sys/kern/kern_ktrace.c +++ b/sys/kern/kern_ktrace.c @@ -76,6 +76,7 @@ __KERNEL_RCSID(0, "$NetBSD: kern_ktrace.c,v 1.179 2022/03/12 17:45:53 riastradh #include #include #include +#include #include #include @@ -807,7 +808,7 @@ ktr_psig(int sig, sig_t action, const sigset_t *mask, } void -ktr_csw(int out, int user) +ktr_csw(int out, int user, const struct syncobj *syncobj) { lwp_t *l = curlwp; struct proc *p = l->l_proc; @@ -819,10 +820,16 @@ ktr_csw(int out, int user) /* * Don't record context switches resulting from blocking on - * locks; it's too easy to get duff results. + * locks; the results are not useful, and the mutex may be in a + * softint, which would lead us to ktealloc in softint context, + * which is forbidden. */ - if (l->l_syncobj == &mutex_syncobj || l->l_syncobj == &rw_syncobj) + if (syncobj == &mutex_syncobj || syncobj == &rw_syncobj) return; + KASSERTMSG(!cpu_intr_p() && !cpu_softintr_p(), + "[%s] syncobj=%p mutex_syncobj=%p rw_syncobj=%p", + l->l_name ? l->l_name : p->p_comm, + syncobj, &mutex_syncobj, &rw_syncobj); /* * We can't sleep if we're already going to sleep (if original diff --git a/sys/kern/kern_sleepq.c b/sys/kern/kern_sleepq.c index c5c86e5a755b..23b5635fd726 100644 --- a/sys/kern/kern_sleepq.c +++ b/sys/kern/kern_sleepq.c @@ -309,8 +309,9 @@ lwp_t *l = curlwp; bool early = false; int biglocks = l->l_biglocks; + struct syncobj *syncobj = l->l_syncobj; - ktrcsw(1, 0); + ktrcsw(1, 0, syncobj); /* * If sleeping interruptably, check for pending signals, exits or @@ -397,7 +398,7 @@ } } - ktrcsw(0, 0); + ktrcsw(0, 0, syncobj); if (__predict_false(biglocks != 0)) { KERNEL_LOCK(biglocks, NULL); } diff --git a/sys/sys/ktrace.h b/sys/sys/ktrace.h index 0a74223b9dcb..18a0fea03380 100644 --- a/sys/sys/ktrace.h +++ b/sys/sys/ktrace.h @@ -297,6 +297,8 @@ __END_DECLS #else +struct syncobj; + void ktrinit(void); void ktrderef(struct proc *); void ktradref(struct proc *); @@ -307,7 +309,7 @@ extern int ktrace_on; int ktruser(const char *, void *, size_t, int); bool ktr_point(int); -void ktr_csw(int, int); +void ktr_csw(int, int, const struct syncobj *); void ktr_emul(void); void ktr_geniov(int, enum uio_rw, struct iovec *, size_t, int); void ktr_genio(int, enum uio_rw, const void *, size_t, int); @@ -349,10 +351,10 @@ ktrpoint(int fac) } static __inline void -ktrcsw(int a, int b) +ktrcsw(int a, int b, const struct syncobj *c) { if (__predict_false(ktrace_on)) - ktr_csw(a, b); + ktr_csw(a, b, c); } static __inline void