From: Dong-hee Na Date: Tue, 16 Nov 2021 13:41:20 +0000 (+0900) Subject: bpo-45429: Support CREATE_WAITABLE_TIMER_HIGH_RESOLUTION if possible (GH-29203) X-Git-Tag: v3.11.0a3~238 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=55868f1a335cd3853938082a5b25cfba66563135;p=thirdparty%2FPython%2Fcpython.git bpo-45429: Support CREATE_WAITABLE_TIMER_HIGH_RESOLUTION if possible (GH-29203) --- diff --git a/Doc/whatsnew/3.11.rst b/Doc/whatsnew/3.11.rst index 62516d207d0b..0c7c74e7c324 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 000000000000..0a274f1ef8ab --- /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 0ef3b2ffaa89..bb713908eb1e 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;