SPU TG: add thread group stop counter

Fix possible race condition introduced by waiting on `running` value
This commit is contained in:
Nekotekina 2018-11-27 20:00:07 +03:00
parent febe4d4a10
commit f442a8a84c
3 changed files with 9 additions and 2 deletions

View file

@ -487,6 +487,7 @@ void spu_thread::cpu_stop()
if (verify(HERE, group->running--) == 1) if (verify(HERE, group->running--) == 1)
{ {
// Notify on last thread stopped // Notify on last thread stopped
group->stop_count++;
group->mutex.lock_unlock(); group->mutex.lock_unlock();
group->cond.notify_all(); group->cond.notify_all();
} }

View file

@ -623,7 +623,9 @@ error_code sys_spu_thread_group_terminate(u32 id, s32 value)
group->join_state |= SPU_TGJSF_TERMINATED; group->join_state |= SPU_TGJSF_TERMINATED;
// Wait until the threads are actually stopped // 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); group->cond.wait(lock);
} }
@ -661,9 +663,11 @@ error_code sys_spu_thread_group_join(ppu_thread& ppu, u32 id, vm::ptr<u32> cause
return CELL_EBUSY; return CELL_EBUSY;
} }
const u64 last_stop = group->stop_count - !group->running;
lv2_obj::sleep(ppu); lv2_obj::sleep(ppu);
while (group->running) while (group->stop_count == last_stop)
{ {
if (ppu.is_stopped()) if (ppu.is_stopped())
{ {

View file

@ -236,6 +236,7 @@ struct lv2_spu_group
atomic_t<u32> join_state; // flags used to detect exit cause atomic_t<u32> join_state; // flags used to detect exit cause
atomic_t<u32> running; // Number of running threads atomic_t<u32> running; // Number of running threads
cond_variable cond; // used to signal waiting PPU thread cond_variable cond; // used to signal waiting PPU thread
atomic_t<u64> stop_count;
std::array<std::shared_ptr<named_thread<spu_thread>>, 256> threads; // SPU Threads std::array<std::shared_ptr<named_thread<spu_thread>>, 256> threads; // SPU Threads
std::array<std::pair<sys_spu_image, std::vector<sys_spu_segment>>, 256> imgs; // SPU Images std::array<std::pair<sys_spu_image, std::vector<sys_spu_segment>>, 256> imgs; // SPU Images
@ -257,6 +258,7 @@ struct lv2_spu_group
, exit_status(0) , exit_status(0)
, join_state(0) , join_state(0)
, running(0) , running(0)
, stop_count(0)
{ {
} }