osdep/timer-win2: use Waitable Timer for sleeping

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.
This commit is contained in:
Kacper Michajłow 2023-07-29 14:07:03 +02:00 committed by Dudemanguy
parent 59dd7d94af
commit a27d402f37
1 changed files with 31 additions and 7 deletions

View File

@ -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);
}