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
|
2024-06-10 23:48:06 +02:00
|
|
|
#include <Windows.h>
|
2024-06-10 21:59:12 +02:00
|
|
|
#include <pthread_time.h>
|
2024-06-10 23:48:06 +02:00
|
|
|
|
|
|
|
// http://stackoverflow.com/a/31411628/4725495
|
|
|
|
static u32(__stdcall* NtDelayExecution)(BOOL Alertable, PLARGE_INTEGER DelayInterval) =
|
|
|
|
(u32(__stdcall*)(BOOL, PLARGE_INTEGER))GetProcAddress(GetModuleHandle("ntdll.dll"),
|
|
|
|
"NtDelayExecution");
|
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));
|
|
|
|
}
|
|
|
|
#else
|
2024-06-11 21:41:35 +02:00
|
|
|
usleep(microseconds);
|
2024-06-10 23:48:06 +02:00
|
|
|
#endif
|
2024-06-10 21:59:12 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int PS4_SYSV_ABI posix_usleep(u32 microseconds) {
|
|
|
|
ASSERT(microseconds >= 1000);
|
|
|
|
std::this_thread::sleep_for(std::chrono::microseconds(microseconds));
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
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) {
|
|
|
|
case 0:
|
|
|
|
pclock_id = CLOCK_REALTIME;
|
|
|
|
break;
|
|
|
|
case 13:
|
|
|
|
case 4:
|
|
|
|
pclock_id = CLOCK_MONOTONIC;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
UNREACHABLE();
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
int PS4_SYSV_ABI clock_gettime(s32 clock_id, OrbisKernelTimespec* time) {
|
|
|
|
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-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);
|
|
|
|
LIB_FUNCTION("1jfXLRVzisc", "libkernel", 1, "libkernel", 1, 1, sceKernelUsleep);
|
|
|
|
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);
|
|
|
|
LIB_FUNCTION("lLMT9vJAck0", "libkernel", 1, "libkernel", 1, 1, clock_gettime);
|
|
|
|
LIB_FUNCTION("lLMT9vJAck0", "libScePosix", 1, "libkernel", 1, 1, clock_gettime);
|
2023-10-30 11:53:52 +01:00
|
|
|
}
|
|
|
|
|
2024-04-13 23:35:48 +02:00
|
|
|
} // namespace Libraries::Kernel
|