1#![allow(non_camel_case_types)]
6#![allow(dead_code)]
7
8use core::{
9 ffi::{c_int, c_long},
10 ops::{Add, Sub},
11};
12
13use crate::{
14 arch::timer::{clock_freq, get_time},
15 kernel::time::REALTIME,
16};
17
18#[repr(C)]
20#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
21pub struct TimeSpec {
22 pub tv_sec: c_long,
24 pub tv_nsec: c_long,
26}
27
28impl TimeSpec {
29 pub const UTIME_NOW: c_long = (1i64 << 30) - 1; pub const UTIME_OMIT: c_long = (1i64 << 30) - 2; pub fn new(sec: c_long, nsec: c_long) -> Self {
42 Self {
43 tv_sec: sec,
44 tv_nsec: nsec,
45 }
46 }
47
48 pub fn into_freq(&self, freq: usize) -> usize {
54 let sec_ticks = (self.tv_sec as u128) * (freq as u128);
55 let nsec_ticks = (self.tv_nsec as u128) * (freq as u128) / 1_000_000_000;
56 (sec_ticks + nsec_ticks) as usize
57 }
58
59 pub fn from_freq(ticks: usize, freq: usize) -> Self {
66 let sec = ticks / freq;
67 let nsec = (ticks % freq) * 1_000_000_000 / freq;
68 Self {
69 tv_sec: sec as c_long,
70 tv_nsec: nsec as c_long,
71 }
72 }
73
74 pub fn now() -> Self {
78 let time = REALTIME.read();
79 let mtime = Self::monotonic_now();
80 mtime + *time
81 }
82
83 pub fn monotonic_now() -> Self {
87 let time = get_time();
88 Self::from_freq(time, clock_freq())
89 }
90
91 pub fn zero() -> Self {
95 Self {
96 tv_sec: 0,
97 tv_nsec: 0,
98 }
99 }
100
101 pub fn validate(&self) -> Result<(), i32> {
107 use crate::uapi::errno::EINVAL;
108
109 if self.tv_nsec == Self::UTIME_NOW || self.tv_nsec == Self::UTIME_OMIT {
111 return Ok(());
112 }
113
114 if self.tv_nsec < 0 || self.tv_nsec >= 1_000_000_000 {
116 return Err(EINVAL);
117 }
118
119 Ok(())
120 }
121
122 pub fn to_timeval(&self) -> timeval {
126 timeval {
127 tv_sec: self.tv_sec,
128 tv_usec: self.tv_nsec / 1000,
129 }
130 }
131
132 #[inline]
134 pub fn is_zero(&self) -> bool {
135 self.tv_sec == 0 && self.tv_nsec == 0
136 }
137
138 #[inline]
140 pub fn is_now(&self) -> bool {
141 self.tv_nsec == Self::UTIME_NOW
142 }
143
144 #[inline]
146 pub fn is_omit(&self) -> bool {
147 self.tv_nsec == Self::UTIME_OMIT
148 }
149}
150
151impl Sub for TimeSpec {
152 type Output = TimeSpec;
153
154 fn sub(self, other: TimeSpec) -> TimeSpec {
155 let sec = self.tv_sec - other.tv_sec;
156 let nsec = self.tv_nsec - other.tv_nsec;
157 if nsec < 0 {
158 TimeSpec {
159 tv_sec: sec - 1,
160 tv_nsec: nsec + 1_000_000_000,
161 }
162 } else {
163 TimeSpec {
164 tv_sec: sec,
165 tv_nsec: nsec,
166 }
167 }
168 }
169}
170
171impl Add for TimeSpec {
172 type Output = TimeSpec;
173
174 fn add(self, other: TimeSpec) -> TimeSpec {
175 let sec = self.tv_sec + other.tv_sec;
176 let nsec = self.tv_nsec + other.tv_nsec;
177 if nsec >= 1_000_000_000 {
178 TimeSpec {
179 tv_sec: sec + 1,
180 tv_nsec: nsec - 1_000_000_000,
181 }
182 } else {
183 TimeSpec {
184 tv_sec: sec,
185 tv_nsec: nsec,
186 }
187 }
188 }
189}
190
191#[repr(C)]
193#[derive(Debug, Clone, Copy, PartialEq, Eq)]
194pub struct timeval {
195 pub tv_sec: c_long,
197 pub tv_usec: c_long,
199}
200
201impl timeval {
202 pub fn to_timespec(&self) -> TimeSpec {
206 TimeSpec {
207 tv_sec: self.tv_sec,
208 tv_nsec: self.tv_usec * 1000,
209 }
210 }
211
212 pub fn into_freq(&self, freq: usize) -> usize {
218 let sec_ticks = (self.tv_sec as u128) * (freq as u128);
219 let usec_ticks = (self.tv_usec as u128) * (freq as u128) / 1_000_000;
220 (sec_ticks + usec_ticks) as usize
221 }
222
223 pub fn new(sec: c_long, usec: c_long) -> Self {
230 Self {
231 tv_sec: sec,
232 tv_usec: usec,
233 }
234 }
235
236 pub fn zero() -> Self {
240 Self {
241 tv_sec: 0,
242 tv_usec: 0,
243 }
244 }
245
246 #[inline]
248 pub fn is_zero(&self) -> bool {
249 self.tv_sec == 0 && self.tv_usec == 0
250 }
251}
252
253#[repr(C)]
255#[derive(Debug, Clone, Copy, PartialEq, Eq)]
256pub struct Itimerspec {
257 pub it_interval: TimeSpec,
259 pub it_value: TimeSpec,
261}
262
263#[repr(C)]
265#[derive(Debug, Clone, Copy, PartialEq, Eq)]
266pub struct Itimerval {
267 pub it_interval: timeval,
269 pub it_value: timeval,
271}
272
273impl Itimerval {
274 pub fn zero() -> Self {
278 Self {
279 it_interval: timeval {
280 tv_sec: 0,
281 tv_usec: 0,
282 },
283 it_value: timeval {
284 tv_sec: 0,
285 tv_usec: 0,
286 },
287 }
288 }
289}
290
291#[repr(C)]
293#[derive(Debug, Clone, Copy, PartialEq, Eq)]
294pub struct timezone {
295 pub tz_minuteswest: c_int,
297 pub tz_dsttime: c_int,
299}
300
301pub mod itimer_id {
303 use super::c_int;
304 pub const ITIMER_REAL: c_int = 0;
306 pub const ITIMER_VIRTUAL: c_int = 1;
308 pub const ITIMER_PROF: c_int = 2;
310}
311
312pub mod clock_id {
314 use super::c_int;
315
316 pub const CLOCK_REALTIME: c_int = 0;
318 pub const CLOCK_MONOTONIC: c_int = 1;
320 pub const CLOCK_PROCESS_CPUTIME_ID: c_int = 2;
322 pub const CLOCK_THREAD_CPUTIME_ID: c_int = 3;
324 pub const CLOCK_MONOTONIC_RAW: c_int = 4;
326 pub const CLOCK_REALTIME_COARSE: c_int = 5;
328 pub const CLOCK_MONOTONIC_COARSE: c_int = 6;
330 pub const CLOCK_BOOTTIME: c_int = 7;
332 pub const CLOCK_REALTIME_ALARM: c_int = 8;
334 pub const CLOCK_BOOTTIME_ALARM: c_int = 9;
336 pub const CLOCK_SGI_CYCLE: c_int = 10;
338 pub const CLOCK_TAI: c_int = 11;
340
341 pub const MAX_CLOCKS: c_int = 16;
343}
344
345pub mod clock_flags {
347 use crate::uapi::time::clock_id::{CLOCK_MONOTONIC, CLOCK_REALTIME};
348
349 use super::c_int;
350
351 pub const CLOCK_AUX: c_int = super::clock_id::MAX_CLOCKS;
353 pub const MAX_AUX_CLOCKS: c_int = 8;
354 pub const CLOCK_AUX_LAST: c_int = CLOCK_AUX + MAX_AUX_CLOCKS - 1;
355
356 pub const CLOCKS_MASK: c_int = CLOCK_REALTIME | CLOCK_MONOTONIC;
358 pub const CLOCKS_MONO: c_int = CLOCK_MONOTONIC;
359
360 pub const TIMER_ABSTIME: c_int = 0x01;
363}