xref: /DragonOS/kernel/src/time/mod.rs (revision 731bc2b32d7b37298883d7a15b6dca659b436ee4)
1 use core::{
2     fmt,
3     intrinsics::unlikely,
4     ops::{self, Sub},
5 };
6 
7 use crate::arch::CurrentTimeArch;
8 
9 use self::timekeeping::getnstimeofday;
10 
11 pub mod clocksource;
12 pub mod jiffies;
13 pub mod sleep;
14 pub mod syscall;
15 pub mod timeconv;
16 pub mod timekeep;
17 pub mod timekeeping;
18 pub mod timer;
19 
20 /* Time structures. (Partitially taken from smoltcp)
21 
22 The `time` module contains structures used to represent both
23 absolute and relative time.
24 
25  - [Instant] is used to represent absolute time.
26  - [Duration] is used to represent relative time.
27 
28 [Instant]: struct.Instant.html
29 [Duration]: struct.Duration.html
30 */
31 #[allow(dead_code)]
32 pub const MSEC_PER_SEC: u32 = 1000;
33 #[allow(dead_code)]
34 pub const USEC_PER_MSEC: u32 = 1000;
35 #[allow(dead_code)]
36 pub const NSEC_PER_USEC: u32 = 1000;
37 #[allow(dead_code)]
38 pub const NSEC_PER_MSEC: u32 = 1000000;
39 #[allow(dead_code)]
40 pub const USEC_PER_SEC: u32 = 1000000;
41 #[allow(dead_code)]
42 pub const NSEC_PER_SEC: u32 = 1000000000;
43 #[allow(dead_code)]
44 pub const FSEC_PER_SEC: u64 = 1000000000000000;
45 
46 /// 表示时间的结构体,符合POSIX标准。
47 #[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
48 #[repr(C)]
49 pub struct PosixTimeSpec {
50     pub tv_sec: i64,
51     pub tv_nsec: i64,
52 }
53 
54 impl PosixTimeSpec {
55     #[allow(dead_code)]
56     pub fn new(sec: i64, nsec: i64) -> PosixTimeSpec {
57         return PosixTimeSpec {
58             tv_sec: sec,
59             tv_nsec: nsec,
60         };
61     }
62 
63     /// 获取当前时间
64     #[inline(always)]
65     pub fn now() -> Self {
66         getnstimeofday()
67     }
68 
69     /// 获取当前CPU时间(使用CPU时钟周期计算,会存在回绕问题)
70     pub fn now_cpu_time() -> Self {
71         #[cfg(target_arch = "x86_64")]
72         {
73             use crate::arch::driver::tsc::TSCManager;
74             let khz = TSCManager::cpu_khz();
75             if unlikely(khz == 0) {
76                 return PosixTimeSpec::default();
77             } else {
78                 return Self::from(Duration::from_millis(
79                     CurrentTimeArch::get_cycles() as u64 / khz,
80                 ));
81             }
82         }
83 
84         #[cfg(target_arch = "riscv64")]
85         {
86             return PosixTimeSpec::new(0, 0);
87         }
88     }
89 
90     /// 换算成纳秒
91     pub fn total_nanos(&self) -> i64 {
92         self.tv_sec * 1000000000 + self.tv_nsec
93     }
94 }
95 
96 impl Sub for PosixTimeSpec {
97     type Output = Duration;
98     fn sub(self, rhs: Self) -> Self::Output {
99         let sec = self.tv_sec.checked_sub(rhs.tv_sec).unwrap_or(0);
100         let nsec = self.tv_nsec.checked_sub(rhs.tv_nsec).unwrap_or(0);
101         Duration::from_micros((sec * 1000000 + nsec / 1000) as u64)
102     }
103 }
104 
105 impl From<Duration> for PosixTimeSpec {
106     fn from(dur: Duration) -> Self {
107         PosixTimeSpec {
108             tv_sec: dur.total_micros() as i64 / 1000000,
109             tv_nsec: (dur.total_micros() as i64 % 1000000) * 1000,
110         }
111     }
112 }
113 
114 impl From<PosixTimeSpec> for Duration {
115     fn from(val: PosixTimeSpec) -> Self {
116         Duration::from_micros(val.tv_sec as u64 * 1000000 + val.tv_nsec as u64 / 1000)
117     }
118 }
119 
120 /// A representation of an absolute time value.
121 ///
122 /// The `Instant` type is a wrapper around a `i64` value that
123 /// represents a number of microseconds, monotonically increasing
124 /// since an arbitrary moment in time, such as system startup.
125 ///
126 /// * A value of `0` is inherently arbitrary.
127 /// * A value less than `0` indicates a time before the starting
128 ///   point.
129 #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
130 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
131 pub struct Instant {
132     micros: i64,
133 }
134 
135 #[allow(dead_code)]
136 impl Instant {
137     pub const ZERO: Instant = Instant::from_micros_const(0);
138 
139     /// mktime64 - 将日期转换为秒。
140     ///
141     /// ## 参数
142     ///
143     /// - year0: 要转换的年份
144     /// - mon0: 要转换的月份
145     /// - day: 要转换的天
146     /// - hour: 要转换的小时
147     /// - min: 要转换的分钟
148     /// - sec: 要转换的秒
149     ///
150     /// 将公历日期转换为1970-01-01 00:00:00以来的秒数。
151     /// 假设输入为正常的日期格式,即1980-12-31 23:59:59 => 年份=1980, 月=12, 日=31, 时=23, 分=59, 秒=59。
152     ///
153     /// [For the Julian calendar(俄罗斯在1917年之前使用,英国及其殖民地在大西洋1752年之前使用,
154     /// 其他地方在1582年之前使用,某些社区仍然在使用)省略-year/100+year/400项,
155     /// 并在结果上加10。]
156     ///
157     /// 这个算法最初由高斯(我认为是)发表。
158     ///
159     /// 要表示闰秒,可以通过将sec设为60(在ISO 8601允许)来调用此函数。
160     /// 闰秒与随后的秒一样处理,因为它们在UNIX时间中不存在。
161     ///
162     /// 支持将午夜作为当日末尾的24:00:00编码 - 即明天的午夜(在ISO 8601允许)。
163     ///
164     /// ## 返回
165     ///
166     /// 返回:给定输入日期自1970-01-01 00:00:00以来的秒数
167     pub fn mktime64(year0: u32, mon0: u32, day: u32, hour: u32, min: u32, sec: u32) -> Self {
168         let mut mon: i64 = mon0.into();
169         let mut year: u64 = year0.into();
170         let day: u64 = day.into();
171         let hour: u64 = hour.into();
172         let min: u64 = min.into();
173         let sec: u64 = sec.into();
174 
175         mon -= 2;
176         /* 1..12 -> 11,12,1..10 */
177         if mon <= 0 {
178             /* Puts Feb last since it has leap day */
179             mon += 12;
180             year -= 1;
181         }
182         let mon = mon as u64;
183 
184         let secs = ((((year / 4 - year / 100 + year / 400 + 367 * mon / 12 + day) + year * 365
185             - 719499)
186             * 24 + hour) /* now have hours - midnight tomorrow handled here */
187             * 60 + min)/* now have minutes */
188             * 60
189             + sec; /* finally seconds */
190 
191         Self::from_secs(secs as i64)
192     }
193 
194     /// Create a new `Instant` from a number of microseconds.
195     pub fn from_micros<T: Into<i64>>(micros: T) -> Instant {
196         Instant {
197             micros: micros.into(),
198         }
199     }
200 
201     pub const fn from_micros_const(micros: i64) -> Instant {
202         Instant { micros }
203     }
204 
205     /// Create a new `Instant` from a number of milliseconds.
206     pub fn from_millis<T: Into<i64>>(millis: T) -> Instant {
207         Instant {
208             micros: millis.into() * 1000,
209         }
210     }
211 
212     /// Create a new `Instant` from a number of milliseconds.
213     pub const fn from_millis_const(millis: i64) -> Instant {
214         Instant {
215             micros: millis * 1000,
216         }
217     }
218 
219     /// Create a new `Instant` from a number of seconds.
220     pub fn from_secs<T: Into<i64>>(secs: T) -> Instant {
221         Instant {
222             micros: secs.into() * 1000000,
223         }
224     }
225 
226     /// Create a new `Instant` from the current time
227     pub fn now() -> Instant {
228         let tm = getnstimeofday();
229         Self::from_micros(tm.tv_sec * 1000000 + tm.tv_nsec / 1000)
230     }
231 
232     /// The fractional number of milliseconds that have passed
233     /// since the beginning of time.
234     pub const fn millis(&self) -> i64 {
235         self.micros % 1000000 / 1000
236     }
237 
238     /// The fractional number of microseconds that have passed
239     /// since the beginning of time.
240     pub const fn micros(&self) -> i64 {
241         self.micros % 1000000
242     }
243 
244     /// The number of whole seconds that have passed since the
245     /// beginning of time.
246     pub const fn secs(&self) -> i64 {
247         self.micros / 1000000
248     }
249 
250     /// The total number of milliseconds that have passed since
251     /// the beginning of time.
252     pub const fn total_millis(&self) -> i64 {
253         self.micros / 1000
254     }
255     /// The total number of milliseconds that have passed since
256     /// the beginning of time.
257     pub const fn total_micros(&self) -> i64 {
258         self.micros
259     }
260 }
261 
262 impl fmt::Display for Instant {
263     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
264         write!(f, "{}.{:0>3}s", self.secs(), self.millis())
265     }
266 }
267 
268 impl ops::Add<Duration> for Instant {
269     type Output = Instant;
270 
271     fn add(self, rhs: Duration) -> Instant {
272         Instant::from_micros(self.micros + rhs.total_micros() as i64)
273     }
274 }
275 
276 impl ops::AddAssign<Duration> for Instant {
277     fn add_assign(&mut self, rhs: Duration) {
278         self.micros += rhs.total_micros() as i64;
279     }
280 }
281 
282 impl ops::Sub<Duration> for Instant {
283     type Output = Instant;
284 
285     fn sub(self, rhs: Duration) -> Instant {
286         Instant::from_micros(self.micros - rhs.total_micros() as i64)
287     }
288 }
289 
290 impl ops::SubAssign<Duration> for Instant {
291     fn sub_assign(&mut self, rhs: Duration) {
292         self.micros -= rhs.total_micros() as i64;
293     }
294 }
295 
296 impl ops::Sub<Instant> for Instant {
297     type Output = Duration;
298 
299     fn sub(self, rhs: Instant) -> Duration {
300         Duration::from_micros((self.micros - rhs.micros).unsigned_abs())
301     }
302 }
303 
304 /// A relative amount of time.
305 #[derive(Debug, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
306 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
307 pub struct Duration {
308     micros: u64,
309 }
310 
311 impl Duration {
312     pub const ZERO: Duration = Duration::from_micros(0);
313     /// Create a new `Duration` from a number of microseconds.
314     pub const fn from_micros(micros: u64) -> Duration {
315         Duration { micros }
316     }
317 
318     /// Create a new `Duration` from a number of milliseconds.
319     pub const fn from_millis(millis: u64) -> Duration {
320         Duration {
321             micros: millis * 1000,
322         }
323     }
324 
325     /// Create a new `Instant` from a number of seconds.
326     pub const fn from_secs(secs: u64) -> Duration {
327         Duration {
328             micros: secs * 1000000,
329         }
330     }
331 
332     /// The fractional number of milliseconds in this `Duration`.
333     pub const fn millis(&self) -> u64 {
334         self.micros / 1000 % 1000
335     }
336 
337     /// The fractional number of milliseconds in this `Duration`.
338     pub const fn micros(&self) -> u64 {
339         self.micros % 1000000
340     }
341 
342     /// The number of whole seconds in this `Duration`.
343     pub const fn secs(&self) -> u64 {
344         self.micros / 1000000
345     }
346 
347     /// The total number of milliseconds in this `Duration`.
348     pub const fn total_millis(&self) -> u64 {
349         self.micros / 1000
350     }
351 
352     /// The total number of microseconds in this `Duration`.
353     pub const fn total_micros(&self) -> u64 {
354         self.micros
355     }
356 }
357 
358 impl fmt::Display for Duration {
359     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
360         write!(f, "{}.{:03}s", self.secs(), self.millis())
361     }
362 }
363 
364 impl ops::Add<Duration> for Duration {
365     type Output = Duration;
366 
367     fn add(self, rhs: Duration) -> Duration {
368         Duration::from_micros(self.micros + rhs.total_micros())
369     }
370 }
371 
372 impl ops::AddAssign<Duration> for Duration {
373     fn add_assign(&mut self, rhs: Duration) {
374         self.micros += rhs.total_micros();
375     }
376 }
377 
378 impl ops::Sub<Duration> for Duration {
379     type Output = Duration;
380 
381     fn sub(self, rhs: Duration) -> Duration {
382         Duration::from_micros(
383             self.micros
384                 .checked_sub(rhs.total_micros())
385                 .expect("overflow when subtracting durations"),
386         )
387     }
388 }
389 
390 impl ops::SubAssign<Duration> for Duration {
391     fn sub_assign(&mut self, rhs: Duration) {
392         self.micros = self
393             .micros
394             .checked_sub(rhs.total_micros())
395             .expect("overflow when subtracting durations");
396     }
397 }
398 
399 impl ops::Mul<u32> for Duration {
400     type Output = Duration;
401 
402     fn mul(self, rhs: u32) -> Duration {
403         Duration::from_micros(self.micros * rhs as u64)
404     }
405 }
406 
407 impl ops::MulAssign<u32> for Duration {
408     fn mul_assign(&mut self, rhs: u32) {
409         self.micros *= rhs as u64;
410     }
411 }
412 
413 impl ops::Div<u32> for Duration {
414     type Output = Duration;
415 
416     fn div(self, rhs: u32) -> Duration {
417         Duration::from_micros(self.micros / rhs as u64)
418     }
419 }
420 
421 impl ops::DivAssign<u32> for Duration {
422     fn div_assign(&mut self, rhs: u32) {
423         self.micros /= rhs as u64;
424     }
425 }
426 
427 impl ops::Shl<u32> for Duration {
428     type Output = Duration;
429 
430     fn shl(self, rhs: u32) -> Duration {
431         Duration::from_micros(self.micros << rhs)
432     }
433 }
434 
435 impl ops::ShlAssign<u32> for Duration {
436     fn shl_assign(&mut self, rhs: u32) {
437         self.micros <<= rhs;
438     }
439 }
440 
441 impl ops::Shr<u32> for Duration {
442     type Output = Duration;
443 
444     fn shr(self, rhs: u32) -> Duration {
445         Duration::from_micros(self.micros >> rhs)
446     }
447 }
448 
449 impl ops::ShrAssign<u32> for Duration {
450     fn shr_assign(&mut self, rhs: u32) {
451         self.micros >>= rhs;
452     }
453 }
454 
455 impl From<::core::time::Duration> for Duration {
456     fn from(other: ::core::time::Duration) -> Duration {
457         Duration::from_micros(other.as_secs() * 1000000 + other.subsec_micros() as u64)
458     }
459 }
460 
461 impl From<Duration> for ::core::time::Duration {
462     fn from(val: Duration) -> Self {
463         ::core::time::Duration::from_micros(val.total_micros())
464     }
465 }
466 
467 /// 支持与smoltcp的时间转换
468 impl From<smoltcp::time::Instant> for Instant {
469     fn from(val: smoltcp::time::Instant) -> Self {
470         Instant::from_micros(val.micros())
471     }
472 }
473 
474 impl From<Instant> for smoltcp::time::Instant {
475     fn from(val: Instant) -> Self {
476         smoltcp::time::Instant::from_millis(val.millis())
477     }
478 }
479 
480 /// 支持与smoltcp的时间转换
481 impl From<smoltcp::time::Duration> for Duration {
482     fn from(val: smoltcp::time::Duration) -> Self {
483         Duration::from_micros(val.micros())
484     }
485 }
486 
487 impl From<Duration> for smoltcp::time::Duration {
488     fn from(val: Duration) -> Self {
489         smoltcp::time::Duration::from_millis(val.millis())
490     }
491 }
492 
493 pub trait TimeArch {
494     /// Get CPU cycles (Read from register)
495     fn get_cycles() -> usize;
496 
497     /// Calculate expire cycles
498     ///
499     /// # Arguments
500     ///
501     /// - `ns` - The time to expire in nanoseconds
502     ///
503     /// # Returns
504     ///
505     /// The expire cycles
506     fn cal_expire_cycles(ns: usize) -> usize;
507 
508     /// 将CPU的时钟周期数转换为纳秒
509     fn cycles2ns(cycles: usize) -> usize;
510 }
511