mirror of
https://github.com/rust-lang/rust.git
synced 2026-01-24 23:17:31 +00:00
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:
@@ -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
|
||||
|
||||
@@ -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"])?;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user