fix: fix audio Mixer freeze
This commit is contained in:
@@ -383,17 +383,36 @@ namespace Drivers::Audio::Mixer {
|
|||||||
g_lock.Acquire();
|
g_lock.Acquire();
|
||||||
VirtualStream& s = g_streams[handle];
|
VirtualStream& s = g_streams[handle];
|
||||||
bool changed = false;
|
bool changed = false;
|
||||||
|
// Pull the ring pointer out of the slot before freeing it. Once
|
||||||
|
// s.active=false and s.ring=nullptr are visible under the lock no
|
||||||
|
// other path can reach this pointer, so the actual PFA free can run
|
||||||
|
// with the lock released — keeping the HDA buffer-complete IRQ from
|
||||||
|
// spinning on g_lock while ReallocConsecutive walks the free list.
|
||||||
|
int16_t* ringToFree = nullptr;
|
||||||
|
bool lastStream = false;
|
||||||
if (s.active) {
|
if (s.active) {
|
||||||
FreeRing(s.ring);
|
ringToFree = s.ring;
|
||||||
s.ring = nullptr;
|
s.ring = nullptr;
|
||||||
s.active = false;
|
s.active = false;
|
||||||
s.ownerPid = 0;
|
s.ownerPid = 0;
|
||||||
s.name[0] = '\0';
|
s.name[0] = '\0';
|
||||||
if (g_activeCount > 0) g_activeCount--;
|
if (g_activeCount > 0) g_activeCount--;
|
||||||
|
lastStream = (g_activeCount == 0);
|
||||||
BumpSerialLocked();
|
BumpSerialLocked();
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
|
// Quiesce the hardware when the final virtual stream goes away so
|
||||||
|
// the HDA DMA ring stops looping its last 32 KiB of samples. The
|
||||||
|
// next Open() reopens the HDA stream via EnsureHdaOpen().
|
||||||
|
bool closeHda = lastStream && g_hdaOpened;
|
||||||
|
int hdaHandle = g_hdaHandle;
|
||||||
|
if (closeHda) {
|
||||||
|
g_hdaOpened = false;
|
||||||
|
g_hdaHandle = -1;
|
||||||
|
}
|
||||||
g_lock.Release();
|
g_lock.Release();
|
||||||
|
if (closeHda) IntelHda::Close(hdaHandle);
|
||||||
|
if (ringToFree) FreeRing(ringToFree);
|
||||||
if (changed) Sched::WakeObjectWaiters((void*)&g_serial);
|
if (changed) Sched::WakeObjectWaiters((void*)&g_serial);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -495,12 +514,14 @@ namespace Drivers::Audio::Mixer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CleanupProcess(int pid) {
|
void CleanupProcess(int pid) {
|
||||||
|
int16_t* ringsToFree[MAX_STREAMS] = {};
|
||||||
|
int ringCount = 0;
|
||||||
g_lock.Acquire();
|
g_lock.Acquire();
|
||||||
bool changed = false;
|
bool changed = false;
|
||||||
for (int i = 0; i < MAX_STREAMS; i++) {
|
for (int i = 0; i < MAX_STREAMS; i++) {
|
||||||
VirtualStream& s = g_streams[i];
|
VirtualStream& s = g_streams[i];
|
||||||
if (s.active && s.ownerPid == pid) {
|
if (s.active && s.ownerPid == pid) {
|
||||||
FreeRing(s.ring);
|
ringsToFree[ringCount++] = s.ring;
|
||||||
s.ring = nullptr;
|
s.ring = nullptr;
|
||||||
s.active = false;
|
s.active = false;
|
||||||
s.ownerPid = 0;
|
s.ownerPid = 0;
|
||||||
@@ -509,8 +530,16 @@ namespace Drivers::Audio::Mixer {
|
|||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
bool closeHda = changed && (g_activeCount == 0) && g_hdaOpened;
|
||||||
|
int hdaHandle = g_hdaHandle;
|
||||||
|
if (closeHda) {
|
||||||
|
g_hdaOpened = false;
|
||||||
|
g_hdaHandle = -1;
|
||||||
|
}
|
||||||
if (changed) BumpSerialLocked();
|
if (changed) BumpSerialLocked();
|
||||||
g_lock.Release();
|
g_lock.Release();
|
||||||
|
if (closeHda) IntelHda::Close(hdaHandle);
|
||||||
|
for (int i = 0; i < ringCount; i++) FreeRing(ringsToFree[i]);
|
||||||
if (changed) Sched::WakeObjectWaiters((void*)&g_serial);
|
if (changed) Sched::WakeObjectWaiters((void*)&g_serial);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user