1use crate::time::utc;
6use fuchsia_runtime::{UtcDuration, UtcInstant};
7use starnix_types::time::{itimerspec_from_deadline_interval, time_from_timespec};
8use starnix_uapi::errors::Errno;
9use starnix_uapi::{itimerspec, timespec};
10use std::ops;
11
12#[derive(Clone, Copy, Debug, PartialEq)]
13pub enum Timeline {
14 RealTime,
15 Monotonic,
16 BootInstant,
17}
18
19impl Timeline {
20 pub fn now(&self) -> TargetTime {
22 match self {
23 Self::RealTime => TargetTime::RealTime(utc::utc_now()),
24 Self::Monotonic => TargetTime::Monotonic(zx::MonotonicInstant::get()),
25 Self::BootInstant => TargetTime::BootInstant(zx::BootInstant::get()),
26 }
27 }
28
29 pub fn target_from_timespec(&self, spec: timespec) -> Result<TargetTime, Errno> {
30 Ok(match self {
31 Timeline::Monotonic => TargetTime::Monotonic(time_from_timespec(spec)?),
32 Timeline::RealTime => TargetTime::RealTime(time_from_timespec(spec)?),
33 Timeline::BootInstant => TargetTime::BootInstant(time_from_timespec(spec)?),
34 })
35 }
36
37 pub fn zero_time(&self) -> TargetTime {
38 match self {
39 Timeline::Monotonic => TargetTime::Monotonic(zx::Instant::ZERO),
40 Timeline::RealTime => TargetTime::RealTime(zx::Instant::ZERO),
41 Timeline::BootInstant => TargetTime::BootInstant(zx::Instant::ZERO),
42 }
43 }
44
45 pub fn is_realtime(&self) -> bool {
47 match self {
48 Timeline::RealTime => true,
49 _ => false,
50 }
51 }
52}
53
54#[derive(Debug)]
55pub enum TimerWakeup {
56 Regular,
58 Alarm,
60}
61
62#[derive(Clone, Copy, Debug, PartialEq)]
63pub enum TargetTime {
64 Monotonic(zx::MonotonicInstant),
65 RealTime(UtcInstant),
66 BootInstant(zx::BootInstant),
67}
68
69impl std::fmt::Display for TargetTime {
70 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
71 match self {
72 TargetTime::Monotonic(t) => write!(f, "{} [MONO]", time_pretty::format_timer(*t)),
73 TargetTime::BootInstant(t) => write!(f, "{} [BOOT]", time_pretty::format_timer(*t)),
74 TargetTime::RealTime(t) => write!(f, "{} [UTC]", time_pretty::format_timer(*t)),
75 }
76 }
77}
78
79impl From<zx::BootInstant> for TargetTime {
80 fn from(value: zx::BootInstant) -> Self {
81 Self::BootInstant(value)
82 }
83}
84
85impl From<UtcInstant> for TargetTime {
86 fn from(value: UtcInstant) -> Self {
87 Self::RealTime(value)
88 }
89}
90
91impl TargetTime {
92 pub fn is_zero(&self) -> bool {
93 0 == match self {
94 TargetTime::Monotonic(t) => t.into_nanos(),
95 TargetTime::RealTime(t) => t.into_nanos(),
96 TargetTime::BootInstant(t) => t.into_nanos(),
97 }
98 }
99
100 pub fn itimerspec(&self, interval: zx::MonotonicDuration) -> itimerspec {
101 match self {
102 TargetTime::Monotonic(t) => itimerspec_from_deadline_interval(*t, interval),
103 TargetTime::BootInstant(t) => itimerspec_from_deadline_interval(*t, interval),
104 TargetTime::RealTime(t) => itimerspec_from_deadline_interval(*t, interval),
105 }
106 }
107
108 pub fn estimate_boot(&self) -> Option<zx::BootInstant> {
109 match self {
110 TargetTime::BootInstant(t) => Some(*t),
111 TargetTime::RealTime(t) => {
112 let (boot_instant, _) = utc::estimate_boot_deadline_from_utc(*t);
113 Some(boot_instant)
114 }
115 TargetTime::Monotonic(_) => None,
117 }
118 }
119
120 pub fn into_resolved_utc_deadline(self) -> TargetTime {
126 match self {
127 orig @ TargetTime::RealTime(t) => {
128 let (boot_instant, started) = utc::estimate_boot_deadline_from_utc(t);
129 if started {
130 orig
131 } else {
132 TargetTime::BootInstant(boot_instant)
136 }
137 }
138 other @ _ => other,
139 }
140 }
141
142 pub fn delta(&self, rhs: &Self) -> Option<GenericDuration> {
145 match (*self, *rhs) {
146 (TargetTime::Monotonic(lhs), TargetTime::Monotonic(rhs)) => {
147 Some(GenericDuration::from(lhs - rhs))
148 }
149 (TargetTime::BootInstant(lhs), TargetTime::BootInstant(rhs)) => {
150 Some(GenericDuration::from(lhs - rhs))
151 }
152 (TargetTime::RealTime(lhs), TargetTime::RealTime(rhs)) => {
153 Some(GenericDuration::from(lhs - rhs))
154 }
155 _ => None,
156 }
157 }
158}
159
160impl std::ops::Add<GenericDuration> for TargetTime {
161 type Output = Self;
162 fn add(self, rhs: GenericDuration) -> Self {
163 match self {
164 Self::RealTime(t) => Self::RealTime(t + rhs.into_utc()),
165 Self::Monotonic(t) => Self::Monotonic(t + rhs.into_mono()),
166 Self::BootInstant(t) => Self::BootInstant(t + rhs.into_boot()),
167 }
168 }
169}
170
171impl std::ops::Sub<GenericDuration> for TargetTime {
172 type Output = Self;
173 fn sub(self, rhs: GenericDuration) -> Self::Output {
174 match self {
175 TargetTime::Monotonic(t) => Self::Monotonic(t - rhs.into_mono()),
176 TargetTime::RealTime(t) => Self::RealTime(t - rhs.into_utc()),
177 TargetTime::BootInstant(t) => Self::BootInstant(t - rhs.into_boot()),
178 }
179 }
180}
181
182impl std::cmp::PartialOrd for TargetTime {
183 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
184 match (self, other) {
185 (Self::Monotonic(lhs), Self::Monotonic(rhs)) => Some(lhs.cmp(rhs)),
186 (Self::RealTime(lhs), Self::RealTime(rhs)) => Some(lhs.cmp(rhs)),
187 (Self::BootInstant(lhs), Self::BootInstant(rhs)) => Some(lhs.cmp(rhs)),
188 _ => None,
189 }
190 }
191}
192
193#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
197pub struct GenericDuration(zx::SyntheticDuration);
198
199impl GenericDuration {
200 pub fn from_nanos(nanos: zx::sys::zx_time_t) -> Self {
201 Self(zx::Duration::from_nanos(nanos))
202 }
203
204 pub fn into_mono(self) -> zx::MonotonicDuration {
205 zx::MonotonicDuration::from_nanos(self.0.into_nanos())
206 }
207
208 #[allow(dead_code)]
211 fn into_boot(self) -> zx::BootDuration {
212 zx::BootDuration::from_nanos(self.0.into_nanos())
213 }
214
215 fn into_utc(self) -> UtcDuration {
216 UtcDuration::from_nanos(self.0.into_nanos())
217 }
218}
219
220impl From<zx::MonotonicDuration> for GenericDuration {
221 fn from(other: zx::MonotonicDuration) -> Self {
222 Self(zx::SyntheticDuration::from_nanos(other.into_nanos()))
223 }
224}
225
226impl From<zx::BootDuration> for GenericDuration {
227 fn from(other: zx::BootDuration) -> Self {
228 Self(zx::SyntheticDuration::from_nanos(other.into_nanos()))
229 }
230}
231
232impl From<zx::SyntheticDuration> for GenericDuration {
233 fn from(other: zx::SyntheticDuration) -> Self {
234 Self(other)
235 }
236}
237
238impl From<UtcDuration> for GenericDuration {
239 fn from(other: UtcDuration) -> Self {
240 Self(zx::SyntheticDuration::from_nanos(other.into_nanos()))
241 }
242}
243
244impl ops::Deref for GenericDuration {
245 type Target = zx::SyntheticDuration;
246
247 #[inline]
248 fn deref(&self) -> &Self::Target {
249 &self.0
250 }
251}