Skip to content

Commit ea658e1

Browse files
Rollup merge of #151161 - joboet:move-pal-time, r=tgross35
std: move time implementations to `sys` This is probably the most complex step of #117276 so far. Unfortunately, quite some of the internal time logic defined in the PAL is also used in other places like the filesystem code, so this isn't just a series of simple moves. I've left all that logic inside the PAL and only moved the actual `SystemTime`/`Instant` implementations. While there are no functional changes, this PR also contains some slight code cleanups on Windows and Hermit, these are explained in the relevant commits. For additional details see the individual commits, I've tried to make the messages as helpful as possible about what's going on.
2 parents 5f675c6 + 5a98a51 commit ea658e1

32 files changed

Lines changed: 674 additions & 723 deletions

File tree

library/std/src/sys/fs/uefi.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -580,7 +580,8 @@ mod uefi_fs {
580580
use crate::path::Path;
581581
use crate::ptr::NonNull;
582582
use crate::sys::pal::helpers::{self, UefiBox};
583-
use crate::sys::time::{self, SystemTime};
583+
use crate::sys::pal::system_time;
584+
use crate::sys::time::SystemTime;
584585

585586
pub(crate) struct File {
586587
protocol: NonNull<file::Protocol>,
@@ -879,7 +880,7 @@ mod uefi_fs {
879880
/// conversion to SystemTime, we use the current time to get the timezone in such cases.
880881
pub(crate) fn uefi_to_systemtime(mut time: r_efi::efi::Time) -> Option<SystemTime> {
881882
time.timezone = if time.timezone == r_efi::efi::UNSPECIFIED_TIMEZONE {
882-
time::system_time_internal::now().timezone
883+
system_time::now().timezone
883884
} else {
884885
time.timezone
885886
};
@@ -888,7 +889,7 @@ mod uefi_fs {
888889

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

library/std/src/sys/fs/unix.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1822,7 +1822,7 @@ impl File {
18221822
_ => {
18231823
#[cfg(all(target_os = "linux", target_env = "gnu", target_pointer_width = "32", not(target_arch = "riscv32")))]
18241824
{
1825-
use crate::sys::{time::__timespec64, weak::weak};
1825+
use crate::sys::pal::{time::__timespec64, weak::weak};
18261826

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

22632263
// Added in glibc 2.34
22642264
weak!(

library/std/src/sys/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ pub mod stdio;
2626
pub mod sync;
2727
pub mod thread;
2828
pub mod thread_local;
29+
pub mod time;
2930

3031
// FIXME(117276): remove this, move feature implementations into individual
3132
// submodules.

library/std/src/sys/net/connection/socket/hermit.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,9 @@ use crate::io::{self, BorrowedBuf, BorrowedCursor, IoSlice, IoSliceMut};
99
use crate::net::{Shutdown, SocketAddr};
1010
use crate::os::hermit::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, RawFd};
1111
use crate::sys::fd::FileDesc;
12-
use crate::sys::time::Instant;
1312
use crate::sys::{AsInner, FromInner, IntoInner};
1413
pub use crate::sys::{cvt, cvt_r};
15-
use crate::time::Duration;
14+
use crate::time::{Duration, Instant};
1615
use crate::{cmp, mem};
1716

1817
#[expect(non_camel_case_types)]
Lines changed: 11 additions & 143 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,32 @@
1-
#![allow(dead_code)]
1+
use hermit_abi::{self, timespec};
22

3-
use core::hash::{Hash, Hasher};
4-
5-
use super::hermit_abi::{self, CLOCK_MONOTONIC, CLOCK_REALTIME, timespec};
63
use crate::cmp::Ordering;
7-
use crate::ops::{Add, AddAssign, Sub, SubAssign};
4+
use crate::hash::{Hash, Hasher};
85
use crate::time::Duration;
96

107
const NSEC_PER_SEC: i32 = 1_000_000_000;
118

129
#[derive(Copy, Clone, Debug)]
13-
struct Timespec {
14-
t: timespec,
10+
pub struct Timespec {
11+
pub t: timespec,
1512
}
1613

1714
impl Timespec {
18-
const MAX: Timespec = Self::new(i64::MAX, 1_000_000_000 - 1);
15+
pub const MAX: Timespec = Self::new(i64::MAX, 1_000_000_000 - 1);
1916

20-
const MIN: Timespec = Self::new(i64::MIN, 0);
17+
pub const MIN: Timespec = Self::new(i64::MIN, 0);
2118

22-
const fn zero() -> Timespec {
19+
pub const fn zero() -> Timespec {
2320
Timespec { t: timespec { tv_sec: 0, tv_nsec: 0 } }
2421
}
2522

26-
const fn new(tv_sec: i64, tv_nsec: i32) -> Timespec {
23+
pub const fn new(tv_sec: i64, tv_nsec: i32) -> Timespec {
2724
assert!(tv_nsec >= 0 && tv_nsec < NSEC_PER_SEC);
2825
// SAFETY: The assert above checks tv_nsec is within the valid range
2926
Timespec { t: timespec { tv_sec, tv_nsec } }
3027
}
3128

32-
fn sub_timespec(&self, other: &Timespec) -> Result<Duration, Duration> {
29+
pub fn sub_timespec(&self, other: &Timespec) -> Result<Duration, Duration> {
3330
fn sub_ge_to_unsigned(a: i64, b: i64) -> u64 {
3431
debug_assert!(a >= b);
3532
a.wrapping_sub(b).cast_unsigned()
@@ -57,7 +54,7 @@ impl Timespec {
5754
}
5855
}
5956

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

6360
// Nano calculations can't overflow because nanos are <1B which fit
@@ -70,7 +67,7 @@ impl Timespec {
7067
Some(Timespec { t: timespec { tv_sec: secs, tv_nsec: nsec as _ } })
7168
}
7269

73-
fn checked_sub_duration(&self, other: &Duration) -> Option<Timespec> {
70+
pub fn checked_sub_duration(&self, other: &Duration) -> Option<Timespec> {
7471
let mut secs = self.t.tv_sec.checked_sub_unsigned(other.as_secs())?;
7572

7673
// Similar to above, nanos can't overflow.
@@ -111,132 +108,3 @@ impl Hash for Timespec {
111108
self.t.tv_nsec.hash(state);
112109
}
113110
}
114-
115-
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
116-
pub struct Instant(Timespec);
117-
118-
impl Instant {
119-
pub fn now() -> Instant {
120-
let mut time: Timespec = Timespec::zero();
121-
let _ = unsafe { hermit_abi::clock_gettime(CLOCK_MONOTONIC, &raw mut time.t) };
122-
123-
Instant(time)
124-
}
125-
126-
#[stable(feature = "time2", since = "1.8.0")]
127-
pub fn elapsed(&self) -> Duration {
128-
Instant::now() - *self
129-
}
130-
131-
pub fn duration_since(&self, earlier: Instant) -> Duration {
132-
self.checked_duration_since(earlier).unwrap_or_default()
133-
}
134-
135-
pub fn checked_duration_since(&self, earlier: Instant) -> Option<Duration> {
136-
self.checked_sub_instant(&earlier)
137-
}
138-
139-
pub fn checked_sub_instant(&self, other: &Instant) -> Option<Duration> {
140-
self.0.sub_timespec(&other.0).ok()
141-
}
142-
143-
pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> {
144-
Some(Instant(self.0.checked_add_duration(other)?))
145-
}
146-
147-
pub fn checked_sub_duration(&self, other: &Duration) -> Option<Instant> {
148-
Some(Instant(self.0.checked_sub_duration(other)?))
149-
}
150-
151-
pub fn checked_add(&self, duration: Duration) -> Option<Instant> {
152-
self.0.checked_add_duration(&duration).map(Instant)
153-
}
154-
155-
pub fn checked_sub(&self, duration: Duration) -> Option<Instant> {
156-
self.0.checked_sub_duration(&duration).map(Instant)
157-
}
158-
}
159-
160-
impl Add<Duration> for Instant {
161-
type Output = Instant;
162-
163-
/// # Panics
164-
///
165-
/// This function may panic if the resulting point in time cannot be represented by the
166-
/// underlying data structure. See [`Instant::checked_add`] for a version without panic.
167-
fn add(self, other: Duration) -> Instant {
168-
self.checked_add(other).expect("overflow when adding duration to instant")
169-
}
170-
}
171-
172-
impl AddAssign<Duration> for Instant {
173-
fn add_assign(&mut self, other: Duration) {
174-
*self = *self + other;
175-
}
176-
}
177-
178-
impl Sub<Duration> for Instant {
179-
type Output = Instant;
180-
181-
fn sub(self, other: Duration) -> Instant {
182-
self.checked_sub(other).expect("overflow when subtracting duration from instant")
183-
}
184-
}
185-
186-
impl SubAssign<Duration> for Instant {
187-
fn sub_assign(&mut self, other: Duration) {
188-
*self = *self - other;
189-
}
190-
}
191-
192-
impl Sub<Instant> for Instant {
193-
type Output = Duration;
194-
195-
/// Returns the amount of time elapsed from another instant to this one,
196-
/// or zero duration if that instant is later than this one.
197-
///
198-
/// # Panics
199-
///
200-
/// Previous Rust versions panicked when `other` was later than `self`. Currently this
201-
/// method saturates. Future versions may reintroduce the panic in some circumstances.
202-
/// See [Monotonicity].
203-
///
204-
/// [Monotonicity]: Instant#monotonicity
205-
fn sub(self, other: Instant) -> Duration {
206-
self.duration_since(other)
207-
}
208-
}
209-
210-
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
211-
pub struct SystemTime(Timespec);
212-
213-
pub const UNIX_EPOCH: SystemTime = SystemTime(Timespec::zero());
214-
215-
impl SystemTime {
216-
pub const MAX: SystemTime = SystemTime(Timespec::MAX);
217-
218-
pub const MIN: SystemTime = SystemTime(Timespec::MIN);
219-
220-
pub fn new(tv_sec: i64, tv_nsec: i32) -> SystemTime {
221-
SystemTime(Timespec::new(tv_sec, tv_nsec))
222-
}
223-
224-
pub fn now() -> SystemTime {
225-
let mut time: Timespec = Timespec::zero();
226-
let _ = unsafe { hermit_abi::clock_gettime(CLOCK_REALTIME, &raw mut time.t) };
227-
228-
SystemTime(time)
229-
}
230-
231-
pub fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> {
232-
self.0.sub_timespec(&other.0)
233-
}
234-
235-
pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
236-
Some(SystemTime(self.0.checked_add_duration(other)?))
237-
}
238-
239-
pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
240-
Some(SystemTime(self.0.checked_sub_duration(other)?))
241-
}
242-
}

library/std/src/sys/pal/itron/time.rs

Lines changed: 11 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -3,38 +3,16 @@ use super::error::expect_success;
33
use crate::mem::MaybeUninit;
44
use crate::time::Duration;
55

6-
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
7-
pub struct Instant(abi::SYSTIM);
8-
9-
impl Instant {
10-
pub fn now() -> Instant {
11-
// Safety: The provided pointer is valid
12-
unsafe {
13-
let mut out = MaybeUninit::uninit();
14-
expect_success(abi::get_tim(out.as_mut_ptr()), &"get_tim");
15-
Instant(out.assume_init())
16-
}
17-
}
18-
19-
pub fn checked_sub_instant(&self, other: &Instant) -> Option<Duration> {
20-
self.0.checked_sub(other.0).map(|ticks| {
21-
// `SYSTIM` is measured in microseconds
22-
Duration::from_micros(ticks)
23-
})
24-
}
25-
26-
pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> {
27-
// `SYSTIM` is measured in microseconds
28-
let ticks = other.as_micros();
29-
30-
Some(Instant(self.0.checked_add(ticks.try_into().ok()?)?))
31-
}
32-
33-
pub fn checked_sub_duration(&self, other: &Duration) -> Option<Instant> {
34-
// `SYSTIM` is measured in microseconds
35-
let ticks = other.as_micros();
6+
#[cfg(test)]
7+
mod tests;
368

37-
Some(Instant(self.0.checked_sub(ticks.try_into().ok()?)?))
9+
#[inline]
10+
pub fn get_tim() -> abi::SYSTIM {
11+
// Safety: The provided pointer is valid
12+
unsafe {
13+
let mut out = MaybeUninit::uninit();
14+
expect_success(abi::get_tim(out.as_mut_ptr()), &"get_tim");
15+
out.assume_init()
3816
}
3917
}
4018

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

101-
let start = Instant::now().0;
79+
let start = get_tim();
10280
let mut elapsed = 0;
10381
let mut er = abi::E_TMOUT;
10482
while elapsed <= ticks {
10583
er = f(elapsed.min(abi::TMAX_RELTIM as abi::SYSTIM) as abi::TMO);
10684
if er != abi::E_TMOUT {
10785
break;
10886
}
109-
elapsed = Instant::now().0.wrapping_sub(start);
87+
elapsed = get_tim().wrapping_sub(start);
11088
}
11189

11290
er
11391
}
114-
115-
#[cfg(test)]
116-
mod tests;

library/std/src/sys/pal/motor/mod.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
#![allow(unsafe_op_in_unsafe_fn)]
22

33
pub mod os;
4-
pub mod time;
54

65
pub use moto_rt::futex;
76

library/std/src/sys/pal/motor/time.rs

Lines changed: 0 additions & 1 deletion
This file was deleted.

library/std/src/sys/pal/sgx/mod.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ pub mod abi;
1212
mod libunwind_integration;
1313
pub mod os;
1414
pub mod thread_parking;
15-
pub mod time;
1615
pub mod waitqueue;
1716

1817
// SAFETY: must be called only once during runtime initialization.

library/std/src/sys/pal/solid/mod.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ pub mod itron {
2121
pub(crate) mod error;
2222
pub mod os;
2323
pub use self::itron::thread_parking;
24-
pub mod time;
2524

2625
// SAFETY: must be called only once during runtime initialization.
2726
// NOTE: this is not guaranteed to run, for example when Rust code is called externally.

0 commit comments

Comments
 (0)