diff --git a/rpcs3/Emu/Cell/Modules/sys_ppu_thread_.cpp b/rpcs3/Emu/Cell/Modules/sys_ppu_thread_.cpp index 0ce6b49a5b..87d099d986 100644 --- a/rpcs3/Emu/Cell/Modules/sys_ppu_thread_.cpp +++ b/rpcs3/Emu/Cell/Modules/sys_ppu_thread_.cpp @@ -12,6 +12,7 @@ extern logs::channel sysPrxForUser; vm::gvar g_ppu_atexit_lwm; +vm::gvar[8]> g_ppu_atexit; vm::gvar g_ppu_once_mutex; static u32 s_tls_addr = 0; // TLS image address @@ -157,8 +158,18 @@ void sys_ppu_thread_exit(ppu_thread& ppu, u64 val) { sysPrxForUser.trace("sys_ppu_thread_exit(val=0x%llx)", val); - // (call registered atexit functions) - // ... + // Call registered atexit functions + verify(HERE), !sys_lwmutex_lock(ppu, g_ppu_atexit_lwm, 0); + + for (auto ptr : *g_ppu_atexit) + { + if (ptr) + { + ptr(ppu); + } + } + + verify(HERE), !sys_lwmutex_unlock(ppu, g_ppu_atexit_lwm); // Deallocate TLS ppu_free_tls(vm::cast(ppu.gpr[13], HERE) - 0x7030); @@ -173,6 +184,55 @@ void sys_ppu_thread_exit(ppu_thread& ppu, u64 val) return _sys_ppu_thread_exit(ppu, val); } +error_code sys_ppu_thread_register_atexit(ppu_thread& ppu, vm::ptr func) +{ + sysPrxForUser.notice("sys_ppu_thread_register_atexit(ptr=*0x%x)", func); + + verify(HERE), !sys_lwmutex_lock(ppu, g_ppu_atexit_lwm, 0); + + for (auto ptr : *g_ppu_atexit) + { + if (ptr == func) + { + verify(HERE), !sys_lwmutex_unlock(ppu, g_ppu_atexit_lwm); + return CELL_EPERM; + } + } + + for (auto& pp : *g_ppu_atexit) + { + if (pp == vm::null) + { + pp = func; + verify(HERE), !sys_lwmutex_unlock(ppu, g_ppu_atexit_lwm); + return CELL_OK; + } + } + + verify(HERE), !sys_lwmutex_unlock(ppu, g_ppu_atexit_lwm); + return CELL_ENOMEM; +} + +error_code sys_ppu_thread_unregister_atexit(ppu_thread& ppu, vm::ptr func) +{ + sysPrxForUser.notice("sys_ppu_thread_unregister_atexit(ptr=*0x%x)", func); + + verify(HERE), !sys_lwmutex_lock(ppu, g_ppu_atexit_lwm, 0); + + for (auto& pp : *g_ppu_atexit) + { + if (pp == func) + { + pp = vm::null; + verify(HERE), !sys_lwmutex_unlock(ppu, g_ppu_atexit_lwm); + return CELL_OK; + } + } + + verify(HERE), !sys_lwmutex_unlock(ppu, g_ppu_atexit_lwm); + return CELL_ESRCH; +} + void sys_ppu_thread_once(ppu_thread& ppu, vm::ptr once_ctrl, vm::ptr init) { sysPrxForUser.notice("sys_ppu_thread_once(once_ctrl=*0x%x, init=*0x%x)", once_ctrl, init); @@ -189,16 +249,6 @@ void sys_ppu_thread_once(ppu_thread& ppu, vm::ptr once_ctrl, vm::ptr