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).
(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
-----------

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 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;