Skip to content

Commit

Permalink
Maximize timer precision on Windows
Browse files Browse the repository at this point in the history
  • Loading branch information
ns6089 committed Jul 7, 2024
1 parent 374485e commit b650400
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 4 deletions.
1 change: 1 addition & 0 deletions cmake/compile_definitions/windows.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ list(PREPEND PLATFORM_LIBRARIES
libstdc++.a
libwinpthread.a
libssp.a
ntdll
ksuser
wsock32
ws2_32
Expand Down
55 changes: 51 additions & 4 deletions src/platform/windows/misc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,38 @@
#define WLAN_API_MAKE_VERSION(_major, _minor) (((DWORD) (_minor)) << 16 | (_major))
#endif

#include <winternl.h>
extern "C" {
NTSTATUS NTAPI
NtSetTimerResolution(ULONG DesiredResolution, BOOLEAN SetResolution, PULONG CurrentResolution);
}

namespace {

std::atomic<bool> used_nt_set_timer_resolution = false;

bool
nt_set_timer_resolution_max() {
ULONG minimum, maximum, current;
if (!NT_SUCCESS(NtQueryTimerResolution(&minimum, &maximum, &current)) ||
!NT_SUCCESS(NtSetTimerResolution(maximum, TRUE, &current))) {
return false;
}
return true;
}

bool
nt_set_timer_resolution_min() {
ULONG minimum, maximum, current;
if (!NT_SUCCESS(NtQueryTimerResolution(&minimum, &maximum, &current)) ||
!NT_SUCCESS(NtSetTimerResolution(minimum, TRUE, &current))) {
return false;
}
return true;
}

} // namespace

namespace bp = boost::process;

using namespace std::literals;
Expand Down Expand Up @@ -1115,8 +1147,15 @@ namespace platf {
// Enable MMCSS scheduling for DWM
DwmEnableMMCSS(true);

// Reduce timer period to 1ms
timeBeginPeriod(1);
// Reduce timer period to 0.5ms
if (nt_set_timer_resolution_max()) {
used_nt_set_timer_resolution = true;
}
else {
BOOST_LOG(error) << "NtSetTimerResolution() failed, falling back to timeBeginPeriod()";
timeBeginPeriod(1);
used_nt_set_timer_resolution = false;
}

// Promote ourselves to high priority class
SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);
Expand Down Expand Up @@ -1199,8 +1238,16 @@ namespace platf {
// Demote ourselves back to normal priority class
SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);

// End our 1ms timer request
timeEndPeriod(1);
// End our 0.5ms timer request
if (used_nt_set_timer_resolution) {
used_nt_set_timer_resolution = false;
if (!nt_set_timer_resolution_min()) {
BOOST_LOG(error) << "nt_set_timer_resolution_min() failed even though nt_set_timer_resolution_max() succeeded";
}
}
else {
timeEndPeriod(1);
}

// Disable MMCSS scheduling for DWM
DwmEnableMMCSS(false);
Expand Down

0 comments on commit b650400

Please sign in to comment.