1use core::fmt;
11use core::time::Duration;
12
13use bitflags::bitflags;
14
15const NANOS_PER_SECOND: u32 = 1_000_000_000;
16
17#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
19#[repr(i32)]
20pub enum Clock {
21 Realtime = 0,
23 Monotonic = 1,
25 ProcessCpuTime = 2,
27 ThreadCpuTime = 3,
29 MonotonicRaw = 4,
31 RealtimeCoarse = 5,
33 MonotonicCoarse = 6,
35 Boottime = 7,
37 RealtimeAlarm = 8,
39 BoottimeAlarm = 9,
41 Tai = 11,
43}
44
45impl Clock {
46 #[must_use]
48 #[inline]
49 pub const fn as_raw(self) -> i32 {
50 self as i32
51 }
52
53 #[must_use]
55 pub const fn try_from_raw(value: i32) -> Option<Self> {
56 match value {
57 0 => Some(Self::Realtime),
58 1 => Some(Self::Monotonic),
59 2 => Some(Self::ProcessCpuTime),
60 3 => Some(Self::ThreadCpuTime),
61 4 => Some(Self::MonotonicRaw),
62 5 => Some(Self::RealtimeCoarse),
63 6 => Some(Self::MonotonicCoarse),
64 7 => Some(Self::Boottime),
65 8 => Some(Self::RealtimeAlarm),
66 9 => Some(Self::BoottimeAlarm),
67 11 => Some(Self::Tai),
68 _ => None,
69 }
70 }
71
72 #[must_use]
74 pub const fn name(self) -> &'static str {
75 match self {
76 Self::Realtime => "CLOCK_REALTIME",
77 Self::Monotonic => "CLOCK_MONOTONIC",
78 Self::ProcessCpuTime => "CLOCK_PROCESS_CPUTIME_ID",
79 Self::ThreadCpuTime => "CLOCK_THREAD_CPUTIME_ID",
80 Self::MonotonicRaw => "CLOCK_MONOTONIC_RAW",
81 Self::RealtimeCoarse => "CLOCK_REALTIME_COARSE",
82 Self::MonotonicCoarse => "CLOCK_MONOTONIC_COARSE",
83 Self::Boottime => "CLOCK_BOOTTIME",
84 Self::RealtimeAlarm => "CLOCK_REALTIME_ALARM",
85 Self::BoottimeAlarm => "CLOCK_BOOTTIME_ALARM",
86 Self::Tai => "CLOCK_TAI",
87 }
88 }
89}
90
91#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
93pub struct Instant {
94 clock: Clock,
95 seconds: i64,
96 nanoseconds: u32,
97}
98
99impl Instant {
100 #[must_use]
102 pub const fn try_new(clock: Clock, seconds: i64, nanoseconds: u32) -> Option<Self> {
103 if nanoseconds >= NANOS_PER_SECOND {
104 return None;
105 }
106 Some(Self {
107 clock,
108 seconds,
109 nanoseconds,
110 })
111 }
112
113 #[must_use]
115 #[inline]
116 pub const fn clock(self) -> Clock {
117 self.clock
118 }
119
120 #[must_use]
122 #[inline]
123 pub const fn seconds(self) -> i64 {
124 self.seconds
125 }
126
127 #[must_use]
129 #[inline]
130 pub const fn nanoseconds(self) -> u32 {
131 self.nanoseconds
132 }
133
134 #[must_use]
138 pub fn as_duration_since_epoch(self) -> Duration {
139 if self.seconds < 0 {
140 return Duration::ZERO;
141 }
142 let secs = u64::try_from(self.seconds).expect("non-negative seconds checked above");
143 Duration::new(secs, self.nanoseconds)
144 }
145
146 #[must_use]
148 pub fn checked_duration_since(self, earlier: Instant) -> Option<Duration> {
149 if self.clock != earlier.clock {
150 return None;
151 }
152 if (self.seconds, self.nanoseconds) < (earlier.seconds, earlier.nanoseconds) {
153 return None;
154 }
155 let nanos_per_second = i128::from(NANOS_PER_SECOND);
156 let self_nanos = i128::from(self.seconds)
157 .checked_mul(nanos_per_second)?
158 .checked_add(i128::from(self.nanoseconds))?;
159 let earlier_nanos = i128::from(earlier.seconds)
160 .checked_mul(nanos_per_second)?
161 .checked_add(i128::from(earlier.nanoseconds))?;
162 let diff = self_nanos.checked_sub(earlier_nanos)?;
163 let secs_i128 = diff.checked_div(nanos_per_second)?;
164 let nanos_i128 = diff.checked_rem(nanos_per_second)?;
165 let secs_u64 = u64::try_from(secs_i128).ok()?;
166 let nanos = u32::try_from(nanos_i128).ok()?;
167 Some(Duration::new(secs_u64, nanos))
168 }
169
170 #[must_use]
172 pub fn saturating_duration_since(self, earlier: Instant) -> Duration {
173 self.checked_duration_since(earlier)
174 .unwrap_or(Duration::ZERO)
175 }
176}
177
178#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
180pub enum SleepDeadline {
181 Relative(Duration),
183 AbsoluteInstant(Instant),
185}
186
187#[derive(Debug, Clone, Copy, PartialEq, Eq)]
189pub enum SleepError {
190 Interrupted {
192 remaining: Duration,
194 },
195 Other(crate::Errno),
197}
198
199impl fmt::Display for SleepError {
200 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
201 match self {
202 Self::Interrupted { remaining } => {
203 write!(f, "sleep interrupted with {:?} remaining", remaining)
204 }
205 Self::Other(errno) => errno.fmt(f),
206 }
207 }
208}
209
210impl core::error::Error for SleepError {}
211
212bitflags! {
213 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
215 pub struct TimerFdFlags: i32 {
216 const NONBLOCK = 0x800;
218 const CLOEXEC = 0x80000;
220 }
221}
222
223bitflags! {
224 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
226 pub struct TimerSetFlags: i32 {
227 const ABSTIME = 1;
229 const CANCEL_ON_SET = 2;
231 }
232}
233
234#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
236pub struct TimerFdSpecification {
237 pub initial: Duration,
239 pub interval: Duration,
241}
242
243#[cfg(test)]
244mod tests;