diff --git a/Utilities/Thread.h b/Utilities/Thread.h index c065776466..fb707117dc 100644 --- a/Utilities/Thread.h +++ b/Utilities/Thread.h @@ -234,6 +234,23 @@ public: _wait_for(-1, true); } + // Wait for both thread sync var and provided atomic var + template + static inline void wait_on(T& wait, U old, u64 usec = -1) + { + auto _this = g_tls_this_thread; + + if (_this->m_sync.bit_test_reset(2)) + { + return; + } + + atomic_wait::list<2> list{}; + list.set<0, op>(wait, old); + list.set<1>(_this->m_sync, 0, 4 + 1); + list.wait(atomic_wait_timeout{usec <= 0xffff'ffff'ffff'ffff / 1000 ? usec * 1000 : 0xffff'ffff'ffff'ffff}); + } + // Exit. [[noreturn]] static void emergency_exit(std::string_view reason); diff --git a/rpcs3/Emu/Cell/lv2/sys_ppu_thread.cpp b/rpcs3/Emu/Cell/lv2/sys_ppu_thread.cpp index c72b335b71..8d0db46af1 100644 --- a/rpcs3/Emu/Cell/lv2/sys_ppu_thread.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_ppu_thread.cpp @@ -99,7 +99,7 @@ void _sys_ppu_thread_exit(ppu_thread& ppu, u64 errorcode) if (old_status == ppu_join_status::joinable) { // Wait for termination - ppu.joiner.wait(ppu_join_status::zombie); + thread_ctrl::wait_on(ppu.joiner, ppu_join_status::zombie); } ppu_thread_exit(ppu);