Skip to content

Commit 1ed0fef

Browse files
committed
time: use clock_gettime on macos
Replace `mach_{absolute_time,timebase_info}` with `clock_gettime(CLOCK_REALTIME)` on: ``` all(target_os = "macos", not(target_arch = "aarch64")), target_os = "ios", target_os = "watchos", target_os = "tvos" ))] ``` `mach_{absolute_time,timebase_info}` were first used in time-rs/time@cc367ed which predated the introduction of `clock_gettime` support in macOS 10.12 Sierra which became the minimum supported version in 58bbca9. Note that this change was made for aarch64 in 5008a31 which predated 10.12 becoming the minimum supported version. The discussion took place in #91417 and in particular #91417 (comment) and #91417 (comment) are relevant. It's not clear from reading that thread why CLOCK_UPTIME_RAW was used rather than CLOCK_MONOTONIC. The latter is now used.
1 parent b21eb4f commit 1ed0fef

File tree

2 files changed

+20
-151
lines changed

2 files changed

+20
-151
lines changed

Diff for: library/std/src/sys/unix/time.rs

+19-149
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
use crate::fmt;
22
use crate::time::Duration;
33

4-
pub use self::inner::Instant;
5-
64
const NSEC_PER_SEC: u64 = 1_000_000_000;
75
pub const UNIX_EPOCH: SystemTime = SystemTime { t: Timespec::zero() };
86
#[allow(dead_code)] // Used for pthread condvar timeouts
@@ -249,162 +247,34 @@ impl From<__timespec64> for Timespec {
249247
Timespec::new(t.tv_sec, t.tv_nsec.into())
250248
}
251249
}
250+
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
251+
pub struct Instant {
252+
t: Timespec,
253+
}
252254

253-
#[cfg(any(
254-
all(target_os = "macos", not(target_arch = "aarch64")),
255-
target_os = "ios",
256-
target_os = "watchos",
257-
target_os = "tvos"
258-
))]
259-
mod inner {
260-
use crate::sync::atomic::{AtomicU64, Ordering};
261-
use crate::sys_common::mul_div_u64;
262-
use crate::time::Duration;
263-
264-
use super::{SystemTime, Timespec, NSEC_PER_SEC};
265-
266-
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
267-
pub struct Instant {
268-
t: u64,
269-
}
270-
271-
#[repr(C)]
272-
#[derive(Copy, Clone)]
273-
struct mach_timebase_info {
274-
numer: u32,
275-
denom: u32,
276-
}
277-
type mach_timebase_info_t = *mut mach_timebase_info;
278-
type kern_return_t = libc::c_int;
279-
280-
impl Instant {
281-
pub fn now() -> Instant {
282-
extern "C" {
283-
fn mach_absolute_time() -> u64;
284-
}
285-
Instant { t: unsafe { mach_absolute_time() } }
286-
}
287-
288-
pub fn checked_sub_instant(&self, other: &Instant) -> Option<Duration> {
289-
let diff = self.t.checked_sub(other.t)?;
290-
let info = info();
291-
let nanos = mul_div_u64(diff, info.numer as u64, info.denom as u64);
292-
Some(Duration::new(nanos / NSEC_PER_SEC, (nanos % NSEC_PER_SEC) as u32))
293-
}
294-
295-
pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> {
296-
Some(Instant { t: self.t.checked_add(checked_dur2intervals(other)?)? })
297-
}
298-
299-
pub fn checked_sub_duration(&self, other: &Duration) -> Option<Instant> {
300-
Some(Instant { t: self.t.checked_sub(checked_dur2intervals(other)?)? })
301-
}
302-
}
303-
304-
impl From<libc::timeval> for Timespec {
305-
fn from(t: libc::timeval) -> Timespec {
306-
Timespec::new(t.tv_sec as i64, 1000 * t.tv_usec as i64)
307-
}
308-
}
309-
310-
impl From<libc::timeval> for SystemTime {
311-
fn from(t: libc::timeval) -> SystemTime {
312-
SystemTime { t: Timespec::from(t) }
313-
}
314-
}
315-
316-
fn checked_dur2intervals(dur: &Duration) -> Option<u64> {
317-
let nanos =
318-
dur.as_secs().checked_mul(NSEC_PER_SEC)?.checked_add(dur.subsec_nanos() as u64)?;
319-
let info = info();
320-
Some(mul_div_u64(nanos, info.denom as u64, info.numer as u64))
255+
impl Instant {
256+
pub fn now() -> Instant {
257+
Instant { t: Timespec::now(libc::CLOCK_MONOTONIC) }
321258
}
322259

323-
fn info() -> mach_timebase_info {
324-
// INFO_BITS conceptually is an `Option<mach_timebase_info>`. We can do
325-
// this in 64 bits because we know 0 is never a valid value for the
326-
// `denom` field.
327-
//
328-
// Encoding this as a single `AtomicU64` allows us to use `Relaxed`
329-
// operations, as we are only interested in the effects on a single
330-
// memory location.
331-
static INFO_BITS: AtomicU64 = AtomicU64::new(0);
332-
333-
// If a previous thread has initialized `INFO_BITS`, use it.
334-
let info_bits = INFO_BITS.load(Ordering::Relaxed);
335-
if info_bits != 0 {
336-
return info_from_bits(info_bits);
337-
}
338-
339-
// ... otherwise learn for ourselves ...
340-
extern "C" {
341-
fn mach_timebase_info(info: mach_timebase_info_t) -> kern_return_t;
342-
}
343-
344-
let mut info = info_from_bits(0);
345-
unsafe {
346-
mach_timebase_info(&mut info);
347-
}
348-
INFO_BITS.store(info_to_bits(info), Ordering::Relaxed);
349-
info
260+
pub fn checked_sub_instant(&self, other: &Instant) -> Option<Duration> {
261+
self.t.sub_timespec(&other.t).ok()
350262
}
351263

352-
#[inline]
353-
fn info_to_bits(info: mach_timebase_info) -> u64 {
354-
((info.denom as u64) << 32) | (info.numer as u64)
264+
pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> {
265+
Some(Instant { t: self.t.checked_add_duration(other)? })
355266
}
356267

357-
#[inline]
358-
fn info_from_bits(bits: u64) -> mach_timebase_info {
359-
mach_timebase_info { numer: bits as u32, denom: (bits >> 32) as u32 }
268+
pub fn checked_sub_duration(&self, other: &Duration) -> Option<Instant> {
269+
Some(Instant { t: self.t.checked_sub_duration(other)? })
360270
}
361271
}
362272

363-
#[cfg(not(any(
364-
all(target_os = "macos", not(target_arch = "aarch64")),
365-
target_os = "ios",
366-
target_os = "watchos",
367-
target_os = "tvos"
368-
)))]
369-
mod inner {
370-
use crate::fmt;
371-
use crate::time::Duration;
372-
373-
use super::Timespec;
374-
375-
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
376-
pub struct Instant {
377-
t: Timespec,
378-
}
379-
380-
impl Instant {
381-
pub fn now() -> Instant {
382-
#[cfg(target_os = "macos")]
383-
const clock_id: libc::clockid_t = libc::CLOCK_UPTIME_RAW;
384-
#[cfg(not(target_os = "macos"))]
385-
const clock_id: libc::clockid_t = libc::CLOCK_MONOTONIC;
386-
Instant { t: Timespec::now(clock_id) }
387-
}
388-
389-
pub fn checked_sub_instant(&self, other: &Instant) -> Option<Duration> {
390-
self.t.sub_timespec(&other.t).ok()
391-
}
392-
393-
pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> {
394-
Some(Instant { t: self.t.checked_add_duration(other)? })
395-
}
396-
397-
pub fn checked_sub_duration(&self, other: &Duration) -> Option<Instant> {
398-
Some(Instant { t: self.t.checked_sub_duration(other)? })
399-
}
400-
}
401-
402-
impl fmt::Debug for Instant {
403-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
404-
f.debug_struct("Instant")
405-
.field("tv_sec", &self.t.tv_sec)
406-
.field("tv_nsec", &self.t.tv_nsec.0)
407-
.finish()
408-
}
273+
impl fmt::Debug for Instant {
274+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
275+
f.debug_struct("Instant")
276+
.field("tv_sec", &self.t.tv_sec)
277+
.field("tv_nsec", &self.t.tv_nsec.0)
278+
.finish()
409279
}
410280
}

Diff for: library/std/src/time.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ pub use core::time::TryFromFloatSecsError;
109109
/// |-----------|----------------------------------------------------------------------|
110110
/// | SGX | [`insecure_time` usercall]. More information on [timekeeping in SGX] |
111111
/// | UNIX | [clock_gettime (Monotonic Clock)] |
112-
/// | Darwin | [mach_absolute_time] |
112+
/// | Darwin | [clock_gettime (Monotonic Clock)] |
113113
/// | VXWorks | [clock_gettime (Monotonic Clock)] |
114114
/// | SOLID | `get_tim` |
115115
/// | WASI | [__wasi_clock_time_get (Monotonic Clock)] |
@@ -121,7 +121,6 @@ pub use core::time::TryFromFloatSecsError;
121121
/// [timekeeping in SGX]: https://edp.fortanix.com/docs/concepts/rust-std/#codestdtimecode
122122
/// [__wasi_clock_time_get (Monotonic Clock)]: https://github.com/WebAssembly/WASI/blob/main/legacy/preview1/docs.md#clock_time_get
123123
/// [clock_gettime (Monotonic Clock)]: https://linux.die.net/man/3/clock_gettime
124-
/// [mach_absolute_time]: https://developer.apple.com/library/archive/documentation/Darwin/Conceptual/KernelProgramming/services/services.html
125124
///
126125
/// **Disclaimer:** These system calls might change over time.
127126
///

0 commit comments

Comments
 (0)