From nobody Fri Jan 30 18:46:03 2026 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4f2lMb6LxYz6QKvc for ; Fri, 30 Jan 2026 18:46:03 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R13" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4f2lMb11rtz3KPC for ; Fri, 30 Jan 2026 18:46:03 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1769798763; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=SgWMO2u+faamm0phazH9AJtiVXFzv3m8+LdoUDOAFxo=; b=iMHZ17v0DLtbfPt2I+V8KtLwXGV6P6dMH53YQDe8cra3Ech2w3Gh+ll2c8EsYcnqqy5IIU 7PNOMJFhtJ59iNp6h0664XUpwSSe1DOE/WHnWik6vmPgnggUD5nr82zXRr0xnTzFTmlTzz GMPWCWBsT3MLzJ4XA6j6n9phJahysV7Qhd7AzGy4UTWcKGqqa8DltK00oXPySG1weXMsHz pZuzd7xmfxvvVDmgCqt/kmjFJyX3A+8818+Lhpz0mWw7GdhnVPAwjIuVLeq07b1Q3yk9Zg mULDuSm9iQueucF+C+k7mY6nozUb3PnbdUGmepr7X0g0Poh0FldLpBqaBPidcQ== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1769798763; a=rsa-sha256; cv=none; b=S1LcALZ/89YRSK7x3UXLZ799KuRAFiad/Xhr9uOGHSc8dJUqEv6Yg7f7S9rNZ6XAy3jmuf iGLCNtBaHyoIJ5ce3cMF7hCive1qLMYFubK4afF1yTcc0Gbd5IopvxsDFkAvQwjTOkw+9m st5RC7OJXYsJu5c7kLw1QnNyzkmpl/HeSy6BYEEKCPti+dW3SAPmJx2Ooq36hgyd9WnISM v9EPqKwWIuJ4quO6Kj97afF59TGzoGb7bkssQga0bdTNFGJOEqPxOxxe4v3nUK2sKbgM4h M29Db5YZc6y8gdLr8zKgPMNQxzg8DVKisUm9NRvkCKTT7hLV7PEGeNlLYnbj2w== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1769798763; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=SgWMO2u+faamm0phazH9AJtiVXFzv3m8+LdoUDOAFxo=; b=CauOAIXNb+hV7NNLG5JwnUaLxb1OskoWAx3I/d3NAaGTYIZKu0QFQZPstU+2s1qE/PrnMC /1OXefXaZzUudqga0kCWfyeTHCoRU0OcNqQT2Atqy3SZe+BMy7mwmbY1j+QZbKGyxY59vC 1RepV8tXR2GpoKr2aDXQceFd9FsekwzhrlgPEGLSPKLE4WHYo2iDmkK+4yETXekrVBEYm5 qgScWSqMZRdHZV7B3N2ZutGrN/ptOVh5Ij4pcml60ITheLa3VeWHvJJnVwsmik+QJgqSE5 aoWFqgH9JlE+FwsenVuVYuIhmrEy03OlobczeLeuqIMtexWElO7SEumwylZ3ew== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4f2lMb0ZGSz4hx for ; Fri, 30 Jan 2026 18:46:03 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 9f35 by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Fri, 30 Jan 2026 18:46:03 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Konstantin Belousov Subject: git: 245157fd8a38 - main - ktrcsw(): should not be called when the thread is owning interlock or on sleepq List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: kib X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 245157fd8a382c3989075789ee98582665f3b31d Auto-Submitted: auto-generated Date: Fri, 30 Jan 2026 18:46:03 +0000 Message-Id: <697cfc6b.9f35.3899c36b@gitrepo.freebsd.org> The branch main has been updated by kib: URL: https://cgit.FreeBSD.org/src/commit/?id=245157fd8a382c3989075789ee98582665f3b31d commit 245157fd8a382c3989075789ee98582665f3b31d Author: Konstantin Belousov AuthorDate: 2026-01-22 21:46:01 +0000 Commit: Konstantin Belousov CommitDate: 2026-01-30 18:45:48 +0000 ktrcsw(): should not be called when the thread is owning interlock or on sleepq The issue is that for ktrcsw() we lock the ktrace_mtx mutex while owning the interlock from a subsystem that called msleep(). In particular, the VM subsystem might call msleep() if page allocation failed. This establishes order VM locks (e.g. domain free queue lock) -> ktrace_mtx. Calling free() while owning ktrace_mtx gives the reverse order. Worse, msleep_spin_sbt() call s ktrcsw() while the thread is put on sleep queue. Then, since the mutex might be contested, the thread needs to be put on turnstil, which cannot work. Move the ktrcsw() call for switch-out after the wakeup, when the thread does not yet re-obtained any locks. From there, we call a special version of ktrcsw(), which is passed the actual time when the context switch occured. The drawback is that the switch-out record is only written in the ktrace.out file after the switch-in occurred, but this is probably not too serious. Reported and tested by: pho Reviewed by: markj Sponsored by: The FreeBSD Foundation MFC after: 1 week Differential revision: https://reviews.freebsd.org/D54831 --- sys/kern/kern_ktrace.c | 18 ++++++++++++++++-- sys/kern/kern_synch.c | 26 +++++++++++--------------- sys/sys/ktrace.h | 1 + 3 files changed, 28 insertions(+), 17 deletions(-) diff --git a/sys/kern/kern_ktrace.c b/sys/kern/kern_ktrace.c index b58e69a3f38e..f3ee1c53fafd 100644 --- a/sys/kern/kern_ktrace.c +++ b/sys/kern/kern_ktrace.c @@ -838,8 +838,8 @@ ktrpsig(int sig, sig_t action, sigset_t *mask, int code) ktrace_exit(td); } -void -ktrcsw(int out, int user, const char *wmesg) +static void +ktrcsw_impl(int out, int user, const char *wmesg, const struct timespec *tv) { struct thread *td = curthread; struct ktr_request *req; @@ -854,6 +854,8 @@ ktrcsw(int out, int user, const char *wmesg) kc = &req->ktr_data.ktr_csw; kc->out = out; kc->user = user; + if (tv != NULL) + req->ktr_header.ktr_time = *tv; if (wmesg != NULL) strlcpy(kc->wmesg, wmesg, sizeof(kc->wmesg)); else @@ -862,6 +864,18 @@ ktrcsw(int out, int user, const char *wmesg) ktrace_exit(td); } +void +ktrcsw(int out, int user, const char *wmesg) +{ + ktrcsw_impl(out, user, wmesg, NULL); +} + +void +ktrcsw_out(const struct timespec *tv, const char *wmesg) +{ + ktrcsw_impl(1, 0, wmesg, tv); +} + void ktrstruct(const char *name, const void *data, size_t datalen) { diff --git a/sys/kern/kern_synch.c b/sys/kern/kern_synch.c index fc6c9857463c..22628c78d8a5 100644 --- a/sys/kern/kern_synch.c +++ b/sys/kern/kern_synch.c @@ -133,6 +133,7 @@ _sleep(const void *ident, struct lock_object *lock, int priority, { struct thread *td __ktrace_used; struct lock_class *class; + struct timespec sw_out_tv __ktrace_used; uintptr_t lock_state; int catch, pri, rval, sleepq_flags; WITNESS_SAVE_DECL(lock_witness); @@ -141,7 +142,7 @@ _sleep(const void *ident, struct lock_object *lock, int priority, td = curthread; #ifdef KTRACE if (KTRPOINT(td, KTR_CSW)) - ktrcsw(1, 0, wmesg); + nanotime(&sw_out_tv); #endif WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, lock, "Sleeping on \"%s\"", wmesg); @@ -222,8 +223,10 @@ _sleep(const void *ident, struct lock_object *lock, int priority, rval = 0; } #ifdef KTRACE - if (KTRPOINT(td, KTR_CSW)) + if (KTRPOINT(td, KTR_CSW)) { + ktrcsw_out(&sw_out_tv, wmesg); ktrcsw(0, 0, wmesg); + } #endif PICKUP_GIANT(); if (lock != NULL && lock != &Giant.lock_object && !(priority & PDROP)) { @@ -239,6 +242,7 @@ msleep_spin_sbt(const void *ident, struct mtx *mtx, const char *wmesg, sbintime_t sbt, sbintime_t pr, int flags) { struct thread *td __ktrace_used; + struct timespec sw_out_tv __ktrace_used; int rval; WITNESS_SAVE_DECL(mtx); @@ -266,19 +270,9 @@ msleep_spin_sbt(const void *ident, struct mtx *mtx, const char *wmesg, if (sbt != 0) sleepq_set_timeout_sbt(ident, sbt, pr, flags); - /* - * Can't call ktrace with any spin locks held so it can lock the - * ktrace_mtx lock, and WITNESS_WARN considers it an error to hold - * any spin lock. Thus, we have to drop the sleepq spin lock while - * we handle those requests. This is safe since we have placed our - * thread on the sleep queue already. - */ #ifdef KTRACE - if (KTRPOINT(td, KTR_CSW)) { - sleepq_release(ident); - ktrcsw(1, 0, wmesg); - sleepq_lock(ident); - } + if (KTRPOINT(td, KTR_CSW)) + nanotime(&sw_out_tv); #endif #ifdef WITNESS sleepq_release(ident); @@ -293,8 +287,10 @@ msleep_spin_sbt(const void *ident, struct mtx *mtx, const char *wmesg, rval = 0; } #ifdef KTRACE - if (KTRPOINT(td, KTR_CSW)) + if (KTRPOINT(td, KTR_CSW)) { + ktrcsw_out(&sw_out_tv, wmesg); ktrcsw(0, 0, wmesg); + } #endif PICKUP_GIANT(); mtx_lock_spin(mtx); diff --git a/sys/sys/ktrace.h b/sys/sys/ktrace.h index 822822a6ffe7..1ba5c84000b0 100644 --- a/sys/sys/ktrace.h +++ b/sys/sys/ktrace.h @@ -340,6 +340,7 @@ ktr_get_tracevp(struct proc *p, bool ref) void ktr_io_params_free(struct ktr_io_params *); void ktrnamei(const char *); void ktrcsw(int, int, const char *); +void ktrcsw_out(const struct timespec *, const char *); void ktrpsig(int, sig_t, sigset_t *, int); void ktrfault(vm_offset_t, int); void ktrfaultend(int);