summaryrefslogtreecommitdiff
path: root/src/common/windows/timer_resolution.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/windows/timer_resolution.cpp')
-rw-r--r--src/common/windows/timer_resolution.cpp87
1 files changed, 87 insertions, 0 deletions
diff --git a/src/common/windows/timer_resolution.cpp b/src/common/windows/timer_resolution.cpp
new file mode 100644
index 000000000..6c2063a4c
--- /dev/null
+++ b/src/common/windows/timer_resolution.cpp
@@ -0,0 +1,87 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include <windows.h>
5
6#include "common/windows/timer_resolution.h"
7
8extern "C" {
9// http://undocumented.ntinternals.net/index.html?page=UserMode%2FUndocumented%20Functions%2FTime%2FNtQueryTimerResolution.html
10NTSYSAPI LONG NTAPI NtQueryTimerResolution(PULONG MinimumResolution, PULONG MaximumResolution,
11 PULONG CurrentResolution);
12
13// http://undocumented.ntinternals.net/index.html?page=UserMode%2FUndocumented%20Functions%2FTime%2FNtSetTimerResolution.html
14NTSYSAPI LONG NTAPI NtSetTimerResolution(ULONG DesiredResolution, BOOLEAN SetResolution,
15 PULONG CurrentResolution);
16
17// http://undocumented.ntinternals.net/index.html?page=UserMode%2FUndocumented%20Functions%2FNT%20Objects%2FThread%2FNtDelayExecution.html
18NTSYSAPI LONG NTAPI NtDelayExecution(BOOLEAN Alertable, PLARGE_INTEGER DelayInterval);
19}
20
21namespace Common::Windows {
22
23namespace {
24
25using namespace std::chrono;
26
27constexpr nanoseconds ToNS(ULONG hundred_ns) {
28 return nanoseconds{hundred_ns * 100};
29}
30
31constexpr ULONG ToHundredNS(nanoseconds ns) {
32 return static_cast<ULONG>(ns.count()) / 100;
33}
34
35struct TimerResolution {
36 std::chrono::nanoseconds minimum;
37 std::chrono::nanoseconds maximum;
38 std::chrono::nanoseconds current;
39};
40
41TimerResolution GetTimerResolution() {
42 ULONG MinimumTimerResolution;
43 ULONG MaximumTimerResolution;
44 ULONG CurrentTimerResolution;
45 NtQueryTimerResolution(&MinimumTimerResolution, &MaximumTimerResolution,
46 &CurrentTimerResolution);
47 return {
48 .minimum{ToNS(MinimumTimerResolution)},
49 .maximum{ToNS(MaximumTimerResolution)},
50 .current{ToNS(CurrentTimerResolution)},
51 };
52}
53
54} // Anonymous namespace
55
56nanoseconds GetMinimumTimerResolution() {
57 return GetTimerResolution().minimum;
58}
59
60nanoseconds GetMaximumTimerResolution() {
61 return GetTimerResolution().maximum;
62}
63
64nanoseconds GetCurrentTimerResolution() {
65 return GetTimerResolution().current;
66}
67
68nanoseconds SetCurrentTimerResolution(nanoseconds timer_resolution) {
69 // Set the timer resolution, and return the current timer resolution.
70 const auto DesiredTimerResolution = ToHundredNS(timer_resolution);
71 ULONG CurrentTimerResolution;
72 NtSetTimerResolution(DesiredTimerResolution, TRUE, &CurrentTimerResolution);
73 return ToNS(CurrentTimerResolution);
74}
75
76nanoseconds SetCurrentTimerResolutionToMaximum() {
77 return SetCurrentTimerResolution(GetMaximumTimerResolution());
78}
79
80void SleepForOneTick() {
81 LARGE_INTEGER DelayInterval{
82 .QuadPart{-1},
83 };
84 NtDelayExecution(FALSE, &DelayInterval);
85}
86
87} // namespace Common::Windows