Skip to main content

kernel_api/
time.rs

1//! Temporal quantification
2
3use core::ops::{Add, AddAssign, Sub, SubAssign};
4use core::time::Duration;
5
6/// An opaque measure of the current system time
7#[derive(Copy, Clone, Hash, Debug, Ord, PartialOrd, Eq, PartialEq)]
8pub struct Instant {
9	arch_val: u128
10}
11
12impl Instant {
13	fn nanos(&self) -> u128 {
14		Self::arch_to_nanos(self.arch_val)
15	}
16	
17	fn arch_to_nanos(arch_val: u128) -> u128 {
18		let (num, denom) = crate::bridge::time::system_time_to_nanos();
19
20		arch_val * num / denom.get()
21	}
22
23	fn nanos_to_arch(nanos: u128) -> u128 {
24		let (num, denom) = crate::bridge::time::system_time_to_nanos();
25
26		nanos * denom.get() / num
27	}
28	
29	/// The current system time
30	pub fn now() -> Self {
31		let arch_val = crate::bridge::time::system_time();
32		Self {
33			arch_val
34		}
35	}
36
37	pub fn duration_since(&self, earlier: Instant) -> Duration {
38		self.saturating_duration_since(earlier)
39	}
40
41	pub fn checked_duration_since(&self, earlier: Instant) -> Option<Duration> {
42		let nanos = self.nanos().checked_sub(earlier.nanos())?;
43		Some(Duration::new(
44			(nanos / 1_000_000_000) as u64,
45			(nanos % 1_000_000_000) as u32
46		))
47	}
48
49	pub fn saturating_duration_since(&self, earlier: Instant) -> Duration {
50		let nanos = self.nanos().saturating_sub(earlier.nanos());
51		Duration::new(
52			(nanos / 1_000_000_000) as u64,
53			(nanos % 1_000_000_000) as u32
54		)
55	}
56
57	/// The elapsed [`Duration`] between `self` and the current time as returned by [`Instant::now()`]
58	pub fn elapsed(&self) -> Duration {
59		Self::now() - *self
60	}
61
62	pub fn checked_add(&self, duration: Duration) -> Option<Instant> {
63		let arch_val = self.arch_val.checked_add(Self::nanos_to_arch(duration.as_nanos()))?;
64		Some(Instant { arch_val })
65	}
66
67	pub fn checked_sub(&self, duration: Duration) -> Option<Instant> {
68		let arch_val = self.arch_val.checked_sub(Self::nanos_to_arch(duration.as_nanos()))?;
69		Some(Instant { arch_val })
70	}
71	
72	/// The number of nanoseconds since the system booted
73	/// 
74	/// No guarantees are (yet) provided on time before overflow
75	pub fn nanos_since_boot(&self) -> u128 {
76		self.nanos()
77	}
78	
79	/// Returns the opaque numeric value of the [`Instant`]
80	/// 
81	/// The meaning of the returned value is architecture dependant.
82	/// Behaviour is as follows:
83	/// - `x86`/`x86_64` - value of the timestamp counter as provided by `rdtsc`
84	pub fn get(&self) -> u128 { self.arch_val }
85}
86
87impl Add<Duration> for Instant {
88	type Output = Instant;
89
90	fn add(self, rhs: Duration) -> Self::Output {
91		Instant { arch_val: self.arch_val + Self::nanos_to_arch(rhs.as_nanos()) }
92	}
93}
94
95impl AddAssign<Duration> for Instant {
96	fn add_assign(&mut self, rhs: Duration) {
97		self.arch_val += Self::nanos_to_arch(rhs.as_nanos());
98	}
99}
100
101impl Sub for Instant {
102	type Output = Duration;
103
104	fn sub(self, rhs: Instant) -> Self::Output {
105		self.duration_since(rhs)
106	}
107}
108
109impl Sub<Duration> for Instant {
110	type Output = Instant;
111
112	fn sub(self, rhs: Duration) -> Self::Output {
113		Instant { arch_val: self.arch_val - Self::nanos_to_arch(rhs.as_nanos()) }
114	}
115}
116
117impl SubAssign<Duration> for Instant {
118	fn sub_assign(&mut self, rhs: Duration) {
119		self.arch_val -= Self::nanos_to_arch(rhs.as_nanos());
120	}
121}