Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 30 Jun 2026 06:24:31 +0000
From:      Christos Margiolis <christos@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org
Cc:        Goran=?utf-8?Q? Meki=C4=87?= <meka@tilda.center>
Subject:   git: 0665d5b9d38a - stable/15 - sound: Start each channel individually
Message-ID:  <6a43611f.204fb.dc9b002@gitrepo.freebsd.org>

index | next in thread | raw e-mail

The branch stable/15 has been updated by christos:

URL: https://cgit.FreeBSD.org/src/commit/?id=0665d5b9d38a0b45db50a38244dfe17b8fefebee

commit 0665d5b9d38a0b45db50a38244dfe17b8fefebee
Author:     Goran Mekić <meka@tilda.center>
AuthorDate: 2026-06-17 10:34:05 +0000
Commit:     Christos Margiolis <christos@FreeBSD.org>
CommitDate: 2026-06-30 06:23:40 +0000

    sound: Start each channel individually
    
    Unlock all members before starting any of them. Holding multiple channel
    locks while calling chn_start() on a virtual channel can trigger the
    parent, which acquires PCM_LOCK() while other virtual channels are still
    locked -- a lock order reversal.
    
    Reviewed by:    christos
    Differential Revision:  https://reviews.freebsd.org/D57399
    
    (cherry picked from commit 47ae0a869c7db693ffb1ac058d63dcb79c4e68a8)
---
 sys/dev/sound/pcm/dsp.c | 25 +++++++++++++++++++------
 1 file changed, 19 insertions(+), 6 deletions(-)

diff --git a/sys/dev/sound/pcm/dsp.c b/sys/dev/sound/pcm/dsp.c
index 471db6524aa2..f32446570374 100644
--- a/sys/dev/sound/pcm/dsp.c
+++ b/sys/dev/sound/pcm/dsp.c
@@ -2733,16 +2733,29 @@ dsp_oss_syncstart(int sg_id)
 
 	/* Proceed only if no errors encountered. */
 	if (ret == 0) {
-		/* Launch channels */
-		while ((sm = SLIST_FIRST(&sg->members)) != NULL) {
-			SLIST_REMOVE_HEAD(&sg->members, link);
+		/*
+		 * Unlock all members before starting any of them.
+		 * Holding multiple channel locks while calling chn_start()
+		 * on a virtual channel can trigger the parent, which
+		 * acquires PCM_LOCK() while other virtual channels are
+		 * still locked -- a lock order reversal.
+		 */
+		SLIST_FOREACH(sm, &sg->members, link) {
+			sm->ch->sm = NULL;
+			sm->ch->flags &= ~CHN_F_NOTRIGGER;
+			CHN_UNLOCK(sm->ch);
+		}
 
+		/*
+		 * Start each channel individually, then remove it from
+		 * the sync group and free its member structure.
+		 */
+		while ((sm = SLIST_FIRST(&sg->members)) != NULL) {
 			c = sm->ch;
-			c->sm = NULL;
+			CHN_LOCK(c);
 			chn_start(c, 1);
-			c->flags &= ~CHN_F_NOTRIGGER;
 			CHN_UNLOCK(c);
-
+			SLIST_REMOVE_HEAD(&sg->members, link);
 			free(sm, M_DEVBUF);
 		}
 


home | help

Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?6a43611f.204fb.dc9b002>