sys_spu: Minor cleanup of group termination process

This commit is contained in:
Eladash
2020-05-12 04:46:26 +03:00
committed by Ivan
parent 93122196d9
commit 7ff25588f4
3 changed files with 11 additions and 13 deletions
+4 -2
View File
@@ -983,7 +983,6 @@ void spu_thread::cpu_stop()
{ {
{ {
std::lock_guard lock(group->mutex); std::lock_guard lock(group->mutex);
group->stop_count++;
group->run_state = SPU_THREAD_GROUP_STATUS_INITIALIZED; group->run_state = SPU_THREAD_GROUP_STATUS_INITIALIZED;
if (!group->join_state) if (!group->join_state)
@@ -1010,17 +1009,20 @@ void spu_thread::cpu_stop()
exit_status.set_value(last_exit_status); exit_status.set_value(last_exit_status);
} }
group->stop_count++;
if (const auto ppu = std::exchange(group->waiter, nullptr)) if (const auto ppu = std::exchange(group->waiter, nullptr))
{ {
// Send exit status directly to the joining thread // Send exit status directly to the joining thread
ppu->gpr[4] = group->join_state; ppu->gpr[4] = group->join_state;
ppu->gpr[5] = group->exit_status; ppu->gpr[5] = group->exit_status;
group->join_state.release(0); group->join_state.release(0);
lv2_obj::awake(ppu);
} }
} }
// Notify on last thread stopped // Notify on last thread stopped
group->cond.notify_all(); group->stop_count.notify_all();
} }
else if (status_npc.load().status >> 16 == SYS_SPU_THREAD_STOP_THREAD_EXIT) else if (status_npc.load().status >> 16 == SYS_SPU_THREAD_STOP_THREAD_EXIT)
{ {
+7 -10
View File
@@ -978,10 +978,11 @@ error_code sys_spu_thread_group_terminate(ppu_thread& ppu, u32 id, s32 value)
{ {
// Wait for termination, only then return error code // Wait for termination, only then return error code
const u64 last_stop = group->stop_count; const u64 last_stop = group->stop_count;
lock.unlock();
while (group->stop_count == last_stop) while (group->stop_count == last_stop)
{ {
group->cond.wait(lock); group->stop_count.wait(last_stop);
} }
return CELL_ESTAT; return CELL_ESTAT;
@@ -1010,10 +1011,11 @@ error_code sys_spu_thread_group_terminate(ppu_thread& ppu, u32 id, s32 value)
// Wait until the threads are actually stopped // Wait until the threads are actually stopped
const u64 last_stop = group->stop_count; const u64 last_stop = group->stop_count;
lock.unlock();
while (group->stop_count == last_stop) while (group->stop_count == last_stop)
{ {
group->cond.wait(lock); group->stop_count.wait(last_stop);
} }
return CELL_OK; return CELL_OK;
@@ -1065,29 +1067,24 @@ error_code sys_spu_thread_group_join(ppu_thread& ppu, u32 id, vm::ptr<u32> cause
else else
{ {
// Subscribe to receive status in r4-r5 // Subscribe to receive status in r4-r5
ppu.gpr[4] = 0;
group->waiter = &ppu; group->waiter = &ppu;
} }
lv2_obj::sleep(ppu); lv2_obj::sleep(ppu);
lock.unlock();
while (!ppu.gpr[4]) while (!ppu.state.test_and_reset(cpu_flag::signal))
{ {
if (ppu.is_stopped()) if (ppu.is_stopped())
{ {
return 0; return 0;
} }
group->cond.wait(lock); thread_ctrl::wait();
} }
} }
while (0); while (0);
if (ppu.test_stopped())
{
return 0;
}
if (!cause) if (!cause)
{ {
if (status) if (status)
-1
View File
@@ -278,7 +278,6 @@ struct lv2_spu_group
atomic_t<s32> exit_status; // SPU Thread Group Exit Status atomic_t<s32> exit_status; // SPU Thread Group Exit Status
atomic_t<u32> join_state; // flags used to detect exit cause and signal atomic_t<u32> join_state; // flags used to detect exit cause and signal
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
atomic_t<u64> stop_count; atomic_t<u64> stop_count;
class ppu_thread* waiter = nullptr; class ppu_thread* waiter = nullptr;
bool set_terminate = false; bool set_terminate = false;