Rollup merge of #151403 - joboet:clock_nanosleep_time64, r=Mark-Simulacrum

std: use 64-bit `clock_nanosleep` on GNU/Linux if available

glibc 2.31 added support for both 64-bit `clock_gettime` and 64-bit `clock_nanosleep`. Thus, if [`__clock_nanosleep_time64`](https://sourceware.org/git/?p=glibc.git;a=blob;f=include/time.h;h=22b29ca583549488a0e5395cb820f55ec6e38e5f;hb=e14a91e59d35bf2fa649a9726ccce838b8c6e4b7#l322) and the underlying syscall are available, use them for implementing `sleep_until` to avoid having to fall back to `nanosleep` for long-duration sleeps.
This commit is contained in:
Matthias Krüger
2026-01-24 21:04:17 +01:00
committed by GitHub
2 changed files with 51 additions and 1 deletions

View File

@@ -647,6 +647,56 @@ pub fn sleep(dur: Duration) {
pub fn sleep_until(deadline: crate::time::Instant) {
use crate::time::Instant;
#[cfg(all(
target_os = "linux",
target_env = "gnu",
target_pointer_width = "32",
not(target_arch = "riscv32")
))]
{
use crate::sys::pal::time::__timespec64;
use crate::sys::pal::weak::weak;
// This got added in glibc 2.31, along with a 64-bit `clock_gettime`
// function.
weak! {
fn __clock_nanosleep_time64(
clock_id: libc::clockid_t,
flags: libc::c_int,
req: *const __timespec64,
rem: *mut __timespec64,
) -> libc::c_int;
}
if let Some(clock_nanosleep) = __clock_nanosleep_time64.get() {
let ts = deadline.into_inner().into_timespec().to_timespec64();
loop {
let r = unsafe {
clock_nanosleep(
crate::sys::time::Instant::CLOCK_ID,
libc::TIMER_ABSTIME,
&ts,
core::ptr::null_mut(),
)
};
match r {
0 => return,
libc::EINTR => continue,
// If the underlying kernel doesn't support the 64-bit
// syscall, `__clock_nanosleep_time64` will fail. The
// error code nowadays is EOVERFLOW, but it used to be
// ENOSYS so just don't rely on any particular value.
// The parameters are all valid, so the only reasons
// why the call might fail are EINTR and the call not
// being supported. Fall through to the clamping version
// in that case.
_ => break,
}
}
}
}
let Some(ts) = deadline.into_inner().into_timespec().to_timespec() else {
// The deadline is further in the future then can be passed to
// clock_nanosleep. We have to use Self::sleep instead. This might

View File

@@ -55,7 +55,7 @@ impl<'tcx> MiriMachine<'tcx> {
Os::Linux => {
Self::null_ptr_extern_statics(
ecx,
&["__cxa_thread_atexit_impl", "__clock_gettime64"],
&["__cxa_thread_atexit_impl", "__clock_gettime64", "__clock_nanosleep_time64"],
)?;
Self::weak_symbol_extern_statics(ecx, &["getrandom", "gettid", "statx"])?;
}