Page MenuHomeFreeBSD

D57399.diff
No OneTemporary

D57399.diff

diff --git a/sys/dev/sound/pcm/dsp.c b/sys/dev/sound/pcm/dsp.c
--- a/sys/dev/sound/pcm/dsp.c
+++ b/sys/dev/sound/pcm/dsp.c
@@ -2742,16 +2742,29 @@
/* 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);
}

File Metadata

Mime Type
text/plain
Expires
Thu, Jul 16, 7:24 AM (13 h, 43 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
34049097
Default Alt Text
D57399.diff (1 KB)

Event Timeline