From 82068cf8025fac7adb48d54298b85741277964a9 Mon Sep 17 00:00:00 2001 From: Eladash Date: Thu, 30 Jul 2020 12:07:18 +0300 Subject: [PATCH] SPU: Fix spu_thread::cpu_stop() missed executions (#8656) --- rpcs3/Emu/CPU/CPUThread.cpp | 12 +++++++++++- rpcs3/Emu/CPU/CPUThread.h | 3 +++ rpcs3/Emu/Cell/RawSPUThread.cpp | 4 ++-- rpcs3/Emu/Cell/SPUThread.cpp | 12 +++++------- rpcs3/Emu/Cell/SPUThread.h | 2 +- rpcs3/Emu/Cell/lv2/sys_spu.cpp | 2 +- 6 files changed, 23 insertions(+), 12 deletions(-) diff --git a/rpcs3/Emu/CPU/CPUThread.cpp b/rpcs3/Emu/CPU/CPUThread.cpp index f4ee44b48b..e3c678898c 100644 --- a/rpcs3/Emu/CPU/CPUThread.cpp +++ b/rpcs3/Emu/CPU/CPUThread.cpp @@ -433,11 +433,21 @@ void cpu_thread::operator()() if (!(state & cpu_flag::stop)) { cpu_task(); - state -= cpu_flag::ret; + + if (state & cpu_flag::ret && state.test_and_reset(cpu_flag::ret)) + { + cpu_return(); + } + continue; } thread_ctrl::wait(); + + if (state & cpu_flag::ret && state.test_and_reset(cpu_flag::ret)) + { + cpu_return(); + } } // Complete cleanup gracefully diff --git a/rpcs3/Emu/CPU/CPUThread.h b/rpcs3/Emu/CPU/CPUThread.h index b009764ae4..853d967eec 100644 --- a/rpcs3/Emu/CPU/CPUThread.h +++ b/rpcs3/Emu/CPU/CPUThread.h @@ -120,6 +120,9 @@ public: // Callback for vm::temporary_unlock virtual void cpu_unmem() {} + // Callback for cpu_flag::ret + virtual void cpu_return() {} + // Thread locker class suspend_all { diff --git a/rpcs3/Emu/Cell/RawSPUThread.cpp b/rpcs3/Emu/Cell/RawSPUThread.cpp index de3de7d454..cc025bab67 100644 --- a/rpcs3/Emu/Cell/RawSPUThread.cpp +++ b/rpcs3/Emu/Cell/RawSPUThread.cpp @@ -262,7 +262,7 @@ bool spu_thread::write_reg(const u32 addr, const u32 value) if (get_current_cpu_thread() == this) { // TODO - state += cpu_flag::stop; + state += cpu_flag::stop + cpu_flag::ret; return true; } @@ -270,7 +270,7 @@ bool spu_thread::write_reg(const u32 addr, const u32 value) if (status_npc.load().status & SPU_STATUS_RUNNING) { - state += cpu_flag::stop; + state += cpu_flag::stop + cpu_flag::ret; for (status_npc_sync_var old; (old = status_npc).status & SPU_STATUS_RUNNING;) { diff --git a/rpcs3/Emu/Cell/SPUThread.cpp b/rpcs3/Emu/Cell/SPUThread.cpp index 4e35645c57..406540a4a3 100644 --- a/rpcs3/Emu/Cell/SPUThread.cpp +++ b/rpcs3/Emu/Cell/SPUThread.cpp @@ -1006,7 +1006,7 @@ void spu_thread::cpu_init() gpr[1]._u32[3] = 0x3FFF0; // initial stack frame pointer } -void spu_thread::cpu_stop() +void spu_thread::cpu_return() { if (get_type() >= spu_type::raw) { @@ -1150,8 +1150,6 @@ void spu_thread::cpu_task() spu_runtime::g_interpreter(*this, _ptr(0), nullptr); } } - - cpu_stop(); } void spu_thread::cpu_mem() @@ -2959,7 +2957,7 @@ bool spu_thread::stop_and_signal(u32 code) if (get_type() >= spu_type::raw) { // Save next PC and current SPU Interrupt Status - state += cpu_flag::stop + cpu_flag::wait; + state += cpu_flag::stop + cpu_flag::wait + cpu_flag::ret; set_status_npc(); status_npc.notify_one(); @@ -3306,7 +3304,7 @@ bool spu_thread::stop_and_signal(u32 code) { if (thread && thread.get() != this) { - thread->state += cpu_flag::stop; + thread->state += cpu_flag::stop + cpu_flag::ret; thread_ctrl::raw_notify(*thread); } } @@ -3317,7 +3315,7 @@ bool spu_thread::stop_and_signal(u32 code) break; } - state += cpu_flag::stop; + state += cpu_flag::stop + cpu_flag::ret; check_state(); return true; } @@ -3337,7 +3335,7 @@ bool spu_thread::stop_and_signal(u32 code) spu_log.trace("sys_spu_thread_exit(status=0x%x)", value); last_exit_status.release(value); set_status_npc(); - state += cpu_flag::stop; + state += cpu_flag::stop + cpu_flag::ret; check_state(); return true; } diff --git a/rpcs3/Emu/Cell/SPUThread.h b/rpcs3/Emu/Cell/SPUThread.h index a4a04ade4b..a327cbdcb0 100644 --- a/rpcs3/Emu/Cell/SPUThread.h +++ b/rpcs3/Emu/Cell/SPUThread.h @@ -621,9 +621,9 @@ public: virtual void cpu_task() override final; virtual void cpu_mem() override; virtual void cpu_unmem() override; + virtual void cpu_return() override; virtual ~spu_thread() override; void cpu_init(); - void cpu_stop(); static const u32 id_base = 0x02000000; // TODO (used to determine thread type) static const u32 id_step = 1; diff --git a/rpcs3/Emu/Cell/lv2/sys_spu.cpp b/rpcs3/Emu/Cell/lv2/sys_spu.cpp index 591f6cb535..147c2ca353 100644 --- a/rpcs3/Emu/Cell/lv2/sys_spu.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_spu.cpp @@ -1003,7 +1003,7 @@ error_code sys_spu_thread_group_terminate(ppu_thread& ppu, u32 id, s32 value) { if (thread) { - thread->state += cpu_flag::stop; + thread->state += cpu_flag::stop + cpu_flag::ret; } }