sched_clock/clocks/
linux.rs1use crate::{Clock, Duration, Instant};
7use libc::{clockid_t, timespec, CLOCK_BOOTTIME, CLOCK_MONOTONIC_RAW};
8
9pub trait PosixClock: Default {
11 const CLOCK_ID: clockid_t;
13
14 fn now_raw() -> timespec {
16 unsafe {
17 let mut t: timespec = std::mem::uninitialized();
18 let res = libc::clock_gettime(Self::CLOCK_ID, &mut t);
19 assert_eq!(
20 res,
21 0,
22 "Failed to read Linux clock with id {}",
23 Self::CLOCK_ID
24 );
25 t
26 }
27 }
28
29 fn resolution_raw() -> timespec {
31 unsafe {
32 let mut t: timespec = std::mem::uninitialized();
33 let res = libc::clock_getres(Self::CLOCK_ID, &mut t);
34 assert_eq!(
35 res,
36 0,
37 "Failed to check resolution of Linux clock with id {}",
38 Self::CLOCK_ID
39 );
40 t
41 }
42 }
43
44 fn resolution() -> Duration {
46 let t = Self::resolution_raw();
47 Duration((t.tv_sec as i64) * 1_000_000_000 + (t.tv_nsec as i64))
48 }
49}
50
51impl<C: PosixClock> Clock for C {
52 fn now(&self) -> Instant {
53 let t = Self::now_raw();
54 Instant((t.tv_sec as i64) * 1_000_000_000 + (t.tv_nsec as i64))
55 }
56}
57
58#[derive(Default)]
66pub struct BootTimeClock;
67
68impl PosixClock for BootTimeClock {
69 const CLOCK_ID: clockid_t = CLOCK_BOOTTIME;
70}
71
72#[derive(Default)]
80pub struct MonotonicRawClock;
81
82impl PosixClock for MonotonicRawClock {
83 const CLOCK_ID: clockid_t = CLOCK_MONOTONIC_RAW;
84}
85
86#[cfg(test)]
87mod tests {
88 use super::*;
89 use crate::clocks;
90
91 fn generic_posix_clock_test<C: PosixClock>() {
93 let t_raw_1 = C::now_raw();
95 let t_raw_2 = C::now_raw();
96 assert!(
97 t_raw_2.tv_sec > t_raw_1.tv_sec
98 || (t_raw_2.tv_sec == t_raw_1.tv_sec && t_raw_2.tv_nsec >= t_raw_1.tv_nsec)
99 );
100
101 let r_raw_1 = C::resolution_raw();
103 let r_raw_2 = C::resolution_raw();
104 assert_eq!(r_raw_1.tv_sec, r_raw_2.tv_sec);
105 assert_eq!(r_raw_1.tv_nsec, r_raw_2.tv_nsec);
106
107 let r = C::resolution();
109 assert_eq!(r.as_nanos() / 1_000_000_000, r_raw_2.tv_sec as i64);
110 assert_eq!(r.as_nanos() % 1_000_000_000, r_raw_2.tv_nsec as i64);
111
112 assert!(r <= Duration::MILLISECOND);
114
115 clocks::tests::generic_clock_test::<C>();
117 }
118
119 #[test]
120 fn boot_time_clock() {
121 generic_posix_clock_test::<BootTimeClock>();
122 }
123
124 #[test]
125 fn monotonic_raw_clock() {
126 generic_posix_clock_test::<MonotonicRawClock>();
127 }
128}