From 57db5a378a65f2490e3bfd16e71f37de481e53f5 Mon Sep 17 00:00:00 2001 From: Livius Date: Thu, 23 Sep 2021 00:40:55 +0200 Subject: [PATCH 1/8] replace select() to nanosleep() Replace outdated select() to use nanosleep() for sleep implementation in Unix --- Modules/_multiprocessing/semaphore.c | 22 +++++++++++----------- Modules/_tkinter.c | 7 +++---- Modules/timemodule.c | 6 +++--- 3 files changed, 17 insertions(+), 18 deletions(-) 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 7be9b8c0385b97..baa0ed41487110 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 */ diff --git a/Modules/timemodule.c b/Modules/timemodule.c index 53ec86eb3981ef..4a48693eaa3e5a 100644 --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -2058,7 +2058,7 @@ pysleep(_PyTime_t secs) #ifdef HAVE_CLOCK_NANOSLEEP struct timespec timeout_abs; #else - struct timeval timeout; + struct timespec timeout; #endif _PyTime_t deadline, monotonic; int err = 0; @@ -2075,7 +2075,7 @@ pysleep(_PyTime_t secs) do { #ifndef HAVE_CLOCK_NANOSLEEP - if (_PyTime_AsTimeval(secs, &timeout, _PyTime_ROUND_CEILING) < 0) { + if (_PyTime_AsTimespec(secs, &timeout) < 0) { return -1; } #endif @@ -2088,7 +2088,7 @@ pysleep(_PyTime_t secs) err = ret; #else Py_BEGIN_ALLOW_THREADS - ret = select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &timeout); + ret = nanosleep(&timeout, NULL); Py_END_ALLOW_THREADS err = errno; #endif From 0396b87cdbaed2d3f758dce5d83d8b76951d4190 Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Wed, 22 Sep 2021 23:56:16 +0000 Subject: [PATCH 2/8] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20blu?= =?UTF-8?q?rb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../NEWS.d/next/Library/2021-09-22-23-56-15.bpo-21302.vvQ3Su.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Library/2021-09-22-23-56-15.bpo-21302.vvQ3Su.rst diff --git a/Misc/NEWS.d/next/Library/2021-09-22-23-56-15.bpo-21302.vvQ3Su.rst b/Misc/NEWS.d/next/Library/2021-09-22-23-56-15.bpo-21302.vvQ3Su.rst new file mode 100644 index 00000000000000..c050fd8a3cd0d0 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-09-22-23-56-15.bpo-21302.vvQ3Su.rst @@ -0,0 +1 @@ +In Unix operating systems, :func:`time.sleep` now uses the ``nanosleep()`` function, if ``clock_nanosleep()`` is not available. ``nanosleep()`` allows to sleep with nanosecond precision. \ No newline at end of file From b5142601a80d3cff121569762f0ab1d1967f4c05 Mon Sep 17 00:00:00 2001 From: Livius Date: Thu, 23 Sep 2021 22:02:37 +0200 Subject: [PATCH 3/8] revert some changes --- Modules/_multiprocessing/semaphore.c | 22 +++++++++++----------- Modules/_tkinter.c | 7 ++++--- 2 files changed, 15 insertions(+), 14 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 baa0ed41487110..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 */ From bd984868758d2aa5c6a83fbfa5e333a22f70ebc6 Mon Sep 17 00:00:00 2001 From: Livius Date: Thu, 23 Sep 2021 22:39:37 +0200 Subject: [PATCH 4/8] Add HAVE_NANOSLEEP to configure.ac --- Modules/timemodule.c | 14 +++++++++-- configure | 58 ++++++++++++++++++++++++++++++++++++++++++++ configure.ac | 6 +++++ pyconfig.h.in | 3 +++ 4 files changed, 79 insertions(+), 2 deletions(-) diff --git a/Modules/timemodule.c b/Modules/timemodule.c index 4a48693eaa3e5a..aaf96e3f938682 100644 --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -2057,8 +2057,10 @@ pysleep(_PyTime_t secs) #ifndef MS_WINDOWS #ifdef HAVE_CLOCK_NANOSLEEP struct timespec timeout_abs; -#else +#elif defined(HAVE_NANOSLEEP) struct timespec timeout; +#else + struct timeval timeout; #endif _PyTime_t deadline, monotonic; int err = 0; @@ -2074,10 +2076,14 @@ pysleep(_PyTime_t secs) #endif do { -#ifndef HAVE_CLOCK_NANOSLEEP +#if defined(HAVE_NANOSLEEP) && !defined(HAVE_CLOCK_NANOSLEEP) if (_PyTime_AsTimespec(secs, &timeout) < 0) { return -1; } +#elif !defined(HAVE_CLOCK_NANOSLEEP) + if (_PyTime_AsTimeval(secs, &timeout, _PyTime_ROUND_CEILING) < 0) { + return -1; + } #endif int ret; @@ -2088,7 +2094,11 @@ pysleep(_PyTime_t secs) err = ret; #else Py_BEGIN_ALLOW_THREADS +#ifdef HAVE_NANOSLEEP ret = nanosleep(&timeout, NULL); +#else + ret = select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &timeout); +#endif Py_END_ALLOW_THREADS err = errno; #endif diff --git a/configure b/configure index 2e3c9ba7baddd4..4acf91f22107f4 100755 --- a/configure +++ b/configure @@ -13310,6 +13310,64 @@ fi done +for ac_func in nanosleep +do : + ac_fn_c_check_func "$LINENO" "nanosleep" "ac_cv_func_nanosleep" +if test "x$ac_cv_func_nanosleep" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_NANOSLEEP 1 +_ACEOF + +else + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for nanosleep in -lrt" >&5 +$as_echo_n "checking for nanosleep in -lrt... " >&6; } +if ${ac_cv_lib_rt_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 nanosleep (); +int +main () +{ +return nanosleep (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_rt_nanosleep=yes +else + ac_cv_lib_rt_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_nanosleep" >&5 +$as_echo "$ac_cv_lib_rt_nanosleep" >&6; } +if test "x$ac_cv_lib_rt_nanosleep" = xyes; then : + + $as_echo "#define HAVE_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 4a0694c442f3f7..48d86ef79199e1 100644 --- a/configure.ac +++ b/configure.ac @@ -4121,6 +4121,12 @@ AC_CHECK_FUNCS(clock_nanosleep, [], [ ]) ]) +AC_CHECK_FUNCS(nanosleep, [], [ + AC_CHECK_LIB(rt, nanosleep, [ + AC_DEFINE(HAVE_NANOSLEEP, 1) + ]) +]) + AC_MSG_CHECKING(for major, minor, and makedev) AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #if defined(MAJOR_IN_MKDEV) diff --git a/pyconfig.h.in b/pyconfig.h.in index d6408e9415e2d0..23d7111b9f77e7 100644 --- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -736,6 +736,9 @@ /* Define to 1 if you have the `mremap' function. */ #undef HAVE_MREMAP +/* Define to 1 if you have the `nanosleep' function. */ +#undef HAVE_NANOSLEEP + /* Define to 1 if you have the header file. */ #undef HAVE_NCURSES_H From 050e08e6057623d06afa401c963ff1cf95df922d Mon Sep 17 00:00:00 2001 From: Livius Date: Thu, 23 Sep 2021 22:41:48 +0200 Subject: [PATCH 5/8] Update news rst --- .../next/Library/2021-09-22-23-56-15.bpo-21302.vvQ3Su.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Library/2021-09-22-23-56-15.bpo-21302.vvQ3Su.rst b/Misc/NEWS.d/next/Library/2021-09-22-23-56-15.bpo-21302.vvQ3Su.rst index c050fd8a3cd0d0..52ee8d7cc64f15 100644 --- a/Misc/NEWS.d/next/Library/2021-09-22-23-56-15.bpo-21302.vvQ3Su.rst +++ b/Misc/NEWS.d/next/Library/2021-09-22-23-56-15.bpo-21302.vvQ3Su.rst @@ -1 +1 @@ -In Unix operating systems, :func:`time.sleep` now uses the ``nanosleep()`` function, if ``clock_nanosleep()`` is not available. ``nanosleep()`` allows to sleep with nanosecond precision. \ No newline at end of file +In Unix operating systems, :func:`time.sleep` now uses the ``nanosleep()`` function, if ``clock_nanosleep()`` is not available but ``nanosleep()`` is available. ``nanosleep()`` allows to sleep with nanosecond precision. \ No newline at end of file From 96eaec02f4ce83f53d7fd65b4939f2b06475f6b1 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 24 Sep 2021 12:58:11 +0200 Subject: [PATCH 6/8] Refactor --- Modules/timemodule.c | 62 +++++++++++++++++++++++--------------------- 1 file changed, 32 insertions(+), 30 deletions(-) diff --git a/Modules/timemodule.c b/Modules/timemodule.c index aaf96e3f938682..67b33abbf0154d 100644 --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -63,7 +63,7 @@ #define SEC_TO_NS (1000 * 1000 * 1000) /* Forward declarations */ -static int pysleep(_PyTime_t); +static int pysleep(_PyTime_t timeout); static PyObject* @@ -357,17 +357,17 @@ Return the clk_id of a thread's CPU time clock."); #endif /* HAVE_PTHREAD_GETCPUCLOCKID */ static PyObject * -time_sleep(PyObject *self, PyObject *obj) +time_sleep(PyObject *self, PyObject *timeout_obj) { - _PyTime_t secs; - if (_PyTime_FromSecondsObject(&secs, obj, _PyTime_ROUND_TIMEOUT)) + _PyTime_t timeout; + if (_PyTime_FromSecondsObject(&timeout, timeout_obj, _PyTime_ROUND_TIMEOUT)) return NULL; - if (secs < 0) { + if (timeout < 0) { PyErr_SetString(PyExc_ValueError, "sleep length must be non-negative"); return NULL; } - if (pysleep(secs) != 0) { + if (pysleep(timeout) != 0) { return NULL; } Py_RETURN_NONE; @@ -2050,17 +2050,17 @@ PyInit_time(void) // On error, raise an exception and return -1. // On success, return 0. static int -pysleep(_PyTime_t secs) +pysleep(_PyTime_t timeout) { - assert(secs >= 0); + assert(timeout >= 0); #ifndef MS_WINDOWS #ifdef HAVE_CLOCK_NANOSLEEP struct timespec timeout_abs; #elif defined(HAVE_NANOSLEEP) - struct timespec timeout; + struct timespec timeout_ts; #else - struct timeval timeout; + struct timeval timeout_tv; #endif _PyTime_t deadline, monotonic; int err = 0; @@ -2068,7 +2068,7 @@ pysleep(_PyTime_t secs) if (get_monotonic(&monotonic) < 0) { return -1; } - deadline = monotonic + secs; + deadline = monotonic + timeout; #ifdef HAVE_CLOCK_NANOSLEEP if (_PyTime_AsTimespec(deadline, &timeout_abs) < 0) { return -1; @@ -2076,33 +2076,34 @@ pysleep(_PyTime_t secs) #endif do { -#if defined(HAVE_NANOSLEEP) && !defined(HAVE_CLOCK_NANOSLEEP) - if (_PyTime_AsTimespec(secs, &timeout) < 0) { +#ifdef HAVE_CLOCK_NANOSLEEP + // use timeout_abs +#elif defined(HAVE_NANOSLEEP) + if (_PyTime_AsTimespec(timeout, &timeout_ts) < 0) { return -1; } -#elif !defined(HAVE_CLOCK_NANOSLEEP) - if (_PyTime_AsTimeval(secs, &timeout, _PyTime_ROUND_CEILING) < 0) { +#else + if (_PyTime_AsTimeval(timeout, &timeout_tv, _PyTime_ROUND_CEILING) < 0) { return -1; } #endif int ret; -#ifdef HAVE_CLOCK_NANOSLEEP Py_BEGIN_ALLOW_THREADS +#ifdef HAVE_CLOCK_NANOSLEEP ret = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &timeout_abs, NULL); - Py_END_ALLOW_THREADS - err = ret; -#else - Py_BEGIN_ALLOW_THREADS -#ifdef HAVE_NANOSLEEP - ret = nanosleep(&timeout, NULL); +#elif defined(HAVE_NANOSLEEP) + ret = nanosleep(&timeout_ts, NULL); #else - ret = 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_tv); #endif Py_END_ALLOW_THREADS + +#ifdef HAVE_CLOCK_NANOSLEEP + err = ret; +#else err = errno; #endif - if (ret == 0) { break; } @@ -2122,8 +2123,8 @@ pysleep(_PyTime_t secs) if (get_monotonic(&monotonic) < 0) { return -1; } - secs = deadline - monotonic; - if (secs < 0) { + timeout = deadline - monotonic; + if (timeout < 0) { break; } /* retry with the recomputed delay */ @@ -2132,10 +2133,11 @@ pysleep(_PyTime_t secs) return 0; #else // MS_WINDOWS - _PyTime_t timeout = _PyTime_As100Nanoseconds(secs, _PyTime_ROUND_CEILING); + _PyTime_t timeout_100ns = _PyTime_As100Nanoseconds(timeout, + _PyTime_ROUND_CEILING); // Maintain Windows Sleep() semantics for time.sleep(0) - if (timeout == 0) { + if (timeout_100ns == 0) { Py_BEGIN_ALLOW_THREADS // A value of zero causes the thread to relinquish the remainder of its // time slice to any other thread that is ready to run. If there are no @@ -2148,9 +2150,9 @@ pysleep(_PyTime_t secs) LARGE_INTEGER relative_timeout; // No need to check for integer overflow, both types are signed - assert(sizeof(relative_timeout) == sizeof(timeout)); + assert(sizeof(relative_timeout) == sizeof(timeout_100ns)); // SetWaitableTimer(): a negative due time indicates relative time - relative_timeout.QuadPart = -timeout; + relative_timeout.QuadPart = -timeout_100ns; HANDLE timer = CreateWaitableTimerW(NULL, FALSE, NULL); if (timer == NULL) { From 2a660802d126fae98dfdfe7616936d769908807a Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 24 Sep 2021 23:27:08 +0200 Subject: [PATCH 7/8] Move err assignement just after the function call --- Modules/timemodule.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/Modules/timemodule.c b/Modules/timemodule.c index 67b33abbf0154d..4639afa590a4fa 100644 --- a/Modules/timemodule.c +++ b/Modules/timemodule.c @@ -2092,18 +2092,16 @@ pysleep(_PyTime_t timeout) Py_BEGIN_ALLOW_THREADS #ifdef HAVE_CLOCK_NANOSLEEP ret = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &timeout_abs, NULL); + err = ret; #elif defined(HAVE_NANOSLEEP) ret = nanosleep(&timeout_ts, NULL); + err = errno; #else ret = select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &timeout_tv); + err = errno; #endif Py_END_ALLOW_THREADS -#ifdef HAVE_CLOCK_NANOSLEEP - err = ret; -#else - err = errno; -#endif if (ret == 0) { break; } From d51965779fdf64b1f34fb9854b3dcaf52eae19e7 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sat, 25 Sep 2021 01:35:03 +0200 Subject: [PATCH 8/8] Update the doc --- Doc/library/time.rst | 16 +++++++++------- Doc/whatsnew/3.11.rst | 7 ++++--- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/Doc/library/time.rst b/Doc/library/time.rst index d91862cc38be83..69e5274f1cee74 100644 --- a/Doc/library/time.rst +++ b/Doc/library/time.rst @@ -364,16 +364,18 @@ Functions threads ready to run, the function returns immediately, and the thread continues execution. - Implementation: + Unix implementation: - * On Unix, ``clock_nanosleep()`` is used if available (resolution: 1 ns), - or ``select()`` is used otherwise (resolution: 1 us). - * On Windows, a waitable timer is used (resolution: 100 ns). If *secs* is - zero, ``Sleep(0)`` is used. + * Use ``clock_nanosleep()`` if available (resolution: 1 ns); + * Or use ``nanosleep()`` if available (resolution: 1 ns); + * Or use ``select()`` (resolution: 1 us). + + On Windows, a waitable timer is used (resolution: 100 ns). If *secs* is + zero, ``Sleep(0)`` is used. .. versionchanged:: 3.11 - On Unix, the ``clock_nanosleep()`` function is now used if available. - On Windows, a waitable timer is now used. + On Unix, the ``clock_nanosleep()`` and ``nanosleep()`` functions are now + used if available. On Windows, a waitable timer is now used. .. versionchanged:: 3.5 The function now sleeps at least *secs* even if the sleep is interrupted diff --git a/Doc/whatsnew/3.11.rst b/Doc/whatsnew/3.11.rst index 0e56b462f1231f..818208edbf2631 100644 --- a/Doc/whatsnew/3.11.rst +++ b/Doc/whatsnew/3.11.rst @@ -242,9 +242,10 @@ sqlite3 time ---- -* On Unix, :func:`time.sleep` now uses the ``clock_nanosleep()`` function, if - available, which has a resolution of 1 ns (10^-6 sec), rather than using - ``select()`` which has a resolution of 1 us (10^-9 sec). +* On Unix, :func:`time.sleep` now uses the ``clock_nanosleep()`` or + ``nanosleep()`` function, if available, which has a resolution of 1 ns (10^-6 + sec), rather than using ``select()`` which has a resolution of 1 us (10^-9 + sec). (Contributed by Livius and Victor Stinner in :issue:`21302`.) * On Windows, :func:`time.sleep` now uses a waitable timer which has a