diff --git a/GSR.Emu/EmuManager.cs b/GSR.Emu/EmuManager.cs index 3791f77..d01bd71 100644 --- a/GSR.Emu/EmuManager.cs +++ b/GSR.Emu/EmuManager.cs @@ -31,6 +31,9 @@ public sealed class EmuManager : IDisposable private volatile bool _disposing; private volatile EmuThreadException _emuThreadException; + // hack due to wonky locking in NativeAOT + private volatile bool _wantEmuThreadLock; + private IEmuCore _emuCore; private IEmuController _emuController; private bool _emuPaused; @@ -160,6 +163,14 @@ private void EmuThreadProc() } } } + + if (_wantEmuThreadLock) + { + // if someone else is trying to lock the emu thread, we need to wait a bit after unlocking it + // as it seems (at least under NativeAOT) if it's re-acquired too quickly, other threads have a hard time acquiring it + // (perhaps this is a .NET bug, perhaps it isn't) + Thread.Yield(); + } } } catch (Exception e) @@ -286,8 +297,10 @@ public void DoFrameStep() public void LoadRom(EmuLoadArgs loadArgs) { + _wantEmuThreadLock = true; lock (_emuThreadLock) { + _wantEmuThreadLock = false; UnloadRom(); try { @@ -321,8 +334,10 @@ public void LoadRom(EmuLoadArgs loadArgs) public void UnloadRom() { + _wantEmuThreadLock = true; lock (_emuThreadLock) { + _wantEmuThreadLock = false; CheckEmuThreadException(); SetToNullCore(); } @@ -474,8 +489,10 @@ public EmuVideoBuffer LoadStatePreview(string statePath) public void SetSpeedFactor(int speedFactor) { + _wantEmuThreadLock = true; lock (_emuThreadLock) { + _wantEmuThreadLock = false; _speedFactor = speedFactor; if (_speedFactor == 1) {