diff --git a/Core/Core.cpp b/Core/Core.cpp index 5bf679376444..3c9bf93018e7 100644 --- a/Core/Core.cpp +++ b/Core/Core.cpp @@ -87,7 +87,6 @@ void Core_NotifyLifecycle(CoreLifecycle stage) { void Core_Stop() { Core_UpdateState(CORE_POWERDOWN); - m_StepCond.notify_all(); } bool Core_IsStepping() { @@ -173,6 +172,7 @@ bool UpdateScreenScale(int width, int height) { return false; } +// Note: not used on Android. void UpdateRunLoop() { if (windowHidden && g_Config.bPauseWhenMinimized) { sleep_ms(16); @@ -227,11 +227,13 @@ void Core_RunLoop(GraphicsContext *ctx) { } void Core_DoSingleStep() { + std::lock_guard guard(m_hStepMutex); singleStepPending = true; m_StepCond.notify_all(); } void Core_UpdateSingleStep() { + std::lock_guard guard(m_hStepMutex); m_StepCond.notify_all(); } @@ -241,17 +243,49 @@ void Core_SingleStep() { static inline void CoreStateProcessed() { if (coreStatePending) { + std::lock_guard guard(m_hInactiveMutex); coreStatePending = false; m_InactiveCond.notify_all(); } } +static inline void Core_WaitStepping() { + std::unique_lock guard(m_hStepMutex); + if (!singleStepPending && coreState == CORE_STEPPING) + m_StepCond.wait(guard); +} + +void Core_ProcessStepping() { + CoreStateProcessed(); + + // Check if there's any pending save state actions. + SaveState::Process(); + if (coreState != CORE_STEPPING) { + return; + } + + host->UpdateDisassembly(); + host->UpdateMemView(); + + // Need to check inside the lock to avoid races. + Core_WaitStepping(); + + // We may still be stepping without singleStepPending to process a save state. + if (singleStepPending && coreState == CORE_STEPPING) { + singleStepPending = false; + + Core_SingleStep(); + // Update disasm dialog. + host->UpdateDisassembly(); + host->UpdateMemView(); + } +} + // Many platforms, like Android, do not call this function but handle things on their own. // Instead they simply call NativeRender and NativeUpdate directly. void Core_Run(GraphicsContext *ctx) { host->UpdateDisassembly(); while (true) { -reswitch: if (GetUIState() != UISTATE_INGAME) { CoreStateProcessed(); if (GetUIState() == UISTATE_EXIT) { @@ -270,38 +304,9 @@ void Core_Run(GraphicsContext *ctx) { // We should never get here on Android. case CORE_STEPPING: - singleStepPending = false; - CoreStateProcessed(); - - // Check if there's any pending savestate actions. - SaveState::Process(); - if (coreState == CORE_POWERDOWN) { + Core_ProcessStepping(); + if (coreState == CORE_POWERDOWN) return; - } - - // wait for step command.. - host->UpdateDisassembly(); - host->UpdateMemView(); - host->SendCoreWait(true); - - { - std::unique_lock guard(m_hStepMutex); - m_StepCond.wait(guard); - } - - host->SendCoreWait(false); - // No step pending? Let's go back to the wait. - if (!singleStepPending || coreState != CORE_STEPPING) { - if (coreState == CORE_POWERDOWN) { - return; - } - goto reswitch; - } - - Core_SingleStep(); - // update disasm dialog - host->UpdateDisassembly(); - host->UpdateMemView(); break; case CORE_POWERUP: diff --git a/Core/Core.h b/Core/Core.h index f01a9d03e8b0..84fe707792b7 100644 --- a/Core/Core.h +++ b/Core/Core.h @@ -34,6 +34,7 @@ void Core_SetGraphicsContext(GraphicsContext *ctx); void Core_EnableStepping(bool step); void Core_DoSingleStep(); void Core_UpdateSingleStep(); +void Core_ProcessStepping(); // Changes every time we enter stepping. int Core_GetSteppingCounter(); @@ -54,6 +55,7 @@ bool Core_IsStepping(); bool Core_IsActive(); bool Core_IsInactive(); +// Warning: these currently work only on Windows. void Core_WaitInactive(); void Core_WaitInactive(int milliseconds); diff --git a/Core/Host.h b/Core/Host.h index c7eed94de1ac..b06473c4dcee 100644 --- a/Core/Host.h +++ b/Core/Host.h @@ -50,8 +50,6 @@ class Host { virtual void SaveSymbolMap() {} virtual void SetWindowTitle(const char *message) {} - virtual void SendCoreWait(bool) {} - // While debugging is active, it's perfectly fine for these to block. virtual bool GPUDebuggingActive() { return false; } virtual void GPUNotifyCommand(u32 pc) {}