summaryrefslogtreecommitdiff
path: root/src/common/steady_clock.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/steady_clock.cpp')
-rw-r--r--src/common/steady_clock.cpp80
1 files changed, 80 insertions, 0 deletions
diff --git a/src/common/steady_clock.cpp b/src/common/steady_clock.cpp
new file mode 100644
index 000000000..9415eed29
--- /dev/null
+++ b/src/common/steady_clock.cpp
@@ -0,0 +1,80 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#if defined(_WIN32)
5#include <windows.h>
6#else
7#include <time.h>
8#endif
9
10#include "common/steady_clock.h"
11
12namespace Common {
13
14#ifdef _WIN32
15static s64 WindowsQueryPerformanceFrequency() {
16 LARGE_INTEGER frequency;
17 QueryPerformanceFrequency(&frequency);
18 return frequency.QuadPart;
19}
20
21static s64 WindowsQueryPerformanceCounter() {
22 LARGE_INTEGER counter;
23 QueryPerformanceCounter(&counter);
24 return counter.QuadPart;
25}
26
27static s64 GetSystemTimeNS() {
28 // GetSystemTimePreciseAsFileTime returns the file time in 100ns units.
29 static constexpr s64 Multiplier = 100;
30 // Convert Windows epoch to Unix epoch.
31 static constexpr s64 WindowsEpochToUnixEpoch = 0x19DB1DED53E8000LL;
32
33 FILETIME filetime;
34 GetSystemTimePreciseAsFileTime(&filetime);
35 return Multiplier * ((static_cast<s64>(filetime.dwHighDateTime) << 32) +
36 static_cast<s64>(filetime.dwLowDateTime) - WindowsEpochToUnixEpoch);
37}
38#endif
39
40SteadyClock::time_point SteadyClock::Now() noexcept {
41#if defined(_WIN32)
42 static const auto freq = WindowsQueryPerformanceFrequency();
43 const auto counter = WindowsQueryPerformanceCounter();
44
45 // 10 MHz is a very common QPC frequency on modern PCs.
46 // Optimizing for this specific frequency can double the performance of
47 // this function by avoiding the expensive frequency conversion path.
48 static constexpr s64 TenMHz = 10'000'000;
49
50 if (freq == TenMHz) [[likely]] {
51 static_assert(period::den % TenMHz == 0);
52 static constexpr s64 Multiplier = period::den / TenMHz;
53 return time_point{duration{counter * Multiplier}};
54 }
55
56 const auto whole = (counter / freq) * period::den;
57 const auto part = (counter % freq) * period::den / freq;
58 return time_point{duration{whole + part}};
59#elif defined(__APPLE__)
60 return time_point{duration{clock_gettime_nsec_np(CLOCK_MONOTONIC_RAW)}};
61#else
62 timespec ts;
63 clock_gettime(CLOCK_MONOTONIC, &ts);
64 return time_point{std::chrono::seconds{ts.tv_sec} + std::chrono::nanoseconds{ts.tv_nsec}};
65#endif
66}
67
68RealTimeClock::time_point RealTimeClock::Now() noexcept {
69#if defined(_WIN32)
70 return time_point{duration{GetSystemTimeNS()}};
71#elif defined(__APPLE__)
72 return time_point{duration{clock_gettime_nsec_np(CLOCK_REALTIME)}};
73#else
74 timespec ts;
75 clock_gettime(CLOCK_REALTIME, &ts);
76 return time_point{std::chrono::seconds{ts.tv_sec} + std::chrono::nanoseconds{ts.tv_nsec}};
77#endif
78}
79
80}; // namespace Common