diff options
Diffstat (limited to 'library/std/src/sys/pal')
| -rw-r--r-- | library/std/src/sys/pal/hermit/time.rs | 11 | ||||
| -rw-r--r-- | library/std/src/sys/pal/mod.rs | 4 | ||||
| -rw-r--r-- | library/std/src/sys/pal/unix/os.rs | 2 | ||||
| -rw-r--r-- | library/std/src/sys/pal/unix/stack_overflow.rs | 2 | ||||
| -rw-r--r-- | library/std/src/sys/pal/unix/time.rs | 27 | ||||
| -rw-r--r-- | library/std/src/sys/pal/vexos/mod.rs | 80 | ||||
| -rw-r--r-- | library/std/src/sys/pal/vexos/time.rs | 28 |
7 files changed, 135 insertions, 19 deletions
diff --git a/library/std/src/sys/pal/hermit/time.rs b/library/std/src/sys/pal/hermit/time.rs index f76a5f96c87..bd6fd5a3de4 100644 --- a/library/std/src/sys/pal/hermit/time.rs +++ b/library/std/src/sys/pal/hermit/time.rs @@ -26,15 +26,22 @@ impl Timespec { } 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() + } + if self >= other { + // Logic here is identical to Unix version of `Timestamp::sub_timespec`, + // check comments there why operations do not overflow. Ok(if self.t.tv_nsec >= other.t.tv_nsec { Duration::new( - (self.t.tv_sec - other.t.tv_sec) as u64, + sub_ge_to_unsigned(self.t.tv_sec, other.t.tv_sec), (self.t.tv_nsec - other.t.tv_nsec) as u32, ) } else { Duration::new( - (self.t.tv_sec - 1 - other.t.tv_sec) as u64, + sub_ge_to_unsigned(self.t.tv_sec - 1, other.t.tv_sec), (self.t.tv_nsec + NSEC_PER_SEC - other.t.tv_nsec) as u32, ) }) diff --git a/library/std/src/sys/pal/mod.rs b/library/std/src/sys/pal/mod.rs index 513121c6d30..dd5e83ee570 100644 --- a/library/std/src/sys/pal/mod.rs +++ b/library/std/src/sys/pal/mod.rs @@ -45,6 +45,10 @@ cfg_select! { mod trusty; pub use self::trusty::*; } + target_os = "vexos" => { + mod vexos; + pub use self::vexos::*; + } all(target_os = "wasi", target_env = "p2") => { mod wasip2; pub use self::wasip2::*; diff --git a/library/std/src/sys/pal/unix/os.rs b/library/std/src/sys/pal/unix/os.rs index f0b6068e06c..7c9f3b7992f 100644 --- a/library/std/src/sys/pal/unix/os.rs +++ b/library/std/src/sys/pal/unix/os.rs @@ -16,7 +16,7 @@ use crate::{fmt, io, iter, mem, ptr, slice, str}; const TMPBUF_SZ: usize = 128; -const PATH_SEPARATOR: u8 = if cfg!(target_os = "redox") { b';' } else { b':' }; +const PATH_SEPARATOR: u8 = b':'; unsafe extern "C" { #[cfg(not(any(target_os = "dragonfly", target_os = "vxworks", target_os = "rtems")))] diff --git a/library/std/src/sys/pal/unix/stack_overflow.rs b/library/std/src/sys/pal/unix/stack_overflow.rs index 0d2100d66bc..51463eef5b7 100644 --- a/library/std/src/sys/pal/unix/stack_overflow.rs +++ b/library/std/src/sys/pal/unix/stack_overflow.rs @@ -72,7 +72,7 @@ mod imp { use crate::sync::OnceLock; use crate::sync::atomic::{Atomic, AtomicBool, AtomicPtr, AtomicUsize, Ordering}; use crate::sys::pal::unix::os; - use crate::{io, mem, panic, ptr}; + use crate::{io, mem, ptr}; // Signal handler for the SIGSEGV and SIGBUS handlers. We've got guard pages // (unmapped pages) at the end of every thread's stack, so if a thread ends diff --git a/library/std/src/sys/pal/unix/time.rs b/library/std/src/sys/pal/unix/time.rs index bd7f74fea6a..c207f41cad4 100644 --- a/library/std/src/sys/pal/unix/time.rs +++ b/library/std/src/sys/pal/unix/time.rs @@ -134,28 +134,25 @@ impl Timespec { } pub fn sub_timespec(&self, other: &Timespec) -> Result<Duration, Duration> { + // When a >= b, the difference fits in u64. + fn sub_ge_to_unsigned(a: i64, b: i64) -> u64 { + debug_assert!(a >= b); + a.wrapping_sub(b).cast_unsigned() + } + if self >= other { - // NOTE(eddyb) two aspects of this `if`-`else` are required for LLVM - // to optimize it into a branchless form (see also #75545): - // - // 1. `self.tv_sec - other.tv_sec` shows up as a common expression - // in both branches, i.e. the `else` must have its `- 1` - // subtraction after the common one, not interleaved with it - // (it used to be `self.tv_sec - 1 - other.tv_sec`) - // - // 2. the `Duration::new` call (or any other additional complexity) - // is outside of the `if`-`else`, not duplicated in both branches - // - // Ideally this code could be rearranged such that it more - // directly expresses the lower-cost behavior we want from it. let (secs, nsec) = if self.tv_nsec.as_inner() >= other.tv_nsec.as_inner() { ( - (self.tv_sec - other.tv_sec) as u64, + sub_ge_to_unsigned(self.tv_sec, other.tv_sec), self.tv_nsec.as_inner() - other.tv_nsec.as_inner(), ) } else { + // Following sequence of assertions explain why `self.tv_sec - 1` does not underflow. + debug_assert!(self.tv_nsec < other.tv_nsec); + debug_assert!(self.tv_sec > other.tv_sec); + debug_assert!(self.tv_sec > i64::MIN); ( - (self.tv_sec - other.tv_sec - 1) as u64, + sub_ge_to_unsigned(self.tv_sec - 1, other.tv_sec), self.tv_nsec.as_inner() + (NSEC_PER_SEC as u32) - other.tv_nsec.as_inner(), ) }; diff --git a/library/std/src/sys/pal/vexos/mod.rs b/library/std/src/sys/pal/vexos/mod.rs new file mode 100644 index 00000000000..61a34b0f68a --- /dev/null +++ b/library/std/src/sys/pal/vexos/mod.rs @@ -0,0 +1,80 @@ +#[path = "../unsupported/os.rs"] +pub mod os; +#[path = "../unsupported/pipe.rs"] +pub mod pipe; +pub mod time; + +#[expect(dead_code)] +#[path = "../unsupported/common.rs"] +mod unsupported_common; + +pub use unsupported_common::{ + decode_error_kind, init, is_interrupted, unsupported, unsupported_err, +}; + +use crate::arch::global_asm; +use crate::ptr; +use crate::sys::stdio; +use crate::time::{Duration, Instant}; + +global_asm!( + r#" + .section .boot, "ax" + .global _boot + + _boot: + ldr sp, =__stack_top @ Set up the user stack. + b _start @ Jump to the Rust entrypoint. + "# +); + +#[cfg(not(test))] +#[unsafe(no_mangle)] +pub unsafe extern "C" fn _start() -> ! { + unsafe extern "C" { + static mut __bss_start: u8; + static mut __bss_end: u8; + + fn main() -> i32; + } + + // Clear the .bss (uninitialized statics) section by filling it with zeroes. + // This is required, since the compiler assumes it will be zeroed on first access. + ptr::write_bytes( + &raw mut __bss_start, + 0, + (&raw mut __bss_end).offset_from_unsigned(&raw mut __bss_start), + ); + + main(); + + cleanup(); + abort_internal() +} + +// SAFETY: must be called only once during runtime cleanup. +// NOTE: this is not guaranteed to run, for example when the program aborts. +pub unsafe fn cleanup() { + let exit_time = Instant::now(); + const FLUSH_TIMEOUT: Duration = Duration::from_millis(15); + + // Force the serial buffer to flush + while exit_time.elapsed() < FLUSH_TIMEOUT { + vex_sdk::vexTasksRun(); + + // If the buffer has been fully flushed, exit the loop + if vex_sdk::vexSerialWriteFree(stdio::STDIO_CHANNEL) == (stdio::STDOUT_BUF_SIZE as i32) { + break; + } + } +} + +pub fn abort_internal() -> ! { + unsafe { + vex_sdk::vexSystemExitRequest(); + + loop { + vex_sdk::vexTasksRun(); + } + } +} diff --git a/library/std/src/sys/pal/vexos/time.rs b/library/std/src/sys/pal/vexos/time.rs new file mode 100644 index 00000000000..f95d96cd27a --- /dev/null +++ b/library/std/src/sys/pal/vexos/time.rs @@ -0,0 +1,28 @@ +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); + +impl Instant { + pub fn now() -> Instant { + let micros = unsafe { vex_sdk::vexSystemHighResTimeGet() }; + Self(Duration::from_micros(micros)) + } + + pub fn checked_sub_instant(&self, other: &Instant) -> Option<Duration> { + self.0.checked_sub(other.0) + } + + pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> { + Some(Instant(self.0.checked_add(*other)?)) + } + + pub fn checked_sub_duration(&self, other: &Duration) -> Option<Instant> { + Some(Instant(self.0.checked_sub(*other)?)) + } +} |
