1pub const KTIME_MAX_NANOS: u64 = i64::MAX as u64;
5
6#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
8#[repr(transparent)]
9pub struct MonotonicInstant(u64);
10
11impl MonotonicInstant {
12 pub const fn from_nanos(now_ns: u64) -> Option<Self> {
14 if now_ns <= KTIME_MAX_NANOS {
15 Some(Self(now_ns))
16 } else {
17 None
18 }
19 }
20
21 pub const fn as_nanos(self) -> u64 {
23 self.0
24 }
25
26 pub const fn reached(self, deadline: MonotonicDeadline) -> bool {
28 self.0 >= deadline.0
29 }
30
31 pub fn deadline_after(self, timeout: core::time::Duration) -> MonotonicDeadline {
33 let timeout_ns = timeout.as_nanos();
34 let sum = self.0 as u128 + timeout_ns;
35 if sum >= KTIME_MAX_NANOS as u128 {
36 MonotonicDeadline(KTIME_MAX_NANOS)
39 } else {
40 MonotonicDeadline(sum as u64)
41 }
42 }
43}
44
45#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
47#[repr(transparent)]
48pub struct MonotonicDeadline(u64);
49
50impl MonotonicDeadline {
51 pub const ORIGIN: Self = Self(0);
54
55 pub const fn from_nanos(deadline_ns: u64) -> Option<Self> {
60 if deadline_ns <= KTIME_MAX_NANOS {
61 Some(Self(deadline_ns))
62 } else {
63 None
64 }
65 }
66
67 pub fn from_duration(deadline: core::time::Duration) -> Self {
70 const NANOS_PER_SECOND: u64 = 1_000_000_000;
71 const KTIME_SEC_MAX: u64 = KTIME_MAX_NANOS / NANOS_PER_SECOND;
72
73 if deadline.as_secs() >= KTIME_SEC_MAX {
74 return Self(KTIME_MAX_NANOS);
75 }
76 Self(deadline.as_secs() * NANOS_PER_SECOND + u64::from(deadline.subsec_nanos()))
77 }
78
79 pub const fn as_nanos(self) -> u64 {
81 self.0
82 }
83}
84
85#[derive(Clone, Copy, Debug, Eq, PartialEq)]
94#[repr(C)]
95pub struct RqClockSample {
96 clock: crate::sched::SchedulerTimestamp,
97 hardirq_time_ns: Option<u64>,
98 frequency_capacity: u32,
99 cpu_capacity: u32,
100}
101
102impl RqClockSample {
103 pub const fn new(clock: crate::sched::SchedulerTimestamp, hardirq_time_ns: u64) -> Self {
105 Self {
106 clock,
107 hardirq_time_ns: Some(hardirq_time_ns),
108 frequency_capacity: 1_024,
109 cpu_capacity: 1_024,
110 }
111 }
112
113 pub const fn without_irq_time_accounting(clock: crate::sched::SchedulerTimestamp) -> Self {
115 Self {
116 clock,
117 hardirq_time_ns: None,
118 frequency_capacity: 1_024,
119 cpu_capacity: 1_024,
120 }
121 }
122
123 pub const fn with_capacity_scales(
130 clock: crate::sched::SchedulerTimestamp,
131 hardirq_time_ns: u64,
132 frequency_capacity: u32,
133 cpu_capacity: u32,
134 ) -> Option<Self> {
135 if frequency_capacity == 0
136 || frequency_capacity > 1_024
137 || cpu_capacity == 0
138 || cpu_capacity > 1_024
139 {
140 return None;
141 }
142 Some(Self {
143 clock,
144 hardirq_time_ns: Some(hardirq_time_ns),
145 frequency_capacity,
146 cpu_capacity,
147 })
148 }
149
150 pub const fn clock(self) -> crate::sched::SchedulerTimestamp {
152 self.clock
153 }
154
155 pub const fn hardirq_time_ns(self) -> Option<u64> {
157 self.hardirq_time_ns
158 }
159
160 pub const fn frequency_capacity(self) -> u32 {
162 self.frequency_capacity
163 }
164
165 pub const fn cpu_capacity(self) -> u32 {
167 self.cpu_capacity
168 }
169}
170
171#[derive(Clone, Copy, Debug, Eq, PartialEq)]
173pub struct SchedulerDeadlineUpdate {
174 generation: u64,
175 deadline: Option<MonotonicDeadline>,
176}
177
178impl SchedulerDeadlineUpdate {
179 pub const fn try_new(generation: u64, deadline: Option<MonotonicDeadline>) -> Option<Self> {
183 if generation == 0 {
184 None
185 } else {
186 Some(Self {
187 generation,
188 deadline,
189 })
190 }
191 }
192
193 pub const fn generation(self) -> u64 {
195 self.generation
196 }
197
198 pub const fn deadline(self) -> Option<MonotonicDeadline> {
200 self.deadline
201 }
202}
203
204#[derive(Clone, Copy, Debug, Eq, PartialEq)]
209pub enum SchedulerRuntimeDeadline {
210 Disarmed,
211 Due,
212 After(core::time::Duration),
213}
214
215#[cfg(test)]
216mod monotonic_time_tests {
217 use super::*;
218
219 #[test]
220 fn monotonic_time_matches_linux_ktime_boundaries() {
221 let deadline = MonotonicDeadline::from_nanos(0).unwrap();
222 assert_eq!(deadline, MonotonicDeadline::ORIGIN);
223 assert!(MonotonicInstant::from_nanos(1).unwrap().reached(deadline));
224 assert!(MonotonicInstant::from_nanos(KTIME_MAX_NANOS - 1).is_some());
225 assert!(MonotonicDeadline::from_nanos(KTIME_MAX_NANOS - 1).is_some());
226 assert!(MonotonicInstant::from_nanos(KTIME_MAX_NANOS).is_some());
227 assert_eq!(
228 MonotonicDeadline::from_nanos(KTIME_MAX_NANOS),
229 Some(MonotonicDeadline(KTIME_MAX_NANOS))
230 );
231 assert!(MonotonicDeadline::from_nanos(KTIME_MAX_NANOS + 1).is_none());
232 assert_eq!(
233 MonotonicDeadline::from_duration(core::time::Duration::MAX),
234 MonotonicDeadline::from_nanos(KTIME_MAX_NANOS).unwrap()
235 );
236 let now = MonotonicInstant::from_nanos(KTIME_MAX_NANOS - 2).unwrap();
237 assert_eq!(
238 now.deadline_after(core::time::Duration::from_nanos(2)),
239 MonotonicDeadline::from_nanos(KTIME_MAX_NANOS).unwrap()
240 );
241 }
242}