1pub fn clock_monotonic_ns() -> u64 {
6 clock_monotonic_ns_impl()
7}
8
9#[cfg(unix)]
10fn clock_monotonic_ns_impl() -> u64 {
11 clock_gettime_ns(MONOTONIC_CLOCK_ID)
12}
13
14#[cfg(all(unix, target_vendor = "apple"))]
16const MONOTONIC_CLOCK_ID: libc::clockid_t = libc::CLOCK_UPTIME_RAW;
17
18#[cfg(all(unix, not(target_vendor = "apple")))]
20const MONOTONIC_CLOCK_ID: libc::clockid_t = libc::CLOCK_MONOTONIC;
21
22#[cfg(unix)]
23fn clock_gettime_ns(clock_id: libc::clockid_t) -> u64 {
24 let mut ts = libc::timespec {
25 tv_sec: 0,
26 tv_nsec: 0,
27 };
28 unsafe {
29 libc::clock_gettime(clock_id, &mut ts);
30 }
31 ts.tv_sec as u64 * 1_000_000_000 + ts.tv_nsec as u64
32}
33
34#[cfg(not(unix))]
35fn clock_monotonic_ns_impl() -> u64 {
36 use std::sync::OnceLock;
37 use std::time::Instant;
38 static EPOCH: OnceLock<Instant> = OnceLock::new();
39 (EPOCH.get_or_init(Instant::now).elapsed().as_nanos() as u64).saturating_add(1)
40}
41
42#[cfg(unix)]
44pub(crate) fn clock_realtime_ns() -> u64 {
45 clock_gettime_ns(libc::CLOCK_REALTIME)
46}
47
48#[cfg(not(unix))]
49pub(crate) fn clock_realtime_ns() -> u64 {
50 use std::time::{SystemTime, UNIX_EPOCH};
51 SystemTime::now()
52 .duration_since(UNIX_EPOCH)
53 .expect("system clock should not be before the unix epoch")
54 .as_nanos() as u64
55}
56
57pub(crate) fn clock_pair() -> (u64, u64) {
61 let m1 = clock_monotonic_ns();
62 let r = clock_realtime_ns();
63 let m2 = clock_monotonic_ns();
64 let mono = m1 + m2.saturating_sub(m1) / 2;
65 (mono, r)
66}