Skip to content

Commit

Permalink
osdep/timer-win2: use Waitable Timer for sleeping
Browse files Browse the repository at this point in the history
Allows higher resolution sleeps than Sleep which has milliseconds
resolution. In practice Windows kernel does not really go below 0.5ms,
but we don't have to limit ourselves on API side of things and do the
best we can.
  • Loading branch information
kasper93 authored and Dudemanguy committed Oct 8, 2023
1 parent be27145 commit a016025
Showing 1 changed file with 31 additions and 7 deletions.
38 changes: 31 additions & 7 deletions osdep/timer-win2.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,37 @@ void mp_sleep_ns(int64_t ns)
{
if (ns < 0)
return;
// Sleep(0) won't sleep for one clocktick as the unix usleep
// instead it will only make the thread ready
// it may take some time until it actually starts to run again
if (ns < 1e6)
ns = 1e6;
int hrt = mp_start_hires_timers(ns / 1e6);
Sleep(ns / 1e6);

int hrt = mp_start_hires_timers(ns < 1e6 ? 1 : ns / 1e6);

#ifndef CREATE_WAITABLE_TIMER_HIGH_RESOLUTION
#define CREATE_WAITABLE_TIMER_HIGH_RESOLUTION 0x2
#endif

HANDLE timer = CreateWaitableTimerEx(NULL, NULL,
CREATE_WAITABLE_TIMER_HIGH_RESOLUTION,
TIMER_ALL_ACCESS);

// CREATE_WAITABLE_TIMER_HIGH_RESOLUTION is supported in Windows 10 1803+,
// retry without it.
if (!timer)
timer = CreateWaitableTimerEx(NULL, NULL, 0, TIMER_ALL_ACCESS);

if (!timer)
goto end;

// Time is expected in 100 nanosecond intervals.
// Negative values indicate relative time.
LARGE_INTEGER time = (LARGE_INTEGER){ .QuadPart = -(ns / 100) };
if (!SetWaitableTimer(timer, &time, 0, NULL, NULL, 0))
goto end;

if (WaitForSingleObject(timer, INFINITE) != WAIT_OBJECT_0)
goto end;

end:
if (timer)
CloseHandle(timer);
mp_end_hires_timers(hrt);
}

Expand Down

0 comments on commit a016025

Please sign in to comment.