Skip to content

Commit f6cc562

Browse files
authored
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.
2 parents 9a06ab5 + 93929ef commit f6cc562

2 files changed

Lines changed: 51 additions & 1 deletion

File tree

library/std/src/sys/thread/unix.rs

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -647,6 +647,56 @@ pub fn sleep(dur: Duration) {
647647
pub fn sleep_until(deadline: crate::time::Instant) {
648648
use crate::time::Instant;
649649

650+
#[cfg(all(
651+
target_os = "linux",
652+
target_env = "gnu",
653+
target_pointer_width = "32",
654+
not(target_arch = "riscv32")
655+
))]
656+
{
657+
use crate::sys::pal::time::__timespec64;
658+
use crate::sys::pal::weak::weak;
659+
660+
// This got added in glibc 2.31, along with a 64-bit `clock_gettime`
661+
// function.
662+
weak! {
663+
fn __clock_nanosleep_time64(
664+
clock_id: libc::clockid_t,
665+
flags: libc::c_int,
666+
req: *const __timespec64,
667+
rem: *mut __timespec64,
668+
) -> libc::c_int;
669+
}
670+
671+
if let Some(clock_nanosleep) = __clock_nanosleep_time64.get() {
672+
let ts = deadline.into_inner().into_timespec().to_timespec64();
673+
loop {
674+
let r = unsafe {
675+
clock_nanosleep(
676+
crate::sys::time::Instant::CLOCK_ID,
677+
libc::TIMER_ABSTIME,
678+
&ts,
679+
core::ptr::null_mut(),
680+
)
681+
};
682+
683+
match r {
684+
0 => return,
685+
libc::EINTR => continue,
686+
// If the underlying kernel doesn't support the 64-bit
687+
// syscall, `__clock_nanosleep_time64` will fail. The
688+
// error code nowadays is EOVERFLOW, but it used to be
689+
// ENOSYS – so just don't rely on any particular value.
690+
// The parameters are all valid, so the only reasons
691+
// why the call might fail are EINTR and the call not
692+
// being supported. Fall through to the clamping version
693+
// in that case.
694+
_ => break,
695+
}
696+
}
697+
}
698+
}
699+
650700
let Some(ts) = deadline.into_inner().into_timespec().to_timespec() else {
651701
// The deadline is further in the future then can be passed to
652702
// clock_nanosleep. We have to use Self::sleep instead. This might

src/tools/miri/src/shims/extern_static.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ impl<'tcx> MiriMachine<'tcx> {
5555
Os::Linux => {
5656
Self::null_ptr_extern_statics(
5757
ecx,
58-
&["__cxa_thread_atexit_impl", "__clock_gettime64"],
58+
&["__cxa_thread_atexit_impl", "__clock_gettime64", "__clock_nanosleep_time64"],
5959
)?;
6060
Self::weak_symbol_extern_statics(ecx, &["getrandom", "gettid", "statx"])?;
6161
}

0 commit comments

Comments
 (0)