mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-06-05 18:23:16 +00:00
kernel: re-implement clock_gettime (#2615)
This commit is contained in:
parent
bfb8b46d7d
commit
6b3746f3a6
1 changed files with 168 additions and 24 deletions
|
@ -5,6 +5,7 @@
|
||||||
|
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "common/native_clock.h"
|
#include "common/native_clock.h"
|
||||||
|
#include "core/libraries/kernel/kernel.h"
|
||||||
#include "core/libraries/kernel/orbis_error.h"
|
#include "core/libraries/kernel/orbis_error.h"
|
||||||
#include "core/libraries/kernel/time.h"
|
#include "core/libraries/kernel/time.h"
|
||||||
#include "core/libraries/libs.h"
|
#include "core/libraries/libs.h"
|
||||||
|
@ -19,6 +20,7 @@
|
||||||
#if __APPLE__
|
#if __APPLE__
|
||||||
#include <date/tz.h>
|
#include <date/tz.h>
|
||||||
#endif
|
#endif
|
||||||
|
#include <sys/resource.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
@ -93,46 +95,188 @@ u32 PS4_SYSV_ABI sceKernelSleep(u32 seconds) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceKernelClockGettime(s32 clock_id, OrbisKernelTimespec* tp) {
|
#ifdef _WIN64
|
||||||
if (tp == nullptr) {
|
#ifndef CLOCK_REALTIME
|
||||||
|
#define CLOCK_REALTIME 0
|
||||||
|
#endif
|
||||||
|
#ifndef CLOCK_MONOTONIC
|
||||||
|
#define CLOCK_MONOTONIC 1
|
||||||
|
#endif
|
||||||
|
#ifndef CLOCK_PROCESS_CPUTIME_ID
|
||||||
|
#define CLOCK_PROCESS_CPUTIME_ID 2
|
||||||
|
#endif
|
||||||
|
#ifndef CLOCK_THREAD_CPUTIME_ID
|
||||||
|
#define CLOCK_THREAD_CPUTIME_ID 3
|
||||||
|
#endif
|
||||||
|
#ifndef CLOCK_REALTIME_COARSE
|
||||||
|
#define CLOCK_REALTIME_COARSE 5
|
||||||
|
#endif
|
||||||
|
#ifndef CLOCK_MONOTONIC_COARSE
|
||||||
|
#define CLOCK_MONOTONIC_COARSE 6
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define DELTA_EPOCH_IN_100NS 116444736000000000ULL
|
||||||
|
|
||||||
|
static u64 FileTimeTo100Ns(FILETIME& ft) {
|
||||||
|
return *reinterpret_cast<u64*>(&ft);
|
||||||
|
}
|
||||||
|
|
||||||
|
static s32 clock_gettime(u32 clock_id, struct timespec* ts) {
|
||||||
|
switch (clock_id) {
|
||||||
|
case CLOCK_REALTIME:
|
||||||
|
case CLOCK_REALTIME_COARSE: {
|
||||||
|
FILETIME ft;
|
||||||
|
GetSystemTimeAsFileTime(&ft);
|
||||||
|
const u64 ns = FileTimeTo100Ns(ft) - DELTA_EPOCH_IN_100NS;
|
||||||
|
ts->tv_sec = ns / 10'000'000;
|
||||||
|
ts->tv_nsec = (ns % 10'000'000) * 100;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
case CLOCK_MONOTONIC:
|
||||||
|
case CLOCK_MONOTONIC_COARSE: {
|
||||||
|
static LARGE_INTEGER pf = [] {
|
||||||
|
LARGE_INTEGER res{};
|
||||||
|
QueryPerformanceFrequency(&pf);
|
||||||
|
return res;
|
||||||
|
}();
|
||||||
|
|
||||||
|
LARGE_INTEGER pc{};
|
||||||
|
QueryPerformanceCounter(&pc);
|
||||||
|
ts->tv_sec = pc.QuadPart / pf.QuadPart;
|
||||||
|
ts->tv_nsec = ((pc.QuadPart % pf.QuadPart) * 1000'000'000) / pf.QuadPart;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
case CLOCK_PROCESS_CPUTIME_ID: {
|
||||||
|
FILETIME ct, et, kt, ut;
|
||||||
|
if (!GetProcessTimes(GetCurrentProcess(), &ct, &et, &kt, &ut)) {
|
||||||
|
return EFAULT;
|
||||||
|
}
|
||||||
|
const u64 ns = FileTimeTo100Ns(ut) + FileTimeTo100Ns(kt);
|
||||||
|
ts->tv_sec = ns / 10'000'000;
|
||||||
|
ts->tv_nsec = (ns % 10'000'000) * 100;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
case CLOCK_THREAD_CPUTIME_ID: {
|
||||||
|
FILETIME ct, et, kt, ut;
|
||||||
|
if (!GetThreadTimes(GetCurrentThread(), &ct, &et, &kt, &ut)) {
|
||||||
|
return EFAULT;
|
||||||
|
}
|
||||||
|
const u64 ns = FileTimeTo100Ns(ut) + FileTimeTo100Ns(kt);
|
||||||
|
ts->tv_sec = ns / 10'000'000;
|
||||||
|
ts->tv_nsec = (ns % 10'000'000) * 100;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return EINVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int PS4_SYSV_ABI orbis_clock_gettime(s32 clock_id, struct timespec* ts) {
|
||||||
|
if (ts == nullptr) {
|
||||||
return ORBIS_KERNEL_ERROR_EFAULT;
|
return ORBIS_KERNEL_ERROR_EFAULT;
|
||||||
}
|
}
|
||||||
clockid_t pclock_id = CLOCK_REALTIME;
|
|
||||||
|
clockid_t pclock_id = CLOCK_MONOTONIC;
|
||||||
switch (clock_id) {
|
switch (clock_id) {
|
||||||
case ORBIS_CLOCK_REALTIME:
|
case ORBIS_CLOCK_REALTIME:
|
||||||
case ORBIS_CLOCK_REALTIME_PRECISE:
|
case ORBIS_CLOCK_REALTIME_PRECISE:
|
||||||
case ORBIS_CLOCK_REALTIME_FAST:
|
|
||||||
pclock_id = CLOCK_REALTIME;
|
pclock_id = CLOCK_REALTIME;
|
||||||
break;
|
break;
|
||||||
case ORBIS_CLOCK_SECOND:
|
case ORBIS_CLOCK_SECOND:
|
||||||
|
case ORBIS_CLOCK_REALTIME_FAST:
|
||||||
|
#ifndef __APPLE__
|
||||||
|
pclock_id = CLOCK_REALTIME_COARSE;
|
||||||
|
#else
|
||||||
|
pclock_id = CLOCK_REALTIME;
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
case ORBIS_CLOCK_UPTIME:
|
||||||
|
case ORBIS_CLOCK_UPTIME_PRECISE:
|
||||||
case ORBIS_CLOCK_MONOTONIC:
|
case ORBIS_CLOCK_MONOTONIC:
|
||||||
case ORBIS_CLOCK_MONOTONIC_PRECISE:
|
case ORBIS_CLOCK_MONOTONIC_PRECISE:
|
||||||
case ORBIS_CLOCK_MONOTONIC_FAST:
|
|
||||||
pclock_id = CLOCK_MONOTONIC;
|
pclock_id = CLOCK_MONOTONIC;
|
||||||
break;
|
break;
|
||||||
default:
|
case ORBIS_CLOCK_UPTIME_FAST:
|
||||||
LOG_ERROR(Lib_Kernel, "unsupported = {} using CLOCK_REALTIME", clock_id);
|
case ORBIS_CLOCK_MONOTONIC_FAST:
|
||||||
|
#ifndef __APPLE__
|
||||||
|
pclock_id = CLOCK_MONOTONIC_COARSE;
|
||||||
|
#else
|
||||||
|
pclock_id = CLOCK_MONOTONIC;
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
|
case ORBIS_CLOCK_THREAD_CPUTIME_ID:
|
||||||
|
pclock_id = CLOCK_THREAD_CPUTIME_ID;
|
||||||
|
break;
|
||||||
|
case ORBIS_CLOCK_PROCTIME: {
|
||||||
|
const auto us = sceKernelGetProcessTime();
|
||||||
|
ts->tv_sec = us / 1'000'000;
|
||||||
|
ts->tv_nsec = (us % 1'000'000) * 1000;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
case ORBIS_CLOCK_VIRTUAL: {
|
||||||
|
#ifdef _WIN64
|
||||||
|
FILETIME ct, et, kt, ut;
|
||||||
|
if (!GetProcessTimes(GetCurrentProcess(), &ct, &et, &kt, &ut)) {
|
||||||
|
return EFAULT;
|
||||||
|
}
|
||||||
|
const u64 ns = FileTimeTo100Ns(ut);
|
||||||
|
ts->tv_sec = ns / 10'000'000;
|
||||||
|
ts->tv_nsec = (ns % 10'000'000) * 100;
|
||||||
|
#else
|
||||||
|
struct rusage ru;
|
||||||
|
const auto res = getrusage(RUSAGE_SELF, &ru);
|
||||||
|
if (res < 0) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
ts->tv_sec = ru.ru_utime.tv_sec;
|
||||||
|
ts->tv_nsec = ru.ru_utime.tv_usec * 1000;
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
case ORBIS_CLOCK_PROF: {
|
||||||
|
#ifdef _WIN64
|
||||||
|
FILETIME ct, et, kt, ut;
|
||||||
|
if (!GetProcessTimes(GetCurrentProcess(), &ct, &et, &kt, &ut)) {
|
||||||
|
return EFAULT;
|
||||||
|
}
|
||||||
|
const u64 ns = FileTimeTo100Ns(kt);
|
||||||
|
ts->tv_sec = ns / 10'000'000;
|
||||||
|
ts->tv_nsec = (ns % 10'000'000) * 100;
|
||||||
|
#else
|
||||||
|
struct rusage ru;
|
||||||
|
const auto res = getrusage(RUSAGE_SELF, &ru);
|
||||||
|
if (res < 0) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
ts->tv_sec = ru.ru_stime.tv_sec;
|
||||||
|
ts->tv_nsec = ru.ru_stime.tv_usec * 1000;
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
case ORBIS_CLOCK_EXT_NETWORK:
|
||||||
|
case ORBIS_CLOCK_EXT_DEBUG_NETWORK:
|
||||||
|
case ORBIS_CLOCK_EXT_AD_NETWORK:
|
||||||
|
case ORBIS_CLOCK_EXT_RAW_NETWORK:
|
||||||
|
pclock_id = CLOCK_MONOTONIC;
|
||||||
|
LOG_ERROR(Lib_Kernel, "unsupported = {} using CLOCK_MONOTONIC", clock_id);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
time_t raw_time = time(nullptr);
|
return clock_gettime(pclock_id, ts);
|
||||||
|
|
||||||
if (raw_time == (time_t)(-1)) {
|
|
||||||
return ORBIS_KERNEL_ERROR_EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
tp->tv_sec = static_cast<long>(raw_time);
|
|
||||||
tp->tv_nsec = 0;
|
|
||||||
|
|
||||||
return ORBIS_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI posix_clock_gettime(s32 clock_id, OrbisKernelTimespec* time) {
|
int PS4_SYSV_ABI sceKernelClockGettime(s32 clock_id, OrbisKernelTimespec* tp) {
|
||||||
int result = sceKernelClockGettime(clock_id, time);
|
struct timespec ts;
|
||||||
if (result < 0) {
|
const auto res = orbis_clock_gettime(clock_id, &ts);
|
||||||
UNREACHABLE(); // TODO return posix error code
|
if (res < 0) {
|
||||||
|
return ErrnoToSceKernelError(res);
|
||||||
}
|
}
|
||||||
return result;
|
tp->tv_sec = ts.tv_sec;
|
||||||
|
tp->tv_nsec = ts.tv_nsec;
|
||||||
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI posix_nanosleep(const OrbisKernelTimespec* rqtp, OrbisKernelTimespec* rmtp) {
|
int PS4_SYSV_ABI posix_nanosleep(const OrbisKernelTimespec* rqtp, OrbisKernelTimespec* rmtp) {
|
||||||
|
@ -318,8 +462,8 @@ void RegisterTime(Core::Loader::SymbolsResolver* sym) {
|
||||||
LIB_FUNCTION("yS8U2TGCe1A", "libScePosix", 1, "libkernel", 1, 1, posix_nanosleep);
|
LIB_FUNCTION("yS8U2TGCe1A", "libScePosix", 1, "libkernel", 1, 1, posix_nanosleep);
|
||||||
LIB_FUNCTION("QBi7HCK03hw", "libkernel", 1, "libkernel", 1, 1, sceKernelClockGettime);
|
LIB_FUNCTION("QBi7HCK03hw", "libkernel", 1, "libkernel", 1, 1, sceKernelClockGettime);
|
||||||
LIB_FUNCTION("kOcnerypnQA", "libkernel", 1, "libkernel", 1, 1, sceKernelGettimezone);
|
LIB_FUNCTION("kOcnerypnQA", "libkernel", 1, "libkernel", 1, 1, sceKernelGettimezone);
|
||||||
LIB_FUNCTION("lLMT9vJAck0", "libkernel", 1, "libkernel", 1, 1, posix_clock_gettime);
|
LIB_FUNCTION("lLMT9vJAck0", "libkernel", 1, "libkernel", 1, 1, orbis_clock_gettime);
|
||||||
LIB_FUNCTION("lLMT9vJAck0", "libScePosix", 1, "libkernel", 1, 1, posix_clock_gettime);
|
LIB_FUNCTION("lLMT9vJAck0", "libScePosix", 1, "libkernel", 1, 1, orbis_clock_gettime);
|
||||||
LIB_FUNCTION("smIj7eqzZE8", "libScePosix", 1, "libkernel", 1, 1, posix_clock_getres);
|
LIB_FUNCTION("smIj7eqzZE8", "libScePosix", 1, "libkernel", 1, 1, posix_clock_getres);
|
||||||
LIB_FUNCTION("0NTHN1NKONI", "libkernel", 1, "libkernel", 1, 1, sceKernelConvertLocaltimeToUtc);
|
LIB_FUNCTION("0NTHN1NKONI", "libkernel", 1, "libkernel", 1, 1, sceKernelConvertLocaltimeToUtc);
|
||||||
LIB_FUNCTION("-o5uEDpN+oY", "libkernel", 1, "libkernel", 1, 1, sceKernelConvertUtcToLocaltime);
|
LIB_FUNCTION("-o5uEDpN+oY", "libkernel", 1, "libkernel", 1, 1, sceKernelConvertUtcToLocaltime);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue