fix(libkernel): read the process start before the clock in process time

sceKernelGetProcessTime and sceKernelGetProcessTimeCounter subtracted
GetStartNanos() from GetMonotonicNanos() in one expression. GCC reads the
clock first, so on the first call in a process the start was captured
after it and the result wrapped to about 2^64.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
TideOPL 2026-10-07 11:03:30 +01:00
parent 73ac9ef7f4
commit 383770ff65
3 changed files with 38 additions and 2 deletions

View File

@ -84,6 +84,16 @@ if(BUILD_TESTING)
set_tests_properties(guest_posix_sem_init guest_posix_sem_post PROPERTIES ENVIRONMENT_MODIFICATION
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libkernel>")
endif()
add_test_executable(guest_process_time_tests ${LIBS_INCLUDE_DIR}/tests/GuestProcessTime.cpp)
target_include_directories(guest_process_time_tests PRIVATE ${LIBS_INCLUDE_DIR})
target_link_libraries(guest_process_time_tests PRIVATE libkernel libc)
configure_windows_unwind(guest_process_time_tests)
add_test(NAME guest_process_time COMMAND guest_process_time_tests)
add_test(NAME guest_process_time_counter COMMAND guest_process_time_tests counter)
if(WIN32)
set_tests_properties(guest_process_time guest_process_time_counter PROPERTIES ENVIRONMENT_MODIFICATION
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libkernel>")
endif()
add_library(guest_module_fixture SHARED ${LIBS_INCLUDE_DIR}/tests/GuestModuleFixture.cpp)
target_include_directories(guest_module_fixture PRIVATE ${LIBS_INCLUDE_DIR})
add_custom_command(TARGET guest_module_fixture POST_BUILD

View File

@ -147,11 +147,13 @@ static const bool g_timerSelfTest = [] {
extern "C" {
std::uint64_t APS5_VABI sceKernelGetProcessTime() {
return (GetMonotonicNanos() - GetStartNanos()) / 1000ULL;
const std::uint64_t start = GetStartNanos();
return (GetMonotonicNanos() - start) / 1000ULL;
}
std::uint64_t APS5_VABI sceKernelGetProcessTimeCounter() {
return GetMonotonicNanos() - GetStartNanos();
const std::uint64_t start = GetStartNanos();
return GetMonotonicNanos() - start;
}
std::uint64_t APS5_VABI sceKernelGetProcessTimeCounterFrequency() {

View File

@ -0,0 +1,24 @@
#include "prx/libkernel/Time/include/Time.hpp"
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>
static void Require(bool condition, const char* message) {
if (!condition) {
std::fprintf(stderr, "%s\n", message);
std::abort();
}
}
int main(int argc, char** argv) {
constexpr std::uint64_t minuteMicros = 60ULL * 1000 * 1000;
if (argc > 1 && std::strcmp(argv[1], "counter") == 0) {
Require(sceKernelGetProcessTimeCounter() < minuteMicros * 1000, "first process time counter wrapped");
return 0;
}
const std::uint64_t first = sceKernelGetProcessTime();
Require(first < minuteMicros, "first process time wrapped");
Require(sceKernelGetProcessTime() >= first, "process time went backwards");
return 0;
}