mirror of
https://github.com/boykopovar/AnyPS5.git
synced 2026-10-27 00:28:14 +00:00
57 lines
1.6 KiB
C++
57 lines
1.6 KiB
C++
#include "prx/libkernel/include/Api.hpp"
|
|
#include "SceTypes.hpp"
|
|
#include "prx/libc/include/general/VabiMacros.hpp"
|
|
#include <atomic>
|
|
#include <climits>
|
|
#include <cstdint>
|
|
#include <cstdlib>
|
|
|
|
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<std::uintptr_t>& OnceState(void** once) {
|
|
return *reinterpret_cast<std::atomic<std::uintptr_t>*>(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<std::uint32_t*>(once), static_cast<std::uint32_t>(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();
|
|
}
|
|
|
|
}
|