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