summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDong-hee Na <donghee.na@python.org>2021-11-16 13:41:20 (GMT)
committerGitHub <noreply@github.com>2021-11-16 13:41:20 (GMT)
commit55868f1a335cd3853938082a5b25cfba66563135 (patch)
treed20d02ea465f12080bba5c2934609eee146c9dd4
parent8b06d01507fd708468570eaa43a349828784489a (diff)
downloadcpython-55868f1a335cd3853938082a5b25cfba66563135.zip
cpython-55868f1a335cd3853938082a5b25cfba66563135.tar.gz
cpython-55868f1a335cd3853938082a5b25cfba66563135.tar.bz2
bpo-45429: Support CREATE_WAITABLE_TIMER_HIGH_RESOLUTION if possible (GH-29203)
-rw-r--r--Doc/whatsnew/3.11.rst4
-rw-r--r--Misc/NEWS.d/next/Library/2021-10-25-01-22-49.bpo-45429.VaEyN9.rst2
-rw-r--r--Modules/timemodule.c40
3 files changed, 37 insertions, 9 deletions
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;