mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-09 08:21:29 +12:00
Wait for SPU event to be received in sys_spu_thread_group_exit
Also use atomic check for group->run_state outside the mutex, explicitly forbid group termination while we are waiting for an event to be received.
This commit is contained in:
parent
a9c18964b6
commit
7da8ba5c15
1 changed files with 40 additions and 12 deletions
|
@ -2798,7 +2798,9 @@ bool spu_thread::stop_and_signal(u32 code)
|
||||||
queue.reset();
|
queue.reset();
|
||||||
|
|
||||||
// Check group status, wait if necessary
|
// Check group status, wait if necessary
|
||||||
while (group->run_state >= SPU_THREAD_GROUP_STATUS_WAITING && group->run_state <= SPU_THREAD_GROUP_STATUS_SUSPENDED)
|
for (auto _state = +group->run_state;
|
||||||
|
_state >= SPU_THREAD_GROUP_STATUS_WAITING && _state <= SPU_THREAD_GROUP_STATUS_WAITING_AND_SUSPENDED;
|
||||||
|
_state = group->run_state)
|
||||||
{
|
{
|
||||||
if (is_stopped())
|
if (is_stopped())
|
||||||
{
|
{
|
||||||
|
@ -2876,11 +2878,14 @@ bool spu_thread::stop_and_signal(u32 code)
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
if (is_stopped())
|
if (state & (cpu_flag::exit + cpu_flag::dbg_global_stop))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The thread group cannot be stopped while waiting for an event
|
||||||
|
verify(HERE), !(state & cpu_flag::stop);
|
||||||
|
|
||||||
if (!state.test_and_reset(cpu_flag::signal))
|
if (!state.test_and_reset(cpu_flag::signal))
|
||||||
{
|
{
|
||||||
thread_ctrl::wait();
|
thread_ctrl::wait();
|
||||||
|
@ -3001,19 +3006,42 @@ bool spu_thread::stop_and_signal(u32 code)
|
||||||
|
|
||||||
spu_log.trace("sys_spu_thread_group_exit(status=0x%x)", value);
|
spu_log.trace("sys_spu_thread_group_exit(status=0x%x)", value);
|
||||||
|
|
||||||
std::lock_guard lock(group->mutex);
|
while (true)
|
||||||
|
|
||||||
for (auto& thread : group->threads)
|
|
||||||
{
|
{
|
||||||
if (thread && thread.get() != this)
|
for (auto _state = +group->run_state;
|
||||||
|
_state >= SPU_THREAD_GROUP_STATUS_WAITING && _state <= SPU_THREAD_GROUP_STATUS_WAITING_AND_SUSPENDED;
|
||||||
|
_state = group->run_state)
|
||||||
{
|
{
|
||||||
thread->state += cpu_flag::stop;
|
if (is_stopped())
|
||||||
thread_ctrl::notify(*thread);
|
{
|
||||||
}
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
group->exit_status = value;
|
thread_ctrl::wait();
|
||||||
group->join_state = SYS_SPU_THREAD_GROUP_JOIN_GROUP_EXIT;
|
}
|
||||||
|
|
||||||
|
std::lock_guard lock(group->mutex);
|
||||||
|
|
||||||
|
if (auto _state = +group->run_state;
|
||||||
|
_state >= SPU_THREAD_GROUP_STATUS_WAITING && _state <= SPU_THREAD_GROUP_STATUS_WAITING_AND_SUSPENDED)
|
||||||
|
{
|
||||||
|
// We can't exit while we are waiting on an SPU event
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& thread : group->threads)
|
||||||
|
{
|
||||||
|
if (thread && thread.get() != this)
|
||||||
|
{
|
||||||
|
thread->state += cpu_flag::stop;
|
||||||
|
thread_ctrl::notify(*thread);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
group->exit_status = value;
|
||||||
|
group->join_state = SYS_SPU_THREAD_GROUP_JOIN_GROUP_EXIT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
state += cpu_flag::stop;
|
state += cpu_flag::stop;
|
||||||
check_state();
|
check_state();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue