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)
{
// Notify on last thread stopped
group->stop_count++;
group->mutex.lock_unlock();
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;
// 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<u32> 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())
{

View File

@ -236,6 +236,7 @@ struct lv2_spu_group
atomic_t<u32> join_state; // flags used to detect exit cause
atomic_t<u32> running; // Number of running threads
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::pair<sys_spu_image, std::vector<sys_spu_segment>>, 256> imgs; // SPU Images
@ -257,6 +258,7 @@ struct lv2_spu_group
, exit_status(0)
, join_state(0)
, running(0)
, stop_count(0)
{
}