]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-21302: Add clock_nanosleep() implementation for time.sleep() (GH-28111)
authorLivius <egyszeregy@freemail.hu>
Mon, 13 Sep 2021 12:37:38 +0000 (14:37 +0200)
committerGitHub <noreply@github.com>
Mon, 13 Sep 2021 12:37:38 +0000 (14:37 +0200)
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@python.org>
Misc/NEWS.d/next/Library/2021-09-11-18-44-40.bpo-21302.QxHRpR.rst [new file with mode: 0644]
Modules/timemodule.c
configure
configure.ac
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 (file)
index 0000000..86f0a5a
--- /dev/null
@@ -0,0 +1,2 @@
+In Unix operating systems, :func:`time.sleep` now uses the ``clock_nanosleep()`` function,\r
+if available, which allows to sleep for an interval specified with nanosecond precision.
\ No newline at end of file
index 4caacc3b64d7c87a575002b1a0cb220afec73f01..cf58a18caf1f20d21326c47ecc31e9fed2ffde46 100644 (file)
@@ -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;
index 4f12972540d5f26b40d230fac371442388a04f47..2e3c9ba7baddd4de07b6f0f2ba76ef0ce8de11ad 100755 (executable)
--- a/configure
+++ b/configure
 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"
index bcb205497c1eab7cd3225a4b76058334b145997f..4a0694c442f3f74f70ad44c41c3679267f136588 100644 (file)
@@ -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)
index 49407ab62b417d7ccb679e1c5f738d33c52bf95b..d6408e9415e2d0cd84bfeb265deb5b4bb7b591ce 100644 (file)
 /* 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