Common: improve native clock.
This commit is contained in:
		| @@ -30,6 +30,10 @@ namespace Common { | ||||
| #else | ||||
|     return _udiv128(r[1], r[0], d, &remainder); | ||||
| #endif | ||||
| #else | ||||
| #ifdef __SIZEOF_INT128__ | ||||
|     const auto product = static_cast<unsigned __int128>(a) * static_cast<unsigned __int128>(b); | ||||
|     return static_cast<u64>(product / d); | ||||
| #else | ||||
|     const u64 diva = a / d; | ||||
|     const u64 moda = a % d; | ||||
| @@ -37,6 +41,7 @@ namespace Common { | ||||
|     const u64 modb = b % d; | ||||
|     return diva * b + moda * divb + moda * modb / d; | ||||
| #endif | ||||
| #endif | ||||
| } | ||||
|  | ||||
| // This function multiplies 2 u64 values and produces a u128 value; | ||||
|   | ||||
| @@ -5,7 +5,6 @@ | ||||
| #include <chrono> | ||||
| #include <thread> | ||||
|  | ||||
| #include "common/atomic_ops.h" | ||||
| #include "common/uint128.h" | ||||
| #include "common/x64/native_clock.h" | ||||
|  | ||||
| @@ -65,8 +64,10 @@ 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_} { | ||||
|     time_point.inner.last_measure = FencedRDTSC(); | ||||
|     time_point.inner.accumulated_ticks = 0U; | ||||
|     TimePoint new_time_point{}; | ||||
|     new_time_point.last_measure = FencedRDTSC(); | ||||
|     new_time_point.accumulated_ticks = 0U; | ||||
|     time_point.store(new_time_point); | ||||
|     ns_rtsc_factor = GetFixedPoint64Factor(NS_RATIO, rtsc_frequency); | ||||
|     us_rtsc_factor = GetFixedPoint64Factor(US_RATIO, rtsc_frequency); | ||||
|     ms_rtsc_factor = GetFixedPoint64Factor(MS_RATIO, rtsc_frequency); | ||||
| @@ -76,34 +77,31 @@ NativeClock::NativeClock(u64 emulated_cpu_frequency_, u64 emulated_clock_frequen | ||||
|  | ||||
| u64 NativeClock::GetRTSC() { | ||||
|     TimePoint new_time_point{}; | ||||
|     TimePoint current_time_point{}; | ||||
|  | ||||
|     current_time_point.pack = Common::AtomicLoad128(time_point.pack.data()); | ||||
|     TimePoint current_time_point = time_point.load(std::memory_order_acquire); | ||||
|     do { | ||||
|         const u64 current_measure = FencedRDTSC(); | ||||
|         u64 diff = current_measure - current_time_point.inner.last_measure; | ||||
|         u64 diff = current_measure - current_time_point.last_measure; | ||||
|         diff = diff & ~static_cast<u64>(static_cast<s64>(diff) >> 63); // max(diff, 0) | ||||
|         new_time_point.inner.last_measure = current_measure > current_time_point.inner.last_measure | ||||
|                                                 ? current_measure | ||||
|                                                 : current_time_point.inner.last_measure; | ||||
|         new_time_point.inner.accumulated_ticks = current_time_point.inner.accumulated_ticks + diff; | ||||
|     } while (!Common::AtomicCompareAndSwap(time_point.pack.data(), new_time_point.pack, | ||||
|                                            current_time_point.pack, current_time_point.pack)); | ||||
|         new_time_point.last_measure = current_measure > current_time_point.last_measure | ||||
|                                           ? current_measure | ||||
|                                           : current_time_point.last_measure; | ||||
|         new_time_point.accumulated_ticks = current_time_point.accumulated_ticks + diff; | ||||
|     } while (!time_point.compare_exchange_weak( | ||||
|         current_time_point, new_time_point, std::memory_order_release, std::memory_order_acquire)); | ||||
|     /// The clock cannot be more precise than the guest timer, remove the lower bits | ||||
|     return new_time_point.inner.accumulated_ticks & inaccuracy_mask; | ||||
|     return new_time_point.accumulated_ticks & inaccuracy_mask; | ||||
| } | ||||
|  | ||||
| void NativeClock::Pause(bool is_paused) { | ||||
|     if (!is_paused) { | ||||
|         TimePoint current_time_point{}; | ||||
|         TimePoint new_time_point{}; | ||||
|  | ||||
|         current_time_point.pack = Common::AtomicLoad128(time_point.pack.data()); | ||||
|         TimePoint current_time_point = time_point.load(std::memory_order_acquire); | ||||
|         do { | ||||
|             new_time_point.pack = current_time_point.pack; | ||||
|             new_time_point.inner.last_measure = FencedRDTSC(); | ||||
|         } while (!Common::AtomicCompareAndSwap(time_point.pack.data(), new_time_point.pack, | ||||
|                                                current_time_point.pack, current_time_point.pack)); | ||||
|             new_time_point = current_time_point; | ||||
|             new_time_point.last_measure = FencedRDTSC(); | ||||
|         } while (!time_point.compare_exchange_weak(current_time_point, new_time_point, | ||||
|                                                    std::memory_order_release, | ||||
|                                                    std::memory_order_acquire)); | ||||
|     } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -3,6 +3,7 @@ | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include <atomic> | ||||
| #include "common/wall_clock.h" | ||||
|  | ||||
| namespace Common { | ||||
| @@ -28,13 +29,9 @@ public: | ||||
| private: | ||||
|     u64 GetRTSC(); | ||||
|  | ||||
|     union alignas(16) TimePoint { | ||||
|         TimePoint() : pack{} {} | ||||
|         u128 pack{}; | ||||
|         struct Inner { | ||||
|             u64 last_measure{}; | ||||
|             u64 accumulated_ticks{}; | ||||
|         } inner; | ||||
|     struct alignas(16) TimePoint { | ||||
|         u64 last_measure{}; | ||||
|         u64 accumulated_ticks{}; | ||||
|     }; | ||||
|  | ||||
|     /// value used to reduce the native clocks accuracy as some apss rely on | ||||
| @@ -42,7 +39,7 @@ private: | ||||
|     /// be higher. | ||||
|     static constexpr u64 inaccuracy_mask = ~(UINT64_C(0x400) - 1); | ||||
|  | ||||
|     TimePoint time_point; | ||||
|     std::atomic<TimePoint> time_point; | ||||
|     // factors | ||||
|     u64 clock_rtsc_factor{}; | ||||
|     u64 cpu_rtsc_factor{}; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user