From 7cb2977ede1869c8600fcbb86329d0189d228e2c Mon Sep 17 00:00:00 2001 From: Elad <18193363+elad335@users.noreply.github.com> Date: Tue, 20 May 2025 18:05:44 +0300 Subject: [PATCH 1/2] Emu: Run Qt events while calling Emu.Cleanup --- rpcs3/Emu/System.cpp | 34 ++++++++++++++++++++++++++++++++++ rpcs3/util/fixed_typemap.hpp | 14 ++++++++++++-- 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/rpcs3/Emu/System.cpp b/rpcs3/Emu/System.cpp index 3fdcfae9ab32..6c44f6a6bb82 100644 --- a/rpcs3/Emu/System.cpp +++ b/rpcs3/Emu/System.cpp @@ -3895,6 +3895,40 @@ bool Emulator::Quit(bool force_quit) void Emulator::CleanUp() { + // Signal threads + if (auto rsx = g_fxo->try_get()) + { + *static_cast(rsx) = thread_state::aborting; + } + + for (const auto& [type, data] : *g_fxo) + { + if (type.thread_op) + { + type.thread_op(data, thread_state::aborting); + } + } + + // Join threads + qt_events_aware_op(50, [&]() + { + bool has_running = false; + + for (const auto& [type, data] : *g_fxo) + { + if (type.thread_op) + { + if (type.thread_op(data, thread_state::aborting) != thread_state::finished) + { + has_running = true; + break; + } + } + } + + return has_running == false; + }); + // Deinitialize object manager to prevent any hanging objects at program exit g_fxo->clear(); } diff --git a/rpcs3/util/fixed_typemap.hpp b/rpcs3/util/fixed_typemap.hpp index bcb5f36baaa2..abb6fe9c5734 100644 --- a/rpcs3/util/fixed_typemap.hpp +++ b/rpcs3/util/fixed_typemap.hpp @@ -71,7 +71,7 @@ namespace stx struct typeinfo { bool(*create)(uchar* ptr, manual_typemap&, utils::serial*, std::string_view) noexcept = nullptr; - void(*thread_op)(void* ptr, thread_state) noexcept = nullptr; + thread_state(*thread_op)(void* ptr, thread_state) noexcept = nullptr; void(*save)(void* ptr, utils::serial&) noexcept = nullptr; bool(*saveable)(bool) noexcept = nullptr; void(*destroy)(void* ptr) noexcept = nullptr; @@ -137,10 +137,20 @@ namespace stx } template - static void call_thread_op(void* ptr, thread_state state) noexcept + static thread_state call_thread_op(void* ptr, thread_state state) noexcept { // Abort and/or join (expected thread_state::aborting or thread_state::finished) *std::launder(static_cast(ptr)) = state; + + if constexpr (std::is_convertible_v) + { + return *std::launder(static_cast(ptr)); + } + else + { + constexpr thread_state context_finished{3}; + return context_finished; + } } template From 5133a121828329ec538f25d14e946ee1beb9685b Mon Sep 17 00:00:00 2001 From: Elad <18193363+elad335@users.noreply.github.com> Date: Tue, 20 May 2025 18:18:43 +0300 Subject: [PATCH 2/2] Add early termination for gui_pad_thread --- rpcs3/Emu/System.cpp | 17 ++++------------- rpcs3/Input/gui_pad_thread.cpp | 24 +++++++++++++++++++++++- rpcs3/Input/gui_pad_thread.h | 2 ++ 3 files changed, 29 insertions(+), 14 deletions(-) diff --git a/rpcs3/Emu/System.cpp b/rpcs3/Emu/System.cpp index 6c44f6a6bb82..e105c8fa8401 100644 --- a/rpcs3/Emu/System.cpp +++ b/rpcs3/Emu/System.cpp @@ -3895,23 +3895,14 @@ bool Emulator::Quit(bool force_quit) void Emulator::CleanUp() { - // Signal threads - if (auto rsx = g_fxo->try_get()) - { - *static_cast(rsx) = thread_state::aborting; - } - - for (const auto& [type, data] : *g_fxo) + // Join threads + qt_events_aware_op(50, [&]() { - if (type.thread_op) + if (!g_fxo->is_init()) { - type.thread_op(data, thread_state::aborting); + return true; } - } - // Join threads - qt_events_aware_op(50, [&]() - { bool has_running = false; for (const auto& [type, data] : *g_fxo) diff --git a/rpcs3/Input/gui_pad_thread.cpp b/rpcs3/Input/gui_pad_thread.cpp index f0bf833a4641..31415150eb9b 100644 --- a/rpcs3/Input/gui_pad_thread.cpp +++ b/rpcs3/Input/gui_pad_thread.cpp @@ -45,8 +45,18 @@ gui_pad_thread::gui_pad_thread() m_thread = std::make_unique>>("Gui Pad Thread", [this](){ run(); }); } -gui_pad_thread::~gui_pad_thread() +gui_pad_thread& gui_pad_thread::operator=(thread_state state) noexcept { + if (state == thread_state::aborting) + { + if (m_thread) + { + *m_thread = state; + } + + return *this; + } + // Join thread m_thread.reset(); @@ -63,6 +73,18 @@ gui_pad_thread::~gui_pad_thread() m_uinput_fd = -1; } #endif + + return *this; +} + +gui_pad_thread::operator thread_state() const noexcept +{ + return m_thread && *m_thread != thread_state::finished ? m_thread->operator thread_state() : thread_state::finished; +} + +gui_pad_thread::~gui_pad_thread() +{ + *this = thread_state::finished; } void gui_pad_thread::update_settings(const std::shared_ptr& settings) diff --git a/rpcs3/Input/gui_pad_thread.h b/rpcs3/Input/gui_pad_thread.h index dc04fb456fed..49ca841d6a43 100644 --- a/rpcs3/Input/gui_pad_thread.h +++ b/rpcs3/Input/gui_pad_thread.h @@ -15,6 +15,8 @@ class gui_pad_thread { public: gui_pad_thread(); + gui_pad_thread& operator=(thread_state state) noexcept; + operator thread_state() const noexcept; virtual ~gui_pad_thread(); void update_settings(const std::shared_ptr& settings);