mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-20 02:47:02 +02:00
libUlt abis
This commit is contained in:
+190
-18
@@ -5,6 +5,7 @@
|
|||||||
#include "libs/libs.h"
|
#include "libs/libs.h"
|
||||||
#include "loader/symbolDatabase.h"
|
#include "loader/symbolDatabase.h"
|
||||||
|
|
||||||
|
#include <condition_variable>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@@ -18,10 +19,13 @@ namespace LibUlt {
|
|||||||
|
|
||||||
LIB_VERSION("Ult", 1, "Ult", 1, 1);
|
LIB_VERSION("Ult", 1, "Ult", 1, 1);
|
||||||
|
|
||||||
constexpr int ULT_ERROR_NULL = -2139029503; // 0x80810001
|
constexpr int ULT_ERROR_NULL = -2139029503; // 0x80810001
|
||||||
constexpr int ULT_ERROR_INVALID = -2139029500; // 0x80810004
|
constexpr int ULT_ERROR_ALIGNMENT = -2139029502; // 0x80810002
|
||||||
constexpr int ULT_ERROR_STATE = -2139029498; // 0x80810006
|
constexpr int ULT_ERROR_RANGE = -2139029501; // 0x80810003
|
||||||
constexpr int ULT_ERROR_AGAIN = -2139029496; // 0x80810008
|
constexpr int ULT_ERROR_INVALID = -2139029500; // 0x80810004
|
||||||
|
constexpr int ULT_ERROR_STATE = -2139029498; // 0x80810006
|
||||||
|
constexpr int ULT_ERROR_BUSY = -2139029497; // 0x80810007
|
||||||
|
constexpr int ULT_ERROR_AGAIN = -2139029496; // 0x80810008
|
||||||
|
|
||||||
struct UltMutexOptParam {
|
struct UltMutexOptParam {
|
||||||
uint32_t reserved_header[2];
|
uint32_t reserved_header[2];
|
||||||
@@ -38,6 +42,14 @@ struct UltMutexState {
|
|||||||
uint32_t attribute = 0;
|
uint32_t attribute = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct UltSemaphoreState {
|
||||||
|
std::mutex mutex;
|
||||||
|
std::condition_variable available;
|
||||||
|
int32_t resources = 0;
|
||||||
|
uint32_t waiters = 0;
|
||||||
|
bool alive = true;
|
||||||
|
};
|
||||||
|
|
||||||
struct UltResourcePoolState {
|
struct UltResourcePoolState {
|
||||||
uint32_t num_threads = 0;
|
uint32_t num_threads = 0;
|
||||||
uint32_t num_sync_objects = 0;
|
uint32_t num_sync_objects = 0;
|
||||||
@@ -75,13 +87,14 @@ struct UltUlthreadState {
|
|||||||
LibKernel::Pthread thread = nullptr;
|
LibKernel::Pthread thread = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
static std::mutex g_ult_mutex;
|
static std::mutex g_ult_mutex;
|
||||||
static std::unordered_map<void*, std::shared_ptr<UltMutexState>> g_ult_mutexes;
|
static std::unordered_map<void*, std::shared_ptr<UltMutexState>> g_ult_mutexes;
|
||||||
static std::unordered_map<void*, UltResourcePoolState> g_ult_resource_pools;
|
static std::unordered_map<void*, std::shared_ptr<UltSemaphoreState>> g_ult_semaphores;
|
||||||
static std::unordered_map<void*, UltQueueDataResourcePoolState> g_ult_queue_data_pools;
|
static std::unordered_map<void*, UltResourcePoolState> g_ult_resource_pools;
|
||||||
static std::unordered_map<void*, std::shared_ptr<UltQueueState>> g_ult_queues;
|
static std::unordered_map<void*, UltQueueDataResourcePoolState> g_ult_queue_data_pools;
|
||||||
static std::unordered_map<void*, UltRuntimeState> g_ult_runtimes;
|
static std::unordered_map<void*, std::shared_ptr<UltQueueState>> g_ult_queues;
|
||||||
static std::unordered_map<void*, std::shared_ptr<UltUlthreadState>> g_ult_ulthreads;
|
static std::unordered_map<void*, UltRuntimeState> g_ult_runtimes;
|
||||||
|
static std::unordered_map<void*, std::shared_ptr<UltUlthreadState>> g_ult_ulthreads;
|
||||||
|
|
||||||
static uint64_t ult_align_up(uint64_t value, uint64_t alignment) {
|
static uint64_t ult_align_up(uint64_t value, uint64_t alignment) {
|
||||||
return (value + alignment - 1u) & ~(alignment - 1u);
|
return (value + alignment - 1u) & ~(alignment - 1u);
|
||||||
@@ -109,13 +122,27 @@ static int KYTY_SYSV_ABI UltInitialize() {
|
|||||||
static int KYTY_SYSV_ABI UltFinalize() {
|
static int KYTY_SYSV_ABI UltFinalize() {
|
||||||
PRINT_NAME();
|
PRINT_NAME();
|
||||||
|
|
||||||
std::scoped_lock lock(g_ult_mutex);
|
std::vector<std::shared_ptr<UltSemaphoreState>> semaphores;
|
||||||
g_ult_mutexes.clear();
|
{
|
||||||
g_ult_resource_pools.clear();
|
std::scoped_lock lock(g_ult_mutex);
|
||||||
g_ult_queue_data_pools.clear();
|
semaphores.reserve(g_ult_semaphores.size());
|
||||||
g_ult_queues.clear();
|
for (auto& entry: g_ult_semaphores) {
|
||||||
g_ult_runtimes.clear();
|
auto& state = entry.second;
|
||||||
g_ult_ulthreads.clear();
|
std::scoped_lock state_lock(state->mutex);
|
||||||
|
state->alive = false;
|
||||||
|
semaphores.push_back(state);
|
||||||
|
}
|
||||||
|
g_ult_semaphores.clear();
|
||||||
|
g_ult_mutexes.clear();
|
||||||
|
g_ult_resource_pools.clear();
|
||||||
|
g_ult_queue_data_pools.clear();
|
||||||
|
g_ult_queues.clear();
|
||||||
|
g_ult_runtimes.clear();
|
||||||
|
g_ult_ulthreads.clear();
|
||||||
|
}
|
||||||
|
for (const auto& state: semaphores) {
|
||||||
|
state->available.notify_all();
|
||||||
|
}
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
@@ -540,6 +567,146 @@ static int KYTY_SYSV_ABI UltMutexUnlock(void* mutex) {
|
|||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int UltSemaphoreGetState(void* semaphore, std::shared_ptr<UltSemaphoreState>* state) {
|
||||||
|
EXIT_IF(state == nullptr);
|
||||||
|
|
||||||
|
std::scoped_lock lock(g_ult_mutex);
|
||||||
|
auto it = g_ult_semaphores.find(semaphore);
|
||||||
|
if (it == g_ult_semaphores.end()) {
|
||||||
|
return (semaphore == nullptr ? ULT_ERROR_NULL : ULT_ERROR_STATE);
|
||||||
|
}
|
||||||
|
*state = it->second;
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int KYTY_SYSV_ABI UltSemaphoreCreate(void* semaphore, const char* name,
|
||||||
|
int32_t num_initial_resource,
|
||||||
|
void* waiting_queue_resource_pool,
|
||||||
|
const void* opt_param, uint32_t build_version) {
|
||||||
|
PRINT_NAME();
|
||||||
|
(void)name;
|
||||||
|
(void)build_version;
|
||||||
|
|
||||||
|
if (semaphore == nullptr) {
|
||||||
|
return ULT_ERROR_NULL;
|
||||||
|
}
|
||||||
|
if ((reinterpret_cast<uintptr_t>(semaphore) & 7u) != 0 ||
|
||||||
|
(opt_param != nullptr && (reinterpret_cast<uintptr_t>(opt_param) & 7u) != 0)) {
|
||||||
|
return ULT_ERROR_ALIGNMENT;
|
||||||
|
}
|
||||||
|
if (num_initial_resource < 0) {
|
||||||
|
return ULT_ERROR_RANGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto state = std::make_shared<UltSemaphoreState>();
|
||||||
|
state->resources = num_initial_resource;
|
||||||
|
|
||||||
|
std::scoped_lock lock(g_ult_mutex);
|
||||||
|
if (waiting_queue_resource_pool != nullptr &&
|
||||||
|
g_ult_resource_pools.find(waiting_queue_resource_pool) == g_ult_resource_pools.end()) {
|
||||||
|
return ULT_ERROR_INVALID;
|
||||||
|
}
|
||||||
|
if (g_ult_semaphores.find(semaphore) != g_ult_semaphores.end()) {
|
||||||
|
return ULT_ERROR_STATE;
|
||||||
|
}
|
||||||
|
std::memset(semaphore, 0, 256);
|
||||||
|
g_ult_semaphores[semaphore] = std::move(state);
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int KYTY_SYSV_ABI UltSemaphoreAcquire(void* semaphore, int32_t num_resource) {
|
||||||
|
PRINT_NAME();
|
||||||
|
|
||||||
|
if (num_resource <= 0) {
|
||||||
|
return ULT_ERROR_RANGE;
|
||||||
|
}
|
||||||
|
std::shared_ptr<UltSemaphoreState> state;
|
||||||
|
if (auto ret = UltSemaphoreGetState(semaphore, &state); ret != OK) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_lock lock(state->mutex);
|
||||||
|
if (!state->alive) {
|
||||||
|
return ULT_ERROR_STATE;
|
||||||
|
}
|
||||||
|
state->waiters++;
|
||||||
|
state->available.wait(lock, [&] { return !state->alive || state->resources >= num_resource; });
|
||||||
|
state->waiters--;
|
||||||
|
if (!state->alive) {
|
||||||
|
return ULT_ERROR_STATE;
|
||||||
|
}
|
||||||
|
state->resources -= num_resource;
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int KYTY_SYSV_ABI UltSemaphoreTryAcquire(void* semaphore, int32_t num_resource) {
|
||||||
|
PRINT_NAME();
|
||||||
|
|
||||||
|
if (num_resource <= 0) {
|
||||||
|
return ULT_ERROR_RANGE;
|
||||||
|
}
|
||||||
|
std::shared_ptr<UltSemaphoreState> state;
|
||||||
|
if (auto ret = UltSemaphoreGetState(semaphore, &state); ret != OK) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::scoped_lock lock(state->mutex);
|
||||||
|
if (!state->alive) {
|
||||||
|
return ULT_ERROR_STATE;
|
||||||
|
}
|
||||||
|
if (state->resources < num_resource) {
|
||||||
|
return ULT_ERROR_AGAIN;
|
||||||
|
}
|
||||||
|
state->resources -= num_resource;
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int KYTY_SYSV_ABI UltSemaphoreRelease(void* semaphore, int32_t num_resource) {
|
||||||
|
PRINT_NAME();
|
||||||
|
|
||||||
|
if (num_resource <= 0) {
|
||||||
|
return ULT_ERROR_RANGE;
|
||||||
|
}
|
||||||
|
std::shared_ptr<UltSemaphoreState> state;
|
||||||
|
if (auto ret = UltSemaphoreGetState(semaphore, &state); ret != OK) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
std::scoped_lock lock(state->mutex);
|
||||||
|
if (!state->alive) {
|
||||||
|
return ULT_ERROR_STATE;
|
||||||
|
}
|
||||||
|
if (state->resources > INT32_MAX - num_resource) {
|
||||||
|
return ULT_ERROR_RANGE;
|
||||||
|
}
|
||||||
|
state->resources += num_resource;
|
||||||
|
}
|
||||||
|
state->available.notify_all();
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int KYTY_SYSV_ABI UltSemaphoreDestroy(void* semaphore) {
|
||||||
|
PRINT_NAME();
|
||||||
|
|
||||||
|
if (semaphore == nullptr) {
|
||||||
|
return ULT_ERROR_NULL;
|
||||||
|
}
|
||||||
|
std::scoped_lock global_lock(g_ult_mutex);
|
||||||
|
auto it = g_ult_semaphores.find(semaphore);
|
||||||
|
if (it == g_ult_semaphores.end()) {
|
||||||
|
return ULT_ERROR_STATE;
|
||||||
|
}
|
||||||
|
auto state = it->second;
|
||||||
|
std::scoped_lock state_lock(state->mutex);
|
||||||
|
if (state->waiters != 0) {
|
||||||
|
return ULT_ERROR_BUSY;
|
||||||
|
}
|
||||||
|
state->alive = false;
|
||||||
|
g_ult_semaphores.erase(it);
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
LIB_DEFINE(InitUlt_1) {
|
LIB_DEFINE(InitUlt_1) {
|
||||||
LIB_FUNC("hZIg1EWGsHM", UltInitialize);
|
LIB_FUNC("hZIg1EWGsHM", UltInitialize);
|
||||||
LIB_FUNC("d-kSG2fLrvI", UltFinalize);
|
LIB_FUNC("d-kSG2fLrvI", UltFinalize);
|
||||||
@@ -559,6 +726,11 @@ LIB_DEFINE(InitUlt_1) {
|
|||||||
LIB_FUNC("mmt8Sa6tL6c", UltMutexCreate);
|
LIB_FUNC("mmt8Sa6tL6c", UltMutexCreate);
|
||||||
LIB_FUNC("8hEGkR1pfr8", UltMutexLock);
|
LIB_FUNC("8hEGkR1pfr8", UltMutexLock);
|
||||||
LIB_FUNC("h0XebKiMBtk", UltMutexUnlock);
|
LIB_FUNC("h0XebKiMBtk", UltMutexUnlock);
|
||||||
|
LIB_FUNC("h5QlIYj+Ro8", UltSemaphoreCreate);
|
||||||
|
LIB_FUNC("QAH1ofI97vU", UltSemaphoreAcquire);
|
||||||
|
LIB_FUNC("HA1Ldbi3lPY", UltSemaphoreTryAcquire);
|
||||||
|
LIB_FUNC("lbtk5X1mecw", UltSemaphoreRelease);
|
||||||
|
LIB_FUNC("izXyehpoZGo", UltSemaphoreDestroy);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace LibUlt
|
} // namespace LibUlt
|
||||||
|
|||||||
Reference in New Issue
Block a user