From f442a8a84ca798f20f924279593106454c54cbb8 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Tue, 27 Nov 2018 20:00:07 +0300 Subject: [PATCH] SPU TG: add thread group stop counter Fix possible race condition introduced by waiting on `running` value --- rpcs3/Emu/Cell/SPUThread.cpp | 1 + rpcs3/Emu/Cell/lv2/sys_spu.cpp | 8 ++++++-- rpcs3/Emu/Cell/lv2/sys_spu.h | 2 ++ 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/rpcs3/Emu/Cell/SPUThread.cpp b/rpcs3/Emu/Cell/SPUThread.cpp index afba170867..a2d8ff31bd 100644 --- a/rpcs3/Emu/Cell/SPUThread.cpp +++ b/rpcs3/Emu/Cell/SPUThread.cpp @@ -487,6 +487,7 @@ void spu_thread::cpu_stop() if (verify(HERE, group->running--) == 1) { // Notify on last thread stopped + group->stop_count++; group->mutex.lock_unlock(); group->cond.notify_all(); } diff --git a/rpcs3/Emu/Cell/lv2/sys_spu.cpp b/rpcs3/Emu/Cell/lv2/sys_spu.cpp index 7c198c363f..581e17f812 100644 --- a/rpcs3/Emu/Cell/lv2/sys_spu.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_spu.cpp @@ -623,7 +623,9 @@ error_code sys_spu_thread_group_terminate(u32 id, s32 value) group->join_state |= SPU_TGJSF_TERMINATED; // Wait until the threads are actually stopped - while (group->running) + const u64 last_stop = group->stop_count - !group->running; + + while (group->stop_count == last_stop) { group->cond.wait(lock); } @@ -661,9 +663,11 @@ error_code sys_spu_thread_group_join(ppu_thread& ppu, u32 id, vm::ptr cause return CELL_EBUSY; } + const u64 last_stop = group->stop_count - !group->running; + lv2_obj::sleep(ppu); - while (group->running) + while (group->stop_count == last_stop) { if (ppu.is_stopped()) { diff --git a/rpcs3/Emu/Cell/lv2/sys_spu.h b/rpcs3/Emu/Cell/lv2/sys_spu.h index 853bfb327a..72b416fe2c 100644 --- a/rpcs3/Emu/Cell/lv2/sys_spu.h +++ b/rpcs3/Emu/Cell/lv2/sys_spu.h @@ -236,6 +236,7 @@ struct lv2_spu_group atomic_t join_state; // flags used to detect exit cause atomic_t running; // Number of running threads cond_variable cond; // used to signal waiting PPU thread + atomic_t stop_count; std::array>, 256> threads; // SPU Threads std::array>, 256> imgs; // SPU Images @@ -257,6 +258,7 @@ struct lv2_spu_group , exit_status(0) , join_state(0) , running(0) + , stop_count(0) { }