sys_ppu_thread: fixing detached threads

This commit is contained in:
Nekotekina 2020-03-01 22:17:14 +03:00
parent 752c4a7b0d
commit 6ee9153329

View file

@ -11,6 +11,26 @@
LOG_CHANNEL(sys_ppu_thread);
// Simple structure to cleanup previous thread, because can't remove its own thread
struct ppu_thread_cleaner
{
atomic_t<u32> old_id = 0;
void clean(u32 new_id)
{
if (old_id) [[likely]]
{
if (u32 id = old_id.exchange(new_id)) [[likely]]
{
if (!idm::remove<named_thread<ppu_thread>>(old_id)) [[unlikely]]
{
sys_ppu_thread.fatal("Failed to remove detached thread 0x%x", id);
}
}
}
}
};
void _sys_ppu_thread_exit(ppu_thread& ppu, u64 errorcode)
{
vm::temporary_unlock(ppu);
@ -41,24 +61,7 @@ void _sys_ppu_thread_exit(ppu_thread& ppu, u64 errorcode)
if (jid == umax)
{
// Simple structure to cleanup previous thread, because can't remove its own thread
struct ppu_thread_cleaner
{
atomic_t<u32> id = 0;
};
auto cleaner = g_fxo->get<ppu_thread_cleaner>();
if (cleaner->id || !cleaner->id.compare_and_swap_test(0, ppu.id)) [[likely]]
{
if (u32 old_id = cleaner->id.exchange(ppu.id))
{
if (!idm::remove<named_thread<ppu_thread>>(old_id))
{
sys_ppu_thread.fatal("Failed to remove detached thread 0x%x", old_id);
}
}
}
g_fxo->get<ppu_thread_cleaner>()->clean(ppu.id);
}
else if (jid != 0)
{
@ -88,6 +91,9 @@ error_code sys_ppu_thread_join(ppu_thread& ppu, u32 thread_id, vm::ptr<u64> vptr
sys_ppu_thread.trace("sys_ppu_thread_join(thread_id=0x%x, vptr=*0x%x)", thread_id, vptr);
// Clean some detached thread (hack)
g_fxo->get<ppu_thread_cleaner>()->clean(0);
const auto thread = idm::get<named_thread<ppu_thread>>(thread_id, [&](ppu_thread& thread) -> CellError
{
CellError result = thread.joiner.atomic_op([&](u32& value) -> CellError
@ -161,6 +167,9 @@ error_code sys_ppu_thread_detach(u32 thread_id)
{
sys_ppu_thread.trace("sys_ppu_thread_detach(thread_id=0x%x)", thread_id);
// Clean some detached thread (hack)
g_fxo->get<ppu_thread_cleaner>()->clean(0);
const auto thread = idm::check<named_thread<ppu_thread>>(thread_id, [&](ppu_thread& thread) -> CellError
{
return thread.joiner.atomic_op([&](u32& value) -> CellError
@ -231,6 +240,9 @@ error_code sys_ppu_thread_set_priority(ppu_thread& ppu, u32 thread_id, s32 prio)
return CELL_EINVAL;
}
// Clean some detached thread (hack)
g_fxo->get<ppu_thread_cleaner>()->clean(0);
const auto thread = idm::check<named_thread<ppu_thread>>(thread_id, [&](ppu_thread& thread)
{
if (thread.prio != prio)
@ -251,6 +263,9 @@ error_code sys_ppu_thread_get_priority(u32 thread_id, vm::ptr<s32> priop)
{
sys_ppu_thread.trace("sys_ppu_thread_get_priority(thread_id=0x%x, priop=*0x%x)", thread_id, priop);
// Clean some detached thread (hack)
g_fxo->get<ppu_thread_cleaner>()->clean(0);
const auto thread = idm::check<named_thread<ppu_thread>>(thread_id, [&](ppu_thread& thread)
{
*priop = thread.prio;
@ -325,6 +340,9 @@ error_code _sys_ppu_thread_create(vm::ptr<u64> thread_id, vm::ptr<ppu_thread_par
return CELL_EPERM;
}
// Clean some detached thread (hack)
g_fxo->get<ppu_thread_cleaner>()->clean(0);
// Compute actual stack size and allocate
const u32 stack_size = ::align<u32>(std::max<u32>(_stacksz, 4096), 4096);