From 55faeb62db685a289f4148af6cea32e5c6b4458f Mon Sep 17 00:00:00 2001 From: Livius Date: Wed, 1 Sep 2021 14:41:10 +0200 Subject: [PATCH 01/57] clock_nanosleep() implementation for time.sleep() clock_nanosleep() is available in Linux which has POSIX 2001.12 or newer --- Modules/timemodule.c | 14 +++++++++++ configure | 58 ++++++++++++++++++++++++++++++++++++++++++++ configure.ac | 6 +++++ pyconfig.h.in | 3 +++ 4 files changed, 81 insertions(+) diff --git a/Modules/timemodule.c b/Modules/timemodule.c index 4caacc3b64d7c8..239942e121371a 100644 --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -2053,7 +2053,11 @@ pysleep(_PyTime_t secs) { _PyTime_t deadline, monotonic; #ifndef MS_WINDOWS +#ifdef HAVE_CLOCK_NANOSLEEP + struct timespec timeout_abs; +#else struct timeval timeout; +#endif int err = 0; #else _PyTime_t millisecs; @@ -2066,14 +2070,24 @@ pysleep(_PyTime_t secs) return -1; } deadline = monotonic + secs; +#ifdef HAVE_CLOCK_NANOSLEEP + if (_PyTime_AsTimespec(deadline, &timeout_abs) < 0) + return -1; +#endif do { #ifndef MS_WINDOWS +#ifndef HAVE_CLOCK_NANOSLEEP if (_PyTime_AsTimeval(secs, &timeout, _PyTime_ROUND_CEILING) < 0) return -1; +#endif Py_BEGIN_ALLOW_THREADS +#ifdef HAVE_CLOCK_NANOSLEEP + err = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &timeout_abs, NULL); +#else err = select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &timeout); +#endif Py_END_ALLOW_THREADS if (err == 0) diff --git a/configure b/configure index 050f1836011143..787daa54d7793c 100755 --- a/configure +++ b/configure @@ -13237,6 +13237,64 @@ fi done +for ac_func in clock_nanosleep +do : + ac_fn_c_check_func "$LINENO" "clock_nanosleep" "ac_cv_func_clock_nanosleep" +if test "x$ac_cv_func_clock_nanosleep" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_CLOCK_NANOSLEEP 1 +_ACEOF + +else + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for clock_nanosleep in -lrt" >&5 +$as_echo_n "checking for clock_nanosleep in -lrt... " >&6; } +if ${ac_cv_lib_rt_clock_nanosleep+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lrt $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char clock_nanosleep (); +int +main () +{ +return clock_nanosleep (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_rt_clock_nanosleep=yes +else + ac_cv_lib_rt_clock_nanosleep=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rt_clock_nanosleep" >&5 +$as_echo "$ac_cv_lib_rt_clock_nanosleep" >&6; } +if test "x$ac_cv_lib_rt_clock_nanosleep" = xyes; then : + + $as_echo "#define HAVE_CLOCK_NANOSLEEP 1" >>confdefs.h + + +fi + + +fi +done + + for ac_func in clock_getres do : ac_fn_c_check_func "$LINENO" "clock_getres" "ac_cv_func_clock_getres" diff --git a/configure.ac b/configure.ac index aaff79f720e3c4..3b01f657db57d8 100644 --- a/configure.ac +++ b/configure.ac @@ -4086,6 +4086,12 @@ AC_CHECK_FUNCS(clock_gettime, [], [ ]) ]) +AC_CHECK_FUNCS(clock_nanosleep, [], [ + AC_CHECK_LIB(rt, clock_nanosleep, [ + AC_DEFINE(HAVE_CLOCK_NANOSLEEP, 1) + ]) +]) + AC_CHECK_FUNCS(clock_getres, [], [ AC_CHECK_LIB(rt, clock_getres, [ AC_DEFINE(HAVE_CLOCK_GETRES, 1) diff --git a/pyconfig.h.in b/pyconfig.h.in index 63438d857a070c..9d157970b3151f 100644 --- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -136,6 +136,9 @@ /* Define to 1 if you have the `clock' function. */ #undef HAVE_CLOCK +/* Define to 1 if you have the `clock_nanosleep' function. */ +#undef HAVE_CLOCK_NANOSLEEP + /* Define to 1 if you have the `clock_getres' function. */ #undef HAVE_CLOCK_GETRES From c7bae3b97388116ea48fab99c2a8de866ff4d3ce Mon Sep 17 00:00:00 2001 From: Livius Date: Wed, 1 Sep 2021 16:35:40 +0200 Subject: [PATCH 02/57] Follow PEP 7 rules in time.sleep() PEP 7 rules appled for _PyTime_AsTimespec and _PyTime_AsTimeval error checking in pysleep(). --- Modules/timemodule.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Modules/timemodule.c b/Modules/timemodule.c index 239942e121371a..05844b7ee537c7 100644 --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -2072,14 +2072,18 @@ pysleep(_PyTime_t secs) deadline = monotonic + secs; #ifdef HAVE_CLOCK_NANOSLEEP if (_PyTime_AsTimespec(deadline, &timeout_abs) < 0) + { return -1; + } #endif do { #ifndef MS_WINDOWS #ifndef HAVE_CLOCK_NANOSLEEP if (_PyTime_AsTimeval(secs, &timeout, _PyTime_ROUND_CEILING) < 0) + { return -1; + } #endif Py_BEGIN_ALLOW_THREADS From b3a5c5f113e77c73f3018d4078ba571d6b5e3113 Mon Sep 17 00:00:00 2001 From: Livius Date: Wed, 1 Sep 2021 16:39:53 +0200 Subject: [PATCH 03/57] Adjust braces to PEP 7 --- Modules/timemodule.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Modules/timemodule.c b/Modules/timemodule.c index 05844b7ee537c7..898c23907dcf2e 100644 --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -2071,8 +2071,7 @@ pysleep(_PyTime_t secs) } deadline = monotonic + secs; #ifdef HAVE_CLOCK_NANOSLEEP - if (_PyTime_AsTimespec(deadline, &timeout_abs) < 0) - { + if (_PyTime_AsTimespec(deadline, &timeout_abs) < 0) { return -1; } #endif @@ -2080,8 +2079,7 @@ pysleep(_PyTime_t secs) do { #ifndef MS_WINDOWS #ifndef HAVE_CLOCK_NANOSLEEP - if (_PyTime_AsTimeval(secs, &timeout, _PyTime_ROUND_CEILING) < 0) - { + if (_PyTime_AsTimeval(secs, &timeout, _PyTime_ROUND_CEILING) < 0) { return -1; } #endif From 3e07f39c2c869ad7f2c202b82577f225b1e3d96d Mon Sep 17 00:00:00 2001 From: Livius Date: Wed, 1 Sep 2021 16:43:03 +0200 Subject: [PATCH 04/57] clock_nanosleep check placed after clock_settime --- configure.ac | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/configure.ac b/configure.ac index 3b01f657db57d8..af4c71a778f3c4 100644 --- a/configure.ac +++ b/configure.ac @@ -4086,12 +4086,6 @@ AC_CHECK_FUNCS(clock_gettime, [], [ ]) ]) -AC_CHECK_FUNCS(clock_nanosleep, [], [ - AC_CHECK_LIB(rt, clock_nanosleep, [ - AC_DEFINE(HAVE_CLOCK_NANOSLEEP, 1) - ]) -]) - AC_CHECK_FUNCS(clock_getres, [], [ AC_CHECK_LIB(rt, clock_getres, [ AC_DEFINE(HAVE_CLOCK_GETRES, 1) @@ -4104,6 +4098,12 @@ AC_CHECK_FUNCS(clock_settime, [], [ ]) ]) +AC_CHECK_FUNCS(clock_nanosleep, [], [ + AC_CHECK_LIB(rt, clock_nanosleep, [ + AC_DEFINE(HAVE_CLOCK_NANOSLEEP, 1) + ]) +]) + AC_MSG_CHECKING(for major, minor, and makedev) AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #if defined(MAJOR_IN_MKDEV) From e06ba8478eda66a7914dd7609d9cd3e06729825e Mon Sep 17 00:00:00 2001 From: Livius Date: Wed, 1 Sep 2021 18:46:39 +0200 Subject: [PATCH 05/57] Fix EINTR issue for clock_nanosleep() In calling clock_nanosleep() EINTR is not stored in errno. Need to use return value of clock_nanosleep()/select() for checking it. --- Modules/timemodule.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Modules/timemodule.c b/Modules/timemodule.c index 898c23907dcf2e..31dc2550cbe01b 100644 --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -2095,7 +2095,8 @@ pysleep(_PyTime_t secs) if (err == 0) break; - if (errno != EINTR) { + if (err != EINTR) { + errno = err; PyErr_SetFromErrno(PyExc_OSError); return -1; } From 6e6d4a3391ccb437a82b24d86915bdd95caee965 Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Wed, 1 Sep 2021 17:12:23 +0000 Subject: [PATCH 06/57] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20b?= =?UTF-8?q?lurb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../NEWS.d/next/Library/2021-09-01-17-12-22.bpo-21302.X3qZjV.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Library/2021-09-01-17-12-22.bpo-21302.X3qZjV.rst diff --git a/Misc/NEWS.d/next/Library/2021-09-01-17-12-22.bpo-21302.X3qZjV.rst b/Misc/NEWS.d/next/Library/2021-09-01-17-12-22.bpo-21302.X3qZjV.rst new file mode 100644 index 00000000000000..5ece2bebfcfbd9 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-09-01-17-12-22.bpo-21302.X3qZjV.rst @@ -0,0 +1 @@ +In Linux, time.sleep() has a resolution of nanoseconds if the clock_nanosleep() function is available. \ No newline at end of file From 238f0735f86c1c2826841c13ef6e992edbfbe768 Mon Sep 17 00:00:00 2001 From: Livius Date: Wed, 1 Sep 2021 20:18:28 +0200 Subject: [PATCH 07/57] nanosleep() is available for Unix systems like OSX, FreeBSD --- Modules/timemodule.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/Modules/timemodule.c b/Modules/timemodule.c index 31dc2550cbe01b..7456af59642fb7 100644 --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -2053,11 +2053,7 @@ pysleep(_PyTime_t secs) { _PyTime_t deadline, monotonic; #ifndef MS_WINDOWS -#ifdef HAVE_CLOCK_NANOSLEEP - struct timespec timeout_abs; -#else - struct timeval timeout; -#endif + struct timespec timeout; int err = 0; #else _PyTime_t millisecs; @@ -2071,7 +2067,7 @@ pysleep(_PyTime_t secs) } deadline = monotonic + secs; #ifdef HAVE_CLOCK_NANOSLEEP - if (_PyTime_AsTimespec(deadline, &timeout_abs) < 0) { + if (_PyTime_AsTimespec(deadline, &timeout) < 0) { return -1; } #endif @@ -2079,16 +2075,16 @@ pysleep(_PyTime_t secs) do { #ifndef MS_WINDOWS #ifndef HAVE_CLOCK_NANOSLEEP - if (_PyTime_AsTimeval(secs, &timeout, _PyTime_ROUND_CEILING) < 0) { + if (_PyTime_AsTimespec(secs, &timeout) < 0) { return -1; } #endif Py_BEGIN_ALLOW_THREADS #ifdef HAVE_CLOCK_NANOSLEEP - err = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &timeout_abs, NULL); + err = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &timeout, NULL); #else - err = select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &timeout); + err = nanosleep(&timeout, NULL); #endif Py_END_ALLOW_THREADS From b5a5c6efecd60181694165b302e3c358c562b933 Mon Sep 17 00:00:00 2001 From: Livius Date: Wed, 1 Sep 2021 20:51:23 +0200 Subject: [PATCH 08/57] Update news rst file Unix operating systems eg: Linux, macOS, FreeBSD etc. time.sleep() has a resolution of nanoseconds with using clock_nanosleep() or nanosleep() function. --- .../next/Library/2021-09-01-17-12-22.bpo-21302.X3qZjV.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Library/2021-09-01-17-12-22.bpo-21302.X3qZjV.rst b/Misc/NEWS.d/next/Library/2021-09-01-17-12-22.bpo-21302.X3qZjV.rst index 5ece2bebfcfbd9..ee4fb69c117934 100644 --- a/Misc/NEWS.d/next/Library/2021-09-01-17-12-22.bpo-21302.X3qZjV.rst +++ b/Misc/NEWS.d/next/Library/2021-09-01-17-12-22.bpo-21302.X3qZjV.rst @@ -1 +1 @@ -In Linux, time.sleep() has a resolution of nanoseconds if the clock_nanosleep() function is available. \ No newline at end of file +In Unix operating systems eg: Linux, macOS, FreeBSD etc. time.sleep() has a resolution of nanoseconds with using clock_nanosleep() or nanosleep() function. \ No newline at end of file From d06425554c0424d3fd11888f39581070d4f2d860 Mon Sep 17 00:00:00 2001 From: Livius Date: Thu, 2 Sep 2021 22:22:00 +0200 Subject: [PATCH 09/57] replace select() with nanosleep() In all Unix systems eg: macOS, FreeBSD, Linux etc, nanosleep() is available. --- .../2021-09-01-17-12-22.bpo-21302.X3qZjV.rst | 1 - Modules/_multiprocessing/semaphore.c | 22 +++++++++---------- Modules/_tkinter.c | 7 +++--- 3 files changed, 14 insertions(+), 16 deletions(-) delete mode 100644 Misc/NEWS.d/next/Library/2021-09-01-17-12-22.bpo-21302.X3qZjV.rst diff --git a/Misc/NEWS.d/next/Library/2021-09-01-17-12-22.bpo-21302.X3qZjV.rst b/Misc/NEWS.d/next/Library/2021-09-01-17-12-22.bpo-21302.X3qZjV.rst deleted file mode 100644 index ee4fb69c117934..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-09-01-17-12-22.bpo-21302.X3qZjV.rst +++ /dev/null @@ -1 +0,0 @@ -In Unix operating systems eg: Linux, macOS, FreeBSD etc. time.sleep() has a resolution of nanoseconds with using clock_nanosleep() or nanosleep() function. \ No newline at end of file diff --git a/Modules/_multiprocessing/semaphore.c b/Modules/_multiprocessing/semaphore.c index 9a2d1f85c92fa2..66cfef27620d96 100644 --- a/Modules/_multiprocessing/semaphore.c +++ b/Modules/_multiprocessing/semaphore.c @@ -235,11 +235,11 @@ sem_timedwait_save(sem_t *sem, struct timespec *deadline, PyThreadState *_save) { int res; unsigned long delay, difference; - struct timeval now, tvdeadline, tvdelay; + struct timespec tsdeadline, tsdelay; + struct timeval now; errno = 0; - tvdeadline.tv_sec = deadline->tv_sec; - tvdeadline.tv_usec = deadline->tv_nsec / 1000; + tsdeadline = *deadline; for (delay = 0 ; ; delay += 1000) { /* poll */ @@ -253,16 +253,16 @@ sem_timedwait_save(sem_t *sem, struct timespec *deadline, PyThreadState *_save) return MP_STANDARD_ERROR; /* check for timeout */ - if (tvdeadline.tv_sec < now.tv_sec || - (tvdeadline.tv_sec == now.tv_sec && - tvdeadline.tv_usec <= now.tv_usec)) { + if (tsdeadline.tv_sec < now.tv_sec || + (tsdeadline.tv_sec == now.tv_sec && + tsdeadline.tv_nsec <= (now.tv_usec*1000))) { errno = ETIMEDOUT; return MP_STANDARD_ERROR; } /* calculate how much time is left */ - difference = (tvdeadline.tv_sec - now.tv_sec) * 1000000 + - (tvdeadline.tv_usec - now.tv_usec); + difference = (tsdeadline.tv_sec - now.tv_sec) * 1000000 + + ((tsdeadline.tv_nsec/1000) - now.tv_usec); /* check delay not too long -- maximum is 20 msecs */ if (delay > 20000) @@ -271,9 +271,9 @@ sem_timedwait_save(sem_t *sem, struct timespec *deadline, PyThreadState *_save) delay = difference; /* sleep */ - tvdelay.tv_sec = delay / 1000000; - tvdelay.tv_usec = delay % 1000000; - if (select(0, NULL, NULL, NULL, &tvdelay) < 0) + tsdelay.tv_sec = delay / 1000000; + tsdelay.tv_nsec = (delay % 1000000) * 1000; + if (nanosleep(&tsdelay, NULL) < 0) return MP_STANDARD_ERROR; /* check for signals */ diff --git a/Modules/_tkinter.c b/Modules/_tkinter.c index 329b291729d581..11cf69858d0d4f 100644 --- a/Modules/_tkinter.c +++ b/Modules/_tkinter.c @@ -357,11 +357,10 @@ static int Tkinter_busywaitinterval = 20; static void Sleep(int milli) { - /* XXX Too bad if you don't have select(). */ - struct timeval t; + struct timespec t; t.tv_sec = milli/1000; - t.tv_usec = (milli%1000) * 1000; - select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t); + t.tv_nsec = (milli%1000) * 1000000; + nanosleep(&t, NULL); } #endif /* MS_WINDOWS */ From b70f187b470384cd44a592bb64c699454f708086 Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Thu, 2 Sep 2021 20:27:13 +0000 Subject: [PATCH 10/57] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20b?= =?UTF-8?q?lurb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../NEWS.d/next/Library/2021-09-02-20-27-12.bpo-21302.guX9C3.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Library/2021-09-02-20-27-12.bpo-21302.guX9C3.rst diff --git a/Misc/NEWS.d/next/Library/2021-09-02-20-27-12.bpo-21302.guX9C3.rst b/Misc/NEWS.d/next/Library/2021-09-02-20-27-12.bpo-21302.guX9C3.rst new file mode 100644 index 00000000000000..ee4fb69c117934 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-09-02-20-27-12.bpo-21302.guX9C3.rst @@ -0,0 +1 @@ +In Unix operating systems eg: Linux, macOS, FreeBSD etc. time.sleep() has a resolution of nanoseconds with using clock_nanosleep() or nanosleep() function. \ No newline at end of file From 6ad7c14d869ddad286fd4e84b7a040d374a6fbc8 Mon Sep 17 00:00:00 2001 From: Livius Date: Thu, 2 Sep 2021 23:37:24 +0200 Subject: [PATCH 11/57] Fix test_eintr issue for macOS --- Modules/timemodule.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Modules/timemodule.c b/Modules/timemodule.c index 7456af59642fb7..6302973dc08c19 100644 --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -2091,11 +2091,19 @@ pysleep(_PyTime_t secs) if (err == 0) break; +#ifdef HAVE_CLOCK_NANOSLEEP if (err != EINTR) { errno = err; PyErr_SetFromErrno(PyExc_OSError); return -1; } +#else + if (errno != EINTR) { + PyErr_SetFromErrno(PyExc_OSError); + return -1; + } +#endif + #else millisecs = _PyTime_AsMilliseconds(secs, _PyTime_ROUND_CEILING); if (millisecs > (double)ULONG_MAX) { From 74c45e1b29e42d60234452c60df4bc090f4d91cc Mon Sep 17 00:00:00 2001 From: Livius Date: Thu, 2 Sep 2021 23:39:50 +0200 Subject: [PATCH 12/57] Remove news rst and regenerate --- .../NEWS.d/next/Library/2021-09-02-20-27-12.bpo-21302.guX9C3.rst | 1 - 1 file changed, 1 deletion(-) delete mode 100644 Misc/NEWS.d/next/Library/2021-09-02-20-27-12.bpo-21302.guX9C3.rst diff --git a/Misc/NEWS.d/next/Library/2021-09-02-20-27-12.bpo-21302.guX9C3.rst b/Misc/NEWS.d/next/Library/2021-09-02-20-27-12.bpo-21302.guX9C3.rst deleted file mode 100644 index ee4fb69c117934..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-09-02-20-27-12.bpo-21302.guX9C3.rst +++ /dev/null @@ -1 +0,0 @@ -In Unix operating systems eg: Linux, macOS, FreeBSD etc. time.sleep() has a resolution of nanoseconds with using clock_nanosleep() or nanosleep() function. \ No newline at end of file From 59882227f850dd61e419de017c7daebbaf76456d Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Thu, 2 Sep 2021 21:41:08 +0000 Subject: [PATCH 13/57] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20b?= =?UTF-8?q?lurb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../NEWS.d/next/Library/2021-09-02-21-41-07.bpo-21302.guX9C3.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Library/2021-09-02-21-41-07.bpo-21302.guX9C3.rst diff --git a/Misc/NEWS.d/next/Library/2021-09-02-21-41-07.bpo-21302.guX9C3.rst b/Misc/NEWS.d/next/Library/2021-09-02-21-41-07.bpo-21302.guX9C3.rst new file mode 100644 index 00000000000000..ee4fb69c117934 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-09-02-21-41-07.bpo-21302.guX9C3.rst @@ -0,0 +1 @@ +In Unix operating systems eg: Linux, macOS, FreeBSD etc. time.sleep() has a resolution of nanoseconds with using clock_nanosleep() or nanosleep() function. \ No newline at end of file From 129b0a0f5dd3a1adf770488c2515461b539a58ea Mon Sep 17 00:00:00 2001 From: Livius Date: Fri, 3 Sep 2021 14:22:23 +0200 Subject: [PATCH 14/57] Use waitable timer from Win32 for time.sleep() in Windows Waitable timer is 100 nsec resolution. Now, seconds to nanosec conversion is limited in usec, soon will come the next developing part to improve it in next commit. --- Modules/timemodule.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/Modules/timemodule.c b/Modules/timemodule.c index 6302973dc08c19..e70906d614db54 100644 --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -2059,17 +2059,30 @@ pysleep(_PyTime_t secs) _PyTime_t millisecs; unsigned long ul_millis; DWORD rc; - HANDLE hInterruptEvent; + FILETIME FileTime; + LARGE_INTEGER dueTimeAbs; + HANDLE hTimer = 0; + GetSystemTimeAsFileTime(&FileTime); #endif if (get_monotonic(&monotonic) < 0) { return -1; } deadline = monotonic + secs; -#ifdef HAVE_CLOCK_NANOSLEEP +#if defined(HAVE_CLOCK_NANOSLEEP) && !defined(MS_WINDOWS) if (_PyTime_AsTimespec(deadline, &timeout) < 0) { return -1; } +#else + CopyMemory(&dueTimeAbs, &FileTime, sizeof(FILETIME)); + dueTimeAbs.QuadPart += ((_PyTime_AsMicroseconds(secs, _PyTime_ROUND_CEILING) * 1000) / 100); + hTimer = CreateWaitableTimerW(NULL, FALSE, NULL); + if (NULL == hTimer) { + return -1; + } + if (!SetWaitableTimer(hTimer, &dueTimeAbs, 0, NULL, NULL, FALSE)) { + return -1; + } #endif do { @@ -2106,7 +2119,7 @@ pysleep(_PyTime_t secs) #else millisecs = _PyTime_AsMilliseconds(secs, _PyTime_ROUND_CEILING); - if (millisecs > (double)ULONG_MAX) { + if (millisecs > LLONG_MAX) { PyErr_SetString(PyExc_OverflowError, "sleep length is too large"); return -1; @@ -2123,11 +2136,8 @@ pysleep(_PyTime_t secs) break; } - hInterruptEvent = _PyOS_SigintEvent(); - ResetEvent(hInterruptEvent); - Py_BEGIN_ALLOW_THREADS - rc = WaitForSingleObjectEx(hInterruptEvent, ul_millis, FALSE); + rc = WaitForSingleObjectEx(hTimer, ul_millis*2, FALSE); Py_END_ALLOW_THREADS if (rc != WAIT_OBJECT_0) From d89e13b1e643ec9cd0f4f30f9d7043eafac7d6d3 Mon Sep 17 00:00:00 2001 From: Livius Date: Fri, 3 Sep 2021 23:25:46 +0200 Subject: [PATCH 15/57] Finalized waitable timer for time.sleep() in Windows Waitable timer resolution is 100 nsec but it is limited to 1 usec by round ceiling, moreover sleep for lower then 1 milisec is not possible in Win32 API. --- .../2021-09-02-21-41-07.bpo-21302.guX9C3.rst | 1 - Modules/timemodule.c | 23 ++++++++++++------- 2 files changed, 15 insertions(+), 9 deletions(-) delete mode 100644 Misc/NEWS.d/next/Library/2021-09-02-21-41-07.bpo-21302.guX9C3.rst diff --git a/Misc/NEWS.d/next/Library/2021-09-02-21-41-07.bpo-21302.guX9C3.rst b/Misc/NEWS.d/next/Library/2021-09-02-21-41-07.bpo-21302.guX9C3.rst deleted file mode 100644 index ee4fb69c117934..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-09-02-21-41-07.bpo-21302.guX9C3.rst +++ /dev/null @@ -1 +0,0 @@ -In Unix operating systems eg: Linux, macOS, FreeBSD etc. time.sleep() has a resolution of nanoseconds with using clock_nanosleep() or nanosleep() function. \ No newline at end of file diff --git a/Modules/timemodule.c b/Modules/timemodule.c index e70906d614db54..8120e1b3220037 100644 --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -2057,11 +2057,11 @@ pysleep(_PyTime_t secs) int err = 0; #else _PyTime_t millisecs; - unsigned long ul_millis; + DWORD ul_millis; DWORD rc; FILETIME FileTime; LARGE_INTEGER dueTimeAbs; - HANDLE hTimer = 0; + HANDLE hTimer = NULL; GetSystemTimeAsFileTime(&FileTime); #endif @@ -2075,11 +2075,15 @@ pysleep(_PyTime_t secs) } #else CopyMemory(&dueTimeAbs, &FileTime, sizeof(FILETIME)); - dueTimeAbs.QuadPart += ((_PyTime_AsMicroseconds(secs, _PyTime_ROUND_CEILING) * 1000) / 100); + + /* convert to 100 nsec unit */ + dueTimeAbs.QuadPart += (_PyTime_AsMicroseconds(secs, _PyTime_ROUND_CEILING) * 10); + hTimer = CreateWaitableTimerW(NULL, FALSE, NULL); if (NULL == hTimer) { return -1; } + if (!SetWaitableTimer(hTimer, &dueTimeAbs, 0, NULL, NULL, FALSE)) { return -1; } @@ -2101,8 +2105,9 @@ pysleep(_PyTime_t secs) #endif Py_END_ALLOW_THREADS - if (err == 0) + if (err == 0) { break; + } #ifdef HAVE_CLOCK_NANOSLEEP if (err != EINTR) { @@ -2137,16 +2142,18 @@ pysleep(_PyTime_t secs) } Py_BEGIN_ALLOW_THREADS - rc = WaitForSingleObjectEx(hTimer, ul_millis*2, FALSE); + rc = WaitForSingleObjectEx(hTimer, ul_millis, FALSE); Py_END_ALLOW_THREADS - if (rc != WAIT_OBJECT_0) - break; + if ((rc != WAIT_OBJECT_0) && (rc != WAIT_TIMEOUT)) { + return -1; + } #endif /* sleep was interrupted by SIGINT */ - if (PyErr_CheckSignals()) + if (PyErr_CheckSignals()) { return -1; + } if (get_monotonic(&monotonic) < 0) { return -1; From 47249f5341a66f08d8d1ca39a3d8b5e69669ea21 Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Fri, 3 Sep 2021 21:32:40 +0000 Subject: [PATCH 16/57] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20b?= =?UTF-8?q?lurb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../NEWS.d/next/Library/2021-09-03-21-32-39.bpo-21302.zTYR1A.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Library/2021-09-03-21-32-39.bpo-21302.zTYR1A.rst diff --git a/Misc/NEWS.d/next/Library/2021-09-03-21-32-39.bpo-21302.zTYR1A.rst b/Misc/NEWS.d/next/Library/2021-09-03-21-32-39.bpo-21302.zTYR1A.rst new file mode 100644 index 00000000000000..d3eab1bf518955 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-09-03-21-32-39.bpo-21302.zTYR1A.rst @@ -0,0 +1 @@ +In Unix operating systems eg: Linux, macOS, FreeBSD etc. time.sleep() has a resolution of nanoseconds with using clock_nanosleep() or nanosleep() function. In Windows, time.sleep() has a resolution of microseconds with using waitable timer from Win32 API. \ No newline at end of file From 0bf833010da502278ab35a5b4b94f09775c6a6ea Mon Sep 17 00:00:00 2001 From: Livius Date: Fri, 3 Sep 2021 23:42:18 +0200 Subject: [PATCH 17/57] Fix macOS build issue --- .../next/Library/2021-09-03-21-32-39.bpo-21302.zTYR1A.rst | 1 - Modules/timemodule.c | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) delete mode 100644 Misc/NEWS.d/next/Library/2021-09-03-21-32-39.bpo-21302.zTYR1A.rst diff --git a/Misc/NEWS.d/next/Library/2021-09-03-21-32-39.bpo-21302.zTYR1A.rst b/Misc/NEWS.d/next/Library/2021-09-03-21-32-39.bpo-21302.zTYR1A.rst deleted file mode 100644 index d3eab1bf518955..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-09-03-21-32-39.bpo-21302.zTYR1A.rst +++ /dev/null @@ -1 +0,0 @@ -In Unix operating systems eg: Linux, macOS, FreeBSD etc. time.sleep() has a resolution of nanoseconds with using clock_nanosleep() or nanosleep() function. In Windows, time.sleep() has a resolution of microseconds with using waitable timer from Win32 API. \ No newline at end of file diff --git a/Modules/timemodule.c b/Modules/timemodule.c index 8120e1b3220037..2ed28904f8b9d3 100644 --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -2073,7 +2073,7 @@ pysleep(_PyTime_t secs) if (_PyTime_AsTimespec(deadline, &timeout) < 0) { return -1; } -#else +#elif defined(MS_WINDOWS) CopyMemory(&dueTimeAbs, &FileTime, sizeof(FILETIME)); /* convert to 100 nsec unit */ From 085cbed10fa5e612b1a2f661a86eb968b864c072 Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Fri, 3 Sep 2021 21:43:29 +0000 Subject: [PATCH 18/57] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20b?= =?UTF-8?q?lurb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../NEWS.d/next/Library/2021-09-03-21-43-28.bpo-21302.zTYR1A.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Library/2021-09-03-21-43-28.bpo-21302.zTYR1A.rst diff --git a/Misc/NEWS.d/next/Library/2021-09-03-21-43-28.bpo-21302.zTYR1A.rst b/Misc/NEWS.d/next/Library/2021-09-03-21-43-28.bpo-21302.zTYR1A.rst new file mode 100644 index 00000000000000..d3eab1bf518955 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-09-03-21-43-28.bpo-21302.zTYR1A.rst @@ -0,0 +1 @@ +In Unix operating systems eg: Linux, macOS, FreeBSD etc. time.sleep() has a resolution of nanoseconds with using clock_nanosleep() or nanosleep() function. In Windows, time.sleep() has a resolution of microseconds with using waitable timer from Win32 API. \ No newline at end of file From 2242638d69ed652eaeedd8efd70baa36e5c302b5 Mon Sep 17 00:00:00 2001 From: Livius Date: Sat, 4 Sep 2021 13:44:33 +0200 Subject: [PATCH 19/57] Final optimization in Waitable timer object implementation --- .../2021-09-03-21-43-28.bpo-21302.zTYR1A.rst | 1 - Modules/timemodule.c | 80 ++++++++++--------- 2 files changed, 43 insertions(+), 38 deletions(-) delete mode 100644 Misc/NEWS.d/next/Library/2021-09-03-21-43-28.bpo-21302.zTYR1A.rst diff --git a/Misc/NEWS.d/next/Library/2021-09-03-21-43-28.bpo-21302.zTYR1A.rst b/Misc/NEWS.d/next/Library/2021-09-03-21-43-28.bpo-21302.zTYR1A.rst deleted file mode 100644 index d3eab1bf518955..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-09-03-21-43-28.bpo-21302.zTYR1A.rst +++ /dev/null @@ -1 +0,0 @@ -In Unix operating systems eg: Linux, macOS, FreeBSD etc. time.sleep() has a resolution of nanoseconds with using clock_nanosleep() or nanosleep() function. In Windows, time.sleep() has a resolution of microseconds with using waitable timer from Win32 API. \ No newline at end of file diff --git a/Modules/timemodule.c b/Modules/timemodule.c index 2ed28904f8b9d3..5bef1ba54b6816 100644 --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -2051,8 +2051,8 @@ PyInit_time(void) static int pysleep(_PyTime_t secs) { - _PyTime_t deadline, monotonic; #ifndef MS_WINDOWS + _PyTime_t deadline, monotonic; struct timespec timeout; int err = 0; #else @@ -2060,37 +2060,39 @@ pysleep(_PyTime_t secs) DWORD ul_millis; DWORD rc; FILETIME FileTime; - LARGE_INTEGER dueTimeAbs; + LARGE_INTEGER deadline; HANDLE hTimer = NULL; - GetSystemTimeAsFileTime(&FileTime); #endif +#ifndef MS_WINDOWS if (get_monotonic(&monotonic) < 0) { return -1; } deadline = monotonic + secs; -#if defined(HAVE_CLOCK_NANOSLEEP) && !defined(MS_WINDOWS) +#ifdef HAVE_CLOCK_NANOSLEEP if (_PyTime_AsTimespec(deadline, &timeout) < 0) { return -1; } -#elif defined(MS_WINDOWS) - CopyMemory(&dueTimeAbs, &FileTime, sizeof(FILETIME)); +#endif +#else + GetSystemTimePreciseAsFileTime(&FileTime); + CopyMemory(&deadline, &FileTime, sizeof(FILETIME)); /* convert to 100 nsec unit */ - dueTimeAbs.QuadPart += (_PyTime_AsMicroseconds(secs, _PyTime_ROUND_CEILING) * 10); + deadline.QuadPart += (_PyTime_AsMicroseconds(secs, _PyTime_ROUND_CEILING) * 10); hTimer = CreateWaitableTimerW(NULL, FALSE, NULL); if (NULL == hTimer) { return -1; } - if (!SetWaitableTimer(hTimer, &dueTimeAbs, 0, NULL, NULL, FALSE)) { + if (!SetWaitableTimer(hTimer, &deadline, 0, NULL, NULL, FALSE)) { return -1; } #endif - do { #ifndef MS_WINDOWS + do { #ifndef HAVE_CLOCK_NANOSLEEP if (_PyTime_AsTimespec(secs, &timeout) < 0) { return -1; @@ -2122,34 +2124,6 @@ pysleep(_PyTime_t secs) } #endif -#else - millisecs = _PyTime_AsMilliseconds(secs, _PyTime_ROUND_CEILING); - if (millisecs > LLONG_MAX) { - PyErr_SetString(PyExc_OverflowError, - "sleep length is too large"); - return -1; - } - - /* Allow sleep(0) to maintain win32 semantics, and as decreed - * by Guido, only the main thread can be interrupted. - */ - ul_millis = (unsigned long)millisecs; - if (ul_millis == 0 || !_PyOS_IsMainThread()) { - Py_BEGIN_ALLOW_THREADS - Sleep(ul_millis); - Py_END_ALLOW_THREADS - break; - } - - Py_BEGIN_ALLOW_THREADS - rc = WaitForSingleObjectEx(hTimer, ul_millis, FALSE); - Py_END_ALLOW_THREADS - - if ((rc != WAIT_OBJECT_0) && (rc != WAIT_TIMEOUT)) { - return -1; - } -#endif - /* sleep was interrupted by SIGINT */ if (PyErr_CheckSignals()) { return -1; @@ -2164,6 +2138,38 @@ pysleep(_PyTime_t secs) } /* retry with the recomputed delay */ } while (1); +#else + millisecs = _PyTime_AsMilliseconds(secs, _PyTime_ROUND_CEILING); + if (millisecs > LLONG_MAX) { + PyErr_SetString(PyExc_OverflowError, + "sleep length is too large"); + return -1; + } + + /* Allow sleep(0) to maintain win32 semantics, and as decreed + * by Guido, only the main thread can be interrupted. + */ + ul_millis = (unsigned long)millisecs; + if (ul_millis == 0 || !_PyOS_IsMainThread()) { + Py_BEGIN_ALLOW_THREADS + Sleep(ul_millis); + Py_END_ALLOW_THREADS + return 0; + } + + Py_BEGIN_ALLOW_THREADS + rc = WaitForSingleObjectEx(hTimer, ul_millis, FALSE); + Py_END_ALLOW_THREADS + + if ((rc != WAIT_OBJECT_0) && (rc != WAIT_TIMEOUT)) { + return -1; + } + + /* sleep was interrupted by SIGINT */ + if (PyErr_CheckSignals()) { + return -1; + } +#endif return 0; } From db7851bf47f06ee51741a414f34d1d616ce0c37d Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Sat, 4 Sep 2021 11:46:06 +0000 Subject: [PATCH 20/57] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20b?= =?UTF-8?q?lurb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../NEWS.d/next/Library/2021-09-04-11-46-05.bpo-21302.zTYR1A.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Library/2021-09-04-11-46-05.bpo-21302.zTYR1A.rst diff --git a/Misc/NEWS.d/next/Library/2021-09-04-11-46-05.bpo-21302.zTYR1A.rst b/Misc/NEWS.d/next/Library/2021-09-04-11-46-05.bpo-21302.zTYR1A.rst new file mode 100644 index 00000000000000..d3eab1bf518955 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-09-04-11-46-05.bpo-21302.zTYR1A.rst @@ -0,0 +1 @@ +In Unix operating systems eg: Linux, macOS, FreeBSD etc. time.sleep() has a resolution of nanoseconds with using clock_nanosleep() or nanosleep() function. In Windows, time.sleep() has a resolution of microseconds with using waitable timer from Win32 API. \ No newline at end of file From f7387e8463454b1b02df71a4ce9d583ba2421ba4 Mon Sep 17 00:00:00 2001 From: Livius Date: Fri, 10 Sep 2021 00:24:28 +0200 Subject: [PATCH 21/57] revert to original --- Modules/_multiprocessing/semaphore.c | 22 +-- Modules/_tkinter.c | 209 +-------------------------- Modules/timemodule.c | 114 +++++---------- 3 files changed, 50 insertions(+), 295 deletions(-) diff --git a/Modules/_multiprocessing/semaphore.c b/Modules/_multiprocessing/semaphore.c index 66cfef27620d96..9a2d1f85c92fa2 100644 --- a/Modules/_multiprocessing/semaphore.c +++ b/Modules/_multiprocessing/semaphore.c @@ -235,11 +235,11 @@ sem_timedwait_save(sem_t *sem, struct timespec *deadline, PyThreadState *_save) { int res; unsigned long delay, difference; - struct timespec tsdeadline, tsdelay; - struct timeval now; + struct timeval now, tvdeadline, tvdelay; errno = 0; - tsdeadline = *deadline; + tvdeadline.tv_sec = deadline->tv_sec; + tvdeadline.tv_usec = deadline->tv_nsec / 1000; for (delay = 0 ; ; delay += 1000) { /* poll */ @@ -253,16 +253,16 @@ sem_timedwait_save(sem_t *sem, struct timespec *deadline, PyThreadState *_save) return MP_STANDARD_ERROR; /* check for timeout */ - if (tsdeadline.tv_sec < now.tv_sec || - (tsdeadline.tv_sec == now.tv_sec && - tsdeadline.tv_nsec <= (now.tv_usec*1000))) { + if (tvdeadline.tv_sec < now.tv_sec || + (tvdeadline.tv_sec == now.tv_sec && + tvdeadline.tv_usec <= now.tv_usec)) { errno = ETIMEDOUT; return MP_STANDARD_ERROR; } /* calculate how much time is left */ - difference = (tsdeadline.tv_sec - now.tv_sec) * 1000000 + - ((tsdeadline.tv_nsec/1000) - now.tv_usec); + difference = (tvdeadline.tv_sec - now.tv_sec) * 1000000 + + (tvdeadline.tv_usec - now.tv_usec); /* check delay not too long -- maximum is 20 msecs */ if (delay > 20000) @@ -271,9 +271,9 @@ sem_timedwait_save(sem_t *sem, struct timespec *deadline, PyThreadState *_save) delay = difference; /* sleep */ - tsdelay.tv_sec = delay / 1000000; - tsdelay.tv_nsec = (delay % 1000000) * 1000; - if (nanosleep(&tsdelay, NULL) < 0) + tvdelay.tv_sec = delay / 1000000; + tvdelay.tv_usec = delay % 1000000; + if (select(0, NULL, NULL, NULL, &tvdelay) < 0) return MP_STANDARD_ERROR; /* check for signals */ diff --git a/Modules/_tkinter.c b/Modules/_tkinter.c index 11cf69858d0d4f..7be9b8c0385b97 100644 --- a/Modules/_tkinter.c +++ b/Modules/_tkinter.c @@ -357,10 +357,11 @@ static int Tkinter_busywaitinterval = 20; static void Sleep(int milli) { - struct timespec t; + /* XXX Too bad if you don't have select(). */ + struct timeval t; t.tv_sec = milli/1000; - t.tv_nsec = (milli%1000) * 1000000; - nanosleep(&t, NULL); + t.tv_usec = (milli%1000) * 1000; + select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &t); } #endif /* MS_WINDOWS */ @@ -505,145 +506,6 @@ unicodeFromTclObj(Tcl_Obj *value) #endif } - -static PyObject * -Split(const char *list) -{ - int argc; - const char **argv; - PyObject *v; - - if (list == NULL) { - Py_RETURN_NONE; - } - - if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) { - /* Not a list. - * Could be a quoted string containing funnies, e.g. {"}. - * Return the string itself. - */ - return unicodeFromTclString(list); - } - - if (argc == 0) - v = PyUnicode_FromString(""); - else if (argc == 1) - v = unicodeFromTclString(argv[0]); - else if ((v = PyTuple_New(argc)) != NULL) { - int i; - PyObject *w; - - for (i = 0; i < argc; i++) { - if ((w = Split(argv[i])) == NULL) { - Py_DECREF(v); - v = NULL; - break; - } - PyTuple_SET_ITEM(v, i, w); - } - } - Tcl_Free(FREECAST argv); - return v; -} - -/* In some cases, Tcl will still return strings that are supposed to - be lists. SplitObj walks through a nested tuple, finding string - objects that need to be split. */ - -static PyObject * -SplitObj(PyObject *arg) -{ - if (PyTuple_Check(arg)) { - Py_ssize_t i, size; - PyObject *elem, *newelem, *result; - - size = PyTuple_GET_SIZE(arg); - result = NULL; - /* Recursively invoke SplitObj for all tuple items. - If this does not return a new object, no action is - needed. */ - for(i = 0; i < size; i++) { - elem = PyTuple_GET_ITEM(arg, i); - newelem = SplitObj(elem); - if (!newelem) { - Py_XDECREF(result); - return NULL; - } - if (!result) { - Py_ssize_t k; - if (newelem == elem) { - Py_DECREF(newelem); - continue; - } - result = PyTuple_New(size); - if (!result) - return NULL; - for(k = 0; k < i; k++) { - elem = PyTuple_GET_ITEM(arg, k); - Py_INCREF(elem); - PyTuple_SET_ITEM(result, k, elem); - } - } - PyTuple_SET_ITEM(result, i, newelem); - } - if (result) - return result; - /* Fall through, returning arg. */ - } - else if (PyList_Check(arg)) { - Py_ssize_t i, size; - PyObject *elem, *newelem, *result; - - size = PyList_GET_SIZE(arg); - result = PyTuple_New(size); - if (!result) - return NULL; - /* Recursively invoke SplitObj for all list items. */ - for(i = 0; i < size; i++) { - elem = PyList_GET_ITEM(arg, i); - newelem = SplitObj(elem); - if (!newelem) { - Py_XDECREF(result); - return NULL; - } - PyTuple_SET_ITEM(result, i, newelem); - } - return result; - } - else if (PyUnicode_Check(arg)) { - int argc; - const char **argv; - const char *list = PyUnicode_AsUTF8(arg); - - if (list == NULL || - Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) { - Py_INCREF(arg); - return arg; - } - Tcl_Free(FREECAST argv); - if (argc > 1) - return Split(list); - /* Fall through, returning arg. */ - } - else if (PyBytes_Check(arg)) { - int argc; - const char **argv; - const char *list = PyBytes_AS_STRING(arg); - - if (Tcl_SplitList((Tcl_Interp *)NULL, (char *)list, &argc, &argv) != TCL_OK) { - Py_INCREF(arg); - return arg; - } - Tcl_Free(FREECAST argv); - if (argc > 1) - return Split(PyBytes_AS_STRING(arg)); - /* Fall through, returning arg. */ - } - Py_INCREF(arg); - return arg; -} - - /*[clinic input] module _tkinter class _tkinter.tkapp "TkappObject *" "&Tkapp_Type_spec" @@ -2341,68 +2203,6 @@ _tkinter_tkapp_splitlist(TkappObject *self, PyObject *arg) return v; } -/*[clinic input] -_tkinter.tkapp.split - - arg: object - / - -[clinic start generated code]*/ - -static PyObject * -_tkinter_tkapp_split(TkappObject *self, PyObject *arg) -/*[clinic end generated code: output=e08ad832363facfd input=a1c78349eacaa140]*/ -{ - PyObject *v; - char *list; - - if (PyErr_WarnEx(PyExc_DeprecationWarning, - "split() is deprecated; consider using splitlist() instead", 1)) - { - return NULL; - } - - if (PyTclObject_Check(arg)) { - Tcl_Obj *value = ((PyTclObject*)arg)->value; - int objc; - Tcl_Obj **objv; - int i; - if (Tcl_ListObjGetElements(Tkapp_Interp(self), value, - &objc, &objv) == TCL_ERROR) { - return FromObj(self, value); - } - if (objc == 0) - return PyUnicode_FromString(""); - if (objc == 1) - return FromObj(self, objv[0]); - if (!(v = PyTuple_New(objc))) - return NULL; - for (i = 0; i < objc; i++) { - PyObject *s = FromObj(self, objv[i]); - if (!s) { - Py_DECREF(v); - return NULL; - } - PyTuple_SET_ITEM(v, i, s); - } - return v; - } - if (PyTuple_Check(arg) || PyList_Check(arg)) - return SplitObj(arg); - - if (!PyArg_Parse(arg, "et:split", "utf-8", &list)) - return NULL; - if (strlen(list) >= INT_MAX) { - PyErr_SetString(PyExc_OverflowError, "string is too long"); - PyMem_Free(list); - return NULL; - } - v = Split(list); - PyMem_Free(list); - return v; -} - - /** Tcl Command **/ @@ -3330,7 +3130,6 @@ static PyMethodDef Tkapp_methods[] = _TKINTER_TKAPP_EXPRDOUBLE_METHODDEF _TKINTER_TKAPP_EXPRBOOLEAN_METHODDEF _TKINTER_TKAPP_SPLITLIST_METHODDEF - _TKINTER_TKAPP_SPLIT_METHODDEF _TKINTER_TKAPP_CREATECOMMAND_METHODDEF _TKINTER_TKAPP_DELETECOMMAND_METHODDEF _TKINTER_TKAPP_CREATEFILEHANDLER_METHODDEF diff --git a/Modules/timemodule.c b/Modules/timemodule.c index 5bef1ba54b6816..4caacc3b64d7c8 100644 --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -2051,83 +2051,71 @@ PyInit_time(void) static int pysleep(_PyTime_t secs) { -#ifndef MS_WINDOWS _PyTime_t deadline, monotonic; - struct timespec timeout; +#ifndef MS_WINDOWS + struct timeval timeout; int err = 0; #else _PyTime_t millisecs; - DWORD ul_millis; + unsigned long ul_millis; DWORD rc; - FILETIME FileTime; - LARGE_INTEGER deadline; - HANDLE hTimer = NULL; + HANDLE hInterruptEvent; #endif -#ifndef MS_WINDOWS if (get_monotonic(&monotonic) < 0) { return -1; } deadline = monotonic + secs; -#ifdef HAVE_CLOCK_NANOSLEEP - if (_PyTime_AsTimespec(deadline, &timeout) < 0) { - return -1; - } -#endif -#else - GetSystemTimePreciseAsFileTime(&FileTime); - CopyMemory(&deadline, &FileTime, sizeof(FILETIME)); - - /* convert to 100 nsec unit */ - deadline.QuadPart += (_PyTime_AsMicroseconds(secs, _PyTime_ROUND_CEILING) * 10); - - hTimer = CreateWaitableTimerW(NULL, FALSE, NULL); - if (NULL == hTimer) { - return -1; - } - - if (!SetWaitableTimer(hTimer, &deadline, 0, NULL, NULL, FALSE)) { - return -1; - } -#endif -#ifndef MS_WINDOWS do { -#ifndef HAVE_CLOCK_NANOSLEEP - if (_PyTime_AsTimespec(secs, &timeout) < 0) { +#ifndef MS_WINDOWS + if (_PyTime_AsTimeval(secs, &timeout, _PyTime_ROUND_CEILING) < 0) return -1; - } -#endif Py_BEGIN_ALLOW_THREADS -#ifdef HAVE_CLOCK_NANOSLEEP - err = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &timeout, NULL); -#else - err = nanosleep(&timeout, NULL); -#endif + err = select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &timeout); Py_END_ALLOW_THREADS - if (err == 0) { + if (err == 0) break; - } -#ifdef HAVE_CLOCK_NANOSLEEP - if (err != EINTR) { - errno = err; + if (errno != EINTR) { PyErr_SetFromErrno(PyExc_OSError); return -1; } #else - if (errno != EINTR) { - PyErr_SetFromErrno(PyExc_OSError); + millisecs = _PyTime_AsMilliseconds(secs, _PyTime_ROUND_CEILING); + if (millisecs > (double)ULONG_MAX) { + PyErr_SetString(PyExc_OverflowError, + "sleep length is too large"); return -1; } + + /* Allow sleep(0) to maintain win32 semantics, and as decreed + * by Guido, only the main thread can be interrupted. + */ + ul_millis = (unsigned long)millisecs; + if (ul_millis == 0 || !_PyOS_IsMainThread()) { + Py_BEGIN_ALLOW_THREADS + Sleep(ul_millis); + Py_END_ALLOW_THREADS + break; + } + + hInterruptEvent = _PyOS_SigintEvent(); + ResetEvent(hInterruptEvent); + + Py_BEGIN_ALLOW_THREADS + rc = WaitForSingleObjectEx(hInterruptEvent, ul_millis, FALSE); + Py_END_ALLOW_THREADS + + if (rc != WAIT_OBJECT_0) + break; #endif /* sleep was interrupted by SIGINT */ - if (PyErr_CheckSignals()) { + if (PyErr_CheckSignals()) return -1; - } if (get_monotonic(&monotonic) < 0) { return -1; @@ -2138,38 +2126,6 @@ pysleep(_PyTime_t secs) } /* retry with the recomputed delay */ } while (1); -#else - millisecs = _PyTime_AsMilliseconds(secs, _PyTime_ROUND_CEILING); - if (millisecs > LLONG_MAX) { - PyErr_SetString(PyExc_OverflowError, - "sleep length is too large"); - return -1; - } - - /* Allow sleep(0) to maintain win32 semantics, and as decreed - * by Guido, only the main thread can be interrupted. - */ - ul_millis = (unsigned long)millisecs; - if (ul_millis == 0 || !_PyOS_IsMainThread()) { - Py_BEGIN_ALLOW_THREADS - Sleep(ul_millis); - Py_END_ALLOW_THREADS - return 0; - } - - Py_BEGIN_ALLOW_THREADS - rc = WaitForSingleObjectEx(hTimer, ul_millis, FALSE); - Py_END_ALLOW_THREADS - - if ((rc != WAIT_OBJECT_0) && (rc != WAIT_TIMEOUT)) { - return -1; - } - - /* sleep was interrupted by SIGINT */ - if (PyErr_CheckSignals()) { - return -1; - } -#endif return 0; } From a35b0b4606bf4b0d4038f1978fc0b6d225bdcfe6 Mon Sep 17 00:00:00 2001 From: Livius Date: Fri, 10 Sep 2021 00:27:51 +0200 Subject: [PATCH 22/57] remove news --- .../2021-09-04-11-46-05.bpo-21302.zTYR1A.rst | 1 - Modules/_tkinter.c | 202 ++++++++++++++++++ 2 files changed, 202 insertions(+), 1 deletion(-) delete mode 100644 Misc/NEWS.d/next/Library/2021-09-04-11-46-05.bpo-21302.zTYR1A.rst diff --git a/Misc/NEWS.d/next/Library/2021-09-04-11-46-05.bpo-21302.zTYR1A.rst b/Misc/NEWS.d/next/Library/2021-09-04-11-46-05.bpo-21302.zTYR1A.rst deleted file mode 100644 index d3eab1bf518955..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-09-04-11-46-05.bpo-21302.zTYR1A.rst +++ /dev/null @@ -1 +0,0 @@ -In Unix operating systems eg: Linux, macOS, FreeBSD etc. time.sleep() has a resolution of nanoseconds with using clock_nanosleep() or nanosleep() function. In Windows, time.sleep() has a resolution of microseconds with using waitable timer from Win32 API. \ No newline at end of file diff --git a/Modules/_tkinter.c b/Modules/_tkinter.c index 7be9b8c0385b97..329b291729d581 100644 --- a/Modules/_tkinter.c +++ b/Modules/_tkinter.c @@ -506,6 +506,145 @@ unicodeFromTclObj(Tcl_Obj *value) #endif } + +static PyObject * +Split(const char *list) +{ + int argc; + const char **argv; + PyObject *v; + + if (list == NULL) { + Py_RETURN_NONE; + } + + if (Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) { + /* Not a list. + * Could be a quoted string containing funnies, e.g. {"}. + * Return the string itself. + */ + return unicodeFromTclString(list); + } + + if (argc == 0) + v = PyUnicode_FromString(""); + else if (argc == 1) + v = unicodeFromTclString(argv[0]); + else if ((v = PyTuple_New(argc)) != NULL) { + int i; + PyObject *w; + + for (i = 0; i < argc; i++) { + if ((w = Split(argv[i])) == NULL) { + Py_DECREF(v); + v = NULL; + break; + } + PyTuple_SET_ITEM(v, i, w); + } + } + Tcl_Free(FREECAST argv); + return v; +} + +/* In some cases, Tcl will still return strings that are supposed to + be lists. SplitObj walks through a nested tuple, finding string + objects that need to be split. */ + +static PyObject * +SplitObj(PyObject *arg) +{ + if (PyTuple_Check(arg)) { + Py_ssize_t i, size; + PyObject *elem, *newelem, *result; + + size = PyTuple_GET_SIZE(arg); + result = NULL; + /* Recursively invoke SplitObj for all tuple items. + If this does not return a new object, no action is + needed. */ + for(i = 0; i < size; i++) { + elem = PyTuple_GET_ITEM(arg, i); + newelem = SplitObj(elem); + if (!newelem) { + Py_XDECREF(result); + return NULL; + } + if (!result) { + Py_ssize_t k; + if (newelem == elem) { + Py_DECREF(newelem); + continue; + } + result = PyTuple_New(size); + if (!result) + return NULL; + for(k = 0; k < i; k++) { + elem = PyTuple_GET_ITEM(arg, k); + Py_INCREF(elem); + PyTuple_SET_ITEM(result, k, elem); + } + } + PyTuple_SET_ITEM(result, i, newelem); + } + if (result) + return result; + /* Fall through, returning arg. */ + } + else if (PyList_Check(arg)) { + Py_ssize_t i, size; + PyObject *elem, *newelem, *result; + + size = PyList_GET_SIZE(arg); + result = PyTuple_New(size); + if (!result) + return NULL; + /* Recursively invoke SplitObj for all list items. */ + for(i = 0; i < size; i++) { + elem = PyList_GET_ITEM(arg, i); + newelem = SplitObj(elem); + if (!newelem) { + Py_XDECREF(result); + return NULL; + } + PyTuple_SET_ITEM(result, i, newelem); + } + return result; + } + else if (PyUnicode_Check(arg)) { + int argc; + const char **argv; + const char *list = PyUnicode_AsUTF8(arg); + + if (list == NULL || + Tcl_SplitList((Tcl_Interp *)NULL, list, &argc, &argv) != TCL_OK) { + Py_INCREF(arg); + return arg; + } + Tcl_Free(FREECAST argv); + if (argc > 1) + return Split(list); + /* Fall through, returning arg. */ + } + else if (PyBytes_Check(arg)) { + int argc; + const char **argv; + const char *list = PyBytes_AS_STRING(arg); + + if (Tcl_SplitList((Tcl_Interp *)NULL, (char *)list, &argc, &argv) != TCL_OK) { + Py_INCREF(arg); + return arg; + } + Tcl_Free(FREECAST argv); + if (argc > 1) + return Split(PyBytes_AS_STRING(arg)); + /* Fall through, returning arg. */ + } + Py_INCREF(arg); + return arg; +} + + /*[clinic input] module _tkinter class _tkinter.tkapp "TkappObject *" "&Tkapp_Type_spec" @@ -2203,6 +2342,68 @@ _tkinter_tkapp_splitlist(TkappObject *self, PyObject *arg) return v; } +/*[clinic input] +_tkinter.tkapp.split + + arg: object + / + +[clinic start generated code]*/ + +static PyObject * +_tkinter_tkapp_split(TkappObject *self, PyObject *arg) +/*[clinic end generated code: output=e08ad832363facfd input=a1c78349eacaa140]*/ +{ + PyObject *v; + char *list; + + if (PyErr_WarnEx(PyExc_DeprecationWarning, + "split() is deprecated; consider using splitlist() instead", 1)) + { + return NULL; + } + + if (PyTclObject_Check(arg)) { + Tcl_Obj *value = ((PyTclObject*)arg)->value; + int objc; + Tcl_Obj **objv; + int i; + if (Tcl_ListObjGetElements(Tkapp_Interp(self), value, + &objc, &objv) == TCL_ERROR) { + return FromObj(self, value); + } + if (objc == 0) + return PyUnicode_FromString(""); + if (objc == 1) + return FromObj(self, objv[0]); + if (!(v = PyTuple_New(objc))) + return NULL; + for (i = 0; i < objc; i++) { + PyObject *s = FromObj(self, objv[i]); + if (!s) { + Py_DECREF(v); + return NULL; + } + PyTuple_SET_ITEM(v, i, s); + } + return v; + } + if (PyTuple_Check(arg) || PyList_Check(arg)) + return SplitObj(arg); + + if (!PyArg_Parse(arg, "et:split", "utf-8", &list)) + return NULL; + if (strlen(list) >= INT_MAX) { + PyErr_SetString(PyExc_OverflowError, "string is too long"); + PyMem_Free(list); + return NULL; + } + v = Split(list); + PyMem_Free(list); + return v; +} + + /** Tcl Command **/ @@ -3130,6 +3331,7 @@ static PyMethodDef Tkapp_methods[] = _TKINTER_TKAPP_EXPRDOUBLE_METHODDEF _TKINTER_TKAPP_EXPRBOOLEAN_METHODDEF _TKINTER_TKAPP_SPLITLIST_METHODDEF + _TKINTER_TKAPP_SPLIT_METHODDEF _TKINTER_TKAPP_CREATECOMMAND_METHODDEF _TKINTER_TKAPP_DELETECOMMAND_METHODDEF _TKINTER_TKAPP_CREATEFILEHANDLER_METHODDEF From 3abf81233618a1702b8b52b52da1dfce6efcc9d8 Mon Sep 17 00:00:00 2001 From: Livius Date: Fri, 10 Sep 2021 00:37:35 +0200 Subject: [PATCH 23/57] add clock_nanosleep() only --- Modules/timemodule.c | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/Modules/timemodule.c b/Modules/timemodule.c index 4caacc3b64d7c8..dae11ca7d583cc 100644 --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -2053,7 +2053,11 @@ pysleep(_PyTime_t secs) { _PyTime_t deadline, monotonic; #ifndef MS_WINDOWS +#ifdef HAVE_CLOCK_NANOSLEEP + struct timespec timeout; +#else struct timeval timeout; +#endif int err = 0; #else _PyTime_t millisecs; @@ -2066,23 +2070,44 @@ pysleep(_PyTime_t secs) return -1; } deadline = monotonic + secs; +#if defined(HAVE_CLOCK_NANOSLEEP) && !defined(MS_WINDOWS) + if (_PyTime_AsTimespec(deadline, &timeout) < 0) { + return -1; + } +#endif do { #ifndef MS_WINDOWS - if (_PyTime_AsTimeval(secs, &timeout, _PyTime_ROUND_CEILING) < 0) +#ifndef HAVE_CLOCK_NANOSLEEP + if (_PyTime_AsTimeval(secs, &timeout, _PyTime_ROUND_CEILING) < 0) { return -1; + } +#endif Py_BEGIN_ALLOW_THREADS +#ifdef HAVE_CLOCK_NANOSLEEP + err = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &timeout, NULL); +#else err = select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &timeout); +#endif Py_END_ALLOW_THREADS - if (err == 0) + if (err == 0) { break; + } +#ifdef HAVE_CLOCK_NANOSLEEP + if (err != EINTR) { + errno = err; + PyErr_SetFromErrno(PyExc_OSError); + return -1; + } +#else if (errno != EINTR) { PyErr_SetFromErrno(PyExc_OSError); return -1; } +#endif #else millisecs = _PyTime_AsMilliseconds(secs, _PyTime_ROUND_CEILING); if (millisecs > (double)ULONG_MAX) { @@ -2114,8 +2139,9 @@ pysleep(_PyTime_t secs) #endif /* sleep was interrupted by SIGINT */ - if (PyErr_CheckSignals()) + if (PyErr_CheckSignals()) { return -1; + } if (get_monotonic(&monotonic) < 0) { return -1; From 4cbfde2d60e83fe564d75384626ab211f24a2283 Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Fri, 10 Sep 2021 00:24:09 +0000 Subject: [PATCH 24/57] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20b?= =?UTF-8?q?lurb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../NEWS.d/next/Library/2021-09-10-00-24-08.bpo-21302.XS_frc.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Library/2021-09-10-00-24-08.bpo-21302.XS_frc.rst diff --git a/Misc/NEWS.d/next/Library/2021-09-10-00-24-08.bpo-21302.XS_frc.rst b/Misc/NEWS.d/next/Library/2021-09-10-00-24-08.bpo-21302.XS_frc.rst new file mode 100644 index 00000000000000..c9b77c1f2f002e --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-09-10-00-24-08.bpo-21302.XS_frc.rst @@ -0,0 +1 @@ +In Unix operating systems time.sleep() has a resolution of nanoseconds with using clock_nanosleep() function. \ No newline at end of file From d99c06e7793736942ddc949f07cdbf1a59fcb33e Mon Sep 17 00:00:00 2001 From: Livius Date: Fri, 10 Sep 2021 21:19:17 +0200 Subject: [PATCH 25/57] Update Misc/NEWS.d/next/Library/2021-09-10-00-24-08.bpo-21302.XS_frc.rst suggested description Co-authored-by: Victor Stinner --- .../next/Library/2021-09-10-00-24-08.bpo-21302.XS_frc.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Library/2021-09-10-00-24-08.bpo-21302.XS_frc.rst b/Misc/NEWS.d/next/Library/2021-09-10-00-24-08.bpo-21302.XS_frc.rst index c9b77c1f2f002e..2e64089d4f0166 100644 --- a/Misc/NEWS.d/next/Library/2021-09-10-00-24-08.bpo-21302.XS_frc.rst +++ b/Misc/NEWS.d/next/Library/2021-09-10-00-24-08.bpo-21302.XS_frc.rst @@ -1 +1,2 @@ -In Unix operating systems time.sleep() has a resolution of nanoseconds with using clock_nanosleep() function. \ No newline at end of file +In Unix operating systems, :func:`time.sleep` now uses the ``clock_nanosleep()`` function, +if available, which allows to sleep for an interval specified with nanosecond precision. \ No newline at end of file From 117dc62bffac92e78487830426c069e165d10b5f Mon Sep 17 00:00:00 2001 From: Livius Date: Fri, 10 Sep 2021 21:36:11 +0200 Subject: [PATCH 26/57] timeout_abs renaming --- Modules/timemodule.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Modules/timemodule.c b/Modules/timemodule.c index dae11ca7d583cc..eebbda014bcea3 100644 --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -2054,7 +2054,7 @@ pysleep(_PyTime_t secs) _PyTime_t deadline, monotonic; #ifndef MS_WINDOWS #ifdef HAVE_CLOCK_NANOSLEEP - struct timespec timeout; + struct timespec timeout_abs; #else struct timeval timeout; #endif @@ -2071,7 +2071,7 @@ pysleep(_PyTime_t secs) } deadline = monotonic + secs; #if defined(HAVE_CLOCK_NANOSLEEP) && !defined(MS_WINDOWS) - if (_PyTime_AsTimespec(deadline, &timeout) < 0) { + if (_PyTime_AsTimespec(deadline, &timeout_abs) < 0) { return -1; } #endif @@ -2086,7 +2086,7 @@ pysleep(_PyTime_t secs) Py_BEGIN_ALLOW_THREADS #ifdef HAVE_CLOCK_NANOSLEEP - err = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &timeout, NULL); + err = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &timeout_abs, NULL); #else err = select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &timeout); #endif From 92061f35808a39d43465b508ac68f9393994eba3 Mon Sep 17 00:00:00 2001 From: Livius Date: Fri, 10 Sep 2021 21:47:12 +0200 Subject: [PATCH 27/57] Simplified HAVE_CLOCK_NANOSLEEP macro blocks --- Modules/timemodule.c | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/Modules/timemodule.c b/Modules/timemodule.c index eebbda014bcea3..975779df9e7ef7 100644 --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -2070,44 +2070,46 @@ pysleep(_PyTime_t secs) return -1; } deadline = monotonic + secs; + #if defined(HAVE_CLOCK_NANOSLEEP) && !defined(MS_WINDOWS) if (_PyTime_AsTimespec(deadline, &timeout_abs) < 0) { return -1; } -#endif + + Py_BEGIN_ALLOW_THREADS + err = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &timeout_abs, NULL); + Py_END_ALLOW_THREADS + + if (err != EINTR) { + errno = err; + PyErr_SetFromErrno(PyExc_OSError); + return -1; + } + + /* sleep was interrupted by SIGINT */ + if (PyErr_CheckSignals()) { + return -1; + } +#else do { #ifndef MS_WINDOWS -#ifndef HAVE_CLOCK_NANOSLEEP if (_PyTime_AsTimeval(secs, &timeout, _PyTime_ROUND_CEILING) < 0) { return -1; } -#endif Py_BEGIN_ALLOW_THREADS -#ifdef HAVE_CLOCK_NANOSLEEP - err = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &timeout_abs, NULL); -#else err = select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &timeout); -#endif Py_END_ALLOW_THREADS if (err == 0) { break; } -#ifdef HAVE_CLOCK_NANOSLEEP - if (err != EINTR) { - errno = err; - PyErr_SetFromErrno(PyExc_OSError); - return -1; - } -#else if (errno != EINTR) { PyErr_SetFromErrno(PyExc_OSError); return -1; } -#endif #else millisecs = _PyTime_AsMilliseconds(secs, _PyTime_ROUND_CEILING); if (millisecs > (double)ULONG_MAX) { @@ -2152,6 +2154,7 @@ pysleep(_PyTime_t secs) } /* retry with the recomputed delay */ } while (1); +#endif return 0; } From f0450470f6b4e26bf2fba9629ccb3e907a47a4ab Mon Sep 17 00:00:00 2001 From: Livius Date: Fri, 10 Sep 2021 23:00:37 +0200 Subject: [PATCH 28/57] remake news --- .../next/Library/2021-09-10-00-24-08.bpo-21302.XS_frc.rst | 2 -- 1 file changed, 2 deletions(-) delete mode 100644 Misc/NEWS.d/next/Library/2021-09-10-00-24-08.bpo-21302.XS_frc.rst diff --git a/Misc/NEWS.d/next/Library/2021-09-10-00-24-08.bpo-21302.XS_frc.rst b/Misc/NEWS.d/next/Library/2021-09-10-00-24-08.bpo-21302.XS_frc.rst deleted file mode 100644 index 2e64089d4f0166..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-09-10-00-24-08.bpo-21302.XS_frc.rst +++ /dev/null @@ -1,2 +0,0 @@ -In Unix operating systems, :func:`time.sleep` now uses the ``clock_nanosleep()`` function, -if available, which allows to sleep for an interval specified with nanosecond precision. \ No newline at end of file From 24f9975d6cbcc69890dd86f8675280783caf5991 Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Fri, 10 Sep 2021 21:01:32 +0000 Subject: [PATCH 29/57] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20b?= =?UTF-8?q?lurb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../next/Library/2021-09-10-21-01-32.bpo-21302.QxHRpR.rst | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 Misc/NEWS.d/next/Library/2021-09-10-21-01-32.bpo-21302.QxHRpR.rst diff --git a/Misc/NEWS.d/next/Library/2021-09-10-21-01-32.bpo-21302.QxHRpR.rst b/Misc/NEWS.d/next/Library/2021-09-10-21-01-32.bpo-21302.QxHRpR.rst new file mode 100644 index 00000000000000..86f0a5ac4c2a5a --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-09-10-21-01-32.bpo-21302.QxHRpR.rst @@ -0,0 +1,2 @@ +In Unix operating systems, :func:`time.sleep` now uses the ``clock_nanosleep()`` function, +if available, which allows to sleep for an interval specified with nanosecond precision. \ No newline at end of file From 34e38839cdfc07626b4a136485c9c1f6e4dc574f Mon Sep 17 00:00:00 2001 From: Livius Date: Sat, 11 Sep 2021 01:06:54 +0200 Subject: [PATCH 30/57] Fix err checking --- .../next/Library/2021-09-10-21-01-32.bpo-21302.QxHRpR.rst | 2 -- Modules/timemodule.c | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) delete mode 100644 Misc/NEWS.d/next/Library/2021-09-10-21-01-32.bpo-21302.QxHRpR.rst diff --git a/Misc/NEWS.d/next/Library/2021-09-10-21-01-32.bpo-21302.QxHRpR.rst b/Misc/NEWS.d/next/Library/2021-09-10-21-01-32.bpo-21302.QxHRpR.rst deleted file mode 100644 index 86f0a5ac4c2a5a..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-09-10-21-01-32.bpo-21302.QxHRpR.rst +++ /dev/null @@ -1,2 +0,0 @@ -In Unix operating systems, :func:`time.sleep` now uses the ``clock_nanosleep()`` function, -if available, which allows to sleep for an interval specified with nanosecond precision. \ No newline at end of file diff --git a/Modules/timemodule.c b/Modules/timemodule.c index 975779df9e7ef7..a9919d1c93a5ca 100644 --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -2080,7 +2080,7 @@ pysleep(_PyTime_t secs) err = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &timeout_abs, NULL); Py_END_ALLOW_THREADS - if (err != EINTR) { + if ((err != EINTR) && (err != 0)) { errno = err; PyErr_SetFromErrno(PyExc_OSError); return -1; From fec634f81cf2e8751a66cea86d84a918fe11a4c0 Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Fri, 10 Sep 2021 23:09:48 +0000 Subject: [PATCH 31/57] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20b?= =?UTF-8?q?lurb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../next/Library/2021-09-10-23-09-47.bpo-21302.QxHRpR.rst | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 Misc/NEWS.d/next/Library/2021-09-10-23-09-47.bpo-21302.QxHRpR.rst diff --git a/Misc/NEWS.d/next/Library/2021-09-10-23-09-47.bpo-21302.QxHRpR.rst b/Misc/NEWS.d/next/Library/2021-09-10-23-09-47.bpo-21302.QxHRpR.rst new file mode 100644 index 00000000000000..86f0a5ac4c2a5a --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-09-10-23-09-47.bpo-21302.QxHRpR.rst @@ -0,0 +1,2 @@ +In Unix operating systems, :func:`time.sleep` now uses the ``clock_nanosleep()`` function, +if available, which allows to sleep for an interval specified with nanosecond precision. \ No newline at end of file From 80220620440de5a93f46cef98db93b0b62833c41 Mon Sep 17 00:00:00 2001 From: Livius Date: Sat, 11 Sep 2021 01:26:23 +0200 Subject: [PATCH 32/57] revert changes Can not simplify HAVE_CLOCK_NANOSLEEP blocks because do {} while loop need for EINTR error handling --- .../2021-09-10-23-09-47.bpo-21302.QxHRpR.rst | 2 -- Modules/timemodule.c | 33 +++++++++---------- 2 files changed, 15 insertions(+), 20 deletions(-) delete mode 100644 Misc/NEWS.d/next/Library/2021-09-10-23-09-47.bpo-21302.QxHRpR.rst diff --git a/Misc/NEWS.d/next/Library/2021-09-10-23-09-47.bpo-21302.QxHRpR.rst b/Misc/NEWS.d/next/Library/2021-09-10-23-09-47.bpo-21302.QxHRpR.rst deleted file mode 100644 index 86f0a5ac4c2a5a..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-09-10-23-09-47.bpo-21302.QxHRpR.rst +++ /dev/null @@ -1,2 +0,0 @@ -In Unix operating systems, :func:`time.sleep` now uses the ``clock_nanosleep()`` function, -if available, which allows to sleep for an interval specified with nanosecond precision. \ No newline at end of file diff --git a/Modules/timemodule.c b/Modules/timemodule.c index a9919d1c93a5ca..eebbda014bcea3 100644 --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -2070,46 +2070,44 @@ pysleep(_PyTime_t secs) return -1; } deadline = monotonic + secs; - #if defined(HAVE_CLOCK_NANOSLEEP) && !defined(MS_WINDOWS) if (_PyTime_AsTimespec(deadline, &timeout_abs) < 0) { return -1; } - - Py_BEGIN_ALLOW_THREADS - err = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &timeout_abs, NULL); - Py_END_ALLOW_THREADS - - if ((err != EINTR) && (err != 0)) { - errno = err; - PyErr_SetFromErrno(PyExc_OSError); - return -1; - } - - /* sleep was interrupted by SIGINT */ - if (PyErr_CheckSignals()) { - return -1; - } -#else +#endif do { #ifndef MS_WINDOWS +#ifndef HAVE_CLOCK_NANOSLEEP if (_PyTime_AsTimeval(secs, &timeout, _PyTime_ROUND_CEILING) < 0) { return -1; } +#endif Py_BEGIN_ALLOW_THREADS +#ifdef HAVE_CLOCK_NANOSLEEP + err = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &timeout_abs, NULL); +#else err = select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &timeout); +#endif Py_END_ALLOW_THREADS if (err == 0) { break; } +#ifdef HAVE_CLOCK_NANOSLEEP + if (err != EINTR) { + errno = err; + PyErr_SetFromErrno(PyExc_OSError); + return -1; + } +#else if (errno != EINTR) { PyErr_SetFromErrno(PyExc_OSError); return -1; } +#endif #else millisecs = _PyTime_AsMilliseconds(secs, _PyTime_ROUND_CEILING); if (millisecs > (double)ULONG_MAX) { @@ -2154,7 +2152,6 @@ pysleep(_PyTime_t secs) } /* retry with the recomputed delay */ } while (1); -#endif return 0; } From 4685ec778232c8d3d1e1677390792b47bda75d3c Mon Sep 17 00:00:00 2001 From: Livius Date: Sat, 11 Sep 2021 01:30:18 +0200 Subject: [PATCH 33/57] get_monotonic() and secs re-calculation are useless for clock_nanosleep() --- Modules/timemodule.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Modules/timemodule.c b/Modules/timemodule.c index eebbda014bcea3..b6699fb4891825 100644 --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -2143,6 +2143,7 @@ pysleep(_PyTime_t secs) return -1; } +#ifndef HAVE_CLOCK_NANOSLEEP if (get_monotonic(&monotonic) < 0) { return -1; } @@ -2151,6 +2152,7 @@ pysleep(_PyTime_t secs) break; } /* retry with the recomputed delay */ +#endif } while (1); return 0; From 0ad19e0e1e72e624cc94a2847ee8378d3321202a Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Fri, 10 Sep 2021 23:37:31 +0000 Subject: [PATCH 34/57] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20b?= =?UTF-8?q?lurb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../next/Library/2021-09-10-23-37-30.bpo-21302.QxHRpR.rst | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 Misc/NEWS.d/next/Library/2021-09-10-23-37-30.bpo-21302.QxHRpR.rst diff --git a/Misc/NEWS.d/next/Library/2021-09-10-23-37-30.bpo-21302.QxHRpR.rst b/Misc/NEWS.d/next/Library/2021-09-10-23-37-30.bpo-21302.QxHRpR.rst new file mode 100644 index 00000000000000..86f0a5ac4c2a5a --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-09-10-23-37-30.bpo-21302.QxHRpR.rst @@ -0,0 +1,2 @@ +In Unix operating systems, :func:`time.sleep` now uses the ``clock_nanosleep()`` function, +if available, which allows to sleep for an interval specified with nanosecond precision. \ No newline at end of file From 0839d0d31bdae39f22bbb3fbdb35bf17f04e60be Mon Sep 17 00:00:00 2001 From: Livius Date: Sat, 11 Sep 2021 11:22:44 +0200 Subject: [PATCH 35/57] merge errno in HAVE_CLOCK_NANOSLEEP --- Modules/timemodule.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/Modules/timemodule.c b/Modules/timemodule.c index b6699fb4891825..3a9a5c137e83dd 100644 --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -2087,6 +2087,7 @@ pysleep(_PyTime_t secs) Py_BEGIN_ALLOW_THREADS #ifdef HAVE_CLOCK_NANOSLEEP err = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &timeout_abs, NULL); + errno = err; #else err = select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &timeout); #endif @@ -2096,18 +2097,10 @@ pysleep(_PyTime_t secs) break; } -#ifdef HAVE_CLOCK_NANOSLEEP - if (err != EINTR) { - errno = err; - PyErr_SetFromErrno(PyExc_OSError); - return -1; - } -#else if (errno != EINTR) { PyErr_SetFromErrno(PyExc_OSError); return -1; } -#endif #else millisecs = _PyTime_AsMilliseconds(secs, _PyTime_ROUND_CEILING); if (millisecs > (double)ULONG_MAX) { From 39cff8f32731914aef5ad94bb211f9ad2cf6953e Mon Sep 17 00:00:00 2001 From: Livius Date: Sat, 11 Sep 2021 12:09:16 +0200 Subject: [PATCH 36/57] remake news rst --- .../next/Library/2021-09-10-23-37-30.bpo-21302.QxHRpR.rst | 2 -- 1 file changed, 2 deletions(-) delete mode 100644 Misc/NEWS.d/next/Library/2021-09-10-23-37-30.bpo-21302.QxHRpR.rst diff --git a/Misc/NEWS.d/next/Library/2021-09-10-23-37-30.bpo-21302.QxHRpR.rst b/Misc/NEWS.d/next/Library/2021-09-10-23-37-30.bpo-21302.QxHRpR.rst deleted file mode 100644 index 86f0a5ac4c2a5a..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-09-10-23-37-30.bpo-21302.QxHRpR.rst +++ /dev/null @@ -1,2 +0,0 @@ -In Unix operating systems, :func:`time.sleep` now uses the ``clock_nanosleep()`` function, -if available, which allows to sleep for an interval specified with nanosecond precision. \ No newline at end of file From 87d57121389befd77c8e4bee13a72b83d31e28a5 Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Sat, 11 Sep 2021 10:10:24 +0000 Subject: [PATCH 37/57] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20b?= =?UTF-8?q?lurb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../next/Library/2021-09-11-10-10-23.bpo-21302.QxHRpR.rst | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 Misc/NEWS.d/next/Library/2021-09-11-10-10-23.bpo-21302.QxHRpR.rst diff --git a/Misc/NEWS.d/next/Library/2021-09-11-10-10-23.bpo-21302.QxHRpR.rst b/Misc/NEWS.d/next/Library/2021-09-11-10-10-23.bpo-21302.QxHRpR.rst new file mode 100644 index 00000000000000..86f0a5ac4c2a5a --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-09-11-10-10-23.bpo-21302.QxHRpR.rst @@ -0,0 +1,2 @@ +In Unix operating systems, :func:`time.sleep` now uses the ``clock_nanosleep()`` function, +if available, which allows to sleep for an interval specified with nanosecond precision. \ No newline at end of file From 56cb8e1c599d1d70701a374f2b0002208554c834 Mon Sep 17 00:00:00 2001 From: Livius Date: Sat, 11 Sep 2021 14:02:59 +0200 Subject: [PATCH 38/57] Try to fix Address sanitizer test issue --- .../2021-09-11-10-10-23.bpo-21302.QxHRpR.rst | 2 -- Modules/timemodule.c | 13 ++++++++----- 2 files changed, 8 insertions(+), 7 deletions(-) delete mode 100644 Misc/NEWS.d/next/Library/2021-09-11-10-10-23.bpo-21302.QxHRpR.rst diff --git a/Misc/NEWS.d/next/Library/2021-09-11-10-10-23.bpo-21302.QxHRpR.rst b/Misc/NEWS.d/next/Library/2021-09-11-10-10-23.bpo-21302.QxHRpR.rst deleted file mode 100644 index 86f0a5ac4c2a5a..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-09-11-10-10-23.bpo-21302.QxHRpR.rst +++ /dev/null @@ -1,2 +0,0 @@ -In Unix operating systems, :func:`time.sleep` now uses the ``clock_nanosleep()`` function, -if available, which allows to sleep for an interval specified with nanosecond precision. \ No newline at end of file diff --git a/Modules/timemodule.c b/Modules/timemodule.c index 3a9a5c137e83dd..e540987d03c9eb 100644 --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -2059,6 +2059,7 @@ pysleep(_PyTime_t secs) struct timeval timeout; #endif int err = 0; + int ret = 0; #else _PyTime_t millisecs; unsigned long ul_millis; @@ -2086,18 +2087,20 @@ pysleep(_PyTime_t secs) Py_BEGIN_ALLOW_THREADS #ifdef HAVE_CLOCK_NANOSLEEP - err = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &timeout_abs, NULL); - errno = err; + ret = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &timeout_abs, NULL); + err = ret; #else - err = select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &timeout); + ret = select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &timeout); + err = errno; #endif Py_END_ALLOW_THREADS - if (err == 0) { + if (ret == 0) { break; } - if (errno != EINTR) { + if (err != EINTR) { + errno = err; PyErr_SetFromErrno(PyExc_OSError); return -1; } From 8ec03be0292fabbd24595b865553a085cfe44e60 Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Sat, 11 Sep 2021 12:24:21 +0000 Subject: [PATCH 39/57] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20b?= =?UTF-8?q?lurb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../next/Library/2021-09-11-12-24-20.bpo-21302.QxHRpR.rst | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 Misc/NEWS.d/next/Library/2021-09-11-12-24-20.bpo-21302.QxHRpR.rst diff --git a/Misc/NEWS.d/next/Library/2021-09-11-12-24-20.bpo-21302.QxHRpR.rst b/Misc/NEWS.d/next/Library/2021-09-11-12-24-20.bpo-21302.QxHRpR.rst new file mode 100644 index 00000000000000..86f0a5ac4c2a5a --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-09-11-12-24-20.bpo-21302.QxHRpR.rst @@ -0,0 +1,2 @@ +In Unix operating systems, :func:`time.sleep` now uses the ``clock_nanosleep()`` function, +if available, which allows to sleep for an interval specified with nanosecond precision. \ No newline at end of file From b1ccdbaa7ac919c63b04209d895f68db4abee3e1 Mon Sep 17 00:00:00 2001 From: Livius Date: Sat, 11 Sep 2021 15:56:22 +0200 Subject: [PATCH 40/57] #2 Try to fix Address sanitizer test issue --- .../next/Library/2021-09-11-12-24-20.bpo-21302.QxHRpR.rst | 2 -- Modules/timemodule.c | 8 ++++++-- 2 files changed, 6 insertions(+), 4 deletions(-) delete mode 100644 Misc/NEWS.d/next/Library/2021-09-11-12-24-20.bpo-21302.QxHRpR.rst diff --git a/Misc/NEWS.d/next/Library/2021-09-11-12-24-20.bpo-21302.QxHRpR.rst b/Misc/NEWS.d/next/Library/2021-09-11-12-24-20.bpo-21302.QxHRpR.rst deleted file mode 100644 index 86f0a5ac4c2a5a..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-09-11-12-24-20.bpo-21302.QxHRpR.rst +++ /dev/null @@ -1,2 +0,0 @@ -In Unix operating systems, :func:`time.sleep` now uses the ``clock_nanosleep()`` function, -if available, which allows to sleep for an interval specified with nanosecond precision. \ No newline at end of file diff --git a/Modules/timemodule.c b/Modules/timemodule.c index e540987d03c9eb..e8fae1f3e4b0e0 100644 --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -2085,15 +2085,19 @@ pysleep(_PyTime_t secs) } #endif - Py_BEGIN_ALLOW_THREADS + #ifdef HAVE_CLOCK_NANOSLEEP + Py_BEGIN_ALLOW_THREADS ret = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &timeout_abs, NULL); + Py_END_ALLOW_THREADS err = ret; #else + Py_BEGIN_ALLOW_THREADS ret = select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &timeout); + Py_END_ALLOW_THREADS err = errno; #endif - Py_END_ALLOW_THREADS + if (ret == 0) { break; From c8372c89ae7b1c8f3f71d18a7fdd4a92dedc7e05 Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Sat, 11 Sep 2021 13:57:04 +0000 Subject: [PATCH 41/57] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20b?= =?UTF-8?q?lurb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../next/Library/2021-09-11-13-57-03.bpo-21302.QxHRpR.rst | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 Misc/NEWS.d/next/Library/2021-09-11-13-57-03.bpo-21302.QxHRpR.rst diff --git a/Misc/NEWS.d/next/Library/2021-09-11-13-57-03.bpo-21302.QxHRpR.rst b/Misc/NEWS.d/next/Library/2021-09-11-13-57-03.bpo-21302.QxHRpR.rst new file mode 100644 index 00000000000000..86f0a5ac4c2a5a --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-09-11-13-57-03.bpo-21302.QxHRpR.rst @@ -0,0 +1,2 @@ +In Unix operating systems, :func:`time.sleep` now uses the ``clock_nanosleep()`` function, +if available, which allows to sleep for an interval specified with nanosecond precision. \ No newline at end of file From 1cf2205b38487dced605ccc1fbea62e9668e8cff Mon Sep 17 00:00:00 2001 From: Livius Date: Sat, 11 Sep 2021 17:14:05 +0200 Subject: [PATCH 42/57] remake news rst --- .../next/Library/2021-09-11-13-57-03.bpo-21302.QxHRpR.rst | 2 -- 1 file changed, 2 deletions(-) delete mode 100644 Misc/NEWS.d/next/Library/2021-09-11-13-57-03.bpo-21302.QxHRpR.rst diff --git a/Misc/NEWS.d/next/Library/2021-09-11-13-57-03.bpo-21302.QxHRpR.rst b/Misc/NEWS.d/next/Library/2021-09-11-13-57-03.bpo-21302.QxHRpR.rst deleted file mode 100644 index 86f0a5ac4c2a5a..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-09-11-13-57-03.bpo-21302.QxHRpR.rst +++ /dev/null @@ -1,2 +0,0 @@ -In Unix operating systems, :func:`time.sleep` now uses the ``clock_nanosleep()`` function, -if available, which allows to sleep for an interval specified with nanosecond precision. \ No newline at end of file From 1e725dafd42d61b5dfefa2bed5107949b348284f Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Sat, 11 Sep 2021 15:46:39 +0000 Subject: [PATCH 43/57] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20b?= =?UTF-8?q?lurb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../next/Library/2021-09-11-15-46-38.bpo-21302.QxHRpR.rst | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 Misc/NEWS.d/next/Library/2021-09-11-15-46-38.bpo-21302.QxHRpR.rst diff --git a/Misc/NEWS.d/next/Library/2021-09-11-15-46-38.bpo-21302.QxHRpR.rst b/Misc/NEWS.d/next/Library/2021-09-11-15-46-38.bpo-21302.QxHRpR.rst new file mode 100644 index 00000000000000..86f0a5ac4c2a5a --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-09-11-15-46-38.bpo-21302.QxHRpR.rst @@ -0,0 +1,2 @@ +In Unix operating systems, :func:`time.sleep` now uses the ``clock_nanosleep()`` function, +if available, which allows to sleep for an interval specified with nanosecond precision. \ No newline at end of file From 3566c59e7820e7df361858fde38dfb3c8115089a Mon Sep 17 00:00:00 2001 From: Livius Date: Sat, 11 Sep 2021 20:08:43 +0200 Subject: [PATCH 44/57] re-make news rst --- .../next/Library/2021-09-11-15-46-38.bpo-21302.QxHRpR.rst | 2 -- Modules/timemodule.c | 2 -- 2 files changed, 4 deletions(-) delete mode 100644 Misc/NEWS.d/next/Library/2021-09-11-15-46-38.bpo-21302.QxHRpR.rst diff --git a/Misc/NEWS.d/next/Library/2021-09-11-15-46-38.bpo-21302.QxHRpR.rst b/Misc/NEWS.d/next/Library/2021-09-11-15-46-38.bpo-21302.QxHRpR.rst deleted file mode 100644 index 86f0a5ac4c2a5a..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-09-11-15-46-38.bpo-21302.QxHRpR.rst +++ /dev/null @@ -1,2 +0,0 @@ -In Unix operating systems, :func:`time.sleep` now uses the ``clock_nanosleep()`` function, -if available, which allows to sleep for an interval specified with nanosecond precision. \ No newline at end of file diff --git a/Modules/timemodule.c b/Modules/timemodule.c index e8fae1f3e4b0e0..cf58a18caf1f20 100644 --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -2085,7 +2085,6 @@ pysleep(_PyTime_t secs) } #endif - #ifdef HAVE_CLOCK_NANOSLEEP Py_BEGIN_ALLOW_THREADS ret = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &timeout_abs, NULL); @@ -2097,7 +2096,6 @@ pysleep(_PyTime_t secs) Py_END_ALLOW_THREADS err = errno; #endif - if (ret == 0) { break; From 278aaa2a4d8a07bcad99bf6b94c551da10cd9e47 Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Sat, 11 Sep 2021 18:44:41 +0000 Subject: [PATCH 45/57] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20b?= =?UTF-8?q?lurb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../next/Library/2021-09-11-18-44-40.bpo-21302.QxHRpR.rst | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 Misc/NEWS.d/next/Library/2021-09-11-18-44-40.bpo-21302.QxHRpR.rst diff --git a/Misc/NEWS.d/next/Library/2021-09-11-18-44-40.bpo-21302.QxHRpR.rst b/Misc/NEWS.d/next/Library/2021-09-11-18-44-40.bpo-21302.QxHRpR.rst new file mode 100644 index 00000000000000..86f0a5ac4c2a5a --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-09-11-18-44-40.bpo-21302.QxHRpR.rst @@ -0,0 +1,2 @@ +In Unix operating systems, :func:`time.sleep` now uses the ``clock_nanosleep()`` function, +if available, which allows to sleep for an interval specified with nanosecond precision. \ No newline at end of file From df7e4c938729d68c9d84b8a725a6eb201bb4157f Mon Sep 17 00:00:00 2001 From: Livius Date: Tue, 14 Sep 2021 21:57:13 +0200 Subject: [PATCH 46/57] Add Waitable timer implmentation in time.sleep() for Windows --- Modules/timemodule.c | 96 ++++++++++++++++++++++++++------------------ 1 file changed, 58 insertions(+), 38 deletions(-) diff --git a/Modules/timemodule.c b/Modules/timemodule.c index cf58a18caf1f20..28148900c9c7c2 100644 --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -2051,34 +2051,51 @@ PyInit_time(void) static int pysleep(_PyTime_t secs) { - _PyTime_t deadline, monotonic; #ifndef MS_WINDOWS #ifdef HAVE_CLOCK_NANOSLEEP struct timespec timeout_abs; #else struct timeval timeout; #endif + _PyTime_t deadline, monotonic; int err = 0; int ret = 0; -#else - _PyTime_t millisecs; - unsigned long ul_millis; - DWORD rc; - HANDLE hInterruptEvent; -#endif if (get_monotonic(&monotonic) < 0) { return -1; } deadline = monotonic + secs; -#if defined(HAVE_CLOCK_NANOSLEEP) && !defined(MS_WINDOWS) +#ifdef HAVE_CLOCK_NANOSLEEP if (_PyTime_AsTimespec(deadline, &timeout_abs) < 0) { return -1; } #endif +#else + _PyTime_t millisecs; + DWORD ul_millis; + DWORD rc; + FILETIME FileTime; + LARGE_INTEGER deadline; + HANDLE hTimer = NULL; + + GetSystemTimePreciseAsFileTime(&FileTime); + CopyMemory(&deadline, &FileTime, sizeof(FILETIME)); + + /* convert to 100 nsec unit */ + deadline.QuadPart += (_PyTime_AsMicroseconds(secs, _PyTime_ROUND_CEILING) * 10); + + hTimer = CreateWaitableTimerW(NULL, FALSE, NULL); + if (NULL == hTimer) { + return -1; + } + + if (!SetWaitableTimer(hTimer, &deadline, 0, NULL, NULL, FALSE)) { + return -1; + } +#endif - do { #ifndef MS_WINDOWS + do { #ifndef HAVE_CLOCK_NANOSLEEP if (_PyTime_AsTimeval(secs, &timeout, _PyTime_ROUND_CEILING) < 0) { return -1; @@ -2106,35 +2123,6 @@ pysleep(_PyTime_t secs) PyErr_SetFromErrno(PyExc_OSError); return -1; } -#else - millisecs = _PyTime_AsMilliseconds(secs, _PyTime_ROUND_CEILING); - if (millisecs > (double)ULONG_MAX) { - PyErr_SetString(PyExc_OverflowError, - "sleep length is too large"); - return -1; - } - - /* Allow sleep(0) to maintain win32 semantics, and as decreed - * by Guido, only the main thread can be interrupted. - */ - ul_millis = (unsigned long)millisecs; - if (ul_millis == 0 || !_PyOS_IsMainThread()) { - Py_BEGIN_ALLOW_THREADS - Sleep(ul_millis); - Py_END_ALLOW_THREADS - break; - } - - hInterruptEvent = _PyOS_SigintEvent(); - ResetEvent(hInterruptEvent); - - Py_BEGIN_ALLOW_THREADS - rc = WaitForSingleObjectEx(hInterruptEvent, ul_millis, FALSE); - Py_END_ALLOW_THREADS - - if (rc != WAIT_OBJECT_0) - break; -#endif /* sleep was interrupted by SIGINT */ if (PyErr_CheckSignals()) { @@ -2152,6 +2140,38 @@ pysleep(_PyTime_t secs) /* retry with the recomputed delay */ #endif } while (1); +#else + millisecs = _PyTime_AsMilliseconds(secs, _PyTime_ROUND_CEILING); + if (millisecs > LLONG_MAX) { + PyErr_SetString(PyExc_OverflowError, + "sleep length is too large"); + return -1; + } + + /* Allow sleep(0) to maintain win32 semantics, and as decreed + * by Guido, only the main thread can be interrupted. + */ + ul_millis = (unsigned long)millisecs; + if (ul_millis == 0 || !_PyOS_IsMainThread()) { + Py_BEGIN_ALLOW_THREADS + Sleep(ul_millis); + Py_END_ALLOW_THREADS + return 0; + } + + Py_BEGIN_ALLOW_THREADS + rc = WaitForSingleObjectEx(hTimer, ul_millis, FALSE); + Py_END_ALLOW_THREADS + + if ((rc != WAIT_OBJECT_0) && (rc != WAIT_TIMEOUT)) { + return -1; + } + + /* sleep was interrupted by SIGINT */ + if (PyErr_CheckSignals()) { + return -1; + } +#endif return 0; } From 79a06c40a4e73239b8703071af5d6d2f666677cb Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Tue, 14 Sep 2021 21:00:46 +0000 Subject: [PATCH 47/57] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20b?= =?UTF-8?q?lurb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../NEWS.d/next/Library/2021-09-14-21-00-45.bpo-21302.KTsR8i.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Library/2021-09-14-21-00-45.bpo-21302.KTsR8i.rst diff --git a/Misc/NEWS.d/next/Library/2021-09-14-21-00-45.bpo-21302.KTsR8i.rst b/Misc/NEWS.d/next/Library/2021-09-14-21-00-45.bpo-21302.KTsR8i.rst new file mode 100644 index 00000000000000..d1dd8c983dbcd3 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-09-14-21-00-45.bpo-21302.KTsR8i.rst @@ -0,0 +1 @@ +In Windows operating system, :func:`time.sleep` now uses the ``waitable timer`` object, which allows to sleep for an interval specified with microsecond precision. \ No newline at end of file From 6fb2c1d0752ba4b8cbbbc77437d55ffa53f603b7 Mon Sep 17 00:00:00 2001 From: Livius Date: Wed, 15 Sep 2021 00:52:24 +0200 Subject: [PATCH 48/57] =?UTF-8?q?Revert=20"=F0=9F=93=9C=F0=9F=A4=96=20Adde?= =?UTF-8?q?d=20by=20blurb=5Fit."?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 79a06c40a4e73239b8703071af5d6d2f666677cb. --- .../NEWS.d/next/Library/2021-09-14-21-00-45.bpo-21302.KTsR8i.rst | 1 - 1 file changed, 1 deletion(-) delete mode 100644 Misc/NEWS.d/next/Library/2021-09-14-21-00-45.bpo-21302.KTsR8i.rst diff --git a/Misc/NEWS.d/next/Library/2021-09-14-21-00-45.bpo-21302.KTsR8i.rst b/Misc/NEWS.d/next/Library/2021-09-14-21-00-45.bpo-21302.KTsR8i.rst deleted file mode 100644 index d1dd8c983dbcd3..00000000000000 --- a/Misc/NEWS.d/next/Library/2021-09-14-21-00-45.bpo-21302.KTsR8i.rst +++ /dev/null @@ -1 +0,0 @@ -In Windows operating system, :func:`time.sleep` now uses the ``waitable timer`` object, which allows to sleep for an interval specified with microsecond precision. \ No newline at end of file From 41fe5d8a1f183306cab33f6127be8397716125af Mon Sep 17 00:00:00 2001 From: Livius Date: Wed, 15 Sep 2021 01:13:41 +0200 Subject: [PATCH 49/57] Fix timer handle closing, simplify ifdef blocks --- Modules/timemodule.c | 63 +++++++++++++++++++++++--------------------- 1 file changed, 33 insertions(+), 30 deletions(-) diff --git a/Modules/timemodule.c b/Modules/timemodule.c index 28148900c9c7c2..c5c90aec9d5056 100644 --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -2051,6 +2051,7 @@ PyInit_time(void) static int pysleep(_PyTime_t secs) { + int ret = -1; #ifndef MS_WINDOWS #ifdef HAVE_CLOCK_NANOSLEEP struct timespec timeout_abs; @@ -2059,7 +2060,6 @@ pysleep(_PyTime_t secs) #endif _PyTime_t deadline, monotonic; int err = 0; - int ret = 0; if (get_monotonic(&monotonic) < 0) { return -1; @@ -2070,31 +2070,7 @@ pysleep(_PyTime_t secs) return -1; } #endif -#else - _PyTime_t millisecs; - DWORD ul_millis; - DWORD rc; - FILETIME FileTime; - LARGE_INTEGER deadline; - HANDLE hTimer = NULL; - GetSystemTimePreciseAsFileTime(&FileTime); - CopyMemory(&deadline, &FileTime, sizeof(FILETIME)); - - /* convert to 100 nsec unit */ - deadline.QuadPart += (_PyTime_AsMicroseconds(secs, _PyTime_ROUND_CEILING) * 10); - - hTimer = CreateWaitableTimerW(NULL, FALSE, NULL); - if (NULL == hTimer) { - return -1; - } - - if (!SetWaitableTimer(hTimer, &deadline, 0, NULL, NULL, FALSE)) { - return -1; - } -#endif - -#ifndef MS_WINDOWS do { #ifndef HAVE_CLOCK_NANOSLEEP if (_PyTime_AsTimeval(secs, &timeout, _PyTime_ROUND_CEILING) < 0) { @@ -2141,11 +2117,33 @@ pysleep(_PyTime_t secs) #endif } while (1); #else + _PyTime_t millisecs; + DWORD ul_millis; + DWORD rc; + FILETIME FileTime; + LARGE_INTEGER deadline; + HANDLE hTimer = NULL; + + GetSystemTimePreciseAsFileTime(&FileTime); + CopyMemory(&deadline, &FileTime, sizeof(FILETIME)); + + /* convert to 100 nsec unit and add */ + deadline.QuadPart += (_PyTime_AsMicroseconds(secs, _PyTime_ROUND_CEILING) * 10); + + hTimer = CreateWaitableTimerW(NULL, FALSE, NULL); + if (NULL == hTimer) { + return -1; + } + + if (!SetWaitableTimer(hTimer, &deadline, 0, NULL, NULL, FALSE)) { + goto out; + } + millisecs = _PyTime_AsMilliseconds(secs, _PyTime_ROUND_CEILING); if (millisecs > LLONG_MAX) { PyErr_SetString(PyExc_OverflowError, "sleep length is too large"); - return -1; + goto out; } /* Allow sleep(0) to maintain win32 semantics, and as decreed @@ -2156,7 +2154,8 @@ pysleep(_PyTime_t secs) Py_BEGIN_ALLOW_THREADS Sleep(ul_millis); Py_END_ALLOW_THREADS - return 0; + ret = 0; + goto out; } Py_BEGIN_ALLOW_THREADS @@ -2164,14 +2163,18 @@ pysleep(_PyTime_t secs) Py_END_ALLOW_THREADS if ((rc != WAIT_OBJECT_0) && (rc != WAIT_TIMEOUT)) { - return -1; + goto out; } /* sleep was interrupted by SIGINT */ if (PyErr_CheckSignals()) { - return -1; + goto out; } + + ret = 0; +out: + CloseHandle(hTimer); #endif - return 0; + return ret; } From ac8ab07a473c72a3532c887fdc1a2e09a6194ce2 Mon Sep 17 00:00:00 2001 From: Livius Date: Thu, 16 Sep 2021 00:52:09 +0200 Subject: [PATCH 50/57] Add _PyTime_As100Nanoseconds() --- Include/cpython/pytime.h | 4 ++++ Modules/timemodule.c | 2 +- Python/pytime.c | 9 +++++++++ 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/Include/cpython/pytime.h b/Include/cpython/pytime.h index b0453884398cbf..3b46e3e3e74e3e 100644 --- a/Include/cpython/pytime.h +++ b/Include/cpython/pytime.h @@ -114,6 +114,10 @@ PyAPI_FUNC(_PyTime_t) _PyTime_AsMicroseconds(_PyTime_t t, /* Convert timestamp to a number of nanoseconds (10^-9 seconds). */ PyAPI_FUNC(_PyTime_t) _PyTime_AsNanoseconds(_PyTime_t t); +/* Convert timestamp to a number of 100 nanoseconds (10^-7 seconds). */ +PyAPI_FUNC(_PyTime_t) _PyTime_As100Nanoseconds(_PyTime_t t, + _PyTime_round_t round); + /* Convert timestamp to a number of nanoseconds (10^-9 seconds) as a Python int object. */ PyAPI_FUNC(PyObject *) _PyTime_AsNanosecondsObject(_PyTime_t t); diff --git a/Modules/timemodule.c b/Modules/timemodule.c index 087f036d6fb805..5a864c11a9f67e 100644 --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -2128,7 +2128,7 @@ pysleep(_PyTime_t secs) CopyMemory(&deadline, &FileTime, sizeof(FILETIME)); /* convert to 100 nsec unit and add */ - deadline.QuadPart += (_PyTime_AsMicroseconds(secs, _PyTime_ROUND_CEILING) * 10); + deadline.QuadPart += _PyTime_As100Nanoseconds(secs, _PyTime_ROUND_CEILING); hTimer = CreateWaitableTimerW(NULL, FALSE, NULL); if (NULL == hTimer) { diff --git a/Python/pytime.c b/Python/pytime.c index 8035a5f8a28b48..01396d25a52b7c 100644 --- a/Python/pytime.c +++ b/Python/pytime.c @@ -33,6 +33,7 @@ /* Conversion from nanoseconds */ #define NS_TO_MS (1000 * 1000) #define NS_TO_US (1000) +#define NS_TO_100NS (100) static void @@ -568,6 +569,14 @@ _PyTime_AsNanoseconds(_PyTime_t t) } +_PyTime_t +_PyTime_As100Nanoseconds(_PyTime_t t, _PyTime_round_t round) +{ + _PyTime_t ns = pytime_as_nanoseconds(t); + return pytime_divide(ns, NS_TO_100NS, round); +} + + _PyTime_t _PyTime_AsMicroseconds(_PyTime_t t, _PyTime_round_t round) { From b79ce487e35bd5f11102b4d03d6f7c19bd1d1254 Mon Sep 17 00:00:00 2001 From: Livius Date: Thu, 16 Sep 2021 01:24:30 +0200 Subject: [PATCH 51/57] Fix test_eintr failed issue in macOS --- Modules/timemodule.c | 1 + 1 file changed, 1 insertion(+) diff --git a/Modules/timemodule.c b/Modules/timemodule.c index 5a864c11a9f67e..66713bf8c9cd79 100644 --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -2111,6 +2111,7 @@ pysleep(_PyTime_t secs) } secs = deadline - monotonic; if (secs < 0) { + ret = 0; break; } /* retry with the recomputed delay */ From 7a3fbc2c1617a083638757156778ee6aa57e9686 Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Wed, 15 Sep 2021 23:49:22 +0000 Subject: [PATCH 52/57] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20b?= =?UTF-8?q?lurb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../NEWS.d/next/Library/2021-09-15-23-49-21.bpo-21302.KTsR8i.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Library/2021-09-15-23-49-21.bpo-21302.KTsR8i.rst diff --git a/Misc/NEWS.d/next/Library/2021-09-15-23-49-21.bpo-21302.KTsR8i.rst b/Misc/NEWS.d/next/Library/2021-09-15-23-49-21.bpo-21302.KTsR8i.rst new file mode 100644 index 00000000000000..d1dd8c983dbcd3 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-09-15-23-49-21.bpo-21302.KTsR8i.rst @@ -0,0 +1 @@ +In Windows operating system, :func:`time.sleep` now uses the ``waitable timer`` object, which allows to sleep for an interval specified with microsecond precision. \ No newline at end of file From 4e7c4eb061e3bd61a5370080a8d7b70e1431562d Mon Sep 17 00:00:00 2001 From: Livius Date: Thu, 16 Sep 2021 19:09:43 +0200 Subject: [PATCH 53/57] time.sleep() sleep again if SIGINT does not raise an exception --- Modules/timemodule.c | 68 +++++++++++++++++++++++++------------------- 1 file changed, 38 insertions(+), 30 deletions(-) diff --git a/Modules/timemodule.c b/Modules/timemodule.c index 66713bf8c9cd79..2755dd8f81712c 100644 --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -2124,6 +2124,7 @@ pysleep(_PyTime_t secs) FILETIME FileTime; LARGE_INTEGER deadline; HANDLE hTimer = NULL; + int timer_ready = 0; GetSystemTimePreciseAsFileTime(&FileTime); CopyMemory(&deadline, &FileTime, sizeof(FILETIME)); @@ -2137,43 +2138,50 @@ pysleep(_PyTime_t secs) } if (!SetWaitableTimer(hTimer, &deadline, 0, NULL, NULL, FALSE)) { - goto out; + ret = -1; + timer_ready = 0; } - - millisecs = _PyTime_AsMilliseconds(secs, _PyTime_ROUND_CEILING); - if (millisecs > LLONG_MAX) { - PyErr_SetString(PyExc_OverflowError, - "sleep length is too large"); - goto out; + else { + timer_ready = 1; } - - /* Allow sleep(0) to maintain win32 semantics, and as decreed - * by Guido, only the main thread can be interrupted. - */ - ul_millis = (unsigned long)millisecs; - if (ul_millis == 0 || !_PyOS_IsMainThread()) { + + while (timer_ready) { + millisecs = _PyTime_AsMilliseconds(secs, _PyTime_ROUND_CEILING); + if (millisecs > LLONG_MAX) { + PyErr_SetString(PyExc_OverflowError, + "sleep length is too large"); + ret = -1; + break; + } + + /* Allow sleep(0) to maintain win32 semantics, and as decreed + * by Guido, only the main thread can be interrupted. + */ + ul_millis = (unsigned long)millisecs; + if (ul_millis == 0 || !_PyOS_IsMainThread()) { + Py_BEGIN_ALLOW_THREADS + Sleep(ul_millis); + Py_END_ALLOW_THREADS + ret = 0; + break; + } + Py_BEGIN_ALLOW_THREADS - Sleep(ul_millis); + rc = WaitForSingleObjectEx(hTimer, ul_millis, FALSE); Py_END_ALLOW_THREADS - ret = 0; - goto out; - } - - Py_BEGIN_ALLOW_THREADS - rc = WaitForSingleObjectEx(hTimer, ul_millis, FALSE); - Py_END_ALLOW_THREADS - - if ((rc != WAIT_OBJECT_0) && (rc != WAIT_TIMEOUT)) { - goto out; - } - /* sleep was interrupted by SIGINT */ - if (PyErr_CheckSignals()) { - goto out; + if ((rc == WAIT_OBJECT_0) || (rc == WAIT_TIMEOUT)) { + ret = 0; + break; + } + + /* sleep was interrupted by SIGINT */ + if (PyErr_CheckSignals()) { + ret = -1; + break; + } } - ret = 0; -out: CloseHandle(hTimer); #endif From ab1740123150e041c408bce8e6e1261c38a8b567 Mon Sep 17 00:00:00 2001 From: Livius Date: Thu, 16 Sep 2021 23:06:50 +0200 Subject: [PATCH 54/57] use WaitForMultipleObjectsEx() --- Modules/timemodule.c | 38 ++++++++++++++++++++++++++++++-------- 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/Modules/timemodule.c b/Modules/timemodule.c index 2755dd8f81712c..55b63f855692d1 100644 --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -2044,6 +2044,14 @@ PyInit_time(void) return PyModuleDef_Init(&timemodule); } +#ifdef MS_WINDOWS +enum event_indexes { + EVENT_TIMER, + EVENT_INTERRUPT, + EVENT_SIZE +}; +#endif + /* Implement pysleep() for various platforms. When interrupted (or when another error occurs), return -1 and set an exception; else return 0. */ @@ -2118,13 +2126,14 @@ pysleep(_PyTime_t secs) #endif } while (1); #else + int timer_ready = 0; _PyTime_t millisecs; DWORD ul_millis; DWORD rc; FILETIME FileTime; LARGE_INTEGER deadline; - HANDLE hTimer = NULL; - int timer_ready = 0; + /* hTimer, hInterruptEvent */ + HANDLE hEvents[EVENT_SIZE] = {NULL, NULL}; GetSystemTimePreciseAsFileTime(&FileTime); CopyMemory(&deadline, &FileTime, sizeof(FILETIME)); @@ -2132,12 +2141,12 @@ pysleep(_PyTime_t secs) /* convert to 100 nsec unit and add */ deadline.QuadPart += _PyTime_As100Nanoseconds(secs, _PyTime_ROUND_CEILING); - hTimer = CreateWaitableTimerW(NULL, FALSE, NULL); - if (NULL == hTimer) { + hEvents[EVENT_TIMER] = CreateWaitableTimerW(NULL, FALSE, NULL); + if (NULL == hEvents[EVENT_TIMER]) { return -1; } - if (!SetWaitableTimer(hTimer, &deadline, 0, NULL, NULL, FALSE)) { + if (!SetWaitableTimer(hEvents[EVENT_TIMER], &deadline, 0, NULL, NULL, FALSE)) { ret = -1; timer_ready = 0; } @@ -2166,11 +2175,24 @@ pysleep(_PyTime_t secs) break; } + hEvents[EVENT_INTERRUPT] = _PyOS_SigintEvent(); + ResetEvent(hEvents[EVENT_INTERRUPT]); + Py_BEGIN_ALLOW_THREADS - rc = WaitForSingleObjectEx(hTimer, ul_millis, FALSE); + rc = WaitForMultipleObjectsEx(EVENT_SIZE, hEvents, FALSE, ul_millis, FALSE); Py_END_ALLOW_THREADS - if ((rc == WAIT_OBJECT_0) || (rc == WAIT_TIMEOUT)) { + if (rc == WAIT_FAILED) { + ret = -1; + break; + } + + if ((rc == (WAIT_OBJECT_0 + EVENT_TIMER)) || (rc == WAIT_TIMEOUT)) { + ret = 0; + break; + } + + if (rc != (WAIT_OBJECT_0 + EVENT_INTERRUPT)) { ret = 0; break; } @@ -2182,7 +2204,7 @@ pysleep(_PyTime_t secs) } } - CloseHandle(hTimer); + CloseHandle(hEvents[EVENT_TIMER]); #endif return ret; From d2eb0fcfb524f950c2fce0d9b873df6f47e11b3a Mon Sep 17 00:00:00 2001 From: Livius Date: Sat, 18 Sep 2021 13:33:31 +0200 Subject: [PATCH 55/57] Some code refactoring and finalizing --- Include/cpython/pytime.h | 3 ++- Modules/timemodule.c | 8 ++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Include/cpython/pytime.h b/Include/cpython/pytime.h index 3b46e3e3e74e3e..24b9cd7be57f45 100644 --- a/Include/cpython/pytime.h +++ b/Include/cpython/pytime.h @@ -114,7 +114,8 @@ PyAPI_FUNC(_PyTime_t) _PyTime_AsMicroseconds(_PyTime_t t, /* Convert timestamp to a number of nanoseconds (10^-9 seconds). */ PyAPI_FUNC(_PyTime_t) _PyTime_AsNanoseconds(_PyTime_t t); -/* Convert timestamp to a number of 100 nanoseconds (10^-7 seconds). */ +/* Convert timestamp to a number of 100 nanoseconds (10^-7 seconds). + Can be used for Waitable timer object in Windows. */ PyAPI_FUNC(_PyTime_t) _PyTime_As100Nanoseconds(_PyTime_t t, _PyTime_round_t round); diff --git a/Modules/timemodule.c b/Modules/timemodule.c index 55b63f855692d1..cbcd43468aaa16 100644 --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -2126,7 +2126,7 @@ pysleep(_PyTime_t secs) #endif } while (1); #else - int timer_ready = 0; + int is_timer_ready = 0; _PyTime_t millisecs; DWORD ul_millis; DWORD rc; @@ -2148,13 +2148,13 @@ pysleep(_PyTime_t secs) if (!SetWaitableTimer(hEvents[EVENT_TIMER], &deadline, 0, NULL, NULL, FALSE)) { ret = -1; - timer_ready = 0; + is_timer_ready = 0; } else { - timer_ready = 1; + is_timer_ready = 1; } - while (timer_ready) { + while (is_timer_ready) { millisecs = _PyTime_AsMilliseconds(secs, _PyTime_ROUND_CEILING); if (millisecs > LLONG_MAX) { PyErr_SetString(PyExc_OverflowError, From aad2c31d682f22ce8d73dac023bcc8046c588cea Mon Sep 17 00:00:00 2001 From: Livius Date: Mon, 20 Sep 2021 14:13:18 +0200 Subject: [PATCH 56/57] Fulfilling requests of last review --- Modules/timemodule.c | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/Modules/timemodule.c b/Modules/timemodule.c index cbcd43468aaa16..09074e22af537c 100644 --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -2126,7 +2126,6 @@ pysleep(_PyTime_t secs) #endif } while (1); #else - int is_timer_ready = 0; _PyTime_t millisecs; DWORD ul_millis; DWORD rc; @@ -2148,15 +2147,12 @@ pysleep(_PyTime_t secs) if (!SetWaitableTimer(hEvents[EVENT_TIMER], &deadline, 0, NULL, NULL, FALSE)) { ret = -1; - is_timer_ready = 0; - } - else { - is_timer_ready = 1; + goto exit; } - while (is_timer_ready) { + do { millisecs = _PyTime_AsMilliseconds(secs, _PyTime_ROUND_CEILING); - if (millisecs > LLONG_MAX) { + if (millisecs > ((_PyTime_t)ULONG_MAX)) { PyErr_SetString(PyExc_OverflowError, "sleep length is too large"); ret = -1; @@ -2179,31 +2175,40 @@ pysleep(_PyTime_t secs) ResetEvent(hEvents[EVENT_INTERRUPT]); Py_BEGIN_ALLOW_THREADS - rc = WaitForMultipleObjectsEx(EVENT_SIZE, hEvents, FALSE, ul_millis, FALSE); + rc = WaitForMultipleObjectsEx(EVENT_SIZE, hEvents, FALSE, INFINITE, FALSE); Py_END_ALLOW_THREADS + /* Something went wrong */ if (rc == WAIT_FAILED) { ret = -1; break; } - if ((rc == (WAIT_OBJECT_0 + EVENT_TIMER)) || (rc == WAIT_TIMEOUT)) { + /* Timer signaled: we are done */ + if (rc == (WAIT_OBJECT_0 + EVENT_TIMER)) { ret = 0; break; } - if (rc != (WAIT_OBJECT_0 + EVENT_INTERRUPT)) { - ret = 0; - break; - } + /* Does it make sense to check? */ + //if (rc != (WAIT_OBJECT_0 + EVENT_INTERRUPT)) { + // ret = 0; + // break; + //} /* sleep was interrupted by SIGINT */ if (PyErr_CheckSignals()) { ret = -1; break; } - } + /* The SIGINT signal handler was called and did not raise a Python exception. + * Restart sleeping. The timer deadline doesn't need to be recomputed: + * SetWaitableTimer() uses absolute time. + */ + } while (1); + +exit: CloseHandle(hEvents[EVENT_TIMER]); #endif From 0daf08058a14eb6543f17f8e4a3b42af8ee39f9d Mon Sep 17 00:00:00 2001 From: Livius Date: Mon, 20 Sep 2021 21:13:47 +0200 Subject: [PATCH 57/57] Update news rst --- .../next/Library/2021-09-15-23-49-21.bpo-21302.KTsR8i.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Library/2021-09-15-23-49-21.bpo-21302.KTsR8i.rst b/Misc/NEWS.d/next/Library/2021-09-15-23-49-21.bpo-21302.KTsR8i.rst index d1dd8c983dbcd3..0d45ad3453c5f9 100644 --- a/Misc/NEWS.d/next/Library/2021-09-15-23-49-21.bpo-21302.KTsR8i.rst +++ b/Misc/NEWS.d/next/Library/2021-09-15-23-49-21.bpo-21302.KTsR8i.rst @@ -1 +1 @@ -In Windows operating system, :func:`time.sleep` now uses the ``waitable timer`` object, which allows to sleep for an interval specified with microsecond precision. \ No newline at end of file +In Windows operating system, :func:`time.sleep` now uses the ``waitable timer`` object, which allows to sleep for an interval absolute time. Desired sleep time can be set in 100 nsecs resolution. \ No newline at end of file