mirror of
https://github.com/python/cpython.git
synced 2025-09-26 18:29:57 +00:00
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@python.org>
This commit is contained in:
parent
3e19409d64
commit
85a4748118
5 changed files with 100 additions and 5 deletions
|
@ -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.
|
|
@ -2053,8 +2053,13 @@ pysleep(_PyTime_t secs)
|
||||||
{
|
{
|
||||||
_PyTime_t deadline, monotonic;
|
_PyTime_t deadline, monotonic;
|
||||||
#ifndef MS_WINDOWS
|
#ifndef MS_WINDOWS
|
||||||
|
#ifdef HAVE_CLOCK_NANOSLEEP
|
||||||
|
struct timespec timeout_abs;
|
||||||
|
#else
|
||||||
struct timeval timeout;
|
struct timeval timeout;
|
||||||
|
#endif
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
int ret = 0;
|
||||||
#else
|
#else
|
||||||
_PyTime_t millisecs;
|
_PyTime_t millisecs;
|
||||||
unsigned long ul_millis;
|
unsigned long ul_millis;
|
||||||
|
@ -2066,20 +2071,38 @@ pysleep(_PyTime_t secs)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
deadline = monotonic + secs;
|
deadline = monotonic + secs;
|
||||||
|
#if defined(HAVE_CLOCK_NANOSLEEP) && !defined(MS_WINDOWS)
|
||||||
|
if (_PyTime_AsTimespec(deadline, &timeout_abs) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
do {
|
do {
|
||||||
#ifndef MS_WINDOWS
|
#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;
|
return -1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_CLOCK_NANOSLEEP
|
||||||
Py_BEGIN_ALLOW_THREADS
|
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
|
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;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (errno != EINTR) {
|
if (err != EINTR) {
|
||||||
|
errno = err;
|
||||||
PyErr_SetFromErrno(PyExc_OSError);
|
PyErr_SetFromErrno(PyExc_OSError);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -2114,9 +2137,11 @@ pysleep(_PyTime_t secs)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* sleep was interrupted by SIGINT */
|
/* sleep was interrupted by SIGINT */
|
||||||
if (PyErr_CheckSignals())
|
if (PyErr_CheckSignals()) {
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef HAVE_CLOCK_NANOSLEEP
|
||||||
if (get_monotonic(&monotonic) < 0) {
|
if (get_monotonic(&monotonic) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -2125,6 +2150,7 @@ pysleep(_PyTime_t secs)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* retry with the recomputed delay */
|
/* retry with the recomputed delay */
|
||||||
|
#endif
|
||||||
} while (1);
|
} while (1);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
58
configure
vendored
58
configure
vendored
|
@ -13252,6 +13252,64 @@ fi
|
||||||
done
|
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
|
for ac_func in clock_getres
|
||||||
do :
|
do :
|
||||||
ac_fn_c_check_func "$LINENO" "clock_getres" "ac_cv_func_clock_getres"
|
ac_fn_c_check_func "$LINENO" "clock_getres" "ac_cv_func_clock_getres"
|
||||||
|
|
|
@ -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_MSG_CHECKING(for major, minor, and makedev)
|
||||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
|
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
|
||||||
#if defined(MAJOR_IN_MKDEV)
|
#if defined(MAJOR_IN_MKDEV)
|
||||||
|
|
|
@ -136,6 +136,9 @@
|
||||||
/* Define to 1 if you have the `clock' function. */
|
/* Define to 1 if you have the `clock' function. */
|
||||||
#undef HAVE_CLOCK
|
#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. */
|
/* Define to 1 if you have the `clock_getres' function. */
|
||||||
#undef HAVE_CLOCK_GETRES
|
#undef HAVE_CLOCK_GETRES
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue