From 93929ef064b1497182acd2929137d6e4886c0e47 Mon Sep 17 00:00:00 2001 From: joboet Date: Tue, 20 Jan 2026 11:15:12 +0100 Subject: [PATCH] std: use 64-bit `clock_nanosleep` on Linux if available --- library/std/src/sys/thread/unix.rs | 50 +++++++++++++++++++++++ src/tools/miri/src/shims/extern_static.rs | 2 +- 2 files changed, 51 insertions(+), 1 deletion(-) diff --git a/library/std/src/sys/thread/unix.rs b/library/std/src/sys/thread/unix.rs index b1f27c32fedd..cf3d31835b09 100644 --- a/library/std/src/sys/thread/unix.rs +++ b/library/std/src/sys/thread/unix.rs @@ -609,6 +609,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 diff --git a/src/tools/miri/src/shims/extern_static.rs b/src/tools/miri/src/shims/extern_static.rs index fc9971641088..6c7f3470600b 100644 --- a/src/tools/miri/src/shims/extern_static.rs +++ b/src/tools/miri/src/shims/extern_static.rs @@ -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"])?; }