Kernel: Changes to scekernelUsleep to improve precision.

This commit is contained in:
Dmugetsu 2025-03-09 13:47:56 -06:00
parent 74c2c6c74f
commit d1604bc776

View File

@ -72,17 +72,13 @@ int PS4_SYSV_ABI sceKernelUsleep(u32 microseconds) {
return 0; return 0;
#else #else
timespec start; struct timespec req, rem;
timespec remain; req.tv_sec = microseconds / 1000000;
start.tv_sec = microseconds / 1000000; req.tv_nsec = (microseconds % 1000000) * 1000;
start.tv_nsec = (microseconds % 1000000) * 1000; while (nanosleep(&req, &rem) == -1) {
timespec* requested = &start; req = rem;
int ret = 0; }
do { return 0;
ret = nanosleep(requested, &remain);
requested = &remain;
} while (ret != 0);
return ret;
#endif #endif
} }
@ -114,6 +110,9 @@ u32 PS4_SYSV_ABI sceKernelSleep(u32 seconds) {
#ifndef CLOCK_MONOTONIC_COARSE #ifndef CLOCK_MONOTONIC_COARSE
#define CLOCK_MONOTONIC_COARSE 6 #define CLOCK_MONOTONIC_COARSE 6
#endif #endif
#ifndef CLOCK_MONOTONIC_RAW
#define CLOCK_MONOTONIC_RAW 7
#endif
#define DELTA_EPOCH_IN_100NS 116444736000000000ULL #define DELTA_EPOCH_IN_100NS 116444736000000000ULL
@ -133,7 +132,7 @@ static s32 clock_gettime(u32 clock_id, struct timespec* ts) {
return 0; return 0;
} }
case CLOCK_MONOTONIC: case CLOCK_MONOTONIC:
case CLOCK_MONOTONIC_COARSE: { case CLOCK_MONOTONIC_RAW: {
static LARGE_INTEGER pf = [] { static LARGE_INTEGER pf = [] {
LARGE_INTEGER res{}; LARGE_INTEGER res{};
QueryPerformanceFrequency(&pf); QueryPerformanceFrequency(&pf);
@ -158,7 +157,7 @@ static s32 clock_gettime(u32 clock_id, struct timespec* ts) {
} }
case CLOCK_THREAD_CPUTIME_ID: { case CLOCK_THREAD_CPUTIME_ID: {
FILETIME ct, et, kt, ut; FILETIME ct, et, kt, ut;
if (!GetThreadTimes(GetCurrentThread(), &ct, &et, &kt, &ut)) { if (!GetThreadTimes(GetCurrentProcess(), &ct, &et, &kt, &ut)) {
return EFAULT; return EFAULT;
} }
const u64 ns = FileTimeTo100Ns(ut) + FileTimeTo100Ns(kt); const u64 ns = FileTimeTo100Ns(ut) + FileTimeTo100Ns(kt);
@ -172,8 +171,8 @@ static s32 clock_gettime(u32 clock_id, struct timespec* ts) {
} }
#endif #endif
int PS4_SYSV_ABI orbis_clock_gettime(s32 clock_id, struct timespec* ts) { int PS4_SYSV_ABI orbis_clock_gettime(s32 clock_id, OrbisKernelTimespec* tp) {
if (ts == nullptr) { if (tp == nullptr) {
return ORBIS_KERNEL_ERROR_EFAULT; return ORBIS_KERNEL_ERROR_EFAULT;
} }
@ -185,12 +184,11 @@ int PS4_SYSV_ABI orbis_clock_gettime(s32 clock_id, struct timespec* ts) {
break; break;
case ORBIS_CLOCK_SECOND: case ORBIS_CLOCK_SECOND:
case ORBIS_CLOCK_REALTIME_FAST: case ORBIS_CLOCK_REALTIME_FAST:
#ifndef __APPLE__ #ifdef __APPLE__
pclock_id = CLOCK_REALTIME_COARSE;
#else
pclock_id = CLOCK_REALTIME; pclock_id = CLOCK_REALTIME;
#endif #else
break; pclock_id = CLOCK_REALTIME_COARSE;
#endif break;
case ORBIS_CLOCK_UPTIME: case ORBIS_CLOCK_UPTIME:
case ORBIS_CLOCK_UPTIME_PRECISE: case ORBIS_CLOCK_UPTIME_PRECISE:
case ORBIS_CLOCK_MONOTONIC: case ORBIS_CLOCK_MONOTONIC:
@ -199,19 +197,15 @@ int PS4_SYSV_ABI orbis_clock_gettime(s32 clock_id, struct timespec* ts) {
break; break;
case ORBIS_CLOCK_UPTIME_FAST: case ORBIS_CLOCK_UPTIME_FAST:
case ORBIS_CLOCK_MONOTONIC_FAST: case ORBIS_CLOCK_MONOTONIC_FAST:
#ifndef __APPLE__ pclock_id = CLOCK_MONOTONIC_RAW;
pclock_id = CLOCK_MONOTONIC_COARSE;
#else
pclock_id = CLOCK_MONOTONIC;
#endif
break; break;
case ORBIS_CLOCK_THREAD_CPUTIME_ID: case ORBIS_CLOCK_THREAD_CPUTIME_ID:
pclock_id = CLOCK_THREAD_CPUTIME_ID; pclock_id = CLOCK_THREAD_CPUTIME_ID;
break; break;
case ORBIS_CLOCK_PROCTIME: { case ORBIS_CLOCK_PROCTIME: {
const auto us = sceKernelGetProcessTime(); const auto us = sceKernelGetProcessTime();
ts->tv_sec = us / 1'000'000; tp->tv_sec = us / 1'000'000;
ts->tv_nsec = (us % 1'000'000) * 1000; tp->tv_nsec = (us % 1'000'000) * 1000;
return 0; return 0;
} }
case ORBIS_CLOCK_VIRTUAL: { case ORBIS_CLOCK_VIRTUAL: {
@ -221,16 +215,16 @@ int PS4_SYSV_ABI orbis_clock_gettime(s32 clock_id, struct timespec* ts) {
return EFAULT; return EFAULT;
} }
const u64 ns = FileTimeTo100Ns(ut); const u64 ns = FileTimeTo100Ns(ut);
ts->tv_sec = ns / 10'000'000; tp->tv_sec = ns / 10'000'000;
ts->tv_nsec = (ns % 10'000'000) * 100; tp->tv_nsec = (ns % 10'000'000) * 100;
#else #else
struct rusage ru; struct rusage ru;
const auto res = getrusage(RUSAGE_SELF, &ru); const auto res = getrusage(RUSAGE_SELF, &ru);
if (res < 0) { if (res < 0) {
return res; return res;
} }
ts->tv_sec = ru.ru_utime.tv_sec; tp->tv_sec = ru.ru_utime.tv_sec;
ts->tv_nsec = ru.ru_utime.tv_usec * 1000; tp->tv_nsec = ru.ru_utime.tv_usec * 1000;
#endif #endif
return 0; return 0;
} }
@ -241,16 +235,16 @@ int PS4_SYSV_ABI orbis_clock_gettime(s32 clock_id, struct timespec* ts) {
return EFAULT; return EFAULT;
} }
const u64 ns = FileTimeTo100Ns(kt); const u64 ns = FileTimeTo100Ns(kt);
ts->tv_sec = ns / 10'000'000; tp->tv_sec = ns / 10'000'000;
ts->tv_nsec = (ns % 10'000'000) * 100; tp->tv_nsec = (ns % 10'000'000) * 100;
#else #else
struct rusage ru; struct rusage ru;
const auto res = getrusage(RUSAGE_SELF, &ru); const auto res = getrusage(RUSAGE_SELF, &ru);
if (res < 0) { if (res < 0) {
return res; return res;
} }
ts->tv_sec = ru.ru_stime.tv_sec; tp->tv_sec = ru.ru_stime.tv_sec;
ts->tv_nsec = ru.ru_stime.tv_usec * 1000; tp->tv_nsec = ru.ru_stime.tv_usec * 1000;
#endif #endif
return 0; return 0;
} }
@ -265,17 +259,23 @@ int PS4_SYSV_ABI orbis_clock_gettime(s32 clock_id, struct timespec* ts) {
return EINVAL; return EINVAL;
} }
return clock_gettime(pclock_id, ts); struct timespec ts;
const auto res = clock_gettime(pclock_id, &ts);
if (res < 0) {
return res;
}
tp->tv_sec = ts.tv_sec;
tp->tv_nsec = ts.tv_nsec;
return 0;
} }
int PS4_SYSV_ABI sceKernelClockGettime(s32 clock_id, OrbisKernelTimespec* tp) { int PS4_SYSV_ABI sceKernelClockGettime(s32 clock_id, OrbisKernelTimespec* tp) {
struct timespec ts; const auto res = orbis_clock_gettime(clock_id, tp);
const auto res = orbis_clock_gettime(clock_id, &ts);
if (res < 0) { if (res < 0) {
return ErrnoToSceKernelError(res); return ErrnoToSceKernelError(res);
} }
tp->tv_sec = ts.tv_sec;
tp->tv_nsec = ts.tv_nsec;
return ORBIS_OK; return ORBIS_OK;
} }
@ -469,4 +469,4 @@ void RegisterTime(Core::Loader::SymbolsResolver* sym) {
LIB_FUNCTION("-o5uEDpN+oY", "libkernel", 1, "libkernel", 1, 1, sceKernelConvertUtcToLocaltime); LIB_FUNCTION("-o5uEDpN+oY", "libkernel", 1, "libkernel", 1, 1, sceKernelConvertUtcToLocaltime);
} }
} // namespace Libraries::Kernel } // namespace Libraries::Kernel