limen_core/platform/
linux.rs1use crate::platform::PlatformClock;
4use crate::types::Ticks;
5
6const NANOSECONDS_PER_SECOND: u128 = 1_000_000_000;
8
9#[derive(Debug, Default, Clone, Copy)]
11pub struct NoStdLinuxMonotonicClock;
12
13impl NoStdLinuxMonotonicClock {
14 #[inline]
16 pub const fn new() -> NoStdLinuxMonotonicClock {
17 NoStdLinuxMonotonicClock
18 }
19
20 #[allow(unsafe_code)]
25 #[inline]
26 fn read_monotonic_nanoseconds() -> u64 {
27 let mut timespec_value = libc::timespec {
29 tv_sec: 0,
30 tv_nsec: 0,
31 };
32
33 let return_code =
35 unsafe { libc::clock_gettime(libc::CLOCK_MONOTONIC, &mut timespec_value) };
36
37 if return_code != 0 {
39 return 0;
40 }
41
42 if timespec_value.tv_sec < 0 as libc::time_t {
44 return 0;
45 }
46
47 if timespec_value.tv_nsec < 0 as libc::c_long
48 || timespec_value.tv_nsec >= 1_000_000_000 as libc::c_long
49 {
50 return 0;
51 }
52
53 let seconds_as_u64 = timespec_value.tv_sec as u64;
54 let nanoseconds_as_u64 = timespec_value.tv_nsec as u64;
55
56 let total_nanoseconds_as_u128 = (seconds_as_u64 as u128)
58 .saturating_mul(NANOSECONDS_PER_SECOND)
59 .saturating_add(nanoseconds_as_u64 as u128);
60
61 if total_nanoseconds_as_u128 > u64::MAX as u128 {
62 u64::MAX
63 } else {
64 total_nanoseconds_as_u128 as u64
65 }
66 }
67}
68
69impl PlatformClock for NoStdLinuxMonotonicClock {
70 #[inline]
71 fn now_ticks(&self) -> Ticks {
72 Ticks::new(Self::read_monotonic_nanoseconds())
74 }
75
76 #[inline]
77 fn ticks_to_nanos(&self, ticks: Ticks) -> u64 {
78 *ticks.as_u64()
80 }
81
82 #[inline]
83 fn nanos_to_ticks(&self, nanoseconds: u64) -> Ticks {
84 Ticks::new(nanoseconds)
86 }
87}
88
89#[cfg(feature = "std")]
94#[derive(Debug, Clone)]
95pub struct StdLinuxMonotonicClock {
96 origin: std::time::Instant,
97}
98
99#[cfg(feature = "std")]
100impl StdLinuxMonotonicClock {
101 #[inline]
103 pub fn new() -> StdLinuxMonotonicClock {
104 StdLinuxMonotonicClock {
105 origin: std::time::Instant::now(),
106 }
107 }
108}
109
110#[cfg(feature = "std")]
111impl Default for StdLinuxMonotonicClock {
112 #[inline]
113 fn default() -> StdLinuxMonotonicClock {
114 StdLinuxMonotonicClock::new()
115 }
116}
117
118#[cfg(feature = "std")]
119impl PlatformClock for StdLinuxMonotonicClock {
120 #[inline]
121 fn now_ticks(&self) -> Ticks {
122 let duration_since_origin = std::time::Instant::now().duration_since(self.origin);
123
124 let total_nanoseconds_as_u128 = duration_since_origin.as_nanos();
126
127 if total_nanoseconds_as_u128 > u64::MAX as u128 {
129 Ticks::new(u64::MAX)
130 } else {
131 Ticks::new(total_nanoseconds_as_u128 as u64)
132 }
133 }
134
135 #[inline]
136 fn ticks_to_nanos(&self, ticks: Ticks) -> u64 {
137 *ticks.as_u64()
139 }
140
141 #[inline]
142 fn nanos_to_ticks(&self, nanoseconds: u64) -> Ticks {
143 Ticks::new(nanoseconds)
145 }
146}