sys_spu: Fix warning and theoretical bug
This commit is contained in:
@@ -1603,6 +1603,7 @@ void spu_thread::cpu_return()
|
|||||||
|
|
||||||
if (ensure(group->running)-- == 1)
|
if (ensure(group->running)-- == 1)
|
||||||
{
|
{
|
||||||
|
u32 last_stop = 0;
|
||||||
{
|
{
|
||||||
lv2_obj::notify_all_t notify;
|
lv2_obj::notify_all_t notify;
|
||||||
std::lock_guard lock(group->mutex);
|
std::lock_guard lock(group->mutex);
|
||||||
@@ -1632,7 +1633,17 @@ void spu_thread::cpu_return()
|
|||||||
exit_status.set_value(last_exit_status);
|
exit_status.set_value(last_exit_status);
|
||||||
}
|
}
|
||||||
|
|
||||||
group->stop_count++;
|
last_stop = group->stop_count;
|
||||||
|
|
||||||
|
if (last_stop == umax)
|
||||||
|
{
|
||||||
|
// Restart with some high count to preserve some meaning
|
||||||
|
group->stop_count = 1000;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
group->stop_count++;
|
||||||
|
}
|
||||||
|
|
||||||
if (const auto ppu = std::exchange(group->waiter, nullptr))
|
if (const auto ppu = std::exchange(group->waiter, nullptr))
|
||||||
{
|
{
|
||||||
@@ -1646,6 +1657,12 @@ void spu_thread::cpu_return()
|
|||||||
|
|
||||||
// Notify on last thread stopped
|
// Notify on last thread stopped
|
||||||
group->stop_count.notify_all();
|
group->stop_count.notify_all();
|
||||||
|
|
||||||
|
// Wait for terminators manually if needed (ensuring they quit before value-wrapping)
|
||||||
|
while (last_stop == umax && group->wait_term_count)
|
||||||
|
{
|
||||||
|
std::this_thread::yield();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
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)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1352,7 +1352,8 @@ error_code sys_spu_thread_group_terminate(ppu_thread& ppu, u32 id, s32 value)
|
|||||||
if (group->set_terminate)
|
if (group->set_terminate)
|
||||||
{
|
{
|
||||||
// Wait for termination, only then return error code
|
// Wait for termination, only then return error code
|
||||||
const u64 last_stop = group->stop_count;
|
const u32 last_stop = group->stop_count;
|
||||||
|
group->wait_term_count++;
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
short_sleep(ppu);
|
short_sleep(ppu);
|
||||||
|
|
||||||
@@ -1361,6 +1362,7 @@ error_code sys_spu_thread_group_terminate(ppu_thread& ppu, u32 id, s32 value)
|
|||||||
group->stop_count.wait(last_stop);
|
group->stop_count.wait(last_stop);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
group->wait_term_count--;
|
||||||
return CELL_ESTAT;
|
return CELL_ESTAT;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1414,7 +1416,8 @@ error_code sys_spu_thread_group_terminate(ppu_thread& ppu, u32 id, s32 value)
|
|||||||
group->join_state = SYS_SPU_THREAD_GROUP_JOIN_TERMINATED;
|
group->join_state = SYS_SPU_THREAD_GROUP_JOIN_TERMINATED;
|
||||||
|
|
||||||
// Wait until the threads are actually stopped
|
// Wait until the threads are actually stopped
|
||||||
const u64 last_stop = group->stop_count;
|
const u32 last_stop = group->stop_count;
|
||||||
|
group->wait_term_count++;
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
short_sleep(ppu);
|
short_sleep(ppu);
|
||||||
|
|
||||||
@@ -1423,6 +1426,7 @@ error_code sys_spu_thread_group_terminate(ppu_thread& ppu, u32 id, s32 value)
|
|||||||
group->stop_count.wait(last_stop);
|
group->stop_count.wait(last_stop);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
group->wait_term_count--;
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -289,7 +289,8 @@ 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 = 0; // Number of running threads
|
atomic_t<u32> running = 0; // Number of running threads
|
||||||
atomic_t<u64> stop_count = 0;
|
atomic_t<u32> stop_count = 0;
|
||||||
|
atomic_t<u32> wait_term_count = 0;
|
||||||
u32 waiter_spu_index = -1; // Index of SPU executing a waiting syscall
|
u32 waiter_spu_index = -1; // Index of SPU executing a waiting syscall
|
||||||
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