summaryrefslogtreecommitdiff
path: root/Source/Core/Common/Timer.cpp
diff options
context:
space:
mode:
authorJMC47 <JMC4789@gmail.com>2025-08-28 13:58:26 -0400
committerGitHub <noreply@github.com>2025-08-28 13:58:26 -0400
commite0c72cd963bbde29f01fa33b06c22f7dff871e5d (patch)
tree3cbd60189a9aa5aa6174ac3ad7cb91027b6b481a /Source/Core/Common/Timer.cpp
parentdce27fb58a9f071c707ad31085611cc3d72bad33 (diff)
parent81ebf45c9ba652083446929eea551dc8ba2f05be (diff)
Merge pull request #13825 from jordan-woyak/dont-count-playtime-while-suspended
Common/Timer: Add a SteadyAwakeClock class to make play time tracking ignore time while suspended.
Diffstat (limited to 'Source/Core/Common/Timer.cpp')
-rw-r--r--Source/Core/Common/Timer.cpp34
1 files changed, 34 insertions, 0 deletions
diff --git a/Source/Core/Common/Timer.cpp b/Source/Core/Common/Timer.cpp
index 0a23080c6f..0e260b833c 100644
--- a/Source/Core/Common/Timer.cpp
+++ b/Source/Core/Common/Timer.cpp
@@ -5,6 +5,7 @@
#include <chrono>
#include <thread>
+#include "Common/CommonFuncs.h"
#ifdef _WIN32
#include <Windows.h>
@@ -194,4 +195,37 @@ void PrecisionTimer::SleepUntil(Clock::time_point target)
}
}
+// Results are appropriately slewed on Linux, but not on Windows, macOS, or FreeBSD.
+// Clocks with that functionality seem to not be available there.
+auto SteadyAwakeClock::now() -> time_point
+{
+#if defined(_WIN32)
+ // The count is system time "in units of 100 nanoseconds".
+ using InterruptDuration = std::chrono::duration<ULONGLONG, std::ratio<100, std::nano::den>::type>;
+
+ ULONGLONG interrupt_time{};
+ if (!QueryUnbiasedInterruptTime(&interrupt_time))
+ ERROR_LOG_FMT(COMMON, "QueryUnbiasedInterruptTime");
+
+ return time_point{InterruptDuration{interrupt_time}};
+#else
+ // Note that Linux's CLOCK_MONOTONIC "does not count time that the system is suspended".
+ // This is in contrast to the behavior on macOS and FreeBSD.
+ static constexpr auto clock_id =
+#if defined(__linux__)
+ CLOCK_MONOTONIC;
+#elif defined(__APPLE__)
+ CLOCK_UPTIME_RAW;
+#else
+ CLOCK_UPTIME;
+#endif
+
+ timespec ts{};
+ if (clock_gettime(clock_id, &ts) != 0)
+ ERROR_LOG_FMT(COMMON, "clock_gettime: {}", LastStrerrorString());
+
+ return time_point{std::chrono::seconds{ts.tv_sec} + std::chrono::nanoseconds{ts.tv_nsec}};
+#endif
+}
+
} // Namespace Common