sys_spu: Minor cleanup of group termination process
This commit is contained in:
@@ -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)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user