From fe51f9debcaf35692bc1760850577f5e6846a009 Mon Sep 17 00:00:00 2001 From: joboet Date: Thu, 15 Jan 2026 15:25:14 +0100 Subject: [PATCH] std: move time implementations to `sys` (Hermit) Last on the list: Hermit. Since I anticipate that Hermit will share the UNIX implementation in the future, I've left `Timespec` in the PAL to maintain a similar structure. Also, I noticed that some public `Instant` methods were redefined on the internal `Instant`. But the networking code can just use the public `Instant`, so I've removed them. --- .../src/sys/net/connection/socket/hermit.rs | 3 +- library/std/src/sys/pal/hermit/time.rs | 154 ++---------------- library/std/src/sys/time/hermit.rs | 63 +++++++ 3 files changed, 75 insertions(+), 145 deletions(-) create mode 100644 library/std/src/sys/time/hermit.rs diff --git a/library/std/src/sys/net/connection/socket/hermit.rs b/library/std/src/sys/net/connection/socket/hermit.rs index d57a075eb42d..59f515d31aff 100644 --- a/library/std/src/sys/net/connection/socket/hermit.rs +++ b/library/std/src/sys/net/connection/socket/hermit.rs @@ -9,10 +9,9 @@ use crate::io::{self, BorrowedBuf, BorrowedCursor, IoSlice, IoSliceMut}; use crate::net::{Shutdown, SocketAddr}; use crate::os::hermit::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, RawFd}; use crate::sys::fd::FileDesc; -use crate::sys::time::Instant; use crate::sys::{AsInner, FromInner, IntoInner}; pub use crate::sys::{cvt, cvt_r}; -use crate::time::Duration; +use crate::time::{Duration, Instant}; use crate::{cmp, mem}; #[expect(non_camel_case_types)] diff --git a/library/std/src/sys/pal/hermit/time.rs b/library/std/src/sys/pal/hermit/time.rs index 734ad2540a18..b9851eb6754d 100644 --- a/library/std/src/sys/pal/hermit/time.rs +++ b/library/std/src/sys/pal/hermit/time.rs @@ -1,35 +1,32 @@ -#![allow(dead_code)] +use hermit_abi::{self, timespec}; -use core::hash::{Hash, Hasher}; - -use super::hermit_abi::{self, CLOCK_MONOTONIC, CLOCK_REALTIME, timespec}; use crate::cmp::Ordering; -use crate::ops::{Add, AddAssign, Sub, SubAssign}; +use crate::hash::{Hash, Hasher}; use crate::time::Duration; const NSEC_PER_SEC: i32 = 1_000_000_000; #[derive(Copy, Clone, Debug)] -struct Timespec { - t: timespec, +pub struct Timespec { + pub t: timespec, } impl Timespec { - const MAX: Timespec = Self::new(i64::MAX, 1_000_000_000 - 1); + pub const MAX: Timespec = Self::new(i64::MAX, 1_000_000_000 - 1); - const MIN: Timespec = Self::new(i64::MIN, 0); + pub const MIN: Timespec = Self::new(i64::MIN, 0); - const fn zero() -> Timespec { + pub const fn zero() -> Timespec { Timespec { t: timespec { tv_sec: 0, tv_nsec: 0 } } } - const fn new(tv_sec: i64, tv_nsec: i32) -> Timespec { + pub const fn new(tv_sec: i64, tv_nsec: i32) -> Timespec { assert!(tv_nsec >= 0 && tv_nsec < NSEC_PER_SEC); // SAFETY: The assert above checks tv_nsec is within the valid range Timespec { t: timespec { tv_sec, tv_nsec } } } - fn sub_timespec(&self, other: &Timespec) -> Result { + pub fn sub_timespec(&self, other: &Timespec) -> Result { fn sub_ge_to_unsigned(a: i64, b: i64) -> u64 { debug_assert!(a >= b); a.wrapping_sub(b).cast_unsigned() @@ -57,7 +54,7 @@ impl Timespec { } } - fn checked_add_duration(&self, other: &Duration) -> Option { + pub fn checked_add_duration(&self, other: &Duration) -> Option { let mut secs = self.t.tv_sec.checked_add_unsigned(other.as_secs())?; // Nano calculations can't overflow because nanos are <1B which fit @@ -70,7 +67,7 @@ impl Timespec { Some(Timespec { t: timespec { tv_sec: secs, tv_nsec: nsec as _ } }) } - fn checked_sub_duration(&self, other: &Duration) -> Option { + pub fn checked_sub_duration(&self, other: &Duration) -> Option { let mut secs = self.t.tv_sec.checked_sub_unsigned(other.as_secs())?; // Similar to above, nanos can't overflow. @@ -111,132 +108,3 @@ impl Hash for Timespec { self.t.tv_nsec.hash(state); } } - -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] -pub struct Instant(Timespec); - -impl Instant { - pub fn now() -> Instant { - let mut time: Timespec = Timespec::zero(); - let _ = unsafe { hermit_abi::clock_gettime(CLOCK_MONOTONIC, &raw mut time.t) }; - - Instant(time) - } - - #[stable(feature = "time2", since = "1.8.0")] - pub fn elapsed(&self) -> Duration { - Instant::now() - *self - } - - pub fn duration_since(&self, earlier: Instant) -> Duration { - self.checked_duration_since(earlier).unwrap_or_default() - } - - pub fn checked_duration_since(&self, earlier: Instant) -> Option { - self.checked_sub_instant(&earlier) - } - - pub fn checked_sub_instant(&self, other: &Instant) -> Option { - self.0.sub_timespec(&other.0).ok() - } - - pub fn checked_add_duration(&self, other: &Duration) -> Option { - Some(Instant(self.0.checked_add_duration(other)?)) - } - - pub fn checked_sub_duration(&self, other: &Duration) -> Option { - Some(Instant(self.0.checked_sub_duration(other)?)) - } - - pub fn checked_add(&self, duration: Duration) -> Option { - self.0.checked_add_duration(&duration).map(Instant) - } - - pub fn checked_sub(&self, duration: Duration) -> Option { - self.0.checked_sub_duration(&duration).map(Instant) - } -} - -impl Add for Instant { - type Output = Instant; - - /// # Panics - /// - /// This function may panic if the resulting point in time cannot be represented by the - /// underlying data structure. See [`Instant::checked_add`] for a version without panic. - fn add(self, other: Duration) -> Instant { - self.checked_add(other).expect("overflow when adding duration to instant") - } -} - -impl AddAssign for Instant { - fn add_assign(&mut self, other: Duration) { - *self = *self + other; - } -} - -impl Sub for Instant { - type Output = Instant; - - fn sub(self, other: Duration) -> Instant { - self.checked_sub(other).expect("overflow when subtracting duration from instant") - } -} - -impl SubAssign for Instant { - fn sub_assign(&mut self, other: Duration) { - *self = *self - other; - } -} - -impl Sub for Instant { - type Output = Duration; - - /// Returns the amount of time elapsed from another instant to this one, - /// or zero duration if that instant is later than this one. - /// - /// # Panics - /// - /// Previous Rust versions panicked when `other` was later than `self`. Currently this - /// method saturates. Future versions may reintroduce the panic in some circumstances. - /// See [Monotonicity]. - /// - /// [Monotonicity]: Instant#monotonicity - fn sub(self, other: Instant) -> Duration { - self.duration_since(other) - } -} - -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] -pub struct SystemTime(Timespec); - -pub const UNIX_EPOCH: SystemTime = SystemTime(Timespec::zero()); - -impl SystemTime { - pub const MAX: SystemTime = SystemTime(Timespec::MAX); - - pub const MIN: SystemTime = SystemTime(Timespec::MIN); - - pub fn new(tv_sec: i64, tv_nsec: i32) -> SystemTime { - SystemTime(Timespec::new(tv_sec, tv_nsec)) - } - - pub fn now() -> SystemTime { - let mut time: Timespec = Timespec::zero(); - let _ = unsafe { hermit_abi::clock_gettime(CLOCK_REALTIME, &raw mut time.t) }; - - SystemTime(time) - } - - pub fn sub_time(&self, other: &SystemTime) -> Result { - self.0.sub_timespec(&other.0) - } - - pub fn checked_add_duration(&self, other: &Duration) -> Option { - Some(SystemTime(self.0.checked_add_duration(other)?)) - } - - pub fn checked_sub_duration(&self, other: &Duration) -> Option { - Some(SystemTime(self.0.checked_sub_duration(other)?)) - } -} diff --git a/library/std/src/sys/time/hermit.rs b/library/std/src/sys/time/hermit.rs new file mode 100644 index 000000000000..18ece2e3010d --- /dev/null +++ b/library/std/src/sys/time/hermit.rs @@ -0,0 +1,63 @@ +use hermit_abi::{self, CLOCK_MONOTONIC, CLOCK_REALTIME}; + +use crate::hash::Hash; +use crate::sys::pal::time::Timespec; +use crate::time::Duration; + +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] +pub struct Instant(Timespec); + +impl Instant { + pub fn now() -> Instant { + let mut time: Timespec = Timespec::zero(); + let _ = unsafe { hermit_abi::clock_gettime(CLOCK_MONOTONIC, &raw mut time.t) }; + + Instant(time) + } + + pub fn checked_sub_instant(&self, other: &Instant) -> Option { + self.0.sub_timespec(&other.0).ok() + } + + pub fn checked_add_duration(&self, other: &Duration) -> Option { + Some(Instant(self.0.checked_add_duration(other)?)) + } + + pub fn checked_sub_duration(&self, other: &Duration) -> Option { + Some(Instant(self.0.checked_sub_duration(other)?)) + } +} + +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] +pub struct SystemTime(Timespec); + +pub const UNIX_EPOCH: SystemTime = SystemTime(Timespec::zero()); + +impl SystemTime { + pub const MAX: SystemTime = SystemTime(Timespec::MAX); + + pub const MIN: SystemTime = SystemTime(Timespec::MIN); + + pub fn new(tv_sec: i64, tv_nsec: i32) -> SystemTime { + SystemTime(Timespec::new(tv_sec, tv_nsec)) + } + + pub fn now() -> SystemTime { + let mut time: Timespec = Timespec::zero(); + let _ = unsafe { hermit_abi::clock_gettime(CLOCK_REALTIME, &raw mut time.t) }; + + SystemTime(time) + } + + pub fn sub_time(&self, other: &SystemTime) -> Result { + self.0.sub_timespec(&other.0) + } + + pub fn checked_add_duration(&self, other: &Duration) -> Option { + Some(SystemTime(self.0.checked_add_duration(other)?)) + } + + pub fn checked_sub_duration(&self, other: &Duration) -> Option { + Some(SystemTime(self.0.checked_sub_duration(other)?)) + } +}