[Python-checkins] bpo-21302: Add clock_nanosleep() implementation for time.sleep() (GH-28111)

vstinner webhook-mailer at python.org
Mon Sep 13 08:37:42 EDT 2021


https://github.com/python/cpython/commit/85a4748118c3793be7047ecbcbfc79dd07cb2a75
commit: 85a4748118c3793be7047ecbcbfc79dd07cb2a75
branch: main
author: Livius <egyszeregy at freemail.hu>
committer: vstinner <vstinner at python.org>
date: 2021-09-13T14:37:38+02:00
summary:

bpo-21302: Add clock_nanosleep() implementation for time.sleep() (GH-28111)

In Unix operating systems, time.sleep() now uses the clock_nanosleep() function,
if available, which allows to sleep for an interval specified with nanosecond precision.

Co-authored-by: Victor Stinner <vstinner at python.org>

files:
A Misc/NEWS.d/next/Library/2021-09-11-18-44-40.bpo-21302.QxHRpR.rst
M Modules/timemodule.c
M configure
M configure.ac
M pyconfig.h.in

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 0000000000000..86f0a5ac4c2a5
--- /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
diff --git a/Modules/timemodule.c b/Modules/timemodule.c
index 4caacc3b64d7c..cf58a18caf1f2 100644
--- a/Modules/timemodule.c
+++ b/Modules/timemodule.c
@@ -2053,8 +2053,13 @@ 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;
+    int ret = 0;
 #else
     _PyTime_t millisecs;
     unsigned long ul_millis;
@@ -2066,20 +2071,38 @@ 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
 
     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
 
+#ifdef HAVE_CLOCK_NANOSLEEP
         Py_BEGIN_ALLOW_THREADS
-        err = select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &timeout);
+        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
 
-        if (err == 0)
+        if (ret == 0) {
             break;
+        }
 
-        if (errno != EINTR) {
+        if (err != EINTR) {
+            errno = err;
             PyErr_SetFromErrno(PyExc_OSError);
             return -1;
         }
@@ -2114,9 +2137,11 @@ pysleep(_PyTime_t secs)
 #endif
 
         /* sleep was interrupted by SIGINT */
-        if (PyErr_CheckSignals())
+        if (PyErr_CheckSignals()) {
             return -1;
+        }
 
+#ifndef HAVE_CLOCK_NANOSLEEP
         if (get_monotonic(&monotonic) < 0) {
             return -1;
         }
@@ -2125,6 +2150,7 @@ pysleep(_PyTime_t secs)
             break;
         }
         /* retry with the recomputed delay */
+#endif
     } while (1);
 
     return 0;
diff --git a/configure b/configure
index 4f12972540d5f..2e3c9ba7baddd 100755
--- a/configure
+++ b/configure
@@ -13252,6 +13252,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 bcb205497c1ea..4a0694c442f3f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -4115,6 +4115,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)
diff --git a/pyconfig.h.in b/pyconfig.h.in
index 49407ab62b417..d6408e9415e2d 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
 



More information about the Python-checkins mailing list