Skip to content

Commit

Permalink
time: use clock_gettime on all unixen
Browse files Browse the repository at this point in the history
This retires gettimeofday in favor of clock_gettime(CLOCK_REALTIME) on:

```
    all(target_os = "macos", not(target_arch = "aarch64")),
    target_os = "ios",
    target_os = "watchos",
    target_os = "tvos"
))]
```

gettimeofday was first used in
time-rs/time@cc367ed
which predated the introduction of clock_gettime support in macOS 10.12
Sierra. As of 58bbca9, this is the
minimum supported version.
  • Loading branch information
tamird committed Sep 28, 2023
1 parent f264d28 commit 9033c83
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 51 deletions.
84 changes: 35 additions & 49 deletions library/std/src/sys/unix/time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ impl SystemTime {
SystemTime { t: Timespec::new(tv_sec, tv_nsec) }
}

pub fn now() -> SystemTime {
SystemTime { t: Timespec::now(libc::CLOCK_REALTIME) }
}

pub fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> {
self.t.sub_timespec(&other.t)
}
Expand Down Expand Up @@ -79,6 +83,36 @@ impl Timespec {
Timespec { tv_sec, tv_nsec: unsafe { Nanoseconds(tv_nsec as u32) } }
}

pub fn now(clock: libc::clockid_t) -> Timespec {
use crate::mem::MaybeUninit;
use crate::sys::cvt;

// Try to use 64-bit time in preparation for Y2038.
#[cfg(all(
target_os = "linux",
target_env = "gnu",
target_pointer_width = "32",
not(target_arch = "riscv32")
))]
{
use crate::sys::weak::weak;

// __clock_gettime64 was added to 32-bit arches in glibc 2.34,
// and it handles both vDSO calls and ENOSYS fallbacks itself.
weak!(fn __clock_gettime64(libc::clockid_t, *mut super::__timespec64) -> libc::c_int);

if let Some(clock_gettime64) = __clock_gettime64.get() {
let mut t = MaybeUninit::uninit();
cvt(unsafe { clock_gettime64(clock, t.as_mut_ptr()) }).unwrap();
return Timespec::from(unsafe { t.assume_init() });
}
}

let mut t = MaybeUninit::uninit();
cvt(unsafe { libc::clock_gettime(clock, t.as_mut_ptr()) }).unwrap();
Timespec::from(unsafe { t.assume_init() })
}

pub fn sub_timespec(&self, other: &Timespec) -> Result<Duration, Duration> {
if self >= other {
// NOTE(eddyb) two aspects of this `if`-`else` are required for LLVM
Expand Down Expand Up @@ -224,7 +258,6 @@ impl From<__timespec64> for Timespec {
))]
mod inner {
use crate::sync::atomic::{AtomicU64, Ordering};
use crate::sys::cvt;
use crate::sys_common::mul_div_u64;
use crate::time::Duration;

Expand Down Expand Up @@ -268,16 +301,6 @@ mod inner {
}
}

impl SystemTime {
pub fn now() -> SystemTime {
use crate::ptr;

let mut s = libc::timeval { tv_sec: 0, tv_usec: 0 };
cvt(unsafe { libc::gettimeofday(&mut s, ptr::null_mut()) }).unwrap();
return SystemTime::from(s);
}
}

impl From<libc::timeval> for Timespec {
fn from(t: libc::timeval) -> Timespec {
Timespec::new(t.tv_sec as i64, 1000 * t.tv_usec as i64)
Expand Down Expand Up @@ -345,11 +368,9 @@ mod inner {
)))]
mod inner {
use crate::fmt;
use crate::mem::MaybeUninit;
use crate::sys::cvt;
use crate::time::Duration;

use super::{SystemTime, Timespec};
use super::Timespec;

#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Instant {
Expand Down Expand Up @@ -386,39 +407,4 @@ mod inner {
.finish()
}
}

impl SystemTime {
pub fn now() -> SystemTime {
SystemTime { t: Timespec::now(libc::CLOCK_REALTIME) }
}
}

impl Timespec {
pub fn now(clock: libc::clockid_t) -> Timespec {
// Try to use 64-bit time in preparation for Y2038.
#[cfg(all(
target_os = "linux",
target_env = "gnu",
target_pointer_width = "32",
not(target_arch = "riscv32")
))]
{
use crate::sys::weak::weak;

// __clock_gettime64 was added to 32-bit arches in glibc 2.34,
// and it handles both vDSO calls and ENOSYS fallbacks itself.
weak!(fn __clock_gettime64(libc::clockid_t, *mut super::__timespec64) -> libc::c_int);

if let Some(clock_gettime64) = __clock_gettime64.get() {
let mut t = MaybeUninit::uninit();
cvt(unsafe { clock_gettime64(clock, t.as_mut_ptr()) }).unwrap();
return Timespec::from(unsafe { t.assume_init() });
}
}

let mut t = MaybeUninit::uninit();
cvt(unsafe { libc::clock_gettime(clock, t.as_mut_ptr()) }).unwrap();
Timespec::from(unsafe { t.assume_init() })
}
}
}
3 changes: 1 addition & 2 deletions library/std/src/time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ pub struct Instant(time::Instant);
/// |-----------|----------------------------------------------------------------------|
/// | SGX | [`insecure_time` usercall]. More information on [timekeeping in SGX] |
/// | UNIX | [clock_gettime (Realtime Clock)] |
/// | Darwin | [gettimeofday] |
/// | Darwin | [clock_gettime (Realtime Clock)] |
/// | VXWorks | [clock_gettime (Realtime Clock)] |
/// | SOLID | `SOLID_RTC_ReadTime` |
/// | WASI | [__wasi_clock_time_get (Realtime Clock)] |
Expand All @@ -230,7 +230,6 @@ pub struct Instant(time::Instant);
/// [currently]: crate::io#platform-specific-behavior
/// [`insecure_time` usercall]: https://edp.fortanix.com/docs/api/fortanix_sgx_abi/struct.Usercalls.html#method.insecure_time
/// [timekeeping in SGX]: https://edp.fortanix.com/docs/concepts/rust-std/#codestdtimecode
/// [gettimeofday]: https://man7.org/linux/man-pages/man2/gettimeofday.2.html
/// [clock_gettime (Realtime Clock)]: https://linux.die.net/man/3/clock_gettime
/// [__wasi_clock_time_get (Realtime Clock)]: https://github.com/WebAssembly/WASI/blob/main/legacy/preview1/docs.md#clock_time_get
/// [GetSystemTimePreciseAsFileTime]: https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getsystemtimepreciseasfiletime
Expand Down

0 comments on commit 9033c83

Please sign in to comment.