DF-2915 fix: sleepq_lock() assumed objcache_get() returns zeroed sleepqueue_wchan objects. sleepq_wc_cache is an objcache_create_simple() cache: its allocator objcache_malloc_alloc() (kern_objcache.c:571-577) kmalloc()s WITHOUT M_ZERO and no ctor is registered (kern_objcache.c:386-389), so freshly allocated wc's contain garbage. The KKASSERT at the old line fires (panics INVARIANTS kernels) or the garbage object enters sc_wchead and permanently breaks the free-slot invariant (production kernels: stuck entries, inflated sc_free_count, unbounded re-allocation loop). Explicitly zero the object after objcache_get(). Recycled objects were already reset by the release paths, so this only fixes the fresh-alloc case and is otherwise a no-op. --- a/sys/kern/subr_sleepqueue.c +++ b/sys/kern/subr_sleepqueue.c @@ -206,7 +206,13 @@ */ spin_unlock(&sc->sc_spin); wc = objcache_get(sleepq_wc_cache, M_WAITOK); - KKASSERT(wc->wc_wchan == NULL && wc->wc_refs == 0); + /* + * DF-2915: objcache_create_simple() applies no zeroing + * (objcache_malloc_alloc, kern_objcache.c) and we register + * no ctor, so a freshly kmalloc'd wc contains garbage. + * Initialize it explicitly. + */ + bzero(wc, sizeof(*wc)); wc->wc_sc = sc; spin_lock(&sc->sc_spin); TAILQ_INSERT_TAIL(&sc->sc_wchead, wc, wc_entry);