Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Small sys_spu thread group termination fixes #8049

Merged
merged 4 commits into from Apr 28, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
55 changes: 44 additions & 11 deletions rpcs3/Emu/Cell/SPUThread.cpp
Expand Up @@ -3040,7 +3040,9 @@ bool spu_thread::stop_and_signal(u32 code)
queue.reset();

// 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())
{
Expand All @@ -3054,6 +3056,11 @@ bool spu_thread::stop_and_signal(u32 code)

std::lock_guard lock(group->mutex);

if (is_stopped())
{
return false;
}

if (group->run_state >= SPU_THREAD_GROUP_STATUS_WAITING && group->run_state <= SPU_THREAD_GROUP_STATUS_WAITING_AND_SUSPENDED)
{
// Try again
Expand Down Expand Up @@ -3113,11 +3120,14 @@ bool spu_thread::stop_and_signal(u32 code)

while (true)
{
if (is_stopped())
if (state & (cpu_flag::exit + cpu_flag::dbg_global_stop))
{
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))
{
thread_ctrl::wait();
Expand Down Expand Up @@ -3238,19 +3248,42 @@ bool spu_thread::stop_and_signal(u32 code)

spu_log.trace("sys_spu_thread_group_exit(status=0x%x)", value);

std::lock_guard lock(group->mutex);

for (auto& thread : group->threads)
while (true)
{
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)
{
if (is_stopped())
{
return false;
}

thread_ctrl::wait();
}

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)
{
thread->state += cpu_flag::stop;
thread_ctrl::notify(*thread);
// We can't exit while we are waiting on an SPU event
continue;
}
}

group->exit_status = value;
group->join_state = SYS_SPU_THREAD_GROUP_JOIN_GROUP_EXIT;
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;
check_state();
Expand Down
6 changes: 5 additions & 1 deletion rpcs3/Emu/Cell/lv2/sys_spu.cpp
Expand Up @@ -668,6 +668,7 @@ error_code sys_spu_thread_group_start(ppu_thread& ppu, u32 id)

group->join_state = 0;
group->running = max_threads;
group->set_terminate = false;

for (auto& thread : group->threads)
{
Expand Down Expand Up @@ -859,11 +860,14 @@ error_code sys_spu_thread_group_terminate(ppu_thread& ppu, u32 id, s32 value)

if (group->run_state <= SPU_THREAD_GROUP_STATUS_INITIALIZED ||
group->run_state == SPU_THREAD_GROUP_STATUS_WAITING ||
group->run_state == SPU_THREAD_GROUP_STATUS_WAITING_AND_SUSPENDED)
group->run_state == SPU_THREAD_GROUP_STATUS_WAITING_AND_SUSPENDED ||
group->set_terminate)
{
return CELL_ESTAT;
}

group->set_terminate = true;

for (auto& thread : group->threads)
{
if (thread)
Expand Down
1 change: 1 addition & 0 deletions rpcs3/Emu/Cell/lv2/sys_spu.h
Expand Up @@ -270,6 +270,7 @@ struct lv2_spu_group
cond_variable cond; // used to signal waiting PPU thread
atomic_t<u64> stop_count;
class ppu_thread* waiter = nullptr;
bool set_terminate = false;

std::array<std::shared_ptr<named_thread<spu_thread>>, 8> threads; // SPU Threads
std::array<s8, 256> threads_map; // SPU Threads map based number
Expand Down