Skip to content

Commit 8bf5e44

Browse files
committed
std: move time implementations to sys (UNIX)
Now for UNIX: `Timespec` is also used for things like futex or `Condvar` timeouts, so it stays in the PAL along with some related definitions. Everything else is `SystemTime`- and `Instant`-specific, and is thus moved to `sys::time`.
1 parent 8aa4088 commit 8bf5e44

4 files changed

Lines changed: 121 additions & 112 deletions

File tree

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/pal/unix/time.rs

Lines changed: 7 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
use core::num::niche_types::Nanoseconds;
22

3-
use crate::sys::AsInner;
3+
use crate::io;
44
use crate::time::Duration;
5-
use crate::{fmt, io};
65

76
const NSEC_PER_SEC: u64 = 1_000_000_000;
8-
pub const UNIX_EPOCH: SystemTime = SystemTime { t: Timespec::zero() };
7+
98
#[allow(dead_code)] // Used for pthread condvar timeouts
109
pub const TIMESPEC_MAX: libc::timespec =
1110
libc::timespec { tv_sec: <libc::time_t>::MAX, tv_nsec: 1_000_000_000 - 1 };
@@ -18,60 +17,19 @@ pub(in crate::sys) const TIMESPEC_MAX_CAPPED: libc::timespec = libc::timespec {
1817
tv_nsec: (u64::MAX % NSEC_PER_SEC) as i64,
1918
};
2019

21-
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
22-
pub struct SystemTime {
23-
pub(crate) t: Timespec,
24-
}
25-
2620
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
2721
pub(crate) struct Timespec {
28-
tv_sec: i64,
29-
tv_nsec: Nanoseconds,
30-
}
31-
32-
impl SystemTime {
33-
pub const MAX: SystemTime = SystemTime { t: Timespec::MAX };
34-
35-
pub const MIN: SystemTime = SystemTime { t: Timespec::MIN };
36-
37-
#[cfg_attr(any(target_os = "horizon", target_os = "hurd"), allow(unused))]
38-
pub fn new(tv_sec: i64, tv_nsec: i64) -> Result<SystemTime, io::Error> {
39-
Ok(SystemTime { t: Timespec::new(tv_sec, tv_nsec)? })
40-
}
41-
42-
pub fn now() -> SystemTime {
43-
SystemTime { t: Timespec::now(libc::CLOCK_REALTIME) }
44-
}
45-
46-
pub fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> {
47-
self.t.sub_timespec(&other.t)
48-
}
49-
50-
pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
51-
Some(SystemTime { t: self.t.checked_add_duration(other)? })
52-
}
53-
54-
pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
55-
Some(SystemTime { t: self.t.checked_sub_duration(other)? })
56-
}
57-
}
58-
59-
impl fmt::Debug for SystemTime {
60-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
61-
f.debug_struct("SystemTime")
62-
.field("tv_sec", &self.t.tv_sec)
63-
.field("tv_nsec", &self.t.tv_nsec)
64-
.finish()
65-
}
22+
pub tv_sec: i64,
23+
pub tv_nsec: Nanoseconds,
6624
}
6725

6826
impl Timespec {
69-
const MAX: Timespec = unsafe { Self::new_unchecked(i64::MAX, 1_000_000_000 - 1) };
27+
pub const MAX: Timespec = unsafe { Self::new_unchecked(i64::MAX, 1_000_000_000 - 1) };
7028

7129
// As described below, on Apple OS, dates before epoch are represented differently.
7230
// This is not an issue here however, because we are using tv_sec = i64::MIN,
7331
// which will cause the compatibility wrapper to not be executed at all.
74-
const MIN: Timespec = unsafe { Self::new_unchecked(i64::MIN, 0) };
32+
pub const MIN: Timespec = unsafe { Self::new_unchecked(i64::MIN, 0) };
7533

7634
const unsafe fn new_unchecked(tv_sec: i64, tv_nsec: i64) -> Timespec {
7735
Timespec { tv_sec, tv_nsec: unsafe { Nanoseconds::new_unchecked(tv_nsec as u32) } }
@@ -81,7 +39,7 @@ impl Timespec {
8139
unsafe { Self::new_unchecked(0, 0) }
8240
}
8341

84-
const fn new(tv_sec: i64, tv_nsec: i64) -> Result<Timespec, io::Error> {
42+
pub const fn new(tv_sec: i64, tv_nsec: i64) -> Result<Timespec, io::Error> {
8543
// On Apple OS, dates before epoch are represented differently than on other
8644
// Unix platforms: e.g. 1/10th of a second before epoch is represented as `seconds=-1`
8745
// and `nanoseconds=100_000_000` on other platforms, but is `seconds=0` and
@@ -263,64 +221,3 @@ impl __timespec64 {
263221
Self { tv_sec, tv_nsec, _padding: 0 }
264222
}
265223
}
266-
267-
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
268-
pub struct Instant {
269-
t: Timespec,
270-
}
271-
272-
impl Instant {
273-
#[cfg(target_vendor = "apple")]
274-
pub(crate) const CLOCK_ID: libc::clockid_t = libc::CLOCK_UPTIME_RAW;
275-
#[cfg(not(target_vendor = "apple"))]
276-
pub(crate) const CLOCK_ID: libc::clockid_t = libc::CLOCK_MONOTONIC;
277-
pub fn now() -> Instant {
278-
// https://pubs.opengroup.org/onlinepubs/9799919799/functions/clock_getres.html
279-
//
280-
// CLOCK_UPTIME_RAW clock that increments monotonically, in the same man-
281-
// ner as CLOCK_MONOTONIC_RAW, but that does not incre-
282-
// ment while the system is asleep. The returned value
283-
// is identical to the result of mach_absolute_time()
284-
// after the appropriate mach_timebase conversion is
285-
// applied.
286-
//
287-
// Instant on macos was historically implemented using mach_absolute_time;
288-
// we preserve this value domain out of an abundance of caution.
289-
Instant { t: Timespec::now(Self::CLOCK_ID) }
290-
}
291-
292-
pub fn checked_sub_instant(&self, other: &Instant) -> Option<Duration> {
293-
self.t.sub_timespec(&other.t).ok()
294-
}
295-
296-
pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> {
297-
Some(Instant { t: self.t.checked_add_duration(other)? })
298-
}
299-
300-
pub fn checked_sub_duration(&self, other: &Duration) -> Option<Instant> {
301-
Some(Instant { t: self.t.checked_sub_duration(other)? })
302-
}
303-
304-
#[cfg_attr(
305-
not(target_os = "linux"),
306-
allow(unused, reason = "needed by the `sleep_until` on some unix platforms")
307-
)]
308-
pub(crate) fn into_timespec(self) -> Timespec {
309-
self.t
310-
}
311-
}
312-
313-
impl AsInner<Timespec> for Instant {
314-
fn as_inner(&self) -> &Timespec {
315-
&self.t
316-
}
317-
}
318-
319-
impl fmt::Debug for Instant {
320-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
321-
f.debug_struct("Instant")
322-
.field("tv_sec", &self.t.tv_sec)
323-
.field("tv_nsec", &self.t.tv_nsec)
324-
.finish()
325-
}
326-
}

library/std/src/sys/time/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ cfg_select! {
1414
mod uefi;
1515
use uefi as imp;
1616
}
17+
target_family = "unix" => {
18+
mod unix;
19+
use unix as imp;
20+
}
1721
target_os = "vexos" => {
1822
mod vexos;
1923
#[expect(unused)]

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

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
use crate::sys::AsInner;
2+
use crate::sys::pal::time::Timespec;
3+
use crate::time::Duration;
4+
use crate::{fmt, io};
5+
6+
pub const UNIX_EPOCH: SystemTime = SystemTime { t: Timespec::zero() };
7+
8+
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
9+
pub struct SystemTime {
10+
pub(crate) t: Timespec,
11+
}
12+
13+
impl SystemTime {
14+
pub const MAX: SystemTime = SystemTime { t: Timespec::MAX };
15+
16+
pub const MIN: SystemTime = SystemTime { t: Timespec::MIN };
17+
18+
#[cfg_attr(any(target_os = "horizon", target_os = "hurd"), allow(unused))]
19+
pub fn new(tv_sec: i64, tv_nsec: i64) -> Result<SystemTime, io::Error> {
20+
Ok(SystemTime { t: Timespec::new(tv_sec, tv_nsec)? })
21+
}
22+
23+
pub fn now() -> SystemTime {
24+
SystemTime { t: Timespec::now(libc::CLOCK_REALTIME) }
25+
}
26+
27+
pub fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> {
28+
self.t.sub_timespec(&other.t)
29+
}
30+
31+
pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
32+
Some(SystemTime { t: self.t.checked_add_duration(other)? })
33+
}
34+
35+
pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
36+
Some(SystemTime { t: self.t.checked_sub_duration(other)? })
37+
}
38+
}
39+
40+
impl fmt::Debug for SystemTime {
41+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
42+
f.debug_struct("SystemTime")
43+
.field("tv_sec", &self.t.tv_sec)
44+
.field("tv_nsec", &self.t.tv_nsec)
45+
.finish()
46+
}
47+
}
48+
49+
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
50+
pub struct Instant {
51+
t: Timespec,
52+
}
53+
54+
impl Instant {
55+
#[cfg(target_vendor = "apple")]
56+
pub(crate) const CLOCK_ID: libc::clockid_t = libc::CLOCK_UPTIME_RAW;
57+
#[cfg(not(target_vendor = "apple"))]
58+
pub(crate) const CLOCK_ID: libc::clockid_t = libc::CLOCK_MONOTONIC;
59+
pub fn now() -> Instant {
60+
// https://pubs.opengroup.org/onlinepubs/9799919799/functions/clock_getres.html
61+
//
62+
// CLOCK_UPTIME_RAW clock that increments monotonically, in the same man-
63+
// ner as CLOCK_MONOTONIC_RAW, but that does not incre-
64+
// ment while the system is asleep. The returned value
65+
// is identical to the result of mach_absolute_time()
66+
// after the appropriate mach_timebase conversion is
67+
// applied.
68+
//
69+
// Instant on macos was historically implemented using mach_absolute_time;
70+
// we preserve this value domain out of an abundance of caution.
71+
Instant { t: Timespec::now(Self::CLOCK_ID) }
72+
}
73+
74+
pub fn checked_sub_instant(&self, other: &Instant) -> Option<Duration> {
75+
self.t.sub_timespec(&other.t).ok()
76+
}
77+
78+
pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> {
79+
Some(Instant { t: self.t.checked_add_duration(other)? })
80+
}
81+
82+
pub fn checked_sub_duration(&self, other: &Duration) -> Option<Instant> {
83+
Some(Instant { t: self.t.checked_sub_duration(other)? })
84+
}
85+
86+
#[cfg_attr(
87+
not(target_os = "linux"),
88+
allow(unused, reason = "needed by the `sleep_until` on some unix platforms")
89+
)]
90+
pub(crate) fn into_timespec(self) -> Timespec {
91+
self.t
92+
}
93+
}
94+
95+
impl AsInner<Timespec> for Instant {
96+
fn as_inner(&self) -> &Timespec {
97+
&self.t
98+
}
99+
}
100+
101+
impl fmt::Debug for Instant {
102+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
103+
f.debug_struct("Instant")
104+
.field("tv_sec", &self.t.tv_sec)
105+
.field("tv_nsec", &self.t.tv_nsec)
106+
.finish()
107+
}
108+
}

0 commit comments

Comments
 (0)