bpo-45429: Support CREATE_WAITABLE_TIMER_HIGH_RESOLUTION if possible (GH-29203)

This commit is contained in:
Dong-hee Na 2021-11-16 22:41:20 +09:00 committed by GitHub
parent 8b06d01507
commit 55868f1a33
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 37 additions and 9 deletions

View File

@ -283,6 +283,10 @@ time
a resolution of 1 millisecond (10\ :sup:`-3` seconds). a resolution of 1 millisecond (10\ :sup:`-3` seconds).
(Contributed by Benjamin Szőke and Victor Stinner in :issue:`21302`.) (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 unicodedata
----------- -----------

View File

@ -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.

View File

@ -408,6 +408,13 @@ static PyStructSequence_Desc struct_time_type_desc = {
static int initialized; static int initialized;
static PyTypeObject StructTimeType; 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 * static PyObject *
tmtotuple(struct tm *p tmtotuple(struct tm *p
@ -2017,6 +2024,23 @@ time_exec(PyObject *module)
utc_string = tm.tm_zone; utc_string = tm.tm_zone;
#endif #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; return 0;
} }
@ -2150,20 +2174,18 @@ pysleep(_PyTime_t timeout)
// SetWaitableTimer(): a negative due time indicates relative time // SetWaitableTimer(): a negative due time indicates relative time
relative_timeout.QuadPart = -timeout_100ns; relative_timeout.QuadPart = -timeout_100ns;
HANDLE timer = CreateWaitableTimerW(NULL, FALSE, NULL); HANDLE timer = CreateWaitableTimerExW(NULL, NULL, timer_flags,
TIMER_ALL_ACCESS);
if (timer == NULL) { if (timer == NULL) {
PyErr_SetFromWindowsErr(0); PyErr_SetFromWindowsErr(0);
return -1; return -1;
} }
if (!SetWaitableTimer(timer, &relative_timeout, if (!SetWaitableTimerEx(timer, &relative_timeout,
// period: the timer is signaled once 0, // no period; the timer is signaled once
0, NULL, NULL, // no completion routine
// no completion routine NULL, // no wake context; do not resume from suspend
NULL, NULL, 0)) // no tolerable delay for timer coalescing
// Don't restore a system in suspended power
// conservation mode when the timer is signaled.
FALSE))
{ {
PyErr_SetFromWindowsErr(0); PyErr_SetFromWindowsErr(0);
goto error; goto error;