From f3f6186a75cd561b851bb39c6942f87eca051031 Mon Sep 17 00:00:00 2001 From: Elad <18193363+elad335@users.noreply.github.com> Date: Sun, 12 Oct 2025 09:36:50 +0300 Subject: [PATCH] SaveStates: Fix Gem Thread Reboot --- Utilities/Thread.cpp | 5 +++++ Utilities/Thread.h | 7 +++++++ rpcs3/Emu/Cell/Modules/cellGem.cpp | 8 ++++---- rpcs3/Emu/RSX/RSXThread.cpp | 2 +- rpcs3/Emu/System.cpp | 11 ++++++++++- rpcs3/Emu/System.h | 1 + 6 files changed, 28 insertions(+), 6 deletions(-) diff --git a/Utilities/Thread.cpp b/Utilities/Thread.cpp index c67e720b6f..9b6d250c19 100644 --- a/Utilities/Thread.cpp +++ b/Utilities/Thread.cpp @@ -106,6 +106,11 @@ thread_local u64 g_tls_wait_fail = 0; thread_local bool g_tls_access_violation_recovered = false; extern thread_local std::string(*g_tls_log_prefix)(); +namespace stx +{ + atomic_t g_launch_retainer{0}; +} + // Report error and call std::abort(), defined in main.cpp [[noreturn]] void report_fatal_error(std::string_view text, bool is_html = false, bool include_help_text = true); diff --git a/Utilities/Thread.h b/Utilities/Thread.h index da5b25ce96..02e5db56ff 100644 --- a/Utilities/Thread.h +++ b/Utilities/Thread.h @@ -465,6 +465,8 @@ public: namespace stx { struct launch_retainer; + + extern atomic_t g_launch_retainer; } // Derived from the callable object Context, possibly a lambda @@ -481,6 +483,11 @@ class named_thread final : public Context, result_storage, thread_base u64 entry_point2() { + while (u32 value = stx::g_launch_retainer) + { + stx::g_launch_retainer.wait(value); + } + thread::initialize([]() { if constexpr (!result::empty) diff --git a/rpcs3/Emu/Cell/Modules/cellGem.cpp b/rpcs3/Emu/Cell/Modules/cellGem.cpp index 9d39b3c7eb..c50c93fc44 100644 --- a/rpcs3/Emu/Cell/Modules/cellGem.cpp +++ b/rpcs3/Emu/Cell/Modules/cellGem.cpp @@ -361,7 +361,7 @@ public: case move_handler::mouse: case move_handler::raw_mouse: { - auto& handler = g_fxo->get(); + auto& handler = *ensure(g_fxo->try_get()); std::lock_guard mouse_lock(handler.mutex); const MouseInfo& info = handler.GetInfo(); @@ -374,7 +374,7 @@ public: #ifdef HAVE_LIBEVDEV case move_handler::gun: { - gun_thread& gun = g_fxo->get(); + gun_thread& gun = *ensure(g_fxo->try_get()); std::scoped_lock lock(gun.handler.mutex); gun.num_devices = gun.handler.init() ? gun.handler.get_num_guns() : 0; @@ -505,7 +505,7 @@ public: case move_handler::mouse: case move_handler::raw_mouse: { - auto& handler = g_fxo->get(); + auto& handler = *ensure(g_fxo->try_get()); std::lock_guard mouse_lock(handler.mutex); // Make sure that the mouse handler is initialized @@ -522,7 +522,7 @@ public: #ifdef HAVE_LIBEVDEV case move_handler::gun: { - gun_thread& gun = g_fxo->get(); + gun_thread& gun = *ensure(g_fxo->try_get()); std::scoped_lock lock(gun.handler.mutex); gun.num_devices = gun.handler.init() ? gun.handler.get_num_guns() : 0; connected_controllers = std::min(std::min(attribute.max_connect, CELL_GEM_MAX_NUM), gun.num_devices); diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index bdb75531e7..cc91e52750 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -837,7 +837,7 @@ namespace rsx { while (Emu.IsReady()) { - thread_ctrl::wait_for(1000); + Emu.WaitReady(); } do diff --git a/rpcs3/Emu/System.cpp b/rpcs3/Emu/System.cpp index 2721cff539..26b5bfff03 100644 --- a/rpcs3/Emu/System.cpp +++ b/rpcs3/Emu/System.cpp @@ -221,13 +221,19 @@ void init_fxo_for_exec(utils::serial* ar, bool full = false) Emu.ConfigurePPUCache(); + stx::g_launch_retainer = 1; + g_fxo->init(false, ar, [](){ Emu.ExecPostponedInitCode(); }); Emu.GetCallbacks().init_gs_render(ar); - Emu.GetCallbacks().init_pad_handler(Emu.GetTitleID()); Emu.GetCallbacks().init_kb_handler(); Emu.GetCallbacks().init_mouse_handler(); + stx::g_launch_retainer = 0; + stx::g_launch_retainer.notify_all(); + + Emu.GetCallbacks().init_pad_handler(Emu.GetTitleID()); + usz pos = 0; if (ar) @@ -859,6 +865,7 @@ bool Emulator::BootRsxCapture(const std::string& path) GetCallbacks().on_run(false); m_state = system_state::starting; + m_state.notify_all(); ensure(g_fxo->init>("RSX Replay", std::move(frame))); @@ -2472,6 +2479,7 @@ void Emulator::Run(bool start_playtime) rpcs3::utils::configure_logs(); m_state = system_state::starting; + m_state.notify_all(); if (g_cfg.misc.prevent_display_sleep) { @@ -3254,6 +3262,7 @@ void Emulator::Kill(bool allow_autoexit, bool savestate, savestate_stage* save_s } // Signal threads + m_state.notify_all(); if (auto rsx = g_fxo->try_get()) { diff --git a/rpcs3/Emu/System.h b/rpcs3/Emu/System.h index fcdb60cf8d..41dd6229bd 100644 --- a/rpcs3/Emu/System.h +++ b/rpcs3/Emu/System.h @@ -439,6 +439,7 @@ public: bool IsStopped(bool test_fully = false) const { return test_fully ? m_state == system_state::stopped : m_state <= system_state::stopping; } bool IsReady() const { return m_state == system_state::ready; } bool IsStarting() const { return m_state == system_state::starting; } + void WaitReady() const { m_state.wait(system_state::ready); } auto GetStatus(bool fixup = true) const { system_state state = m_state; return fixup && state == system_state::frozen ? system_state::paused : fixup && state == system_state::stopping ? system_state::stopped : state; } bool HasGui() const { return m_has_gui; }