Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion core/libs/prx/libSceJobManager/Export.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1018,7 +1018,7 @@ int Initialize(void* self, void* memory, std::uint64_t size, std::uint32_t worke
std::unique_ptr<Manager, decltype(&DestroyManager)> owner(manager, DestroyManager);
manager->running = true;
manager->workerCount = workers;
manager->spinTicks = sceKernelGetTscFrequency() / 1000000 * settings.spinMicroseconds;
manager->spinTicks = HostTscFrequency_nid_no_patch() / 1000000 * settings.spinMicroseconds;
for (std::uint32_t index = 0; index < layout.nodes; ++index) std::construct_at(&manager->nodes[index]);
for (std::uint32_t index = layout.nodes; index > 1; --index) ReturnNode(*manager, &manager->nodes[index - 1]);
manager->freeSequences = sequences == MaxSequences ? ~std::uint32_t{0} : (std::uint32_t{1} << sequences) - 1;
Expand Down
6 changes: 4 additions & 2 deletions core/libs/prx/libkernel/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -239,9 +239,11 @@ if(BUILD_TESTING)
endif()
add_test(NAME guest_process_time_tsc COMMAND guest_process_time_tests tsc)
add_test(NAME guest_process_time_tsc_scaled COMMAND guest_process_time_tests tsc)
set_tests_properties(guest_process_time_tsc_scaled PROPERTIES ENVIRONMENT "APS5_TIME_SCALE=0.5")
add_test(NAME guest_process_time_rdtsc COMMAND guest_process_time_tests rdtsc)
add_test(NAME guest_process_time_rdtsc_scaled COMMAND guest_process_time_tests rdtsc)
set_tests_properties(guest_process_time_tsc_scaled guest_process_time_rdtsc_scaled PROPERTIES ENVIRONMENT "APS5_TIME_SCALE=0.5")
if(WIN32)
set_tests_properties(guest_process_time_tsc guest_process_time_tsc_scaled PROPERTIES ENVIRONMENT_MODIFICATION
set_tests_properties(guest_process_time_tsc guest_process_time_tsc_scaled guest_process_time_rdtsc guest_process_time_rdtsc_scaled PROPERTIES ENVIRONMENT_MODIFICATION
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libkernel>")
endif()
add_test_executable(guest_process_arguments_tests ${LIBS_INCLUDE_DIR}/tests/GuestProcessArguments.cpp)
Expand Down
11 changes: 7 additions & 4 deletions core/libs/prx/libkernel/Time/Time.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -849,12 +849,10 @@ int APS5_VABI sceKernelGettimezone(KernelTimezone* tz) {
}

uint64_t APS5_VABI sceKernelReadTsc(void) {
if (TimeScale() == 1.0) return __rdtsc();
static const std::uint64_t origin = __rdtsc();
return origin + static_cast<std::uint64_t>(static_cast<double>(__rdtsc() - origin) * TimeScale());
return __rdtsc();
}

uint64_t APS5_VABI sceKernelGetTscFrequency(void) {
std::uint64_t APS5_VABI HostTscFrequency_nid_no_patch() {
static const std::uint64_t frequency = [] {
const CurrentCpuPin pin;
const std::uint64_t startNanos = RawMonotonicNanos();
Expand All @@ -867,6 +865,11 @@ uint64_t APS5_VABI sceKernelGetTscFrequency(void) {
return frequency;
}

uint64_t APS5_VABI sceKernelGetTscFrequency(void) {
static const std::uint64_t frequency = static_cast<std::uint64_t>(static_cast<double>(HostTscFrequency_nid_no_patch()) / TimeScale());
return frequency;
}

std::int64_t APS5_VABI sceKernelGetCpuFrequency(void) {
return static_cast<std::int64_t>(sceKernelGetTscFrequency());
}
Expand Down
1 change: 1 addition & 0 deletions core/libs/prx/libkernel/Time/include/Time.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ extern "C" {
std::uint64_t APS5_VABI sceKernelGetProcessTimeCounter();
std::uint64_t APS5_VABI sceKernelGetProcessTimeCounterFrequency();
std::uint64_t APS5_VABI sceKernelGetTscFrequency();
std::uint64_t APS5_VABI HostTscFrequency_nid_no_patch();
int APS5_VABI sceKernelUsleep_nid_postfix(KernelUseconds microseconds);
int APS5_VABI sceKernelNanosleep(const KernelTimespec* rqtp, KernelTimespec* rmtp);
int APS5_VABI nanosleep_nid_postfix(const KernelTimespec* rqtp, KernelTimespec* rmtp);
Expand Down
13 changes: 13 additions & 0 deletions core/libs/tests/GuestProcessTime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <cstdlib>
#include <cstring>
#include <thread>
#include <x86intrin.h>

static void Require(bool condition, const char* message) {
if (!condition) {
Expand All @@ -21,6 +22,18 @@ int main(int argc, char** argv) {
const double scale = scaleText ? std::strtod(scaleText, nullptr) : 1.0;
const auto elapsedMicros = static_cast<std::uint64_t>(static_cast<double>(sleptMicros) * (scale > 0.0 ? scale : 1.0));
const auto minimumElapsedMicros = elapsedMicros * 19 / 20;
if (argc > 1 && std::strcmp(argv[1], "rdtsc") == 0) {
const std::uint64_t frequency = sceKernelGetTscFrequency();
const std::uint64_t nativeStart = __rdtsc();
const std::uint64_t readStart = sceKernelReadTsc();
const auto until = std::chrono::steady_clock::now() + std::chrono::microseconds(sleptMicros);
while (std::chrono::steady_clock::now() < until) std::this_thread::sleep_until(until);
const std::uint64_t nativeMicros = (__rdtsc() - nativeStart) * 1000000 / frequency;
const std::uint64_t readMicros = (sceKernelReadTsc() - readStart) * 1000000 / frequency;
Require(nativeMicros >= minimumElapsedMicros && nativeMicros < elapsedMicros * 3 / 2, "native rdtsc ticks over the reported TSC frequency do not follow the time scale");
Require(readMicros >= minimumElapsedMicros && readMicros < elapsedMicros * 3 / 2, "sceKernelReadTsc ticks over the reported TSC frequency do not follow the time scale");
return 0;
}
const auto slept = std::chrono::steady_clock::now() + std::chrono::microseconds(sleptMicros);
while (std::chrono::steady_clock::now() < slept) std::this_thread::sleep_until(slept);
if (argc > 1 && std::strcmp(argv[1], "tsc") == 0) {
Expand Down
Loading