From 55868f1a335cd3853938082a5b25cfba66563135 Mon Sep 17 00:00:00 2001 From: Dong-hee Na Date: Tue, 16 Nov 2021 22:41:20 +0900 Subject: bpo-45429: Support CREATE_WAITABLE_TIMER_HIGH_RESOLUTION if possible (GH-29203) --- Doc/whatsnew/3.11.rst | 4 +++ .../2021-10-25-01-22-49.bpo-45429.VaEyN9.rst | 2 ++ Modules/timemodule.c | 40 +++++++++++++++++----- 3 files changed, 37 insertions(+), 9 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2021-10-25-01-22-49.bpo-45429.VaEyN9.rst diff --git a/Doc/whatsnew/3.11.rst b/Doc/whatsnew/3.11.rst index 62516d2..0c7c74e 100644 --- a/Doc/whatsnew/3.11.rst +++ b/Doc/whatsnew/3.11.rst @@ -283,6 +283,10 @@ time a resolution of 1 millisecond (10\ :sup:`-3` seconds). (Contributed by Benjamin Szőke and Victor Stinner in :issue:`21302`.) +* On Windows, :func:`time.sleep` now uses a waitable timer which supports high-resolution timers. + In Python 3.10, the best resolution was 1 ms, from Python 3.11 it's now smaller than 1 ms. + (Contributed by Dong-hee Na and Eryk Sun in :issue:`45429`.) + unicodedata ----------- diff --git a/Misc/NEWS.d/next/Library/2021-10-25-01-22-49.bpo-45429.VaEyN9.rst b/Misc/NEWS.d/next/Library/2021-10-25-01-22-49.bpo-45429.VaEyN9.rst new file mode 100644 index 0000000..0a274f1 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-10-25-01-22-49.bpo-45429.VaEyN9.rst @@ -0,0 +1,2 @@ +On Windows, :func:`time.sleep` now uses a waitable timer which supports +high-resolution timers. Patch by Dong-hee Na and Eryk Sun. diff --git a/Modules/timemodule.c b/Modules/timemodule.c index 0ef3b2f..bb71390 100644 --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -408,6 +408,13 @@ static PyStructSequence_Desc struct_time_type_desc = { static int initialized; static PyTypeObject StructTimeType; +#if defined(MS_WINDOWS) +#ifndef CREATE_WAITABLE_TIMER_HIGH_RESOLUTION + #define CREATE_WAITABLE_TIMER_HIGH_RESOLUTION 0x00000002 +#endif + +static DWORD timer_flags = (DWORD)-1; +#endif static PyObject * tmtotuple(struct tm *p @@ -2017,6 +2024,23 @@ time_exec(PyObject *module) utc_string = tm.tm_zone; #endif +#if defined(MS_WINDOWS) + if (timer_flags == (DWORD)-1) { + DWORD test_flags = CREATE_WAITABLE_TIMER_HIGH_RESOLUTION; + HANDLE timer = CreateWaitableTimerExW(NULL, NULL, test_flags, + TIMER_ALL_ACCESS); + if (timer == NULL) { + // CREATE_WAITABLE_TIMER_HIGH_RESOLUTION is not supported. + timer_flags = 0; + } + else { + // CREATE_WAITABLE_TIMER_HIGH_RESOLUTION is supported. + timer_flags = CREATE_WAITABLE_TIMER_HIGH_RESOLUTION; + CloseHandle(timer); + } + } +#endif + return 0; } @@ -2150,20 +2174,18 @@ pysleep(_PyTime_t timeout) // SetWaitableTimer(): a negative due time indicates relative time relative_timeout.QuadPart = -timeout_100ns; - HANDLE timer = CreateWaitableTimerW(NULL, FALSE, NULL); + HANDLE timer = CreateWaitableTimerExW(NULL, NULL, timer_flags, + TIMER_ALL_ACCESS); if (timer == NULL) { PyErr_SetFromWindowsErr(0); return -1; } - if (!SetWaitableTimer(timer, &relative_timeout, - // period: the timer is signaled once - 0, - // no completion routine - NULL, NULL, - // Don't restore a system in suspended power - // conservation mode when the timer is signaled. - FALSE)) + if (!SetWaitableTimerEx(timer, &relative_timeout, + 0, // no period; the timer is signaled once + NULL, NULL, // no completion routine + NULL, // no wake context; do not resume from suspend + 0)) // no tolerable delay for timer coalescing { PyErr_SetFromWindowsErr(0); goto error; -- cgit v0.12