diff --git a/osdep/timer-win2.c b/osdep/timer-win2.c index db4c39d7ef..7867b5a525 100644 --- a/osdep/timer-win2.c +++ b/osdep/timer-win2.c @@ -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); }