From bd66dfedc90e0a30312a1d7008ad8cb744bf605b Mon Sep 17 00:00:00 2001 From: Eladash Date: Tue, 7 Sep 2021 19:42:08 +0300 Subject: [PATCH] Do not allow to unpause after fatal error occured in emulation * Plus fix #10590 --- Utilities/Thread.cpp | 2 +- rpcs3/Emu/Cell/SPURecompiler.cpp | 1 - rpcs3/Emu/System.cpp | 25 +++++++++++++++++++++---- rpcs3/Emu/System.h | 5 +++-- rpcs3/main.cpp | 2 +- 5 files changed, 26 insertions(+), 9 deletions(-) diff --git a/Utilities/Thread.cpp b/Utilities/Thread.cpp index 4a85d12fb4..17ac7ace70 100644 --- a/Utilities/Thread.cpp +++ b/Utilities/Thread.cpp @@ -1580,7 +1580,7 @@ bool handle_access_violation(u32 addr, bool is_writing, x64_context* context) no } } - Emu.Pause(); + Emu.Pause(true); if (!g_tls_access_violation_recovered) { diff --git a/rpcs3/Emu/Cell/SPURecompiler.cpp b/rpcs3/Emu/Cell/SPURecompiler.cpp index d9f1a9ed7e..8c3554bc00 100644 --- a/rpcs3/Emu/Cell/SPURecompiler.cpp +++ b/rpcs3/Emu/Cell/SPURecompiler.cpp @@ -9489,7 +9489,6 @@ struct spu_llvm_worker else { spu_log.fatal("[0x%05x] Compilation failed.", func.entry_point); - Emu.Pause(); return; } diff --git a/rpcs3/Emu/System.cpp b/rpcs3/Emu/System.cpp index cf09992c2b..e4c6d49e4e 100644 --- a/rpcs3/Emu/System.cpp +++ b/rpcs3/Emu/System.cpp @@ -1404,17 +1404,27 @@ void Emulator::Run(bool start_playtime) } } -bool Emulator::Pause() +bool Emulator::Pause(bool freeze_emulation) { const u64 start = get_system_time(); + const system_state pause_state = freeze_emulation ? system_state::frozen : system_state::paused; + // Try to pause - if (!m_state.compare_and_swap_test(system_state::running, system_state::paused)) + if (!m_state.compare_and_swap_test(system_state::running, pause_state)) { - if (!m_state.compare_and_swap_test(system_state::ready, system_state::paused)) + if (!freeze_emulation) { return false; } + + if (!m_state.compare_and_swap_test(system_state::ready, pause_state)) + { + if (!m_state.compare_and_swap_test(system_state::paused, pause_state)) + { + return false; + } + } } // Signal profilers to print results (if enabled) @@ -1424,7 +1434,14 @@ bool Emulator::Pause() static atomic_t pause_mark = 0; - sys_log.success("Emulation is being paused... (mark=%u)", pause_mark++); + if (freeze_emulation) + { + sys_log.warning("Emulation has been frozen! You can either use debugger tools to inspect current emulation state or terminate it."); + } + else + { + sys_log.success("Emulation is being paused... (mark=%u)", pause_mark++); + } // Update pause start time if (m_pause_start_time.exchange(start)) diff --git a/rpcs3/Emu/System.h b/rpcs3/Emu/System.h index 2cb4c08888..24c7ac1ecb 100644 --- a/rpcs3/Emu/System.h +++ b/rpcs3/Emu/System.h @@ -26,6 +26,7 @@ enum class system_state : u32 running, stopped, paused, + frozen, // paused but cannot resume ready, }; @@ -221,7 +222,7 @@ public: game_boot_result Load(const std::string& title_id = "", bool add_only = false, bool force_global_config = false, bool is_disc_patch = false); void Run(bool start_playtime); - bool Pause(); + bool Pause(bool freeze_emulation = false); void Resume(); void Stop(bool restart = false); void Restart() { Stop(true); } @@ -232,7 +233,7 @@ public: bool IsPaused() const { return m_state >= system_state::paused; } // ready is also considered paused by this function bool IsStopped() const { return m_state == system_state::stopped; } bool IsReady() const { return m_state == system_state::ready; } - auto GetStatus() const { return m_state.load(); } + auto GetStatus() const { system_state state = m_state; return state == system_state::frozen ? system_state::paused : state; } bool HasGui() const { return m_has_gui; } void SetHasGui(bool has_gui) { m_has_gui = has_gui; } diff --git a/rpcs3/main.cpp b/rpcs3/main.cpp index 2ce56ec631..515d58fe81 100644 --- a/rpcs3/main.cpp +++ b/rpcs3/main.cpp @@ -221,7 +221,7 @@ struct fatal_error_listener final : logs::listener } #endif // Pause emulation if fatal error encountered - Emu.Pause(); + Emu.Pause(true); } } };