diff --git a/rpcs3/Emu/Cell/lv2/sys_ppu_thread.cpp b/rpcs3/Emu/Cell/lv2/sys_ppu_thread.cpp index 2805e71f01..c6c120696c 100644 --- a/rpcs3/Emu/Cell/lv2/sys_ppu_thread.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_ppu_thread.cpp @@ -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 old_id = 0; + + void clean(u32 new_id) + { + if (old_id) [[likely]] + { + if (u32 id = old_id.exchange(new_id)) [[likely]] + { + if (!idm::remove>(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 id = 0; - }; - - auto cleaner = g_fxo->get(); - - 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>(old_id)) - { - sys_ppu_thread.fatal("Failed to remove detached thread 0x%x", old_id); - } - } - } + g_fxo->get()->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 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()->clean(0); + const auto thread = idm::get>(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()->clean(0); + const auto thread = idm::check>(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()->clean(0); + const auto thread = idm::check>(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 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()->clean(0); + const auto thread = idm::check>(thread_id, [&](ppu_thread& thread) { *priop = thread.prio; @@ -325,6 +340,9 @@ error_code _sys_ppu_thread_create(vm::ptr thread_id, vm::ptrget()->clean(0); + // Compute actual stack size and allocate const u32 stack_size = ::align(std::max(_stacksz, 4096), 4096);