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