diff options
| author | 2021-11-23 03:29:00 +0100 | |
|---|---|---|
| committer | 2022-06-28 01:06:48 +0200 | |
| commit | 096366ead51345bcd170e31b6160b14aaf73e996 (patch) | |
| tree | db99c0d032466f4bd94871baaecf0544fec82f25 /src | |
| parent | Merge pull request #8504 from comex/mesosphere-current-process (diff) | |
| download | yuzu-096366ead51345bcd170e31b6160b14aaf73e996.tar.gz yuzu-096366ead51345bcd170e31b6160b14aaf73e996.tar.xz yuzu-096366ead51345bcd170e31b6160b14aaf73e996.zip | |
Common: improve native clock.
Diffstat (limited to 'src')
| -rw-r--r-- | src/common/uint128.h | 5 | ||||
| -rw-r--r-- | src/common/x64/native_clock.cpp | 40 | ||||
| -rw-r--r-- | src/common/x64/native_clock.h | 13 |
3 files changed, 29 insertions, 29 deletions
diff --git a/src/common/uint128.h b/src/common/uint128.h index f890ffec2..199d0f55e 100644 --- a/src/common/uint128.h +++ b/src/common/uint128.h | |||
| @@ -31,12 +31,17 @@ namespace Common { | |||
| 31 | return _udiv128(r[1], r[0], d, &remainder); | 31 | return _udiv128(r[1], r[0], d, &remainder); |
| 32 | #endif | 32 | #endif |
| 33 | #else | 33 | #else |
| 34 | #ifdef __SIZEOF_INT128__ | ||
| 35 | const auto product = static_cast<unsigned __int128>(a) * static_cast<unsigned __int128>(b); | ||
| 36 | return static_cast<u64>(product / d); | ||
| 37 | #else | ||
| 34 | const u64 diva = a / d; | 38 | const u64 diva = a / d; |
| 35 | const u64 moda = a % d; | 39 | const u64 moda = a % d; |
| 36 | const u64 divb = b / d; | 40 | const u64 divb = b / d; |
| 37 | const u64 modb = b % d; | 41 | const u64 modb = b % d; |
| 38 | return diva * b + moda * divb + moda * modb / d; | 42 | return diva * b + moda * divb + moda * modb / d; |
| 39 | #endif | 43 | #endif |
| 44 | #endif | ||
| 40 | } | 45 | } |
| 41 | 46 | ||
| 42 | // This function multiplies 2 u64 values and produces a u128 value; | 47 | // This function multiplies 2 u64 values and produces a u128 value; |
diff --git a/src/common/x64/native_clock.cpp b/src/common/x64/native_clock.cpp index 1b7194503..427a382cd 100644 --- a/src/common/x64/native_clock.cpp +++ b/src/common/x64/native_clock.cpp | |||
| @@ -5,7 +5,6 @@ | |||
| 5 | #include <chrono> | 5 | #include <chrono> |
| 6 | #include <thread> | 6 | #include <thread> |
| 7 | 7 | ||
| 8 | #include "common/atomic_ops.h" | ||
| 9 | #include "common/uint128.h" | 8 | #include "common/uint128.h" |
| 10 | #include "common/x64/native_clock.h" | 9 | #include "common/x64/native_clock.h" |
| 11 | 10 | ||
| @@ -65,8 +64,10 @@ NativeClock::NativeClock(u64 emulated_cpu_frequency_, u64 emulated_clock_frequen | |||
| 65 | u64 rtsc_frequency_) | 64 | u64 rtsc_frequency_) |
| 66 | : WallClock(emulated_cpu_frequency_, emulated_clock_frequency_, true), rtsc_frequency{ | 65 | : WallClock(emulated_cpu_frequency_, emulated_clock_frequency_, true), rtsc_frequency{ |
| 67 | rtsc_frequency_} { | 66 | rtsc_frequency_} { |
| 68 | time_point.inner.last_measure = FencedRDTSC(); | 67 | TimePoint new_time_point{}; |
| 69 | time_point.inner.accumulated_ticks = 0U; | 68 | new_time_point.last_measure = FencedRDTSC(); |
| 69 | new_time_point.accumulated_ticks = 0U; | ||
| 70 | time_point.store(new_time_point); | ||
| 70 | ns_rtsc_factor = GetFixedPoint64Factor(NS_RATIO, rtsc_frequency); | 71 | ns_rtsc_factor = GetFixedPoint64Factor(NS_RATIO, rtsc_frequency); |
| 71 | us_rtsc_factor = GetFixedPoint64Factor(US_RATIO, rtsc_frequency); | 72 | us_rtsc_factor = GetFixedPoint64Factor(US_RATIO, rtsc_frequency); |
| 72 | ms_rtsc_factor = GetFixedPoint64Factor(MS_RATIO, rtsc_frequency); | 73 | ms_rtsc_factor = GetFixedPoint64Factor(MS_RATIO, rtsc_frequency); |
| @@ -76,34 +77,31 @@ NativeClock::NativeClock(u64 emulated_cpu_frequency_, u64 emulated_clock_frequen | |||
| 76 | 77 | ||
| 77 | u64 NativeClock::GetRTSC() { | 78 | u64 NativeClock::GetRTSC() { |
| 78 | TimePoint new_time_point{}; | 79 | TimePoint new_time_point{}; |
| 79 | TimePoint current_time_point{}; | 80 | TimePoint current_time_point = time_point.load(std::memory_order_acquire); |
| 80 | |||
| 81 | current_time_point.pack = Common::AtomicLoad128(time_point.pack.data()); | ||
| 82 | do { | 81 | do { |
| 83 | const u64 current_measure = FencedRDTSC(); | 82 | const u64 current_measure = FencedRDTSC(); |
| 84 | u64 diff = current_measure - current_time_point.inner.last_measure; | 83 | u64 diff = current_measure - current_time_point.last_measure; |
| 85 | 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) |
| 86 | new_time_point.inner.last_measure = current_measure > current_time_point.inner.last_measure | 85 | new_time_point.last_measure = current_measure > current_time_point.last_measure |
| 87 | ? current_measure | 86 | ? current_measure |
| 88 | : current_time_point.inner.last_measure; | 87 | : current_time_point.last_measure; |
| 89 | new_time_point.inner.accumulated_ticks = current_time_point.inner.accumulated_ticks + diff; | 88 | new_time_point.accumulated_ticks = current_time_point.accumulated_ticks + diff; |
| 90 | } while (!Common::AtomicCompareAndSwap(time_point.pack.data(), new_time_point.pack, | 89 | } while (!time_point.compare_exchange_weak( |
| 91 | current_time_point.pack, current_time_point.pack)); | 90 | current_time_point, new_time_point, std::memory_order_release, std::memory_order_acquire)); |
| 92 | /// The clock cannot be more precise than the guest timer, remove the lower bits | 91 | /// The clock cannot be more precise than the guest timer, remove the lower bits |
| 93 | return new_time_point.inner.accumulated_ticks & inaccuracy_mask; | 92 | return new_time_point.accumulated_ticks & inaccuracy_mask; |
| 94 | } | 93 | } |
| 95 | 94 | ||
| 96 | void NativeClock::Pause(bool is_paused) { | 95 | void NativeClock::Pause(bool is_paused) { |
| 97 | if (!is_paused) { | 96 | if (!is_paused) { |
| 98 | TimePoint current_time_point{}; | ||
| 99 | TimePoint new_time_point{}; | 97 | TimePoint new_time_point{}; |
| 100 | 98 | TimePoint current_time_point = time_point.load(std::memory_order_acquire); | |
| 101 | current_time_point.pack = Common::AtomicLoad128(time_point.pack.data()); | ||
| 102 | do { | 99 | do { |
| 103 | new_time_point.pack = current_time_point.pack; | 100 | new_time_point = current_time_point; |
| 104 | new_time_point.inner.last_measure = FencedRDTSC(); | 101 | new_time_point.last_measure = FencedRDTSC(); |
| 105 | } while (!Common::AtomicCompareAndSwap(time_point.pack.data(), new_time_point.pack, | 102 | } while (!time_point.compare_exchange_weak(current_time_point, new_time_point, |
| 106 | current_time_point.pack, current_time_point.pack)); | 103 | std::memory_order_release, |
| 104 | std::memory_order_acquire)); | ||
| 107 | } | 105 | } |
| 108 | } | 106 | } |
| 109 | 107 | ||
diff --git a/src/common/x64/native_clock.h b/src/common/x64/native_clock.h index 30d2ba2e9..e57446cb9 100644 --- a/src/common/x64/native_clock.h +++ b/src/common/x64/native_clock.h | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | 3 | ||
| 4 | #pragma once | 4 | #pragma once |
| 5 | 5 | ||
| 6 | #include <atomic> | ||
| 6 | #include "common/wall_clock.h" | 7 | #include "common/wall_clock.h" |
| 7 | 8 | ||
| 8 | namespace Common { | 9 | namespace Common { |
| @@ -28,13 +29,9 @@ public: | |||
| 28 | private: | 29 | private: |
| 29 | u64 GetRTSC(); | 30 | u64 GetRTSC(); |
| 30 | 31 | ||
| 31 | union alignas(16) TimePoint { | 32 | struct alignas(16) TimePoint { |
| 32 | TimePoint() : pack{} {} | 33 | u64 last_measure{}; |
| 33 | u128 pack{}; | 34 | u64 accumulated_ticks{}; |
| 34 | struct Inner { | ||
| 35 | u64 last_measure{}; | ||
| 36 | u64 accumulated_ticks{}; | ||
| 37 | } inner; | ||
| 38 | }; | 35 | }; |
| 39 | 36 | ||
| 40 | /// value used to reduce the native clocks accuracy as some apss rely on | 37 | /// value used to reduce the native clocks accuracy as some apss rely on |
| @@ -42,7 +39,7 @@ private: | |||
| 42 | /// be higher. | 39 | /// be higher. |
| 43 | static constexpr u64 inaccuracy_mask = ~(UINT64_C(0x400) - 1); | 40 | static constexpr u64 inaccuracy_mask = ~(UINT64_C(0x400) - 1); |
| 44 | 41 | ||
| 45 | TimePoint time_point; | 42 | std::atomic<TimePoint> time_point; |
| 46 | // factors | 43 | // factors |
| 47 | u64 clock_rtsc_factor{}; | 44 | u64 clock_rtsc_factor{}; |
| 48 | u64 cpu_rtsc_factor{}; | 45 | u64 cpu_rtsc_factor{}; |