feat(libkernel): impl file, time, process, signal for posix
This commit is contained in:
parent
62c16792ff
commit
13c648bebb
|
|
@ -39,7 +39,6 @@ add_library(libkernel SHARED EXCLUDE_FROM_ALL
|
|||
${CMAKE_CURRENT_SOURCE_DIR}/System/src/Sanitizer.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/System/src/Rtld.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/System/src/Process.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/System/src/PosixImportStubs.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/System/src/SystemConfiguration.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/System/src/Signals.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/Time/Time.cpp
|
||||
|
|
|
|||
|
|
@ -2,11 +2,23 @@
|
|||
#include <cstddef>
|
||||
#include "SceTypes.hpp"
|
||||
#include "prx/libc/include/General.hpp"
|
||||
#include "prx/libkernel/File/include/File.hpp"
|
||||
#include "prx/libkernel/File/include/FileFlags.hpp"
|
||||
#include "prx/libkernel/Socket/include/SocketRuntime.hpp"
|
||||
#include <cerrno>
|
||||
#include <cstdarg>
|
||||
#include <string>
|
||||
#ifdef _WIN32
|
||||
#include <io.h>
|
||||
#include <direct.h>
|
||||
static int NativeRmdir(const std::filesystem::path& path) {
|
||||
return ::_wrmdir(path.wstring().c_str());
|
||||
}
|
||||
#else
|
||||
#include <unistd.h>
|
||||
static int NativeRmdir(const std::filesystem::path& path) {
|
||||
return ::rmdir(path.c_str());
|
||||
}
|
||||
#endif
|
||||
|
||||
extern "C" {
|
||||
|
|
@ -27,6 +39,10 @@ int APS5_VABI close_nid_postfix(int d) {
|
|||
#endif
|
||||
}
|
||||
|
||||
int APS5_VABI _close_nid_postfix(int descriptor) {
|
||||
return close_nid_postfix(descriptor);
|
||||
}
|
||||
|
||||
int APS5_VABI flock_nid_postfix(int d, int operation) {
|
||||
(void)d;
|
||||
(void)operation;
|
||||
|
|
@ -71,6 +87,24 @@ int APS5_VABI open_nid_postfix(const char* path, int flags, int mode) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int APS5_VABI _open_nid_postfix(const char* path, int flags, ...) {
|
||||
std::uint16_t mode = 0;
|
||||
if (flags & SCE_KERNEL_O_CREAT) {
|
||||
#ifdef _WIN32
|
||||
__builtin_sysv_va_list arguments;
|
||||
__builtin_sysv_va_start(arguments, flags);
|
||||
mode = static_cast<std::uint16_t>(__builtin_va_arg(arguments, int));
|
||||
__builtin_sysv_va_end(arguments);
|
||||
#else
|
||||
std::va_list arguments;
|
||||
va_start(arguments, flags);
|
||||
mode = static_cast<std::uint16_t>(va_arg(arguments, int));
|
||||
va_end(arguments);
|
||||
#endif
|
||||
}
|
||||
return sceKernelOpen(path, flags, mode);
|
||||
}
|
||||
|
||||
int64_t APS5_VABI pread_nid_postfix(int d, void* buf, size_t nbytes, int64_t offset) {
|
||||
(void)d;
|
||||
(void)buf;
|
||||
|
|
@ -97,6 +131,10 @@ int64_t APS5_VABI read_nid_postfix(int d, void* buf, uint64_t nbytes) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
std::int64_t APS5_VABI _read_nid_postfix(int descriptor, void* buffer, std::size_t count) {
|
||||
return sceKernelRead(descriptor, buffer, count);
|
||||
}
|
||||
|
||||
int64_t APS5_VABI write_nid_postfix(int d, const char* str, int64_t size) {
|
||||
(void)d;
|
||||
(void)str;
|
||||
|
|
@ -105,6 +143,10 @@ int64_t APS5_VABI write_nid_postfix(int d, const char* str, int64_t size) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
std::int64_t APS5_VABI _write_nid_postfix(int descriptor, const void* buffer, std::size_t count) {
|
||||
return sceKernelWrite(descriptor, buffer, count);
|
||||
}
|
||||
|
||||
int APS5_VABI stat_nid_postfix(const char* path, FileStat* sb) {
|
||||
(void)path;
|
||||
(void)sb;
|
||||
|
|
@ -112,6 +154,10 @@ int APS5_VABI stat_nid_postfix(const char* path, FileStat* sb) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int APS5_VABI unlink_nid_postfix(const char* path) {
|
||||
return sceKernelUnlink(path);
|
||||
}
|
||||
|
||||
int APS5_VABI sceKernelCheckReachability(const char* path) {
|
||||
(void)path;
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
|
|
@ -181,9 +227,18 @@ int APS5_VABI sceKernelRename(const char* from, const char* to) {
|
|||
}
|
||||
|
||||
int APS5_VABI sceKernelRmdir(const char* path) {
|
||||
(void)path;
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return 0;
|
||||
if (path == nullptr) {
|
||||
throw std::invalid_argument(std::string(__func__) + ": path is null");
|
||||
}
|
||||
auto native = ResolvePath_nid_no_patch(path);
|
||||
if (NativeRmdir(native) != 0) {
|
||||
throw std::runtime_error(std::string(__func__) + ": rmdir failed for " + native.string() + ", errno=" + std::to_string(errno));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int APS5_VABI rmdir_nid_postfix(const char* path) {
|
||||
return sceKernelRmdir(path);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,20 @@
|
|||
#include <cstddef>
|
||||
#include "SceTypes.hpp"
|
||||
#include "prx/libc/include/General.hpp"
|
||||
#include "../include/Rwlock.hpp"
|
||||
|
||||
namespace {
|
||||
|
||||
int toPosix(int result) {
|
||||
if (result == 0)
|
||||
return 0;
|
||||
const auto error = static_cast<std::uint32_t>(result);
|
||||
if ((error & 0xffff0000u) != 0x80020000u)
|
||||
throw std::runtime_error("Unexpected SCE rwlock error");
|
||||
return static_cast<int>(error & 0xffffu);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
||||
|
|
@ -18,6 +32,14 @@ int APS5_VABI pthread_rwlock_init_nid_postfix(PthreadRwlock* rwlock, const Pthre
|
|||
return 0;
|
||||
}
|
||||
|
||||
int APS5_VABI pthread_rwlock_rdlock_nid_postfix(PthreadRwlock* rwlock) {
|
||||
return toPosix(scePthreadRwlockRdlock(rwlock));
|
||||
}
|
||||
|
||||
int APS5_VABI pthread_rwlock_unlock_nid_postfix(PthreadRwlock* rwlock) {
|
||||
return toPosix(scePthreadRwlockUnlock(rwlock));
|
||||
}
|
||||
|
||||
int APS5_VABI pthread_rwlock_wrlock_nid_postfix(PthreadRwlock* rwlock) {
|
||||
(void)rwlock;
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,21 @@
|
|||
#ifndef CORE_LIBS_PRX_LIBKERNEL_PTHREAD_RWLOCK_HPP
|
||||
#define CORE_LIBS_PRX_LIBKERNEL_PTHREAD_RWLOCK_HPP
|
||||
|
||||
#include "SceTypes.hpp"
|
||||
|
||||
extern "C" {
|
||||
|
||||
int APS5_VABI scePthreadRwlockattrInit(PthreadRwlockattr* attr);
|
||||
int APS5_VABI scePthreadRwlockattrDestroy(PthreadRwlockattr* attr);
|
||||
int APS5_VABI scePthreadRwlockattrSettype(PthreadRwlockattr* attr, int type);
|
||||
int APS5_VABI scePthreadRwlockInit(PthreadRwlock* rwlock, const PthreadRwlockattr* attr, const char* name);
|
||||
int APS5_VABI scePthreadRwlockDestroy(PthreadRwlock* rwlock);
|
||||
int APS5_VABI scePthreadRwlockRdlock(PthreadRwlock* rwlock);
|
||||
int APS5_VABI scePthreadRwlockTryrdlock(PthreadRwlock* rwlock);
|
||||
int APS5_VABI scePthreadRwlockWrlock(PthreadRwlock* rwlock);
|
||||
int APS5_VABI scePthreadRwlockTrywrlock(PthreadRwlock* rwlock);
|
||||
int APS5_VABI scePthreadRwlockUnlock(PthreadRwlock* rwlock);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
#include "../include/Pthread.hpp"
|
||||
#include "../include/Rwlock.hpp"
|
||||
#include "prx/libc/include/General.hpp"
|
||||
|
||||
extern "C" {
|
||||
|
|
|
|||
|
|
@ -1,91 +0,0 @@
|
|||
#include "SceTypes.hpp"
|
||||
#include "prx/libc/include/General.hpp"
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
struct GuestSignalSet;
|
||||
struct GuestResourceUsage;
|
||||
|
||||
extern "C" {
|
||||
|
||||
int APS5_VABI _close_nid_postfix(int descriptor) {
|
||||
(void)descriptor;
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void APS5_VABI _exit_nid_postfix(int status) {
|
||||
(void)status;
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
}
|
||||
|
||||
int APS5_VABI _nanosleep_nid_postfix(const KernelTimespec* requested, KernelTimespec* remaining) {
|
||||
(void)requested;
|
||||
(void)remaining;
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int APS5_VABI _open_nid_postfix(const char* path, int flags, ...) {
|
||||
(void)path;
|
||||
(void)flags;
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::int64_t APS5_VABI _read_nid_postfix(int descriptor, void* buffer, std::size_t count) {
|
||||
(void)descriptor;
|
||||
(void)buffer;
|
||||
(void)count;
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int APS5_VABI _sigprocmask_nid_postfix(int how, const GuestSignalSet* set, GuestSignalSet* previousSet) {
|
||||
(void)how;
|
||||
(void)set;
|
||||
(void)previousSet;
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::int64_t APS5_VABI _write_nid_postfix(int descriptor, const void* buffer, std::size_t count) {
|
||||
(void)descriptor;
|
||||
(void)buffer;
|
||||
(void)count;
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int APS5_VABI getrusage_nid_postfix(int who, GuestResourceUsage* usage) {
|
||||
(void)who;
|
||||
(void)usage;
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int APS5_VABI pthread_rwlock_rdlock_nid_postfix(PthreadRwlock* rwlock) {
|
||||
(void)rwlock;
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int APS5_VABI pthread_rwlock_unlock_nid_postfix(PthreadRwlock* rwlock) {
|
||||
(void)rwlock;
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int APS5_VABI rmdir_nid_postfix(const char* path) {
|
||||
(void)path;
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int APS5_VABI unlink_nid_postfix(const char* path) {
|
||||
(void)path;
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -17,6 +17,7 @@
|
|||
#include <cerrno>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <fstream>
|
||||
#include <limits>
|
||||
|
|
@ -26,6 +27,9 @@
|
|||
#include <string>
|
||||
#include <system_error>
|
||||
#include <vector>
|
||||
#ifndef _WIN32
|
||||
#include <sys/resource.h>
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
|
||||
|
|
@ -116,6 +120,25 @@ void syncVolumes() {
|
|||
|
||||
}
|
||||
|
||||
struct GuestResourceUsage {
|
||||
KernelTimeval ru_utime;
|
||||
KernelTimeval ru_stime;
|
||||
std::int64_t ru_maxrss;
|
||||
std::int64_t ru_ixrss;
|
||||
std::int64_t ru_idrss;
|
||||
std::int64_t ru_isrss;
|
||||
std::int64_t ru_minflt;
|
||||
std::int64_t ru_majflt;
|
||||
std::int64_t ru_nswap;
|
||||
std::int64_t ru_inblock;
|
||||
std::int64_t ru_oublock;
|
||||
std::int64_t ru_msgsnd;
|
||||
std::int64_t ru_msgrcv;
|
||||
std::int64_t ru_nsignals;
|
||||
std::int64_t ru_nvcsw;
|
||||
std::int64_t ru_nivcsw;
|
||||
};
|
||||
|
||||
extern "C" {
|
||||
|
||||
// unknown signature
|
||||
|
|
@ -148,6 +171,10 @@ void APS5_VABI exit_nid_postfix(int code) {
|
|||
LibcExit_nid_no_patch(code);
|
||||
}
|
||||
|
||||
[[noreturn]] void APS5_VABI _exit_nid_postfix(int status) {
|
||||
std::_Exit(status);
|
||||
}
|
||||
|
||||
int APS5_VABI sceKernelGetCurrentCpu(void) {
|
||||
#ifdef _WIN32
|
||||
PROCESSOR_NUMBER processor{};
|
||||
|
|
@ -219,4 +246,72 @@ int APS5_VABI sched_get_priority_min_nid_postfix(int policy) {
|
|||
return 767;
|
||||
}
|
||||
|
||||
int APS5_VABI getrusage_nid_postfix(int who, GuestResourceUsage* usage) {
|
||||
if (usage == nullptr)
|
||||
throw std::invalid_argument("getrusage: usage is null");
|
||||
if (who != 0 && who != 1)
|
||||
throw std::invalid_argument("getrusage: unsupported who");
|
||||
#ifdef _WIN32
|
||||
FILETIME creation{};
|
||||
FILETIME exitTime{};
|
||||
FILETIME kernel{};
|
||||
FILETIME user{};
|
||||
if (who == 0) {
|
||||
if (!GetProcessTimes(GetCurrentProcess(), &creation, &exitTime, &kernel, &user))
|
||||
throw std::system_error(GetLastError(), std::system_category(), "getrusage: GetProcessTimes failed");
|
||||
} else {
|
||||
if (!GetThreadTimes(GetCurrentThread(), &creation, &exitTime, &kernel, &user))
|
||||
throw std::system_error(GetLastError(), std::system_category(), "getrusage: GetThreadTimes failed");
|
||||
}
|
||||
const auto toMicros = [](const FILETIME& time) {
|
||||
return ((static_cast<std::uint64_t>(time.dwHighDateTime) << 32) | time.dwLowDateTime) / 10ULL;
|
||||
};
|
||||
const auto userMicros = toMicros(user);
|
||||
const auto kernelMicros = toMicros(kernel);
|
||||
usage->ru_utime.tv_sec = static_cast<std::int64_t>(userMicros / 1000000ULL);
|
||||
usage->ru_utime.tv_usec = static_cast<std::int64_t>(userMicros % 1000000ULL);
|
||||
usage->ru_stime.tv_sec = static_cast<std::int64_t>(kernelMicros / 1000000ULL);
|
||||
usage->ru_stime.tv_usec = static_cast<std::int64_t>(kernelMicros % 1000000ULL);
|
||||
usage->ru_maxrss = 0;
|
||||
usage->ru_ixrss = 0;
|
||||
usage->ru_idrss = 0;
|
||||
usage->ru_isrss = 0;
|
||||
usage->ru_minflt = 0;
|
||||
usage->ru_majflt = 0;
|
||||
usage->ru_nswap = 0;
|
||||
usage->ru_inblock = 0;
|
||||
usage->ru_oublock = 0;
|
||||
usage->ru_msgsnd = 0;
|
||||
usage->ru_msgrcv = 0;
|
||||
usage->ru_nsignals = 0;
|
||||
usage->ru_nvcsw = 0;
|
||||
usage->ru_nivcsw = 0;
|
||||
#else
|
||||
if (who == 1)
|
||||
throw std::invalid_argument("getrusage: RUSAGE_THREAD is not supported on this platform");
|
||||
struct rusage native{};
|
||||
if (::getrusage(RUSAGE_SELF, &native) != 0)
|
||||
throw std::system_error(errno, std::generic_category(), "getrusage: getrusage failed");
|
||||
usage->ru_utime.tv_sec = static_cast<std::int64_t>(native.ru_utime.tv_sec);
|
||||
usage->ru_utime.tv_usec = static_cast<std::int64_t>(native.ru_utime.tv_usec);
|
||||
usage->ru_stime.tv_sec = static_cast<std::int64_t>(native.ru_stime.tv_sec);
|
||||
usage->ru_stime.tv_usec = static_cast<std::int64_t>(native.ru_stime.tv_usec);
|
||||
usage->ru_maxrss = static_cast<std::int64_t>(native.ru_maxrss);
|
||||
usage->ru_ixrss = static_cast<std::int64_t>(native.ru_ixrss);
|
||||
usage->ru_idrss = static_cast<std::int64_t>(native.ru_idrss);
|
||||
usage->ru_isrss = static_cast<std::int64_t>(native.ru_isrss);
|
||||
usage->ru_minflt = static_cast<std::int64_t>(native.ru_minflt);
|
||||
usage->ru_majflt = static_cast<std::int64_t>(native.ru_majflt);
|
||||
usage->ru_nswap = static_cast<std::int64_t>(native.ru_nswap);
|
||||
usage->ru_inblock = static_cast<std::int64_t>(native.ru_inblock);
|
||||
usage->ru_oublock = static_cast<std::int64_t>(native.ru_oublock);
|
||||
usage->ru_msgsnd = static_cast<std::int64_t>(native.ru_msgsnd);
|
||||
usage->ru_msgrcv = static_cast<std::int64_t>(native.ru_msgrcv);
|
||||
usage->ru_nsignals = static_cast<std::int64_t>(native.ru_nsignals);
|
||||
usage->ru_nvcsw = static_cast<std::int64_t>(native.ru_nvcsw);
|
||||
usage->ru_nivcsw = static_cast<std::int64_t>(native.ru_nivcsw);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@ namespace {
|
|||
using GuestHandler = void (APS5_VABI *)(int);
|
||||
std::atomic<GuestHandler> handlers[32]{};
|
||||
static_assert(std::atomic<GuestHandler>::is_always_lock_free);
|
||||
std::atomic<std::uint32_t> blockedMask{0};
|
||||
static_assert(std::atomic<std::uint32_t>::is_always_lock_free);
|
||||
std::mutex registration;
|
||||
int NativeSignal(int guest) {
|
||||
switch (guest) {
|
||||
|
|
@ -31,10 +33,16 @@ void Dispatch(int native) {
|
|||
// Preserve the guest's persistent registration across CRT delivery.
|
||||
std::signal(native, Dispatch);
|
||||
#endif
|
||||
if ((blockedMask.load() & (1u << guest)) != 0) return;
|
||||
const auto callback = handlers[guest].load();
|
||||
if (reinterpret_cast<std::uintptr_t>(callback) > 1) callback(guest);
|
||||
}
|
||||
}
|
||||
|
||||
struct GuestSignalSet {
|
||||
std::uint32_t bits[4];
|
||||
};
|
||||
|
||||
extern "C" {
|
||||
GuestHandler APS5_VABI signal_nid_postfix(int guest, GuestHandler handler) {
|
||||
const auto invalid = reinterpret_cast<GuestHandler>(static_cast<std::uintptr_t>(-1));
|
||||
|
|
@ -58,6 +66,24 @@ int APS5_VABI raise_nid_postfix(int guest) {
|
|||
if (result) *__error_nid_postfix() = 22;
|
||||
return result ? -1 : 0;
|
||||
}
|
||||
int APS5_VABI _sigprocmask_nid_postfix(int how, const GuestSignalSet* set, GuestSignalSet* previousSet) {
|
||||
std::lock_guard lock(registration);
|
||||
if (previousSet != nullptr) {
|
||||
previousSet->bits[0] = blockedMask.load();
|
||||
previousSet->bits[1] = 0;
|
||||
previousSet->bits[2] = 0;
|
||||
previousSet->bits[3] = 0;
|
||||
}
|
||||
if (set != nullptr) {
|
||||
switch (how) {
|
||||
case 1: blockedMask.fetch_or(set->bits[0]); break;
|
||||
case 2: blockedMask.fetch_and(~set->bits[0]); break;
|
||||
case 3: blockedMask.store(set->bits[0]); break;
|
||||
default: throw std::invalid_argument("_sigprocmask: invalid how");
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
|
|
|||
|
|
@ -92,6 +92,10 @@ int APS5_VABI nanosleep_nid_postfix(const KernelTimespec* rqtp, KernelTimespec*
|
|||
return sceKernelNanosleep(rqtp, rmtp);
|
||||
}
|
||||
|
||||
int APS5_VABI _nanosleep_nid_postfix(const KernelTimespec* rqtp, KernelTimespec* rmtp) {
|
||||
return sceKernelNanosleep(rqtp, rmtp);
|
||||
}
|
||||
|
||||
int APS5_VABI clock_gettime_nid_postfix(int clockId, KernelTimespec* tp) {
|
||||
if (tp == nullptr) {
|
||||
APS5_INVALID_ARG_EX;
|
||||
|
|
|
|||
Loading…
Reference in New Issue