about summary refs log tree commit diff
path: root/library/std/src/sys/pal
diff options
context:
space:
mode:
Diffstat (limited to 'library/std/src/sys/pal')
-rw-r--r--library/std/src/sys/pal/hermit/time.rs11
-rw-r--r--library/std/src/sys/pal/mod.rs4
-rw-r--r--library/std/src/sys/pal/unix/os.rs2
-rw-r--r--library/std/src/sys/pal/unix/stack_overflow.rs2
-rw-r--r--library/std/src/sys/pal/unix/time.rs27
-rw-r--r--library/std/src/sys/pal/vexos/mod.rs80
-rw-r--r--library/std/src/sys/pal/vexos/time.rs28
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)?))
+    }
+}