diff --git a/Utilities/Thread.cpp b/Utilities/Thread.cpp index 75b01dbbf7..1fce7d4762 100644 --- a/Utilities/Thread.cpp +++ b/Utilities/Thread.cpp @@ -1199,36 +1199,6 @@ std::string thread_ctrl_t::get_name() const return name(); } -void thread_ctrl_t::set_current() -{ - const auto old_value = g_tls_this_thread; - - if (old_value == this) - { - return; - } - - if (old_value) - { - vm::reservation_free(); - } - - if (true && assigned.exchange(true)) - { - LOG_ERROR(GENERAL, "Thread '%s' was already assigned to g_tls_this_thread of another thread", get_name()); - g_tls_this_thread = nullptr; - } - else - { - g_tls_this_thread = this; - } - - if (old_value) - { - old_value->assigned = false; - } -} - thread_t::thread_t(std::function name, std::function func) { start(std::move(name), func); @@ -1272,12 +1242,12 @@ void thread_t::start(std::function name, std::function fu // start thread m_thread->m_thread = std::thread([](std::shared_ptr ctrl, std::function func) { - g_thread_count++; + g_tls_this_thread = ctrl.get(); SetCurrentThreadDebugName(ctrl->get_name().c_str()); #if defined(_MSC_VER) - auto old_se_translator = _set_se_translator(_se_translator); + _set_se_translator(_se_translator); #endif #ifdef _WIN32 @@ -1294,16 +1264,9 @@ void thread_t::start(std::function name, std::function fu } #endif - // error handler - const auto error = [&](const char* text) - { - log_message(GENERAL, Emu.IsStopped() ? Log::Severity::Warning : Log::Severity::Error, "Exception: %s", text); - Emu.Pause(); - }; - try { - ctrl->set_current(); + g_thread_count++; if (Ini.HLELogging.GetValue()) { @@ -1311,36 +1274,31 @@ void thread_t::start(std::function name, std::function fu } func(); - } - catch (const char* e) // obsolete - { - LOG_ERROR(GENERAL, "Deprecated exception type (const char*)"); - error(e); - } - catch (const std::string& e) // obsolete - { - LOG_ERROR(GENERAL, "Deprecated exception type (std::string)"); - error(e.c_str()); + + if (Ini.HLELogging.GetValue()) + { + LOG_NOTICE(GENERAL, "Thread ended"); + } } catch (const fmt::exception& e) { - error(e); + LOG_ERROR(GENERAL, "Exception: %s", e.message.get()); + Emu.Pause(); } - - if (Ini.HLELogging.GetValue()) + catch (const std::exception& e) { - LOG_NOTICE(GENERAL, "Thread ended"); + LOG_ERROR(GENERAL, "STD Exception: %s", e.what()); + Emu.Pause(); + } + catch (EmulationStopped) + { + LOG_NOTICE(GENERAL, "Thread aborted"); } - - //ctrl->set_current(false); vm::reservation_free(); g_thread_count--; -#if defined(_MSC_VER) - _set_se_translator(old_se_translator); -#endif }, m_thread, std::move(func)); } diff --git a/Utilities/Thread.h b/Utilities/Thread.h index a7b087ce2c..2e3f5a5c09 100644 --- a/Utilities/Thread.h +++ b/Utilities/Thread.h @@ -13,12 +13,6 @@ class thread_ctrl_t final // name getter const std::function name; - // true if assigned somewhere in TLS - std::atomic assigned{ false }; - - // assign TLS (must be assigned only once) - void set_current(); - public: thread_ctrl_t(std::function name) : name(std::move(name)) diff --git a/rpcs3/Emu/CPU/CPUThread.cpp b/rpcs3/Emu/CPU/CPUThread.cpp index 6fb4c3d0a2..4adcb96d67 100644 --- a/rpcs3/Emu/CPU/CPUThread.cpp +++ b/rpcs3/Emu/CPU/CPUThread.cpp @@ -48,7 +48,7 @@ CPUThread::CPUThread(CPUThreadType type, const std::string& name, std::function< m_state |= CPU_STATE_DEAD; break; } - catch (const fmt::exception&) + catch (...) { dump_info(); throw; diff --git a/rpcs3/Emu/CPU/CPUThread.h b/rpcs3/Emu/CPU/CPUThread.h index 06ea427cac..9f3a686450 100644 --- a/rpcs3/Emu/CPU/CPUThread.h +++ b/rpcs3/Emu/CPU/CPUThread.h @@ -2,11 +2,6 @@ #include "Utilities/Thread.h" -namespace vm -{ - class waiter_lock_t; -} - enum CPUThreadType { CPU_THREAD_PPU, @@ -31,19 +26,25 @@ enum : u64 }; // "HLE return" exception event -class CPUThreadReturn{}; +class CPUThreadReturn {}; // CPUThread::Stop exception event -class CPUThreadStop{}; +class CPUThreadStop {}; // CPUThread::Exit exception event -class CPUThreadExit{}; +class CPUThreadExit {}; class CPUDecoder; -class CPUThread : protected thread_t, public std::enable_shared_from_this +class CPUThread : public thread_t, public std::enable_shared_from_this { + using thread_t::start; + protected: + using thread_t::detach; + using thread_t::join; + using thread_t::joinable; + atomic_t m_state; // thread state flags std::unique_ptr m_dec; @@ -52,15 +53,6 @@ protected: const CPUThreadType m_type; const std::string m_name; // changing m_name would be terribly thread-unsafe in current implementation -public: - using thread_t::mutex; - using thread_t::cv; - using thread_t::is_current; - using thread_t::get_thread_ctrl; - - friend vm::waiter_lock_t; - -protected: CPUThread(CPUThreadType type, const std::string& name, std::function thread_name); public: diff --git a/rpcs3/Emu/Memory/vm.cpp b/rpcs3/Emu/Memory/vm.cpp index d408a794d0..f5d0791774 100644 --- a/rpcs3/Emu/Memory/vm.cpp +++ b/rpcs3/Emu/Memory/vm.cpp @@ -248,6 +248,12 @@ namespace vm return true; } + waiter_lock_t::waiter_lock_t(thread_t& thread, u32 addr, u32 size) + : m_waiter(_add_waiter(thread, addr, size)) + , m_lock(thread.mutex, std::adopt_lock) // must be locked in _add_waiter + { + } + void waiter_lock_t::wait() { // if another thread successfully called pred(), it must be set to null diff --git a/rpcs3/Emu/Memory/vm.h b/rpcs3/Emu/Memory/vm.h index f2ee27ae74..f9d1ef5695 100644 --- a/rpcs3/Emu/Memory/vm.h +++ b/rpcs3/Emu/Memory/vm.h @@ -62,9 +62,6 @@ namespace vm bool try_notify(); }; - // for internal use - waiter_t* _add_waiter(thread_t& thread, u32 addr, u32 size); - class waiter_lock_t { waiter_t* m_waiter; @@ -73,11 +70,7 @@ namespace vm public: waiter_lock_t() = delete; - template inline waiter_lock_t(T& thread, u32 addr, u32 size) - : m_waiter(_add_waiter(static_cast(thread), addr, size)) - , m_lock(thread.mutex, std::adopt_lock) // must be locked in _add_waiter - { - } + waiter_lock_t(thread_t& thread, u32 addr, u32 size); waiter_t* operator ->() const { @@ -90,7 +83,7 @@ namespace vm }; // wait until pred() returns true, addr must be aligned to size which must be a power of 2, pred() may be called by any thread - template auto wait_op(T& thread, u32 addr, u32 size, F pred, Args&&... args) -> decltype(static_cast(pred(args...))) + template auto wait_op(thread_t& thread, u32 addr, u32 size, F pred, Args&&... args) -> decltype(static_cast(pred(args...))) { // return immediately if condition passed (optimistic case) if (pred(args...)) return; diff --git a/rpcs3/Emu/System.h b/rpcs3/Emu/System.h index d34597d024..4e90e083b4 100644 --- a/rpcs3/Emu/System.h +++ b/rpcs3/Emu/System.h @@ -10,6 +10,9 @@ enum Status : u32 Ready, }; +// Emulation Stopped exception event +class EmulationStopped {}; + class CPUThreadManager; class PadManager; class KeyboardManager; @@ -209,7 +212,7 @@ inline bool check_lv2_lock(lv2_lock_t& lv2_lock) #define LV2_LOCK lv2_lock_t lv2_lock(Emu.GetCoreMutex()) #define LV2_DEFER_LOCK lv2_lock_t lv2_lock #define CHECK_LV2_LOCK(x) if (!check_lv2_lock(x)) throw EXCEPTION("lv2_lock is invalid or not locked") -#define CHECK_EMU_STATUS if (Emu.IsStopped()) throw EXCEPTION("Aborted (emulation stopped)") +#define CHECK_EMU_STATUS if (Emu.IsStopped()) throw EmulationStopped{} typedef void(*CallAfterCbType)(std::function func);