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