Skip to content
7 changes: 4 additions & 3 deletions library/std/src/sys/fs/uefi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -580,7 +580,8 @@ mod uefi_fs {
use crate::path::Path;
use crate::ptr::NonNull;
use crate::sys::pal::helpers::{self, UefiBox};
use crate::sys::time::{self, SystemTime};
use crate::sys::pal::system_time;
use crate::sys::time::SystemTime;

pub(crate) struct File {
protocol: NonNull<file::Protocol>,
Expand Down Expand Up @@ -879,7 +880,7 @@ mod uefi_fs {
/// conversion to SystemTime, we use the current time to get the timezone in such cases.
pub(crate) fn uefi_to_systemtime(mut time: r_efi::efi::Time) -> Option<SystemTime> {
time.timezone = if time.timezone == r_efi::efi::UNSPECIFIED_TIMEZONE {
time::system_time_internal::now().timezone
system_time::now().timezone
} else {
time.timezone
};
Expand All @@ -888,7 +889,7 @@ mod uefi_fs {

/// Convert to UEFI Time with the current timezone.
pub(crate) fn systemtime_to_uefi(time: SystemTime) -> r_efi::efi::Time {
let now = time::system_time_internal::now();
let now = system_time::now();
time.to_uefi_loose(now.timezone, now.daylight)
}

Expand Down
4 changes: 2 additions & 2 deletions library/std/src/sys/fs/unix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1822,7 +1822,7 @@ impl File {
_ => {
#[cfg(all(target_os = "linux", target_env = "gnu", target_pointer_width = "32", not(target_arch = "riscv32")))]
{
use crate::sys::{time::__timespec64, weak::weak};
use crate::sys::pal::{time::__timespec64, weak::weak};

// Added in glibc 2.34
weak!(
Expand Down Expand Up @@ -2258,7 +2258,7 @@ fn set_times_impl(p: &CStr, times: FileTimes, follow_symlinks: bool) -> io::Resu
let flags = if follow_symlinks { 0 } else { libc::AT_SYMLINK_NOFOLLOW };
#[cfg(all(target_os = "linux", target_env = "gnu", target_pointer_width = "32", not(target_arch = "riscv32")))]
{
use crate::sys::{time::__timespec64, weak::weak};
use crate::sys::pal::{time::__timespec64, weak::weak};

// Added in glibc 2.34
weak!(
Expand Down
1 change: 1 addition & 0 deletions library/std/src/sys/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ pub mod stdio;
pub mod sync;
pub mod thread;
pub mod thread_local;
pub mod time;

// FIXME(117276): remove this, move feature implementations into individual
// submodules.
Expand Down
3 changes: 1 addition & 2 deletions library/std/src/sys/net/connection/socket/hermit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down
154 changes: 11 additions & 143 deletions library/std/src/sys/pal/hermit/time.rs
Original file line number Diff line number Diff line change
@@ -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<Duration, Duration> {
pub fn sub_timespec(&self, other: &Timespec) -> Result<Duration, Duration> {
fn sub_ge_to_unsigned(a: i64, b: i64) -> u64 {
debug_assert!(a >= b);
a.wrapping_sub(b).cast_unsigned()
Expand Down Expand Up @@ -57,7 +54,7 @@ impl Timespec {
}
}

fn checked_add_duration(&self, other: &Duration) -> Option<Timespec> {
pub fn checked_add_duration(&self, other: &Duration) -> Option<Timespec> {
let mut secs = self.t.tv_sec.checked_add_unsigned(other.as_secs())?;

// Nano calculations can't overflow because nanos are <1B which fit
Expand All @@ -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<Timespec> {
pub fn checked_sub_duration(&self, other: &Duration) -> Option<Timespec> {
let mut secs = self.t.tv_sec.checked_sub_unsigned(other.as_secs())?;

// Similar to above, nanos can't overflow.
Expand Down Expand Up @@ -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<Duration> {
self.checked_sub_instant(&earlier)
}

pub fn checked_sub_instant(&self, other: &Instant) -> Option<Duration> {
self.0.sub_timespec(&other.0).ok()
}

pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> {
Some(Instant(self.0.checked_add_duration(other)?))
}

pub fn checked_sub_duration(&self, other: &Duration) -> Option<Instant> {
Some(Instant(self.0.checked_sub_duration(other)?))
}

pub fn checked_add(&self, duration: Duration) -> Option<Instant> {
self.0.checked_add_duration(&duration).map(Instant)
}

pub fn checked_sub(&self, duration: Duration) -> Option<Instant> {
self.0.checked_sub_duration(&duration).map(Instant)
}
}

impl Add<Duration> 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<Duration> for Instant {
fn add_assign(&mut self, other: Duration) {
*self = *self + other;
}
}

impl Sub<Duration> for Instant {
type Output = Instant;

fn sub(self, other: Duration) -> Instant {
self.checked_sub(other).expect("overflow when subtracting duration from instant")
}
}

impl SubAssign<Duration> for Instant {
fn sub_assign(&mut self, other: Duration) {
*self = *self - other;
}
}

impl Sub<Instant> 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<Duration, Duration> {
self.0.sub_timespec(&other.0)
}

pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
Some(SystemTime(self.0.checked_add_duration(other)?))
}

pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
Some(SystemTime(self.0.checked_sub_duration(other)?))
}
}
47 changes: 11 additions & 36 deletions library/std/src/sys/pal/itron/time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,38 +3,16 @@ use super::error::expect_success;
use crate::mem::MaybeUninit;
use crate::time::Duration;

#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
pub struct Instant(abi::SYSTIM);

impl Instant {
pub fn now() -> Instant {
// Safety: The provided pointer is valid
unsafe {
let mut out = MaybeUninit::uninit();
expect_success(abi::get_tim(out.as_mut_ptr()), &"get_tim");
Instant(out.assume_init())
}
}

pub fn checked_sub_instant(&self, other: &Instant) -> Option<Duration> {
self.0.checked_sub(other.0).map(|ticks| {
// `SYSTIM` is measured in microseconds
Duration::from_micros(ticks)
})
}

pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> {
// `SYSTIM` is measured in microseconds
let ticks = other.as_micros();

Some(Instant(self.0.checked_add(ticks.try_into().ok()?)?))
}

pub fn checked_sub_duration(&self, other: &Duration) -> Option<Instant> {
// `SYSTIM` is measured in microseconds
let ticks = other.as_micros();
#[cfg(test)]
mod tests;

Some(Instant(self.0.checked_sub(ticks.try_into().ok()?)?))
#[inline]
pub fn get_tim() -> abi::SYSTIM {
// Safety: The provided pointer is valid
unsafe {
let mut out = MaybeUninit::uninit();
expect_success(abi::get_tim(out.as_mut_ptr()), &"get_tim");
out.assume_init()
}
}

Expand Down Expand Up @@ -98,19 +76,16 @@ pub fn with_tmos_strong(dur: Duration, mut f: impl FnMut(abi::TMO) -> abi::ER) -
// a problem in practice. (`u64::MAX` μs ≈ 584942 years)
let ticks = dur.as_micros().min(abi::SYSTIM::MAX as u128) as abi::SYSTIM;

let start = Instant::now().0;
let start = get_tim();
let mut elapsed = 0;
let mut er = abi::E_TMOUT;
while elapsed <= ticks {
er = f(elapsed.min(abi::TMAX_RELTIM as abi::SYSTIM) as abi::TMO);
if er != abi::E_TMOUT {
break;
}
elapsed = Instant::now().0.wrapping_sub(start);
elapsed = get_tim().wrapping_sub(start);
}

er
}

#[cfg(test)]
mod tests;
1 change: 0 additions & 1 deletion library/std/src/sys/pal/motor/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
#![allow(unsafe_op_in_unsafe_fn)]

pub mod os;
pub mod time;

pub use moto_rt::futex;

Expand Down
1 change: 0 additions & 1 deletion library/std/src/sys/pal/motor/time.rs

This file was deleted.

1 change: 0 additions & 1 deletion library/std/src/sys/pal/sgx/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ pub mod abi;
mod libunwind_integration;
pub mod os;
pub mod thread_parking;
pub mod time;
pub mod waitqueue;

// SAFETY: must be called only once during runtime initialization.
Expand Down
1 change: 0 additions & 1 deletion library/std/src/sys/pal/solid/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ pub mod itron {
pub(crate) mod error;
pub mod os;
pub use self::itron::thread_parking;
pub mod time;

// SAFETY: must be called only once during runtime initialization.
// NOTE: this is not guaranteed to run, for example when Rust code is called externally.
Expand Down
1 change: 0 additions & 1 deletion library/std/src/sys/pal/teeos/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
#![allow(dead_code)]

pub mod os;
#[allow(non_upper_case_globals)]
#[path = "../unix/time.rs"]
pub mod time;

Expand Down
2 changes: 0 additions & 2 deletions library/std/src/sys/pal/trusty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,5 @@
mod common;
#[path = "../unsupported/os.rs"]
pub mod os;
#[path = "../unsupported/time.rs"]
pub mod time;

pub use common::*;
2 changes: 1 addition & 1 deletion library/std/src/sys/pal/uefi/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

pub mod helpers;
pub mod os;
pub mod time;
pub mod system_time;

#[cfg(test)]
mod tests;
Expand Down
Loading
Loading