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 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..52ee8d7cc64f15 --- /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 but ``nanosleep()`` is available. ``nanosleep()`` allows to sleep with nanosecond precision. \ No newline at end of file diff --git a/Modules/timemodule.c b/Modules/timemodule.c index 53ec86eb3981ef..4639afa590a4fa 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,15 +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_ts; #else - struct timeval timeout; + struct timeval timeout_tv; #endif _PyTime_t deadline, monotonic; int err = 0; @@ -2066,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; @@ -2074,24 +2076,31 @@ pysleep(_PyTime_t secs) #endif do { -#ifndef HAVE_CLOCK_NANOSLEEP - if (_PyTime_AsTimeval(secs, &timeout, _PyTime_ROUND_CEILING) < 0) { +#ifdef HAVE_CLOCK_NANOSLEEP + // use timeout_abs +#elif defined(HAVE_NANOSLEEP) + if (_PyTime_AsTimespec(timeout, &timeout_ts) < 0) { + return -1; + } +#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; +#elif defined(HAVE_NANOSLEEP) + ret = nanosleep(&timeout_ts, NULL); + err = errno; #else - Py_BEGIN_ALLOW_THREADS - ret = select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &timeout); - Py_END_ALLOW_THREADS + ret = select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &timeout_tv); err = errno; #endif + Py_END_ALLOW_THREADS if (ret == 0) { break; @@ -2112,8 +2121,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 */ @@ -2122,10 +2131,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 @@ -2138,9 +2148,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) { 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 pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy