From 731d90416cda431d4d2798cf55d2eed9d5af3091 Mon Sep 17 00:00:00 2001 From: joboet Date: Thu, 15 Jan 2026 14:27:10 +0100 Subject: [PATCH 01/10] std: move time implementations to `sys` (preparation) --- library/std/src/sys/mod.rs | 1 + library/std/src/sys/time/mod.rs | 4 ++++ 2 files changed, 5 insertions(+) create mode 100644 library/std/src/sys/time/mod.rs diff --git a/library/std/src/sys/mod.rs b/library/std/src/sys/mod.rs index c9035938cfdd3..5436c144d3330 100644 --- a/library/std/src/sys/mod.rs +++ b/library/std/src/sys/mod.rs @@ -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. diff --git a/library/std/src/sys/time/mod.rs b/library/std/src/sys/time/mod.rs new file mode 100644 index 0000000000000..015871e6f1ec5 --- /dev/null +++ b/library/std/src/sys/time/mod.rs @@ -0,0 +1,4 @@ +cfg_select! { +} + +pub use imp::{Instant, SystemTime, UNIX_EPOCH}; From ca45fa093c7a0c6ede0795a2c33dfe4f58d5728c Mon Sep 17 00:00:00 2001 From: joboet Date: Thu, 15 Jan 2026 14:38:41 +0100 Subject: [PATCH 02/10] std: move time implementations to `sys` (small platforms) Let's start with the easy ones: * Motor just reexports its platform library * The SGX code is just a trivial move * Trusty, WASM and ZKVM are unsupported, this is very trivial. And we can get rid of some `#[path = ...]`s, yay! --- library/std/src/sys/pal/motor/mod.rs | 1 - library/std/src/sys/pal/motor/time.rs | 1 - library/std/src/sys/pal/sgx/mod.rs | 1 - library/std/src/sys/pal/trusty/mod.rs | 2 -- library/std/src/sys/pal/unsupported/mod.rs | 1 - library/std/src/sys/pal/wasm/mod.rs | 2 -- library/std/src/sys/pal/xous/mod.rs | 1 - library/std/src/sys/pal/zkvm/mod.rs | 2 -- library/std/src/sys/time/mod.rs | 15 +++++++++++++++ .../std/src/sys/{pal/sgx/time.rs => time/sgx.rs} | 2 +- .../unsupported/time.rs => time/unsupported.rs} | 0 .../src/sys/{pal/xous/time.rs => time/xous.rs} | 0 12 files changed, 16 insertions(+), 12 deletions(-) delete mode 100644 library/std/src/sys/pal/motor/time.rs rename library/std/src/sys/{pal/sgx/time.rs => time/sgx.rs} (97%) rename library/std/src/sys/{pal/unsupported/time.rs => time/unsupported.rs} (100%) rename library/std/src/sys/{pal/xous/time.rs => time/xous.rs} (100%) diff --git a/library/std/src/sys/pal/motor/mod.rs b/library/std/src/sys/pal/motor/mod.rs index e5b99cea01d55..a520375a4bbff 100644 --- a/library/std/src/sys/pal/motor/mod.rs +++ b/library/std/src/sys/pal/motor/mod.rs @@ -1,7 +1,6 @@ #![allow(unsafe_op_in_unsafe_fn)] pub mod os; -pub mod time; pub use moto_rt::futex; diff --git a/library/std/src/sys/pal/motor/time.rs b/library/std/src/sys/pal/motor/time.rs deleted file mode 100644 index e917fd466c2e4..0000000000000 --- a/library/std/src/sys/pal/motor/time.rs +++ /dev/null @@ -1 +0,0 @@ -pub use moto_rt::time::{Instant, SystemTime, UNIX_EPOCH}; diff --git a/library/std/src/sys/pal/sgx/mod.rs b/library/std/src/sys/pal/sgx/mod.rs index 7f1c81a0ff7bf..1de3ca4a5d79c 100644 --- a/library/std/src/sys/pal/sgx/mod.rs +++ b/library/std/src/sys/pal/sgx/mod.rs @@ -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. diff --git a/library/std/src/sys/pal/trusty/mod.rs b/library/std/src/sys/pal/trusty/mod.rs index 76a3a75b10c1a..b785c2dbb7892 100644 --- a/library/std/src/sys/pal/trusty/mod.rs +++ b/library/std/src/sys/pal/trusty/mod.rs @@ -5,7 +5,5 @@ mod common; #[path = "../unsupported/os.rs"] pub mod os; -#[path = "../unsupported/time.rs"] -pub mod time; pub use common::*; diff --git a/library/std/src/sys/pal/unsupported/mod.rs b/library/std/src/sys/pal/unsupported/mod.rs index c33d2e5fb02a1..0f157819d5a66 100644 --- a/library/std/src/sys/pal/unsupported/mod.rs +++ b/library/std/src/sys/pal/unsupported/mod.rs @@ -1,7 +1,6 @@ #![deny(unsafe_op_in_unsafe_fn)] pub mod os; -pub mod time; mod common; pub use common::*; diff --git a/library/std/src/sys/pal/wasm/mod.rs b/library/std/src/sys/pal/wasm/mod.rs index 80429a9aae18d..5f56eddd6a819 100644 --- a/library/std/src/sys/pal/wasm/mod.rs +++ b/library/std/src/sys/pal/wasm/mod.rs @@ -18,8 +18,6 @@ #[path = "../unsupported/os.rs"] pub mod os; -#[path = "../unsupported/time.rs"] -pub mod time; #[cfg(target_feature = "atomics")] #[path = "atomics/futex.rs"] diff --git a/library/std/src/sys/pal/xous/mod.rs b/library/std/src/sys/pal/xous/mod.rs index 19575220b22ee..87c99068929c3 100644 --- a/library/std/src/sys/pal/xous/mod.rs +++ b/library/std/src/sys/pal/xous/mod.rs @@ -1,7 +1,6 @@ #![forbid(unsafe_op_in_unsafe_fn)] pub mod os; -pub mod time; #[path = "../unsupported/common.rs"] mod common; diff --git a/library/std/src/sys/pal/zkvm/mod.rs b/library/std/src/sys/pal/zkvm/mod.rs index f09020820a031..1b18adb811d95 100644 --- a/library/std/src/sys/pal/zkvm/mod.rs +++ b/library/std/src/sys/pal/zkvm/mod.rs @@ -12,8 +12,6 @@ pub const WORD_SIZE: usize = size_of::(); pub mod abi; pub mod os; -#[path = "../unsupported/time.rs"] -pub mod time; use crate::io as std_io; diff --git a/library/std/src/sys/time/mod.rs b/library/std/src/sys/time/mod.rs index 015871e6f1ec5..81c568bf93202 100644 --- a/library/std/src/sys/time/mod.rs +++ b/library/std/src/sys/time/mod.rs @@ -1,4 +1,19 @@ cfg_select! { + target_os = "motor" => { + use moto_rt::time as imp; + } + all(target_vendor = "fortanix", target_env = "sgx") => { + mod sgx; + use sgx as imp; + } + target_os = "xous" => { + mod xous; + use xous as imp; + } + _ => { + mod unsupported; + use unsupported as imp; + } } pub use imp::{Instant, SystemTime, UNIX_EPOCH}; diff --git a/library/std/src/sys/pal/sgx/time.rs b/library/std/src/sys/time/sgx.rs similarity index 97% rename from library/std/src/sys/pal/sgx/time.rs rename to library/std/src/sys/time/sgx.rs index a9a448226619e..910e734c916e9 100644 --- a/library/std/src/sys/pal/sgx/time.rs +++ b/library/std/src/sys/time/sgx.rs @@ -1,4 +1,4 @@ -use super::abi::usercalls; +use crate::sys::pal::abi::usercalls; use crate::time::Duration; #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] diff --git a/library/std/src/sys/pal/unsupported/time.rs b/library/std/src/sys/time/unsupported.rs similarity index 100% rename from library/std/src/sys/pal/unsupported/time.rs rename to library/std/src/sys/time/unsupported.rs diff --git a/library/std/src/sys/pal/xous/time.rs b/library/std/src/sys/time/xous.rs similarity index 100% rename from library/std/src/sys/pal/xous/time.rs rename to library/std/src/sys/time/xous.rs From ec28f906e71ab926700c89f62c26ec48736e2b12 Mon Sep 17 00:00:00 2001 From: joboet Date: Thu, 15 Jan 2026 14:57:03 +0100 Subject: [PATCH 03/10] std: move time implementations to `sys` (VEX) Now that the `unsupported` module exists, we can use it for VEX. VEX actually supports `Instant` though, so the implementation-select needs to combine that with the `unsupported` module. --- library/std/src/sys/pal/vexos/mod.rs | 1 - library/std/src/sys/time/mod.rs | 10 ++++++++++ .../std/src/sys/{pal/vexos/time.rs => time/vexos.rs} | 5 ----- 3 files changed, 10 insertions(+), 6 deletions(-) rename library/std/src/sys/{pal/vexos/time.rs => time/vexos.rs} (83%) diff --git a/library/std/src/sys/pal/vexos/mod.rs b/library/std/src/sys/pal/vexos/mod.rs index 0abfc2fd79865..16aa3f088f04b 100644 --- a/library/std/src/sys/pal/vexos/mod.rs +++ b/library/std/src/sys/pal/vexos/mod.rs @@ -1,5 +1,4 @@ pub mod os; -pub mod time; #[expect(dead_code)] #[path = "../unsupported/common.rs"] diff --git a/library/std/src/sys/time/mod.rs b/library/std/src/sys/time/mod.rs index 81c568bf93202..0e3376e2f9106 100644 --- a/library/std/src/sys/time/mod.rs +++ b/library/std/src/sys/time/mod.rs @@ -6,6 +6,16 @@ cfg_select! { mod sgx; use sgx as imp; } + target_os = "vexos" => { + mod vexos; + #[expect(unused)] + mod unsupported; + + mod imp { + pub use super::vexos::Instant; + pub use super::unsupported::{SystemTime, UNIX_EPOCH}; + } + } target_os = "xous" => { mod xous; use xous as imp; diff --git a/library/std/src/sys/pal/vexos/time.rs b/library/std/src/sys/time/vexos.rs similarity index 83% rename from library/std/src/sys/pal/vexos/time.rs rename to library/std/src/sys/time/vexos.rs index f95d96cd27ac0..966c239699cec 100644 --- a/library/std/src/sys/pal/vexos/time.rs +++ b/library/std/src/sys/time/vexos.rs @@ -1,10 +1,5 @@ use crate::time::Duration; -#[expect(dead_code)] -#[path = "../unsupported/time.rs"] -mod unsupported_time; -pub use unsupported_time::{SystemTime, UNIX_EPOCH}; - #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] pub struct Instant(Duration); From 9a3fc648a5dfc7bdb50a7df4d17ac1958a1d53dd Mon Sep 17 00:00:00 2001 From: joboet Date: Thu, 15 Jan 2026 14:47:05 +0100 Subject: [PATCH 04/10] std: move time implementations to `sys` (Solid) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On SOLID, the conversion functions are also used to implement helpers for timeout conversion, so these stay in the PAL. The `Instant` (µITRON) and `SystemTime` (SOLID-specific) implementations are merged into one. While it was nice to have the µITRON parts in a separate module, there really isn't a need for this currently, as there is no other µITRON target. Let's not worry about this until such a target gets added... Note that I've extracted the `get_tim` call from `Instant` into a wrapper function in the PAL to avoid the need to make the inner `Instant` field public for use in the PAL. --- library/std/src/sys/pal/itron/time.rs | 47 +++++-------------- library/std/src/sys/pal/solid/mod.rs | 1 - library/std/src/sys/time/mod.rs | 4 ++ .../sys/{pal/solid/time.rs => time/solid.rs} | 35 ++++++++++++-- 4 files changed, 47 insertions(+), 40 deletions(-) rename library/std/src/sys/{pal/solid/time.rs => time/solid.rs} (65%) diff --git a/library/std/src/sys/pal/itron/time.rs b/library/std/src/sys/pal/itron/time.rs index 7976c27f4952b..ff3cffd2069e9 100644 --- a/library/std/src/sys/pal/itron/time.rs +++ b/library/std/src/sys/pal/itron/time.rs @@ -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 { - 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 { - // `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 { - // `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() } } @@ -98,7 +76,7 @@ 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 { @@ -106,11 +84,8 @@ pub fn with_tmos_strong(dur: Duration, mut f: impl FnMut(abi::TMO) -> abi::ER) - if er != abi::E_TMOUT { break; } - elapsed = Instant::now().0.wrapping_sub(start); + elapsed = get_tim().wrapping_sub(start); } er } - -#[cfg(test)] -mod tests; diff --git a/library/std/src/sys/pal/solid/mod.rs b/library/std/src/sys/pal/solid/mod.rs index 4eec12dacd7ca..1376af8304cf6 100644 --- a/library/std/src/sys/pal/solid/mod.rs +++ b/library/std/src/sys/pal/solid/mod.rs @@ -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. diff --git a/library/std/src/sys/time/mod.rs b/library/std/src/sys/time/mod.rs index 0e3376e2f9106..e5b9a3a057f09 100644 --- a/library/std/src/sys/time/mod.rs +++ b/library/std/src/sys/time/mod.rs @@ -6,6 +6,10 @@ cfg_select! { mod sgx; use sgx as imp; } + target_os = "solid_asp3" => { + mod solid; + use solid as imp; + } target_os = "vexos" => { mod vexos; #[expect(unused)] diff --git a/library/std/src/sys/pal/solid/time.rs b/library/std/src/sys/time/solid.rs similarity index 65% rename from library/std/src/sys/pal/solid/time.rs rename to library/std/src/sys/time/solid.rs index d5cf70f94c987..fa929c67241e3 100644 --- a/library/std/src/sys/pal/solid/time.rs +++ b/library/std/src/sys/time/solid.rs @@ -1,9 +1,38 @@ -use super::abi; -use super::error::expect_success; -pub use super::itron::time::Instant; use crate::mem::MaybeUninit; +use crate::sys::pal::error::expect_success; +use crate::sys::pal::{abi, itron}; use crate::time::Duration; +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] +pub struct Instant(itron::abi::SYSTIM); + +impl Instant { + pub fn now() -> Instant { + Instant(itron::time::get_tim()) + } + + pub fn checked_sub_instant(&self, other: &Instant) -> Option { + 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 { + // `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 { + // `SYSTIM` is measured in microseconds + let ticks = other.as_micros(); + + Some(Instant(self.0.checked_sub(ticks.try_into().ok()?)?)) + } +} + #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] pub struct SystemTime(abi::time_t); From 98053075295551e502409bd7c4b205bd36da08f3 Mon Sep 17 00:00:00 2001 From: joboet Date: Thu, 15 Jan 2026 14:53:52 +0100 Subject: [PATCH 05/10] std: move time implementations to `sys` (UEFI) Next up: UEFI. Unfortunately the time conversion internals are also required by the filesystem code, so I've left them in the PAL. The `Instant` internals however are only used for the `Instant` implementation, so I've moved them to `sys` (for now). --- library/std/src/sys/fs/uefi.rs | 7 +- library/std/src/sys/pal/uefi/mod.rs | 2 +- library/std/src/sys/pal/uefi/system_time.rs | 151 +++++++++++++++ library/std/src/sys/time/mod.rs | 4 + .../sys/{pal/uefi/time.rs => time/uefi.rs} | 172 +----------------- 5 files changed, 168 insertions(+), 168 deletions(-) create mode 100644 library/std/src/sys/pal/uefi/system_time.rs rename library/std/src/sys/{pal/uefi/time.rs => time/uefi.rs} (52%) diff --git a/library/std/src/sys/fs/uefi.rs b/library/std/src/sys/fs/uefi.rs index a1bb0c6e828bd..8135519317a02 100644 --- a/library/std/src/sys/fs/uefi.rs +++ b/library/std/src/sys/fs/uefi.rs @@ -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, @@ -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 { time.timezone = if time.timezone == r_efi::efi::UNSPECIFIED_TIMEZONE { - time::system_time_internal::now().timezone + system_time::now().timezone } else { time.timezone }; @@ -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) } diff --git a/library/std/src/sys/pal/uefi/mod.rs b/library/std/src/sys/pal/uefi/mod.rs index b181d78c2345a..e4a8f50e4274d 100644 --- a/library/std/src/sys/pal/uefi/mod.rs +++ b/library/std/src/sys/pal/uefi/mod.rs @@ -15,7 +15,7 @@ pub mod helpers; pub mod os; -pub mod time; +pub mod system_time; #[cfg(test)] mod tests; diff --git a/library/std/src/sys/pal/uefi/system_time.rs b/library/std/src/sys/pal/uefi/system_time.rs new file mode 100644 index 0000000000000..557a49b27c2d1 --- /dev/null +++ b/library/std/src/sys/pal/uefi/system_time.rs @@ -0,0 +1,151 @@ +use r_efi::efi::{RuntimeServices, Time}; + +use super::helpers; +use crate::mem::MaybeUninit; +use crate::ptr::NonNull; +use crate::time::Duration; + +const SECS_IN_MINUTE: u64 = 60; +const SECS_IN_HOUR: u64 = SECS_IN_MINUTE * 60; +const SECS_IN_DAY: u64 = SECS_IN_HOUR * 24; +const SYSTEMTIME_TIMEZONE: i64 = -1440 * SECS_IN_MINUTE as i64; + +pub(crate) fn now() -> Time { + let runtime_services: NonNull = + helpers::runtime_services().expect("Runtime services are not available"); + let mut t: MaybeUninit