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