From 2882220cbd879b490fe71dc217c9fa2e6c2d72a8 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Tue, 20 Aug 2019 19:07:03 +0300 Subject: [PATCH] Implement cpu_thread::stop_all() --- rpcs3/Emu/CPU/CPUThread.cpp | 33 ++++++++++++++++++++++++++++++++- rpcs3/Emu/CPU/CPUThread.h | 3 +++ rpcs3/Emu/System.cpp | 17 +---------------- 3 files changed, 36 insertions(+), 17 deletions(-) diff --git a/rpcs3/Emu/CPU/CPUThread.cpp b/rpcs3/Emu/CPU/CPUThread.cpp index 9a3fabf17e..dacf66195b 100644 --- a/rpcs3/Emu/CPU/CPUThread.cpp +++ b/rpcs3/Emu/CPU/CPUThread.cpp @@ -8,6 +8,8 @@ #include "Emu/Cell/PPUThread.h" #include "Emu/Cell/SPUThread.h" +#include + DECLARE(cpu_thread::g_threads_created){0}; DECLARE(cpu_thread::g_threads_deleted){0}; @@ -132,7 +134,7 @@ void cpu_thread::operator()() g_cpu_suspend_lock.lock_unlock(); // Check thread status - while (!(state & (cpu_flag::exit + cpu_flag::dbg_global_stop))) + while (!(state & (cpu_flag::exit + cpu_flag::dbg_global_stop)) && !Emu.IsStopped()) { // Check stop status if (!(state & cpu_flag::stop)) @@ -389,3 +391,32 @@ cpu_thread::suspend_all::~suspend_all() m_this->check_state(); } } + +void cpu_thread::stop_all() noexcept +{ + if (g_tls_current_cpu_thread) + { + // Report unsupported but unnecessary case + LOG_FATAL(GENERAL, "cpu_thread::stop_all() has been called from a CPU thread."); + return; + } + else + { + ::vip_lock lock(g_cpu_suspend_lock); + + for_all_cpu([](cpu_thread* cpu) + { + cpu->state += cpu_flag::dbg_global_stop; + cpu->notify(); + }); + } + + LOG_NOTICE(GENERAL, "All CPU threads have been signaled."); + + while (g_cpu_array_sema) + { + std::this_thread::sleep_for(10ms); + } + + LOG_NOTICE(GENERAL, "All CPU threads have been stopped."); +} diff --git a/rpcs3/Emu/CPU/CPUThread.h b/rpcs3/Emu/CPU/CPUThread.h index 4d2d6e9c90..dfbb252e63 100644 --- a/rpcs3/Emu/CPU/CPUThread.h +++ b/rpcs3/Emu/CPU/CPUThread.h @@ -113,6 +113,9 @@ public: suspend_all& operator=(const suspend_all&) = delete; ~suspend_all(); }; + + // Stop all threads with cpu_flag::dbg_global_stop + static void stop_all() noexcept; }; inline cpu_thread* get_current_cpu_thread() noexcept diff --git a/rpcs3/Emu/System.cpp b/rpcs3/Emu/System.cpp index 688b7b8b8f..3cdcd126bf 100644 --- a/rpcs3/Emu/System.cpp +++ b/rpcs3/Emu/System.cpp @@ -1711,22 +1711,7 @@ void Emulator::Stop(bool restart) GetCallbacks().on_stop(); -#ifdef WITH_GDB_DEBUGGER - //fxm for some reason doesn't call on_stop - fxm::get()->on_stop(); - fxm::remove(); -#endif - - auto on_select = [&](u32, cpu_thread& cpu) - { - cpu.state += cpu_flag::dbg_global_stop; - cpu.notify(); - }; - - idm::select>(on_select); - idm::select>(on_select); - - LOG_NOTICE(GENERAL, "All threads signaled..."); + cpu_thread::stop_all(); while (g_thread_count) {