diff --git a/kernel/src/Drivers/Audio/Mixer.cpp b/kernel/src/Drivers/Audio/Mixer.cpp index 00f7242..cea5f9d 100644 --- a/kernel/src/Drivers/Audio/Mixer.cpp +++ b/kernel/src/Drivers/Audio/Mixer.cpp @@ -327,10 +327,18 @@ namespace Drivers::Audio::Mixer { if (bitsPerSample != 16) return -1; if (sampleRate < 8000 || sampleRate > 192000) return -1; + // Allocate the input ring before taking g_lock. Walking the PFA free + // list for 16 contiguous pages and zeroing 64 KiB is long enough that + // doing it under the lock (with IRQs disabled) lets HDA BCIS IRQs + // spin on g_lock on other CPUs — the same hazard that wedged Close(). + int16_t* ring = AllocRing(); + if (!ring) return -1; + g_lock.Acquire(); if (!EnsureHdaOpen()) { g_lock.Release(); + FreeRing(ring); return -1; } @@ -340,16 +348,11 @@ namespace Drivers::Audio::Mixer { } if (slot < 0) { g_lock.Release(); + FreeRing(ring); return -1; } VirtualStream& s = g_streams[slot]; - int16_t* ring = AllocRing(); - if (!ring) { - g_lock.Release(); - return -1; - } - s.active = true; s.ownerPid = ownerPid; int n = 0;