From 972fc6a18ba9b7e76629d921b0d0d06b83998e7e Mon Sep 17 00:00:00 2001 From: Sour Date: Fri, 21 Jan 2022 19:49:51 -0500 Subject: [PATCH] Fixed deadlock when switching game while paused --- Core/Shared/Emulator.cpp | 12 +++++++----- Core/Shared/Emulator.h | 1 - Utilities/SimpleLock.cpp | 7 ++++++- Utilities/SimpleLock.h | 1 + 4 files changed, 14 insertions(+), 7 deletions(-) diff --git a/Core/Shared/Emulator.cpp b/Core/Shared/Emulator.cpp index 6ce67d06..ab5d66ce 100644 --- a/Core/Shared/Emulator.cpp +++ b/Core/Shared/Emulator.cpp @@ -102,8 +102,7 @@ void Emulator::Run() return; } - auto lock = _runLock.AcquireSafe(); - auto emulationLock = _emulationLock.AcquireSafe(); + _runLock.Acquire(); _stopFlag = false; _isRunAheadFrame = false; @@ -151,6 +150,11 @@ void Emulator::Run() _emulationThreadId = thread::id(); + if(_runLock.IsLockedByCurrentThread()) { + //Lock might not be held by current frame is _stopFlag was set to interrupt the thread + _runLock.Release(); + } + PlatformUtilities::RestoreTimerResolution(); } @@ -288,8 +292,6 @@ void Emulator::Stop(bool sendNotification) debugger->Run(); } - _emulationLock.WaitForRelease(); - if(_emuThread) { _emuThread->join(); _emuThread.release(); @@ -686,8 +688,8 @@ void Emulator::WaitForPauseEnd() PlatformUtilities::DisableScreensaver(); PlatformUtilities::EnableHighResolutionTimer(); - _runLock.Acquire(); if(!_stopFlag) { + _runLock.Acquire(); _notificationManager->SendNotification(ConsoleNotificationType::GameResumed); } } diff --git a/Core/Shared/Emulator.h b/Core/Shared/Emulator.h index 63f2b2c7..746b0a1f 100644 --- a/Core/Shared/Emulator.h +++ b/Core/Shared/Emulator.h @@ -78,7 +78,6 @@ private: atomic _lockCounter; SimpleLock _runLock; - SimpleLock _emulationLock; SimpleLock _loadLock; SimpleLock _debuggerLock; diff --git a/Utilities/SimpleLock.cpp b/Utilities/SimpleLock.cpp index b3f6946e..790a6058 100644 --- a/Utilities/SimpleLock.cpp +++ b/Utilities/SimpleLock.cpp @@ -37,6 +37,11 @@ bool SimpleLock::IsFree() return _lockCount == 0; } +bool SimpleLock::IsLockedByCurrentThread() +{ + return _lockCount > 0 && _holderThreadID == _threadID; +} + void SimpleLock::WaitForRelease() { //Wait until we are able to grab a lock, and then release it again @@ -46,7 +51,7 @@ void SimpleLock::WaitForRelease() void SimpleLock::Release() { - if(_lockCount > 0 && _holderThreadID == _threadID) { + if(IsLockedByCurrentThread()) { _lockCount--; if(_lockCount == 0) { _holderThreadID = std::thread::id(); diff --git a/Utilities/SimpleLock.h b/Utilities/SimpleLock.h index 630a3ab6..da7cb77f 100644 --- a/Utilities/SimpleLock.h +++ b/Utilities/SimpleLock.h @@ -30,6 +30,7 @@ public: void Acquire(); bool IsFree(); + bool IsLockedByCurrentThread(); void WaitForRelease(); void Release(); };