summaryrefslogtreecommitdiff
path: root/src/common/x64
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/x64')
-rw-r--r--src/common/x64/native_clock.cpp14
-rw-r--r--src/common/x64/native_clock.h7
2 files changed, 18 insertions, 3 deletions
diff --git a/src/common/x64/native_clock.cpp b/src/common/x64/native_clock.cpp
index 26d4d0ba6..424b39b1f 100644
--- a/src/common/x64/native_clock.cpp
+++ b/src/common/x64/native_clock.cpp
@@ -3,6 +3,7 @@
// Refer to the license.txt file included.
#include <chrono>
+#include <mutex>
#include <thread>
#ifdef _MSC_VER
@@ -52,7 +53,7 @@ NativeClock::NativeClock(u64 emulated_cpu_frequency, u64 emulated_clock_frequenc
}
u64 NativeClock::GetRTSC() {
- rtsc_serialize.lock();
+ std::scoped_lock scope{rtsc_serialize};
_mm_mfence();
const u64 current_measure = __rdtsc();
u64 diff = current_measure - last_measure;
@@ -61,8 +62,15 @@ u64 NativeClock::GetRTSC() {
last_measure = current_measure;
}
accumulated_ticks += diff;
- rtsc_serialize.unlock();
- return accumulated_ticks;
+ /// The clock cannot be more precise than the guest timer, remove the lower bits
+ return accumulated_ticks & inaccuracy_mask;
+}
+
+void NativeClock::Pause(bool is_paused) {
+ if (!is_paused) {
+ _mm_mfence();
+ last_measure = __rdtsc();
+ }
}
std::chrono::nanoseconds NativeClock::GetTimeNS() {
diff --git a/src/common/x64/native_clock.h b/src/common/x64/native_clock.h
index b58cf9f5a..891a3bbfd 100644
--- a/src/common/x64/native_clock.h
+++ b/src/common/x64/native_clock.h
@@ -26,9 +26,16 @@ public:
u64 GetCPUCycles() override;
+ void Pause(bool is_paused) override;
+
private:
u64 GetRTSC();
+ /// value used to reduce the native clocks accuracy as some apss rely on
+ /// undefined behavior where the level of accuracy in the clock shouldn't
+ /// be higher.
+ static constexpr u64 inaccuracy_mask = ~(0x400 - 1);
+
SpinLock rtsc_serialize{};
u64 last_measure{};
u64 accumulated_ticks{};