summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKacper Michajłow <kasper93@gmail.com>2023-07-29 14:07:03 +0200
committerDudemanguy <random342@airmail.cc>2023-10-10 19:10:55 +0000
commita27d402f37e6b85ab5b8ec5561b7180f0a71a9ba (patch)
tree5d70ea470383fabe375408ca961dddeb4eda1de2
parent59dd7d94af7651baf7e60966c5f8e7d52959d958 (diff)
downloadmpv-a27d402f37e6b85ab5b8ec5561b7180f0a71a9ba.tar.bz2
mpv-a27d402f37e6b85ab5b8ec5561b7180f0a71a9ba.tar.xz
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.
-rw-r--r--osdep/timer-win2.c38
1 files changed, 31 insertions, 7 deletions
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);
}