#include "prx/libkernel/include/Api.hpp" #include "SceTypes.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include #include #include namespace { constexpr std::uintptr_t OnceIdle = 0; constexpr std::uintptr_t OnceRunning = 1; constexpr std::uintptr_t OnceDone = 2; constexpr unsigned long InitFailed = 4; std::atomic& OnceState(void** once) { return *reinterpret_cast*>(once); } } extern "C" { int APS5_VABI __std_init_once_begin_initialize_clr_nid_postfix(void** once, unsigned long flags, int* pending, void** context) { (void)flags; (void)context; auto& state = OnceState(once); for (;;) { std::uintptr_t current = state.load(std::memory_order_acquire); if (current == OnceIdle) { if (state.compare_exchange_weak(current, OnceRunning, std::memory_order_acq_rel)) { *pending = 1; return 1; } continue; } if (current == OnceDone) { *pending = 0; return 1; } sceKernelSyncOnAddressWait(reinterpret_cast(once), static_cast(OnceRunning), nullptr, nullptr); } } int APS5_VABI __std_init_once_complete_clr_nid_postfix(void** once, unsigned long flags, void* context) { (void)context; OnceState(once).store(flags == InitFailed ? OnceIdle : OnceDone, std::memory_order_release); sceKernelSyncOnAddressWake(once, INT_MAX); return 1; } [[noreturn]] void APS5_VABI __std_init_once_link_alternate_names_and_abort_nid_postfix() { std::abort(); } }