diff --git a/sys/kern/kern_condvar.c b/sys/kern/kern_condvar.c index f5cc99a166c0..eec9cee0041a 100644 --- a/sys/kern/kern_condvar.c +++ b/sys/kern/kern_condvar.c @@ -70,6 +70,7 @@ static inline void cv_wakeup_one(kcondvar_t *); static inline void cv_wakeup_all(kcondvar_t *); syncobj_t cv_syncobj = { + .sobj_name = "cv", .sobj_flag = SOBJ_SLEEPQ_SORTED, .sobj_unsleep = cv_unsleep, .sobj_changepri = sleepq_changepri, @@ -171,7 +172,7 @@ cv_wait(kcondvar_t *cv, kmutex_t *mtx) KASSERT(mutex_owned(mtx)); cv_enter(cv, mtx, l, false); - (void)sleepq_block(0, false); + (void)sleepq_block(0, false, &cv_syncobj); mutex_enter(mtx); } @@ -192,7 +193,7 @@ cv_wait_sig(kcondvar_t *cv, kmutex_t *mtx) KASSERT(mutex_owned(mtx)); cv_enter(cv, mtx, l, true); - error = sleepq_block(0, true); + error = sleepq_block(0, true, &cv_syncobj); mutex_enter(mtx); return error; } @@ -215,7 +216,7 @@ cv_timedwait(kcondvar_t *cv, kmutex_t *mtx, int timo) KASSERT(mutex_owned(mtx)); cv_enter(cv, mtx, l, false); - error = sleepq_block(timo, false); + error = sleepq_block(timo, false, &cv_syncobj); mutex_enter(mtx); return error; } @@ -240,7 +241,7 @@ cv_timedwait_sig(kcondvar_t *cv, kmutex_t *mtx, int timo) KASSERT(mutex_owned(mtx)); cv_enter(cv, mtx, l, true); - error = sleepq_block(timo, true); + error = sleepq_block(timo, true, &cv_syncobj); mutex_enter(mtx); return error; } diff --git a/sys/kern/kern_ktrace.c b/sys/kern/kern_ktrace.c index a377001760b9..02a8f84736a4 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,14 @@ 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; + KASSERT(!cpu_intr_p()); + KASSERT(!cpu_softintr_p()); /* * We can't sleep if we're already going to sleep (if original diff --git a/sys/kern/kern_mutex.c b/sys/kern/kern_mutex.c index f89242f549fd..ef6bab4dda8a 100644 --- a/sys/kern/kern_mutex.c +++ b/sys/kern/kern_mutex.c @@ -301,6 +301,7 @@ lockops_t mutex_adaptive_lockops = { }; syncobj_t mutex_syncobj = { + .sobj_name = "mutex", .sobj_flag = SOBJ_SLEEPQ_SORTED, .sobj_unsleep = turnstile_unsleep, .sobj_changepri = turnstile_changepri, diff --git a/sys/kern/kern_rwlock.c b/sys/kern/kern_rwlock.c index 1dfbfb5b3521..b45bdaec7103 100644 --- a/sys/kern/kern_rwlock.c +++ b/sys/kern/kern_rwlock.c @@ -134,6 +134,7 @@ lockops_t rwlock_lockops = { }; syncobj_t rw_syncobj = { + .sobj_name = "rw", .sobj_flag = SOBJ_SLEEPQ_SORTED, .sobj_unsleep = turnstile_unsleep, .sobj_changepri = turnstile_changepri, diff --git a/sys/kern/kern_sleepq.c b/sys/kern/kern_sleepq.c index c5c86e5a755b..3f5344738897 100644 --- a/sys/kern/kern_sleepq.c +++ b/sys/kern/kern_sleepq.c @@ -302,7 +319,7 @@ * timo is a timeout in ticks. timo = 0 specifies an infinite timeout. */ int -sleepq_block(int timo, bool catch_p) +sleepq_block(int timo, bool catch_p, struct syncobj *syncobj) { int error = 0, sig; struct proc *p; @@ -310,7 +327,7 @@ bool early = false; int biglocks = l->l_biglocks; - ktrcsw(1, 0); + ktrcsw(1, 0, syncobj); /* * If sleeping interruptably, check for pending signals, exits or @@ -397,7 +414,7 @@ } } - ktrcsw(0, 0); + ktrcsw(0, 0, syncobj); if (__predict_false(biglocks != 0)) { KERNEL_LOCK(biglocks, NULL); } diff --git a/sys/kern/kern_synch.c b/sys/kern/kern_synch.c index 17646499fd51..7c0e710947ae 100644 --- a/sys/kern/kern_synch.c +++ b/sys/kern/kern_synch.c @@ -107,6 +107,7 @@ static void sched_changepri(struct lwp *, pri_t); static void sched_lendpri(struct lwp *, pri_t); syncobj_t sleep_syncobj = { + .sobj_name = "sleep", .sobj_flag = SOBJ_SLEEPQ_SORTED, .sobj_unsleep = sleepq_unsleep, .sobj_changepri = sleepq_changepri, @@ -115,6 +116,7 @@ syncobj_t sleep_syncobj = { }; syncobj_t sched_syncobj = { + .sobj_name = "sched", .sobj_flag = SOBJ_SLEEPQ_SORTED, .sobj_unsleep = sched_unsleep, .sobj_changepri = sched_changepri, @@ -123,6 +125,7 @@ syncobj_t sched_syncobj = { }; syncobj_t kpause_syncobj = { + .sobj_name = "kpause", .sobj_flag = SOBJ_SLEEPQ_NULL, .sobj_unsleep = sleepq_unsleep, .sobj_changepri = sleepq_changepri, @@ -188,7 +191,7 @@ tsleep(wchan_t ident, pri_t priority, const char *wmesg, int timo) sq = sleeptab_lookup(&sleeptab, ident, &mp); sleepq_enter(sq, l, mp); sleepq_enqueue(sq, ident, wmesg, &sleep_syncobj, catch_p); - return sleepq_block(timo, catch_p); + return sleepq_block(timo, catch_p, &sleep_syncobj); } int @@ -215,7 +218,7 @@ mtsleep(wchan_t ident, pri_t priority, const char *wmesg, int timo, sleepq_enter(sq, l, mp); sleepq_enqueue(sq, ident, wmesg, &sleep_syncobj, catch_p); mutex_exit(mtx); - error = sleepq_block(timo, catch_p); + error = sleepq_block(timo, catch_p, &sleep_syncobj); if ((priority & PNORELOCK) == 0) mutex_enter(mtx); @@ -244,7 +247,7 @@ kpause(const char *wmesg, bool intr, int timo, kmutex_t *mtx) BIGUNLOCKED(l); KERNEL_UNLOCK_ALL(NULL, &l->l_biglocks); sleepq_enqueue(NULL, l, wmesg, &kpause_syncobj, intr); - error = sleepq_block(timo, intr); + error = sleepq_block(timo, intr, &kpause_syncobj); if (mtx != NULL) mutex_enter(mtx); diff --git a/sys/kern/kern_timeout.c b/sys/kern/kern_timeout.c index 62338937739f..ca4e4340095c 100644 --- a/sys/kern/kern_timeout.c +++ b/sys/kern/kern_timeout.c @@ -543,7 +543,7 @@ callout_wait(callout_impl_t *c, void *interlock, kmutex_t *lock) sleepq_enter(&cc->cc_sleepq, l, cc->cc_lock); sleepq_enqueue(&cc->cc_sleepq, cc, "callout", &sleep_syncobj, false); - sleepq_block(0, false); + sleepq_block(0, false, &sleep_syncobj); } /* diff --git a/sys/kern/kern_turnstile.c b/sys/kern/kern_turnstile.c index dc8e666aa896..6a3b897290a9 100644 --- a/sys/kern/kern_turnstile.c +++ b/sys/kern/kern_turnstile.c @@ -435,7 +435,7 @@ KPREEMPT_DISABLE(l); KASSERT(lock == l->l_mutex); turnstile_lendpri(l); - sleepq_block(0, false); + sleepq_block(0, false, sobj); l->l_kpribase = obase; KPREEMPT_ENABLE(l); } diff --git a/sys/kern/sys_lwp.c b/sys/kern/sys_lwp.c index 6696f50d99c1..0b5220974cc9 100644 --- a/sys/kern/sys_lwp.c +++ b/sys/kern/sys_lwp.c @@ -58,6 +58,7 @@ __KERNEL_RCSID(0, "$NetBSD: sys_lwp.c,v 1.82 2020/05/23 23:42:43 ad Exp $"); static const stack_t lwp_ss_init = SS_INIT; syncobj_t lwp_park_syncobj = { + .sobj_name = "lwp_park", .sobj_flag = SOBJ_SLEEPQ_NULL, .sobj_unsleep = sleepq_unsleep, .sobj_changepri = sleepq_changepri, @@ -534,7 +535,7 @@ lwp_park(clockid_t clock_id, int flags, struct timespec *ts) BIGUNLOCKED(l); l->l_biglocks = 0; sleepq_enqueue(NULL, l, "parked", &lwp_park_syncobj, true); - error = sleepq_block(timo, true); + error = sleepq_block(timo, true, &lwp_park_syncobj); switch (error) { case EWOULDBLOCK: error = ETIMEDOUT; diff --git a/sys/kern/sys_select.c b/sys/kern/sys_select.c index e490f304d913..80413a9aaad5 100644 --- a/sys/kern/sys_select.c +++ b/sys/kern/sys_select.c @@ -143,6 +143,7 @@ static const int sel_flag[] = { * enqueue LWPs at all, unless subject to a collision. */ syncobj_t select_sobj = { + .sobj_name = "select", .sobj_flag = SOBJ_SLEEPQ_LIFO, .sobj_unsleep = sleepq_unsleep, .sobj_changepri = sleepq_changepri, @@ -322,7 +323,7 @@ state_check: l->l_kpriority = true; sleepq_enter(&sc->sc_sleepq, l, lock); sleepq_enqueue(&sc->sc_sleepq, sc, opname, &select_sobj, true); - error = sleepq_block(timo, true); + error = sleepq_block(timo, true, &select_sobj); if (error != 0) { break; } 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 diff --git a/sys/sys/sleepq.h b/sys/sys/sleepq.h index f9c77d431100..441db2224fdb 100644 --- a/sys/sys/sleepq.h +++ b/sys/sys/sleepq.h @@ -60,7 +60,7 @@ void sleepq_wake(sleepq_t *, wchan_t, u_int, kmutex_t *); int sleepq_abort(kmutex_t *, int); void sleepq_changepri(lwp_t *, pri_t); void sleepq_lendpri(lwp_t *, pri_t); -int sleepq_block(int, bool); +int sleepq_block(int, bool, struct syncobj *); #ifdef _KERNEL typedef union { diff --git a/sys/sys/syncobj.h b/sys/sys/syncobj.h index a6676d0b3ae2..5e19c4efdd5f 100644 --- a/sys/sys/syncobj.h +++ b/sys/sys/syncobj.h @@ -42,6 +42,7 @@ typedef volatile const void *wchan_t; * Synchronisation object operations set. */ typedef struct syncobj { + char sobj_name[16]; u_int sobj_flag; void (*sobj_unsleep)(struct lwp *, bool); void (*sobj_changepri)(struct lwp *, pri_t);