summaryrefslogtreecommitdiff
path: root/src/common/x64/native_clock.cpp
diff options
context:
space:
mode:
authorGravatar merry2022-04-02 21:54:39 +0100
committerGravatar Merry2022-04-03 22:38:10 +0100
commitfdd4d019ef6f37421358ae70f3d5e036857dd758 (patch)
treef1edc3e3a80bbef7463c1ac1b06731528cef7b72 /src/common/x64/native_clock.cpp
parentMerge pull request #8105 from merryhime/atomicload128 (diff)
downloadyuzu-fdd4d019ef6f37421358ae70f3d5e036857dd758.tar.gz
yuzu-fdd4d019ef6f37421358ae70f3d5e036857dd758.tar.xz
yuzu-fdd4d019ef6f37421358ae70f3d5e036857dd758.zip
native_clock: Use lfence with rdtsc
Diffstat (limited to 'src/common/x64/native_clock.cpp')
-rw-r--r--src/common/x64/native_clock.cpp47
1 files changed, 33 insertions, 14 deletions
diff --git a/src/common/x64/native_clock.cpp b/src/common/x64/native_clock.cpp
index 7a3f21dcf..63364f839 100644
--- a/src/common/x64/native_clock.cpp
+++ b/src/common/x64/native_clock.cpp
@@ -10,25 +10,47 @@
10#include "common/uint128.h" 10#include "common/uint128.h"
11#include "common/x64/native_clock.h" 11#include "common/x64/native_clock.h"
12 12
13#ifdef _MSC_VER
14#include <intrin.h>
15#endif
16
13namespace Common { 17namespace Common {
14 18
19inline u64 FencedRDTSC() {
20#ifdef _MSC_VER
21 _mm_lfence();
22 _ReadWriteBarrier();
23 const u64 result = __rdtsc();
24 _mm_lfence();
25 _ReadWriteBarrier();
26 return result;
27#else
28 u64 result;
29 asm volatile("lfence\n\t"
30 "rdtsc\n\t"
31 "shl $32, %%rdx\n\t"
32 "or %%rdx, %0\n\t"
33 "lfence"
34 : "=a"(result)
35 :
36 : "rdx", "memory", "cc");
37 return result;
38#endif
39}
40
15u64 EstimateRDTSCFrequency() { 41u64 EstimateRDTSCFrequency() {
16 // Discard the first result measuring the rdtsc. 42 // Discard the first result measuring the rdtsc.
17 _mm_mfence(); 43 FencedRDTSC();
18 __rdtsc();
19 std::this_thread::sleep_for(std::chrono::milliseconds{1}); 44 std::this_thread::sleep_for(std::chrono::milliseconds{1});
20 _mm_mfence(); 45 FencedRDTSC();
21 __rdtsc();
22 46
23 // Get the current time. 47 // Get the current time.
24 const auto start_time = std::chrono::steady_clock::now(); 48 const auto start_time = std::chrono::steady_clock::now();
25 _mm_mfence(); 49 const u64 tsc_start = FencedRDTSC();
26 const u64 tsc_start = __rdtsc();
27 // Wait for 200 milliseconds. 50 // Wait for 200 milliseconds.
28 std::this_thread::sleep_for(std::chrono::milliseconds{200}); 51 std::this_thread::sleep_for(std::chrono::milliseconds{200});
29 const auto end_time = std::chrono::steady_clock::now(); 52 const auto end_time = std::chrono::steady_clock::now();
30 _mm_mfence(); 53 const u64 tsc_end = FencedRDTSC();
31 const u64 tsc_end = __rdtsc();
32 // Calculate differences. 54 // Calculate differences.
33 const u64 timer_diff = static_cast<u64>( 55 const u64 timer_diff = static_cast<u64>(
34 std::chrono::duration_cast<std::chrono::nanoseconds>(end_time - start_time).count()); 56 std::chrono::duration_cast<std::chrono::nanoseconds>(end_time - start_time).count());
@@ -42,8 +64,7 @@ NativeClock::NativeClock(u64 emulated_cpu_frequency_, u64 emulated_clock_frequen
42 u64 rtsc_frequency_) 64 u64 rtsc_frequency_)
43 : WallClock(emulated_cpu_frequency_, emulated_clock_frequency_, true), rtsc_frequency{ 65 : WallClock(emulated_cpu_frequency_, emulated_clock_frequency_, true), rtsc_frequency{
44 rtsc_frequency_} { 66 rtsc_frequency_} {
45 _mm_mfence(); 67 time_point.inner.last_measure = FencedRDTSC();
46 time_point.inner.last_measure = __rdtsc();
47 time_point.inner.accumulated_ticks = 0U; 68 time_point.inner.accumulated_ticks = 0U;
48 ns_rtsc_factor = GetFixedPoint64Factor(NS_RATIO, rtsc_frequency); 69 ns_rtsc_factor = GetFixedPoint64Factor(NS_RATIO, rtsc_frequency);
49 us_rtsc_factor = GetFixedPoint64Factor(US_RATIO, rtsc_frequency); 70 us_rtsc_factor = GetFixedPoint64Factor(US_RATIO, rtsc_frequency);
@@ -58,8 +79,7 @@ u64 NativeClock::GetRTSC() {
58 79
59 current_time_point.pack = Common::AtomicLoad128(time_point.pack.data()); 80 current_time_point.pack = Common::AtomicLoad128(time_point.pack.data());
60 do { 81 do {
61 _mm_mfence(); 82 const u64 current_measure = FencedRDTSC();
62 const u64 current_measure = __rdtsc();
63 u64 diff = current_measure - current_time_point.inner.last_measure; 83 u64 diff = current_measure - current_time_point.inner.last_measure;
64 diff = diff & ~static_cast<u64>(static_cast<s64>(diff) >> 63); // max(diff, 0) 84 diff = diff & ~static_cast<u64>(static_cast<s64>(diff) >> 63); // max(diff, 0)
65 new_time_point.inner.last_measure = current_measure > current_time_point.inner.last_measure 85 new_time_point.inner.last_measure = current_measure > current_time_point.inner.last_measure
@@ -80,8 +100,7 @@ void NativeClock::Pause(bool is_paused) {
80 current_time_point.pack = Common::AtomicLoad128(time_point.pack.data()); 100 current_time_point.pack = Common::AtomicLoad128(time_point.pack.data());
81 do { 101 do {
82 new_time_point.pack = current_time_point.pack; 102 new_time_point.pack = current_time_point.pack;
83 _mm_mfence(); 103 new_time_point.inner.last_measure = FencedRDTSC();
84 new_time_point.inner.last_measure = __rdtsc();
85 } while (!Common::AtomicCompareAndSwap(time_point.pack.data(), new_time_point.pack, 104 } while (!Common::AtomicCompareAndSwap(time_point.pack.data(), new_time_point.pack,
86 current_time_point.pack, current_time_point.pack)); 105 current_time_point.pack, current_time_point.pack));
87 } 106 }