summaryrefslogtreecommitdiff
path: root/src/common/x64/native_clock.cpp
diff options
context:
space:
mode:
authorGravatar Fernando Sahmkow2021-01-02 02:24:49 +0100
committerGravatar Fernando Sahmkow2021-01-02 04:00:27 +0100
commit53d92318b82cd4a9e08f814fcb8aab624d795c6c (patch)
tree4f5236ffebdcf947297d8ace42151b36810f3144 /src/common/x64/native_clock.cpp
parentX86/NativeClock: Improve performance of clock calculations on hot path. (diff)
downloadyuzu-53d92318b82cd4a9e08f814fcb8aab624d795c6c.tar.gz
yuzu-53d92318b82cd4a9e08f814fcb8aab624d795c6c.tar.xz
yuzu-53d92318b82cd4a9e08f814fcb8aab624d795c6c.zip
X86/NativeClock: Reimplement RTDSC access to be lock free.
Diffstat (limited to '')
-rw-r--r--src/common/x64/native_clock.cpp41
1 files changed, 27 insertions, 14 deletions
diff --git a/src/common/x64/native_clock.cpp b/src/common/x64/native_clock.cpp
index e246432d0..a65f6b832 100644
--- a/src/common/x64/native_clock.cpp
+++ b/src/common/x64/native_clock.cpp
@@ -17,6 +17,7 @@
17#include <x86intrin.h> 17#include <x86intrin.h>
18#endif 18#endif
19 19
20#include "common/atomic_ops.h"
20#include "common/uint128.h" 21#include "common/uint128.h"
21#include "common/x64/native_clock.h" 22#include "common/x64/native_clock.h"
22 23
@@ -102,8 +103,8 @@ NativeClock::NativeClock(u64 emulated_cpu_frequency_, u64 emulated_clock_frequen
102 : WallClock(emulated_cpu_frequency_, emulated_clock_frequency_, true), rtsc_frequency{ 103 : WallClock(emulated_cpu_frequency_, emulated_clock_frequency_, true), rtsc_frequency{
103 rtsc_frequency_} { 104 rtsc_frequency_} {
104 _mm_mfence(); 105 _mm_mfence();
105 last_measure = __rdtsc(); 106 time_point.inner.last_measure = __rdtsc();
106 accumulated_ticks = 0U; 107 time_point.inner.accumulated_ticks = 0U;
107 ns_rtsc_factor = GetFixedPoint64Factor(1000000000, rtsc_frequency); 108 ns_rtsc_factor = GetFixedPoint64Factor(1000000000, rtsc_frequency);
108 us_rtsc_factor = GetFixedPoint64Factor(1000000, rtsc_frequency); 109 us_rtsc_factor = GetFixedPoint64Factor(1000000, rtsc_frequency);
109 ms_rtsc_factor = GetFixedPoint64Factor(1000, rtsc_frequency); 110 ms_rtsc_factor = GetFixedPoint64Factor(1000, rtsc_frequency);
@@ -112,23 +113,35 @@ NativeClock::NativeClock(u64 emulated_cpu_frequency_, u64 emulated_clock_frequen
112} 113}
113 114
114u64 NativeClock::GetRTSC() { 115u64 NativeClock::GetRTSC() {
115 std::scoped_lock scope{rtsc_serialize}; 116 TimePoint new_time_point{};
116 _mm_mfence(); 117 TimePoint current_time_point{};
117 const u64 current_measure = __rdtsc(); 118 do {
118 u64 diff = current_measure - last_measure; 119 current_time_point.pack = time_point.pack;
119 diff = diff & ~static_cast<u64>(static_cast<s64>(diff) >> 63); // max(diff, 0) 120 _mm_mfence();
120 if (current_measure > last_measure) { 121 const u64 current_measure = __rdtsc();
121 last_measure = current_measure; 122 u64 diff = current_measure - current_time_point.inner.last_measure;
122 } 123 diff = diff & ~static_cast<u64>(static_cast<s64>(diff) >> 63); // max(diff, 0)
123 accumulated_ticks += diff; 124 new_time_point.inner.last_measure = current_measure > current_time_point.inner.last_measure
125 ? current_measure
126 : current_time_point.inner.last_measure;
127 new_time_point.inner.accumulated_ticks = current_time_point.inner.accumulated_ticks + diff;
128 } while (!Common::AtomicCompareAndSwap(time_point.pack.data(), new_time_point.pack,
129 current_time_point.pack));
124 /// The clock cannot be more precise than the guest timer, remove the lower bits 130 /// The clock cannot be more precise than the guest timer, remove the lower bits
125 return accumulated_ticks & inaccuracy_mask; 131 return new_time_point.inner.accumulated_ticks & inaccuracy_mask;
126} 132}
127 133
128void NativeClock::Pause(bool is_paused) { 134void NativeClock::Pause(bool is_paused) {
129 if (!is_paused) { 135 if (!is_paused) {
130 _mm_mfence(); 136 TimePoint current_time_point{};
131 last_measure = __rdtsc(); 137 TimePoint new_time_point{};
138 do {
139 current_time_point.pack = time_point.pack;
140 new_time_point.pack = current_time_point.pack;
141 _mm_mfence();
142 new_time_point.inner.last_measure = __rdtsc();
143 } while (!Common::AtomicCompareAndSwap(time_point.pack.data(), new_time_point.pack,
144 current_time_point.pack));
132 } 145 }
133} 146}
134 147