2024-02-23 22:32:32 +01:00
|
|
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
|
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
|
2024-06-10 21:59:12 +02:00
|
|
|
#include <thread>
|
|
|
|
#include "common/assert.h"
|
2024-02-14 23:52:57 +01:00
|
|
|
#include "common/native_clock.h"
|
2024-06-10 21:59:12 +02:00
|
|
|
#include "core/libraries/error_codes.h"
|
2024-04-13 23:35:48 +02:00
|
|
|
#include "core/libraries/kernel/time_management.h"
|
|
|
|
#include "core/libraries/libs.h"
|
2023-10-30 07:48:52 +01:00
|
|
|
|
2024-06-10 21:59:12 +02:00
|
|
|
#ifdef _WIN64
|
|
|
|
#include <pthread_time.h>
|
2024-06-11 22:26:13 +02:00
|
|
|
#include <windows.h>
|
2024-06-10 23:48:06 +02:00
|
|
|
|
2024-07-11 14:35:58 +02:00
|
|
|
#include "common/ntapi.h"
|
|
|
|
|
2024-06-10 21:59:12 +02:00
|
|
|
#else
|
|
|
|
#include <time.h>
|
2024-06-10 23:48:06 +02:00
|
|
|
#include <unistd.h>
|
2024-06-10 21:59:12 +02:00
|
|
|
#endif
|
|
|
|
|
2024-04-13 23:35:48 +02:00
|
|
|
namespace Libraries::Kernel {
|
2023-11-06 00:11:54 +01:00
|
|
|
|
2024-02-14 23:52:57 +01:00
|
|
|
static u64 initial_ptc;
|
|
|
|
static std::unique_ptr<Common::NativeClock> clock;
|
|
|
|
|
2024-05-07 15:28:42 +02:00
|
|
|
u64 PS4_SYSV_ABI sceKernelGetTscFrequency() {
|
|
|
|
return clock->GetTscFrequency();
|
|
|
|
}
|
|
|
|
|
2023-10-30 19:22:25 +01:00
|
|
|
u64 PS4_SYSV_ABI sceKernelGetProcessTime() {
|
2024-02-14 23:52:57 +01:00
|
|
|
return clock->GetProcessTimeUS();
|
2023-10-30 07:48:52 +01:00
|
|
|
}
|
2023-10-30 19:22:25 +01:00
|
|
|
|
2023-11-06 00:11:54 +01:00
|
|
|
u64 PS4_SYSV_ABI sceKernelGetProcessTimeCounter() {
|
2024-02-14 23:52:57 +01:00
|
|
|
return clock->GetUptime() - initial_ptc;
|
2023-11-06 00:11:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
u64 PS4_SYSV_ABI sceKernelGetProcessTimeCounterFrequency() {
|
2024-02-14 23:52:57 +01:00
|
|
|
return clock->GetTscFrequency();
|
2023-11-06 00:11:54 +01:00
|
|
|
}
|
2023-10-30 07:48:52 +01:00
|
|
|
|
2023-11-06 00:11:54 +01:00
|
|
|
u64 PS4_SYSV_ABI sceKernelReadTsc() {
|
2024-02-14 23:52:57 +01:00
|
|
|
return clock->GetUptime();
|
2023-11-06 00:11:54 +01:00
|
|
|
}
|
2023-10-30 07:48:52 +01:00
|
|
|
|
2024-06-10 21:59:12 +02:00
|
|
|
int PS4_SYSV_ABI sceKernelUsleep(u32 microseconds) {
|
2024-06-11 18:36:17 +02:00
|
|
|
#ifdef _WIN64
|
2024-06-11 21:41:35 +02:00
|
|
|
if (microseconds < 1000u) {
|
2024-06-10 23:48:06 +02:00
|
|
|
LARGE_INTEGER interval{
|
|
|
|
.QuadPart = -1 * (microseconds * 10u),
|
|
|
|
};
|
|
|
|
NtDelayExecution(FALSE, &interval);
|
|
|
|
} else {
|
|
|
|
std::this_thread::sleep_for(std::chrono::microseconds(microseconds));
|
|
|
|
}
|
2024-06-21 16:39:37 +02:00
|
|
|
return 0;
|
2024-06-10 23:48:06 +02:00
|
|
|
#else
|
2024-06-21 16:39:37 +02:00
|
|
|
timespec start;
|
|
|
|
timespec remain;
|
|
|
|
start.tv_sec = microseconds / 1000000;
|
|
|
|
start.tv_nsec = (microseconds % 1000000) * 1000;
|
|
|
|
timespec* requested = &start;
|
|
|
|
int ret = 0;
|
|
|
|
do {
|
|
|
|
ret = nanosleep(requested, &remain);
|
|
|
|
requested = &remain;
|
|
|
|
} while (ret != 0);
|
|
|
|
return ret;
|
2024-06-10 23:48:06 +02:00
|
|
|
#endif
|
2024-06-10 21:59:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
int PS4_SYSV_ABI posix_usleep(u32 microseconds) {
|
2024-06-14 09:37:26 +02:00
|
|
|
return sceKernelUsleep(microseconds);
|
2024-06-10 21:59:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
u32 PS4_SYSV_ABI sceKernelSleep(u32 seconds) {
|
|
|
|
std::this_thread::sleep_for(std::chrono::seconds(seconds));
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int PS4_SYSV_ABI sceKernelClockGettime(s32 clock_id, OrbisKernelTimespec* tp) {
|
|
|
|
if (tp == nullptr) {
|
|
|
|
return SCE_KERNEL_ERROR_EFAULT;
|
|
|
|
}
|
|
|
|
clockid_t pclock_id = CLOCK_REALTIME;
|
|
|
|
switch (clock_id) {
|
2024-06-14 09:37:26 +02:00
|
|
|
case ORBIS_CLOCK_REALTIME:
|
|
|
|
case ORBIS_CLOCK_REALTIME_PRECISE:
|
|
|
|
case ORBIS_CLOCK_REALTIME_FAST:
|
2024-06-10 21:59:12 +02:00
|
|
|
pclock_id = CLOCK_REALTIME;
|
|
|
|
break;
|
2024-06-14 09:37:26 +02:00
|
|
|
case ORBIS_CLOCK_SECOND:
|
|
|
|
case ORBIS_CLOCK_MONOTONIC:
|
|
|
|
case ORBIS_CLOCK_MONOTONIC_PRECISE:
|
|
|
|
case ORBIS_CLOCK_MONOTONIC_FAST:
|
2024-06-10 21:59:12 +02:00
|
|
|
pclock_id = CLOCK_MONOTONIC;
|
|
|
|
break;
|
|
|
|
default:
|
2024-07-12 14:19:41 +02:00
|
|
|
LOG_ERROR(Lib_Kernel, "unsupported = {} using CLOCK_REALTIME", clock_id);
|
|
|
|
break;
|
2024-06-10 21:59:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
timespec t{};
|
|
|
|
int result = clock_gettime(pclock_id, &t);
|
|
|
|
tp->tv_sec = t.tv_sec;
|
|
|
|
tp->tv_nsec = t.tv_nsec;
|
|
|
|
if (result == 0) {
|
|
|
|
return SCE_OK;
|
|
|
|
}
|
|
|
|
return SCE_KERNEL_ERROR_EINVAL;
|
|
|
|
}
|
|
|
|
|
2024-06-14 09:37:26 +02:00
|
|
|
int PS4_SYSV_ABI posix_clock_gettime(s32 clock_id, OrbisKernelTimespec* time) {
|
2024-06-10 21:59:12 +02:00
|
|
|
int result = sceKernelClockGettime(clock_id, time);
|
|
|
|
if (result < 0) {
|
|
|
|
UNREACHABLE(); // TODO return posix error code
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
int PS4_SYSV_ABI posix_nanosleep(const OrbisKernelTimespec* rqtp, OrbisKernelTimespec* rmtp) {
|
|
|
|
const auto* request = reinterpret_cast<const timespec*>(rqtp);
|
|
|
|
auto* remain = reinterpret_cast<timespec*>(rmtp);
|
|
|
|
return nanosleep(request, remain);
|
|
|
|
}
|
|
|
|
|
|
|
|
int PS4_SYSV_ABI sceKernelNanosleep(const OrbisKernelTimespec* rqtp, OrbisKernelTimespec* rmtp) {
|
|
|
|
if (!rqtp || !rmtp) {
|
|
|
|
return SCE_KERNEL_ERROR_EFAULT;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (rqtp->tv_sec < 0 || rqtp->tv_nsec < 0) {
|
|
|
|
return SCE_KERNEL_ERROR_EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return posix_nanosleep(rqtp, rmtp);
|
|
|
|
}
|
|
|
|
|
|
|
|
int PS4_SYSV_ABI sceKernelGettimeofday(OrbisKernelTimeval* tp) {
|
|
|
|
if (!tp) {
|
|
|
|
return ORBIS_KERNEL_ERROR_EFAULT;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto now = std::chrono::system_clock::now();
|
|
|
|
auto duration = now.time_since_epoch();
|
|
|
|
auto seconds = std::chrono::duration_cast<std::chrono::seconds>(duration);
|
|
|
|
auto microsecs = std::chrono::duration_cast<std::chrono::microseconds>(duration - seconds);
|
|
|
|
|
|
|
|
tp->tv_sec = seconds.count();
|
|
|
|
tp->tv_usec = microsecs.count();
|
|
|
|
return ORBIS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
int PS4_SYSV_ABI gettimeofday(OrbisKernelTimeval* tp, OrbisKernelTimezone* tz) {
|
|
|
|
// FreeBSD docs mention that the kernel generally does not track these values
|
|
|
|
// and they are usually returned as zero.
|
|
|
|
if (tz) {
|
|
|
|
tz->tz_minuteswest = 0;
|
|
|
|
tz->tz_dsttime = 0;
|
|
|
|
}
|
|
|
|
return sceKernelGettimeofday(tp);
|
|
|
|
}
|
|
|
|
|
2024-06-15 13:36:07 +02:00
|
|
|
s32 PS4_SYSV_ABI sceKernelGettimezone(OrbisKernelTimezone* tz) {
|
|
|
|
#ifdef _WIN64
|
|
|
|
ASSERT(tz);
|
|
|
|
static int tzflag = 0;
|
|
|
|
if (!tzflag) {
|
|
|
|
_tzset();
|
|
|
|
tzflag++;
|
|
|
|
}
|
|
|
|
tz->tz_minuteswest = _timezone / 60;
|
|
|
|
tz->tz_dsttime = _daylight;
|
|
|
|
#else
|
|
|
|
struct timezone tzz;
|
|
|
|
struct timeval tv;
|
|
|
|
gettimeofday(&tv, &tzz);
|
|
|
|
tz->tz_dsttime = tzz.tz_dsttime;
|
|
|
|
tz->tz_minuteswest = tzz.tz_minuteswest;
|
|
|
|
#endif
|
|
|
|
return ORBIS_OK;
|
|
|
|
}
|
|
|
|
|
2024-06-14 09:37:26 +02:00
|
|
|
int PS4_SYSV_ABI posix_clock_getres(u32 clock_id, OrbisKernelTimespec* res) {
|
|
|
|
if (res == nullptr) {
|
|
|
|
return SCE_KERNEL_ERROR_EFAULT;
|
|
|
|
}
|
|
|
|
clockid_t pclock_id = CLOCK_REALTIME;
|
|
|
|
switch (clock_id) {
|
|
|
|
case ORBIS_CLOCK_REALTIME:
|
|
|
|
case ORBIS_CLOCK_REALTIME_PRECISE:
|
|
|
|
case ORBIS_CLOCK_REALTIME_FAST:
|
|
|
|
pclock_id = CLOCK_REALTIME;
|
|
|
|
break;
|
|
|
|
case ORBIS_CLOCK_SECOND:
|
|
|
|
case ORBIS_CLOCK_MONOTONIC:
|
|
|
|
case ORBIS_CLOCK_MONOTONIC_PRECISE:
|
|
|
|
case ORBIS_CLOCK_MONOTONIC_FAST:
|
|
|
|
pclock_id = CLOCK_MONOTONIC;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
UNREACHABLE();
|
|
|
|
}
|
|
|
|
|
|
|
|
timespec t{};
|
|
|
|
int result = clock_getres(pclock_id, &t);
|
|
|
|
res->tv_sec = t.tv_sec;
|
|
|
|
res->tv_nsec = t.tv_nsec;
|
|
|
|
if (result == 0) {
|
|
|
|
return SCE_OK;
|
|
|
|
}
|
|
|
|
return SCE_KERNEL_ERROR_EINVAL;
|
|
|
|
}
|
|
|
|
|
2024-04-13 23:35:48 +02:00
|
|
|
void timeSymbolsRegister(Core::Loader::SymbolsResolver* sym) {
|
2024-02-14 23:52:57 +01:00
|
|
|
clock = std::make_unique<Common::NativeClock>();
|
|
|
|
initial_ptc = clock->GetUptime();
|
2024-02-23 21:57:57 +01:00
|
|
|
LIB_FUNCTION("4J2sUJmuHZQ", "libkernel", 1, "libkernel", 1, 1, sceKernelGetProcessTime);
|
2023-10-30 11:53:52 +01:00
|
|
|
LIB_FUNCTION("fgxnMeTNUtY", "libkernel", 1, "libkernel", 1, 1, sceKernelGetProcessTimeCounter);
|
2024-02-23 21:57:57 +01:00
|
|
|
LIB_FUNCTION("BNowx2l588E", "libkernel", 1, "libkernel", 1, 1,
|
|
|
|
sceKernelGetProcessTimeCounterFrequency);
|
2023-10-30 19:22:25 +01:00
|
|
|
LIB_FUNCTION("-2IRUCO--PM", "libkernel", 1, "libkernel", 1, 1, sceKernelReadTsc);
|
2024-05-07 15:28:42 +02:00
|
|
|
LIB_FUNCTION("1j3S3n-tTW4", "libkernel", 1, "libkernel", 1, 1, sceKernelGetTscFrequency);
|
2024-06-10 21:59:12 +02:00
|
|
|
LIB_FUNCTION("ejekcaNQNq0", "libkernel", 1, "libkernel", 1, 1, sceKernelGettimeofday);
|
|
|
|
LIB_FUNCTION("n88vx3C5nW8", "libkernel", 1, "libkernel", 1, 1, gettimeofday);
|
|
|
|
LIB_FUNCTION("n88vx3C5nW8", "libScePosix", 1, "libkernel", 1, 1, gettimeofday);
|
2024-06-14 09:37:26 +02:00
|
|
|
LIB_FUNCTION("QvsZxomvUHs", "libkernel", 1, "libkernel", 1, 1, sceKernelNanosleep);
|
2024-06-10 21:59:12 +02:00
|
|
|
LIB_FUNCTION("1jfXLRVzisc", "libkernel", 1, "libkernel", 1, 1, sceKernelUsleep);
|
2024-06-15 13:36:07 +02:00
|
|
|
LIB_FUNCTION("QcteRwbsnV0", "libkernel", 1, "libkernel", 1, 1, posix_usleep);
|
2024-06-10 21:59:12 +02:00
|
|
|
LIB_FUNCTION("QcteRwbsnV0", "libScePosix", 1, "libkernel", 1, 1, posix_usleep);
|
|
|
|
LIB_FUNCTION("-ZR+hG7aDHw", "libkernel", 1, "libkernel", 1, 1, sceKernelSleep);
|
|
|
|
LIB_FUNCTION("0wu33hunNdE", "libScePosix", 1, "libkernel", 1, 1, sceKernelSleep);
|
|
|
|
LIB_FUNCTION("yS8U2TGCe1A", "libkernel", 1, "libkernel", 1, 1, posix_nanosleep);
|
2024-06-11 15:42:15 +02:00
|
|
|
LIB_FUNCTION("yS8U2TGCe1A", "libScePosix", 1, "libkernel", 1, 1, posix_nanosleep);
|
2024-06-10 21:59:12 +02:00
|
|
|
LIB_FUNCTION("QBi7HCK03hw", "libkernel", 1, "libkernel", 1, 1, sceKernelClockGettime);
|
2024-06-15 13:36:07 +02:00
|
|
|
LIB_FUNCTION("kOcnerypnQA", "libkernel", 1, "libkernel", 1, 1, sceKernelGettimezone);
|
2024-06-14 09:37:26 +02:00
|
|
|
LIB_FUNCTION("lLMT9vJAck0", "libkernel", 1, "libkernel", 1, 1, posix_clock_gettime);
|
|
|
|
LIB_FUNCTION("lLMT9vJAck0", "libScePosix", 1, "libkernel", 1, 1, posix_clock_gettime);
|
|
|
|
LIB_FUNCTION("smIj7eqzZE8", "libScePosix", 1, "libkernel", 1, 1, posix_clock_getres);
|
2023-10-30 11:53:52 +01:00
|
|
|
}
|
|
|
|
|
2024-04-13 23:35:48 +02:00
|
|
|
} // namespace Libraries::Kernel
|