From dcd13a7566340e80c042da7f626f9747ac71b8a7 Mon Sep 17 00:00:00 2001 From: Morph <39850852+Morph1984@users.noreply.github.com> Date: Sat, 4 Mar 2023 21:44:31 -0500 Subject: native_clock: Re-adjust the RDTSC frequency The RDTSC frequency reported by CPUID is not accurate to its true frequency. We will spawn a separate thread to calculate the true RDTSC frequency after a measurement period of 30 seconds has elapsed. --- src/common/x64/native_clock.cpp | 34 +++++++++++++++++++++++++++++----- src/common/x64/native_clock.h | 5 +++++ 2 files changed, 34 insertions(+), 5 deletions(-) (limited to 'src/common/x64') diff --git a/src/common/x64/native_clock.cpp b/src/common/x64/native_clock.cpp index bc1a973b0..c11590291 100644 --- a/src/common/x64/native_clock.cpp +++ b/src/common/x64/native_clock.cpp @@ -72,13 +72,29 @@ NativeClock::NativeClock(u64 emulated_cpu_frequency_, u64 emulated_clock_frequen u64 rtsc_frequency_) : WallClock(emulated_cpu_frequency_, emulated_clock_frequency_, true), rtsc_frequency{ rtsc_frequency_} { + // Thread to re-adjust the RDTSC frequency after 30 seconds has elapsed. + time_sync_thread = std::jthread{[this](std::stop_token token) { + // Get the current time. + const auto start_time = Common::SteadyClock::Now(); + const u64 tsc_start = FencedRDTSC(); + // Wait for 30 seconds. + if (!Common::StoppableTimedWait(token, std::chrono::seconds{30})) { + return; + } + const auto end_time = Common::SteadyClock::Now(); + const u64 tsc_end = FencedRDTSC(); + // Calculate differences. + const u64 timer_diff = static_cast( + std::chrono::duration_cast(end_time - start_time).count()); + const u64 tsc_diff = tsc_end - tsc_start; + const u64 tsc_freq = MultiplyAndDivide64(tsc_diff, 1000000000ULL, timer_diff); + rtsc_frequency = tsc_freq; + CalculateAndSetFactors(); + }}; + time_point.inner.last_measure = FencedRDTSC(); time_point.inner.accumulated_ticks = 0U; - ns_rtsc_factor = GetFixedPoint64Factor(NS_RATIO, rtsc_frequency); - us_rtsc_factor = GetFixedPoint64Factor(US_RATIO, rtsc_frequency); - ms_rtsc_factor = GetFixedPoint64Factor(MS_RATIO, rtsc_frequency); - clock_rtsc_factor = GetFixedPoint64Factor(emulated_clock_frequency, rtsc_frequency); - cpu_rtsc_factor = GetFixedPoint64Factor(emulated_cpu_frequency, rtsc_frequency); + CalculateAndSetFactors(); } u64 NativeClock::GetRTSC() { @@ -138,6 +154,14 @@ u64 NativeClock::GetCPUCycles() { return MultiplyHigh(rtsc_value, cpu_rtsc_factor); } +void NativeClock::CalculateAndSetFactors() { + ns_rtsc_factor = GetFixedPoint64Factor(NS_RATIO, rtsc_frequency); + us_rtsc_factor = GetFixedPoint64Factor(US_RATIO, rtsc_frequency); + ms_rtsc_factor = GetFixedPoint64Factor(MS_RATIO, rtsc_frequency); + clock_rtsc_factor = GetFixedPoint64Factor(emulated_clock_frequency, rtsc_frequency); + cpu_rtsc_factor = GetFixedPoint64Factor(emulated_cpu_frequency, rtsc_frequency); +} + } // namespace X64 } // namespace Common diff --git a/src/common/x64/native_clock.h b/src/common/x64/native_clock.h index 38ae7a462..03ca291d8 100644 --- a/src/common/x64/native_clock.h +++ b/src/common/x64/native_clock.h @@ -3,6 +3,7 @@ #pragma once +#include "common/polyfill_thread.h" #include "common/wall_clock.h" namespace Common { @@ -28,6 +29,8 @@ public: private: u64 GetRTSC(); + void CalculateAndSetFactors(); + union alignas(16) TimePoint { TimePoint() : pack{} {} u128 pack{}; @@ -47,6 +50,8 @@ private: u64 ms_rtsc_factor{}; u64 rtsc_frequency; + + std::jthread time_sync_thread; }; } // namespace X64 -- cgit v1.2.3 From c27a626b5bc1aa2ae593f44b0a7c10ae3c979291 Mon Sep 17 00:00:00 2001 From: Morph <39850852+Morph1984@users.noreply.github.com> Date: Sun, 5 Mar 2023 02:42:48 -0500 Subject: native_clock: Use RealTimeClock instead of SteadyClock We want to synchronize RDTSC to real time. --- src/common/x64/native_clock.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/common/x64') diff --git a/src/common/x64/native_clock.cpp b/src/common/x64/native_clock.cpp index c11590291..3f90343a5 100644 --- a/src/common/x64/native_clock.cpp +++ b/src/common/x64/native_clock.cpp @@ -53,11 +53,11 @@ u64 EstimateRDTSCFrequency() { FencedRDTSC(); // Get the current time. - const auto start_time = Common::SteadyClock::Now(); + const auto start_time = Common::RealTimeClock::Now(); const u64 tsc_start = FencedRDTSC(); // Wait for 250 milliseconds. std::this_thread::sleep_for(std::chrono::milliseconds{250}); - const auto end_time = Common::SteadyClock::Now(); + const auto end_time = Common::RealTimeClock::Now(); const u64 tsc_end = FencedRDTSC(); // Calculate differences. const u64 timer_diff = static_cast( @@ -75,13 +75,13 @@ NativeClock::NativeClock(u64 emulated_cpu_frequency_, u64 emulated_clock_frequen // Thread to re-adjust the RDTSC frequency after 30 seconds has elapsed. time_sync_thread = std::jthread{[this](std::stop_token token) { // Get the current time. - const auto start_time = Common::SteadyClock::Now(); + const auto start_time = Common::RealTimeClock::Now(); const u64 tsc_start = FencedRDTSC(); // Wait for 30 seconds. if (!Common::StoppableTimedWait(token, std::chrono::seconds{30})) { return; } - const auto end_time = Common::SteadyClock::Now(); + const auto end_time = Common::RealTimeClock::Now(); const u64 tsc_end = FencedRDTSC(); // Calculate differences. const u64 timer_diff = static_cast( -- cgit v1.2.3 From d718eab351292e3c4d168738f9cd543044c335bc Mon Sep 17 00:00:00 2001 From: Morph <39850852+Morph1984@users.noreply.github.com> Date: Sun, 5 Mar 2023 20:54:13 -0500 Subject: native_clock: Wait for 10 seconds instead of 30 It was experimentally determined to be sufficient. --- src/common/x64/native_clock.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/common/x64') diff --git a/src/common/x64/native_clock.cpp b/src/common/x64/native_clock.cpp index 3f90343a5..76c66e7ee 100644 --- a/src/common/x64/native_clock.cpp +++ b/src/common/x64/native_clock.cpp @@ -72,13 +72,13 @@ NativeClock::NativeClock(u64 emulated_cpu_frequency_, u64 emulated_clock_frequen u64 rtsc_frequency_) : WallClock(emulated_cpu_frequency_, emulated_clock_frequency_, true), rtsc_frequency{ rtsc_frequency_} { - // Thread to re-adjust the RDTSC frequency after 30 seconds has elapsed. + // Thread to re-adjust the RDTSC frequency after 10 seconds has elapsed. time_sync_thread = std::jthread{[this](std::stop_token token) { // Get the current time. const auto start_time = Common::RealTimeClock::Now(); const u64 tsc_start = FencedRDTSC(); - // Wait for 30 seconds. - if (!Common::StoppableTimedWait(token, std::chrono::seconds{30})) { + // Wait for 10 seconds. + if (!Common::StoppableTimedWait(token, std::chrono::seconds{10})) { return; } const auto end_time = Common::RealTimeClock::Now(); -- cgit v1.2.3