From b337f2a3da09fbe654b5b224bec56e8d7e8249e2 Mon Sep 17 00:00:00 2001 From: rdb Date: Mon, 16 Sep 2024 21:42:28 +0200 Subject: [PATCH] pipeline: Use a high-precision timer for Thread::sleep() on Win32 This is mainly used for clock mode M_limited, which is currently suffering from terrible imprecision on Windows. This fixes that, making it possible to lower the value of sleep-precision down to 1ms. --- panda/src/pipeline/threadWin32Impl.I | 8 -------- panda/src/pipeline/threadWin32Impl.cxx | 26 ++++++++++++++++++++++++++ panda/src/pipeline/threadWin32Impl.h | 3 ++- 3 files changed, 28 insertions(+), 9 deletions(-) diff --git a/panda/src/pipeline/threadWin32Impl.I b/panda/src/pipeline/threadWin32Impl.I index ca236b78f0..809da14418 100644 --- a/panda/src/pipeline/threadWin32Impl.I +++ b/panda/src/pipeline/threadWin32Impl.I @@ -63,14 +63,6 @@ is_simple_threads() { return false; } -/** - * - */ -INLINE void ThreadWin32Impl:: -sleep(double seconds) { - Sleep((int)(seconds * 1000)); -} - /** * */ diff --git a/panda/src/pipeline/threadWin32Impl.cxx b/panda/src/pipeline/threadWin32Impl.cxx index c8653a4f5c..588704d225 100644 --- a/panda/src/pipeline/threadWin32Impl.cxx +++ b/panda/src/pipeline/threadWin32Impl.cxx @@ -78,6 +78,11 @@ ThreadWin32Impl:: } CloseHandle(_thread); + + if (_timer != nullptr) { + CloseHandle(_timer); + _timer = nullptr; + } } /** @@ -200,6 +205,27 @@ bind_thread(Thread *thread) { return thread; } + +/** + * + */ +void ThreadWin32Impl:: +sleep(double seconds) { + Thread *thread = get_current_thread(); + ThreadWin32Impl *self = &thread->_impl; + + HANDLE timer = self->_timer; + if (timer == nullptr) { + timer = CreateWaitableTimerExW(nullptr, nullptr, CREATE_WAITABLE_TIMER_MANUAL_RESET | CREATE_WAITABLE_TIMER_HIGH_RESOLUTION, TIMER_ALL_ACCESS); + self->_timer = timer; + } + + LARGE_INTEGER ft; + ft.QuadPart = seconds * -10000000LL; + SetWaitableTimer(timer, &ft, 0, nullptr, nullptr, 0); + WaitForSingleObject(timer, INFINITE); +} + /** * Returns the number of context switches that occurred on the current thread. * The first number is the total number of context switches reported by the OS, diff --git a/panda/src/pipeline/threadWin32Impl.h b/panda/src/pipeline/threadWin32Impl.h index 1d62320789..a5528e5588 100644 --- a/panda/src/pipeline/threadWin32Impl.h +++ b/panda/src/pipeline/threadWin32Impl.h @@ -48,7 +48,7 @@ public: INLINE static bool is_threading_supported(); INLINE static bool is_true_threads(); INLINE static bool is_simple_threads(); - INLINE static void sleep(double seconds); + static void sleep(double seconds); INLINE static void yield(); INLINE static void consider_yield(); @@ -72,6 +72,7 @@ private: bool _joinable; Status _status; HANDLE _profiling; + HANDLE _timer = nullptr; }; #include "threadWin32Impl.I"