about summary refs log tree commit diff
path: root/library/std/src
diff options
context:
space:
mode:
Diffstat (limited to 'library/std/src')
-rw-r--r--library/std/src/fs.rs10
-rw-r--r--library/std/src/fs/tests.rs17
-rw-r--r--library/std/src/lib.miri.rs4
-rw-r--r--library/std/src/lib.rs15
-rw-r--r--library/std/src/os/freebsd/net.rs26
-rw-r--r--library/std/src/os/mod.rs2
-rw-r--r--library/std/src/os/netbsd/net.rs26
-rw-r--r--library/std/src/os/unix/mod.rs2
-rw-r--r--library/std/src/os/unix/net/mod.rs2
-rw-r--r--library/std/src/os/unix/net/stream.rs10
-rw-r--r--library/std/src/os/unix/net/ucred.rs16
-rw-r--r--library/std/src/os/unix/net/ucred/tests.rs2
-rw-r--r--library/std/src/os/visionos/fs.rs160
-rw-r--r--library/std/src/os/visionos/mod.rs6
-rw-r--r--library/std/src/os/visionos/raw.rs83
-rw-r--r--library/std/src/os/windows/process.rs56
-rw-r--r--library/std/src/os/xous/ffi.rs2
-rw-r--r--library/std/src/panic.rs3
-rw-r--r--library/std/src/panicking.rs21
-rw-r--r--library/std/src/pat.rs3
-rw-r--r--library/std/src/prelude/common.rs (renamed from library/std/src/prelude/v1.rs)18
-rw-r--r--library/std/src/prelude/mod.rs26
-rw-r--r--library/std/src/process.rs79
-rw-r--r--library/std/src/rt.rs15
-rw-r--r--library/std/src/sync/mutex.rs2
-rw-r--r--library/std/src/sync/once_lock.rs81
-rw-r--r--library/std/src/sync/rwlock.rs15
-rw-r--r--library/std/src/sys/pal/hermit/fd.rs5
-rw-r--r--library/std/src/sys/pal/hermit/fs.rs339
-rw-r--r--library/std/src/sys/pal/hermit/thread.rs20
-rw-r--r--library/std/src/sys/pal/hermit/time.rs10
-rw-r--r--library/std/src/sys/pal/itron/thread.rs20
-rw-r--r--library/std/src/sys/pal/mod.rs6
-rw-r--r--library/std/src/sys/pal/sgx/net.rs2
-rw-r--r--library/std/src/sys/pal/sgx/thread.rs16
-rw-r--r--library/std/src/sys/pal/teeos/thread.rs18
-rw-r--r--library/std/src/sys/pal/uefi/helpers.rs83
-rw-r--r--library/std/src/sys/pal/uefi/os.rs8
-rw-r--r--library/std/src/sys/pal/uefi/thread.rs16
-rw-r--r--library/std/src/sys/pal/unix/args.rs15
-rw-r--r--library/std/src/sys/pal/unix/env.rs11
-rw-r--r--library/std/src/sys/pal/unix/fd.rs30
-rw-r--r--library/std/src/sys/pal/unix/fs.rs91
-rw-r--r--library/std/src/sys/pal/unix/mod.rs3
-rw-r--r--library/std/src/sys/pal/unix/net.rs31
-rw-r--r--library/std/src/sys/pal/unix/os.rs13
-rw-r--r--library/std/src/sys/pal/unix/process/process_unix.rs1
-rw-r--r--library/std/src/sys/pal/unix/rand.rs21
-rw-r--r--library/std/src/sys/pal/unix/stack_overflow.rs312
-rw-r--r--library/std/src/sys/pal/unix/thread.rs362
-rw-r--r--library/std/src/sys/pal/unix/thread_local_dtor.rs10
-rw-r--r--library/std/src/sys/pal/unix/thread_parking/mod.rs1
-rw-r--r--library/std/src/sys/pal/unix/thread_parking/pthread.rs3
-rw-r--r--library/std/src/sys/pal/unix/time.rs5
-rw-r--r--library/std/src/sys/pal/unsupported/net.rs2
-rw-r--r--library/std/src/sys/pal/unsupported/process.rs150
-rw-r--r--library/std/src/sys/pal/unsupported/thread.rs16
-rw-r--r--library/std/src/sys/pal/wasi/net.rs2
-rw-r--r--library/std/src/sys/pal/wasi/thread.rs16
-rw-r--r--library/std/src/sys/pal/wasip2/cabi_realloc.rs65
-rw-r--r--library/std/src/sys/pal/wasip2/mod.rs8
-rw-r--r--library/std/src/sys/pal/wasm/atomics/thread.rs4
-rw-r--r--library/std/src/sys/pal/windows/args.rs105
-rw-r--r--library/std/src/sys/pal/windows/stack_overflow.rs30
-rw-r--r--library/std/src/sys/pal/windows/stack_overflow_uwp.rs9
-rw-r--r--library/std/src/sys/pal/windows/thread.rs40
-rw-r--r--library/std/src/sys/pal/xous/thread.rs16
-rw-r--r--library/std/src/sys/pal/xous/thread_local_key.rs2
-rw-r--r--library/std/src/sys/pal/zkvm/thread_local_key.rs4
-rw-r--r--library/std/src/sys/personality/dwarf/eh.rs2
-rw-r--r--library/std/src/sys/personality/gcc.rs2
-rw-r--r--library/std/src/sys/sync/condvar/pthread.rs3
-rw-r--r--library/std/src/sys/sync/rwlock/queue.rs6
-rw-r--r--library/std/src/sys_common/mod.rs1
-rw-r--r--library/std/src/sys_common/net.rs6
-rw-r--r--library/std/src/sys_common/thread_info.rs53
-rw-r--r--library/std/src/sys_common/thread_local_key.rs5
-rw-r--r--library/std/src/thread/mod.rs59
-rw-r--r--library/std/src/thread/tests.rs23
79 files changed, 1835 insertions, 948 deletions
diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs
index 5d0de2d06a0..b1102b440e0 100644
--- a/library/std/src/fs.rs
+++ b/library/std/src/fs.rs
@@ -37,7 +37,7 @@ use crate::time::SystemTime;
 ///
 /// # Examples
 ///
-/// Creates a new file and write bytes to it (you can also use [`write()`]):
+/// Creates a new file and write bytes to it (you can also use [`write`]):
 ///
 /// ```no_run
 /// use std::fs::File;
@@ -97,7 +97,7 @@ use crate::time::SystemTime;
 /// have been opened for asynchronous I/O (e.g. by using `FILE_FLAG_OVERLAPPED`).
 ///
 /// [`BufReader`]: io::BufReader
-/// [`BufWriter`]: io::BufReader
+/// [`BufWriter`]: io::BufWriter
 /// [`sync_all`]: File::sync_all
 /// [`write`]: File::write
 /// [`read`]: File::read
@@ -385,7 +385,7 @@ impl File {
     /// See the [`OpenOptions::open`] function for more details.
     ///
     /// See also [`std::fs::write()`][self::write] for a simple function to
-    /// create a file with a given data.
+    /// create a file with some given data.
     ///
     /// # Examples
     ///
@@ -1036,7 +1036,7 @@ impl OpenOptions {
     /// [`OpenOptions::append`] access must be used.
     ///
     /// See also [`std::fs::write()`][self::write] for a simple function to
-    /// create a file with a given data.
+    /// create a file with some given data.
     ///
     /// # Examples
     ///
@@ -2018,7 +2018,7 @@ pub fn rename<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> io::Result<()>
 /// the length of the `to` file as reported by `metadata`.
 ///
 /// If you want to copy the contents of one file to another and you’re
-/// working with [`File`]s, see the [`io::copy()`] function.
+/// working with [`File`]s, see the [`io::copy`](io::copy()) function.
 ///
 /// # Platform-specific behavior
 ///
diff --git a/library/std/src/fs/tests.rs b/library/std/src/fs/tests.rs
index 65dec3863cc..6a92832fcdb 100644
--- a/library/std/src/fs/tests.rs
+++ b/library/std/src/fs/tests.rs
@@ -1644,8 +1644,8 @@ fn test_file_times() {
     use crate::os::macos::fs::FileTimesExt;
     #[cfg(target_os = "tvos")]
     use crate::os::tvos::fs::FileTimesExt;
-    #[cfg(target_os = "tvos")]
-    use crate::os::tvos::fs::FileTimesExt;
+    #[cfg(target_os = "visionos")]
+    use crate::os::visionos::fs::FileTimesExt;
     #[cfg(target_os = "watchos")]
     use crate::os::watchos::fs::FileTimesExt;
     #[cfg(windows)]
@@ -1662,6 +1662,7 @@ fn test_file_times() {
         target_os = "macos",
         target_os = "ios",
         target_os = "watchos",
+        target_os = "visionos",
         target_os = "tvos",
     ))]
     let created = SystemTime::UNIX_EPOCH + Duration::from_secs(32123);
@@ -1670,6 +1671,7 @@ fn test_file_times() {
         target_os = "macos",
         target_os = "ios",
         target_os = "watchos",
+        target_os = "visionos",
         target_os = "tvos",
     ))]
     {
@@ -1701,6 +1703,7 @@ fn test_file_times() {
         target_os = "macos",
         target_os = "ios",
         target_os = "watchos",
+        target_os = "visionos",
         target_os = "tvos",
     ))]
     {
@@ -1709,7 +1712,13 @@ fn test_file_times() {
 }
 
 #[test]
-#[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "watchos"))]
+#[cfg(any(
+    target_os = "macos",
+    target_os = "ios",
+    target_os = "tvos",
+    target_os = "watchos",
+    target_os = "visionos"
+))]
 fn test_file_times_pre_epoch_with_nanos() {
     #[cfg(target_os = "ios")]
     use crate::os::ios::fs::FileTimesExt;
@@ -1717,6 +1726,8 @@ fn test_file_times_pre_epoch_with_nanos() {
     use crate::os::macos::fs::FileTimesExt;
     #[cfg(target_os = "tvos")]
     use crate::os::tvos::fs::FileTimesExt;
+    #[cfg(target_os = "visionos")]
+    use crate::os::visionos::fs::FileTimesExt;
     #[cfg(target_os = "watchos")]
     use crate::os::watchos::fs::FileTimesExt;
 
diff --git a/library/std/src/lib.miri.rs b/library/std/src/lib.miri.rs
new file mode 100644
index 00000000000..1f9bfb5b1b5
--- /dev/null
+++ b/library/std/src/lib.miri.rs
@@ -0,0 +1,4 @@
+//! Grep bootstrap for `MIRI_REPLACE_LIBRS_IF_NOT_TEST` to learn what this is about.
+#![no_std]
+extern crate std as realstd;
+pub use realstd::*;
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index c457c39e0c1..c713eefc72c 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -212,15 +212,10 @@
 //! [rust-discord]: https://discord.gg/rust-lang
 //! [array]: prim@array
 //! [slice]: prim@slice
-// To run std tests without x.py without ending up with two copies of std, Miri needs to be
-// able to "empty" this crate. See <https://github.com/rust-lang/miri-test-libstd/issues/4>.
-// rustc itself never sets the feature, so this line has no effect there.
-#![cfg(any(not(feature = "miri-test-libstd"), test, doctest))]
-// miri-test-libstd also prefers to make std use the sysroot versions of the dependencies.
-#![cfg_attr(feature = "miri-test-libstd", feature(rustc_private))]
-//
+
 #![cfg_attr(not(feature = "restricted-std"), stable(feature = "rust1", since = "1.0.0"))]
 #![cfg_attr(feature = "restricted-std", unstable(feature = "restricted_std", issue = "none"))]
+#![cfg_attr(not(bootstrap), rustc_preserve_ub_checks)]
 #![doc(
     html_playground_url = "https://play.rust-lang.org/",
     issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/",
@@ -328,6 +323,7 @@
 #![feature(float_gamma)]
 #![feature(float_minimum_maximum)]
 #![feature(float_next_up_down)]
+#![feature(fmt_internals)]
 #![feature(generic_nonzero)]
 #![feature(hasher_prefixfree_extras)]
 #![feature(hashmap_internals)]
@@ -339,7 +335,7 @@
 #![feature(panic_can_unwind)]
 #![feature(panic_info_message)]
 #![feature(panic_internals)]
-#![feature(pointer_is_aligned)]
+#![feature(pointer_is_aligned_to)]
 #![feature(portable_simd)]
 #![feature(prelude_2024)]
 #![feature(ptr_as_uninit)]
@@ -580,6 +576,9 @@ pub mod net;
 pub mod num;
 pub mod os;
 pub mod panic;
+#[cfg(not(bootstrap))]
+#[unstable(feature = "core_pattern_types", issue = "none")]
+pub mod pat;
 pub mod path;
 pub mod process;
 pub mod sync;
diff --git a/library/std/src/os/freebsd/net.rs b/library/std/src/os/freebsd/net.rs
index 33990d54caa..b7e0fdc0a9a 100644
--- a/library/std/src/os/freebsd/net.rs
+++ b/library/std/src/os/freebsd/net.rs
@@ -2,6 +2,7 @@
 
 #![unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
 
+use crate::ffi::CStr;
 use crate::io;
 use crate::os::unix::net;
 use crate::sealed::Sealed;
@@ -40,6 +41,15 @@ pub trait UnixSocketExt: Sealed {
     /// ```
     #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
     fn set_local_creds_persistent(&self, local_creds_persistent: bool) -> io::Result<()>;
+
+    /// Get a filter name if one had been set previously on the socket.
+    #[unstable(feature = "acceptfilter", issue = "121891")]
+    fn acceptfilter(&self) -> io::Result<&CStr>;
+
+    /// Set or disable a filter on the socket to filter incoming connections
+    /// to defer it before accept(2)
+    #[unstable(feature = "acceptfilter", issue = "121891")]
+    fn set_acceptfilter(&self, name: &CStr) -> io::Result<()>;
 }
 
 #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
@@ -51,6 +61,14 @@ impl UnixSocketExt for net::UnixDatagram {
     fn set_local_creds_persistent(&self, local_creds_persistent: bool) -> io::Result<()> {
         self.as_inner().set_local_creds_persistent(local_creds_persistent)
     }
+
+    fn acceptfilter(&self) -> io::Result<&CStr> {
+        self.as_inner().acceptfilter()
+    }
+
+    fn set_acceptfilter(&self, name: &CStr) -> io::Result<()> {
+        self.as_inner().set_acceptfilter(name)
+    }
 }
 
 #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
@@ -62,4 +80,12 @@ impl UnixSocketExt for net::UnixStream {
     fn set_local_creds_persistent(&self, local_creds_persistent: bool) -> io::Result<()> {
         self.as_inner().set_local_creds_persistent(local_creds_persistent)
     }
+
+    fn acceptfilter(&self) -> io::Result<&CStr> {
+        self.as_inner().acceptfilter()
+    }
+
+    fn set_acceptfilter(&self, name: &CStr) -> io::Result<()> {
+        self.as_inner().set_acceptfilter(name)
+    }
 }
diff --git a/library/std/src/os/mod.rs b/library/std/src/os/mod.rs
index bebf3a797d8..ca3584e82f9 100644
--- a/library/std/src/os/mod.rs
+++ b/library/std/src/os/mod.rs
@@ -149,6 +149,8 @@ pub mod solid;
 pub(crate) mod tvos;
 #[cfg(target_os = "uefi")]
 pub mod uefi;
+#[cfg(target_os = "visionos")]
+pub(crate) mod visionos;
 #[cfg(target_os = "vita")]
 pub mod vita;
 #[cfg(target_os = "vxworks")]
diff --git a/library/std/src/os/netbsd/net.rs b/library/std/src/os/netbsd/net.rs
index 5c82f43077d..b9679c7b3af 100644
--- a/library/std/src/os/netbsd/net.rs
+++ b/library/std/src/os/netbsd/net.rs
@@ -2,6 +2,7 @@
 
 #![unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
 
+use crate::ffi::CStr;
 use crate::io;
 use crate::os::unix::net;
 use crate::sealed::Sealed;
@@ -40,6 +41,15 @@ pub trait UnixSocketExt: Sealed {
     /// ```
     #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
     fn set_local_creds(&self, local_creds: bool) -> io::Result<()>;
+
+    /// Get a filter name if one had been set previously on the socket.
+    #[unstable(feature = "acceptfilter", issue = "121891")]
+    fn acceptfilter(&self) -> io::Result<&CStr>;
+
+    /// Set or disable a filter on the socket to filter incoming connections
+    /// to defer it before accept(2)
+    #[unstable(feature = "acceptfilter", issue = "121891")]
+    fn set_acceptfilter(&self, name: &CStr) -> io::Result<()>;
 }
 
 #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
@@ -51,6 +61,14 @@ impl UnixSocketExt for net::UnixDatagram {
     fn set_local_creds(&self, local_creds: bool) -> io::Result<()> {
         self.as_inner().set_local_creds(local_creds)
     }
+
+    fn acceptfilter(&self) -> io::Result<&CStr> {
+        self.as_inner().acceptfilter()
+    }
+
+    fn set_acceptfilter(&self, name: &CStr) -> io::Result<()> {
+        self.as_inner().set_acceptfilter(name)
+    }
 }
 
 #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
@@ -62,4 +80,12 @@ impl UnixSocketExt for net::UnixStream {
     fn set_local_creds(&self, local_creds: bool) -> io::Result<()> {
         self.as_inner().set_local_creds(local_creds)
     }
+
+    fn acceptfilter(&self) -> io::Result<&CStr> {
+        self.as_inner().acceptfilter()
+    }
+
+    fn set_acceptfilter(&self, name: &CStr) -> io::Result<()> {
+        self.as_inner().set_acceptfilter(name)
+    }
 }
diff --git a/library/std/src/os/unix/mod.rs b/library/std/src/os/unix/mod.rs
index b0633fd7bfc..d7a622012a5 100644
--- a/library/std/src/os/unix/mod.rs
+++ b/library/std/src/os/unix/mod.rs
@@ -79,6 +79,8 @@ mod platform {
     pub use crate::os::solaris::*;
     #[cfg(target_os = "tvos")]
     pub use crate::os::tvos::*;
+    #[cfg(target_os = "visionos")]
+    pub use crate::os::visionos::*;
     #[cfg(target_os = "vita")]
     pub use crate::os::vita::*;
     #[cfg(target_os = "vxworks")]
diff --git a/library/std/src/os/unix/net/mod.rs b/library/std/src/os/unix/net/mod.rs
index 28c1188677b..16d9cd915ac 100644
--- a/library/std/src/os/unix/net/mod.rs
+++ b/library/std/src/os/unix/net/mod.rs
@@ -20,6 +20,7 @@ mod tests;
     target_os = "ios",
     target_os = "tvos",
     target_os = "watchos",
+    target_os = "visionos",
     target_os = "macos",
     target_os = "netbsd",
     target_os = "openbsd",
@@ -46,6 +47,7 @@ pub use self::stream::*;
     target_os = "ios",
     target_os = "tvos",
     target_os = "watchos",
+    target_os = "visionos",
     target_os = "macos",
     target_os = "netbsd",
     target_os = "openbsd",
diff --git a/library/std/src/os/unix/net/stream.rs b/library/std/src/os/unix/net/stream.rs
index d67493aaf4d..82b24dca1c4 100644
--- a/library/std/src/os/unix/net/stream.rs
+++ b/library/std/src/os/unix/net/stream.rs
@@ -7,6 +7,7 @@
     target_os = "tvos",
     target_os = "macos",
     target_os = "watchos",
+    target_os = "visionos",
     target_os = "netbsd",
     target_os = "openbsd",
     target_os = "nto"
@@ -234,6 +235,7 @@ impl UnixStream {
         target_os = "tvos",
         target_os = "macos",
         target_os = "watchos",
+        target_os = "visionos",
         target_os = "netbsd",
         target_os = "openbsd",
         target_os = "nto"
@@ -580,6 +582,10 @@ impl io::Read for UnixStream {
         io::Read::read(&mut &*self, buf)
     }
 
+    fn read_buf(&mut self, buf: io::BorrowedCursor<'_>) -> io::Result<()> {
+        io::Read::read_buf(&mut &*self, buf)
+    }
+
     fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
         io::Read::read_vectored(&mut &*self, bufs)
     }
@@ -596,6 +602,10 @@ impl<'a> io::Read for &'a UnixStream {
         self.0.read(buf)
     }
 
+    fn read_buf(&mut self, buf: io::BorrowedCursor<'_>) -> io::Result<()> {
+        self.0.read_buf(buf)
+    }
+
     fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
         self.0.read_vectored(bufs)
     }
diff --git a/library/std/src/os/unix/net/ucred.rs b/library/std/src/os/unix/net/ucred.rs
index 4c915c57906..3a752a53a50 100644
--- a/library/std/src/os/unix/net/ucred.rs
+++ b/library/std/src/os/unix/net/ucred.rs
@@ -35,7 +35,13 @@ pub(super) use self::impl_linux::peer_cred;
 ))]
 pub(super) use self::impl_bsd::peer_cred;
 
-#[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "watchos"))]
+#[cfg(any(
+    target_os = "macos",
+    target_os = "ios",
+    target_os = "tvos",
+    target_os = "watchos",
+    target_os = "visionos"
+))]
 pub(super) use self::impl_mac::peer_cred;
 
 #[cfg(any(target_os = "linux", target_os = "android"))]
@@ -97,7 +103,13 @@ mod impl_bsd {
     }
 }
 
-#[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "watchos"))]
+#[cfg(any(
+    target_os = "macos",
+    target_os = "ios",
+    target_os = "tvos",
+    target_os = "watchos",
+    target_os = "visionos"
+))]
 mod impl_mac {
     use super::UCred;
     use crate::os::unix::io::AsRawFd;
diff --git a/library/std/src/os/unix/net/ucred/tests.rs b/library/std/src/os/unix/net/ucred/tests.rs
index dd99ecdd819..2a0797877c6 100644
--- a/library/std/src/os/unix/net/ucred/tests.rs
+++ b/library/std/src/os/unix/net/ucred/tests.rs
@@ -11,6 +11,7 @@ use libc::{getegid, geteuid, getpid};
     target_os = "tvos",
     target_os = "macos",
     target_os = "watchos",
+    target_os = "visionos",
     target_os = "openbsd"
 ))]
 fn test_socket_pair() {
@@ -32,6 +33,7 @@ fn test_socket_pair() {
     target_os = "ios",
     target_os = "macos",
     target_os = "watchos",
+    target_os = "visionos",
     target_os = "tvos",
 ))]
 fn test_socket_pair_pids(arg: Type) -> RetType {
diff --git a/library/std/src/os/visionos/fs.rs b/library/std/src/os/visionos/fs.rs
new file mode 100644
index 00000000000..e5df4de0b7f
--- /dev/null
+++ b/library/std/src/os/visionos/fs.rs
@@ -0,0 +1,160 @@
+#![stable(feature = "metadata_ext", since = "1.1.0")]
+
+use crate::fs::{self, Metadata};
+use crate::sealed::Sealed;
+use crate::sys_common::{AsInner, AsInnerMut, IntoInner};
+use crate::time::SystemTime;
+
+#[allow(deprecated)]
+use super::raw;
+
+/// OS-specific extensions to [`fs::Metadata`].
+///
+/// [`fs::Metadata`]: crate::fs::Metadata
+#[stable(feature = "metadata_ext", since = "1.1.0")]
+pub trait MetadataExt {
+    /// Gain a reference to the underlying `stat` structure which contains
+    /// the raw information returned by the OS.
+    ///
+    /// The contents of the returned `stat` are **not** consistent across
+    /// Unix platforms. The `os::unix::fs::MetadataExt` trait contains the
+    /// cross-Unix abstractions contained within the raw stat.
+    #[stable(feature = "metadata_ext", since = "1.1.0")]
+    #[deprecated(
+        since = "1.8.0",
+        note = "deprecated in favor of the accessor \
+                methods of this trait"
+    )]
+    #[allow(deprecated)]
+    fn as_raw_stat(&self) -> &raw::stat;
+
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_dev(&self) -> u64;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_ino(&self) -> u64;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_mode(&self) -> u32;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_nlink(&self) -> u64;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_uid(&self) -> u32;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_gid(&self) -> u32;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_rdev(&self) -> u64;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_size(&self) -> u64;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_atime(&self) -> i64;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_atime_nsec(&self) -> i64;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_mtime(&self) -> i64;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_mtime_nsec(&self) -> i64;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_ctime(&self) -> i64;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_ctime_nsec(&self) -> i64;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_birthtime(&self) -> i64;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_birthtime_nsec(&self) -> i64;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_blksize(&self) -> u64;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_blocks(&self) -> u64;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_flags(&self) -> u32;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_gen(&self) -> u32;
+    #[stable(feature = "metadata_ext2", since = "1.8.0")]
+    fn st_lspare(&self) -> u32;
+}
+
+#[stable(feature = "metadata_ext", since = "1.1.0")]
+impl MetadataExt for Metadata {
+    #[allow(deprecated)]
+    fn as_raw_stat(&self) -> &raw::stat {
+        unsafe { &*(self.as_inner().as_inner() as *const libc::stat as *const raw::stat) }
+    }
+    fn st_dev(&self) -> u64 {
+        self.as_inner().as_inner().st_dev as u64
+    }
+    fn st_ino(&self) -> u64 {
+        self.as_inner().as_inner().st_ino as u64
+    }
+    fn st_mode(&self) -> u32 {
+        self.as_inner().as_inner().st_mode as u32
+    }
+    fn st_nlink(&self) -> u64 {
+        self.as_inner().as_inner().st_nlink as u64
+    }
+    fn st_uid(&self) -> u32 {
+        self.as_inner().as_inner().st_uid as u32
+    }
+    fn st_gid(&self) -> u32 {
+        self.as_inner().as_inner().st_gid as u32
+    }
+    fn st_rdev(&self) -> u64 {
+        self.as_inner().as_inner().st_rdev as u64
+    }
+    fn st_size(&self) -> u64 {
+        self.as_inner().as_inner().st_size as u64
+    }
+    fn st_atime(&self) -> i64 {
+        self.as_inner().as_inner().st_atime as i64
+    }
+    fn st_atime_nsec(&self) -> i64 {
+        self.as_inner().as_inner().st_atime_nsec as i64
+    }
+    fn st_mtime(&self) -> i64 {
+        self.as_inner().as_inner().st_mtime as i64
+    }
+    fn st_mtime_nsec(&self) -> i64 {
+        self.as_inner().as_inner().st_mtime_nsec as i64
+    }
+    fn st_ctime(&self) -> i64 {
+        self.as_inner().as_inner().st_ctime as i64
+    }
+    fn st_ctime_nsec(&self) -> i64 {
+        self.as_inner().as_inner().st_ctime_nsec as i64
+    }
+    fn st_birthtime(&self) -> i64 {
+        self.as_inner().as_inner().st_birthtime as i64
+    }
+    fn st_birthtime_nsec(&self) -> i64 {
+        self.as_inner().as_inner().st_birthtime_nsec as i64
+    }
+    fn st_blksize(&self) -> u64 {
+        self.as_inner().as_inner().st_blksize as u64
+    }
+    fn st_blocks(&self) -> u64 {
+        self.as_inner().as_inner().st_blocks as u64
+    }
+    fn st_gen(&self) -> u32 {
+        self.as_inner().as_inner().st_gen as u32
+    }
+    fn st_flags(&self) -> u32 {
+        self.as_inner().as_inner().st_flags as u32
+    }
+    fn st_lspare(&self) -> u32 {
+        self.as_inner().as_inner().st_lspare as u32
+    }
+}
+
+/// OS-specific extensions to [`fs::FileTimes`].
+#[stable(feature = "file_set_times", since = "1.75.0")]
+pub trait FileTimesExt: Sealed {
+    /// Set the creation time of a file.
+    #[stable(feature = "file_set_times", since = "1.75.0")]
+    fn set_created(self, t: SystemTime) -> Self;
+}
+
+#[stable(feature = "file_set_times", since = "1.75.0")]
+impl FileTimesExt for fs::FileTimes {
+    fn set_created(mut self, t: SystemTime) -> Self {
+        self.as_inner_mut().set_created(t.into_inner());
+        self
+    }
+}
diff --git a/library/std/src/os/visionos/mod.rs b/library/std/src/os/visionos/mod.rs
new file mode 100644
index 00000000000..f4b061ffda8
--- /dev/null
+++ b/library/std/src/os/visionos/mod.rs
@@ -0,0 +1,6 @@
+//! visionos-specific definitions
+
+#![stable(feature = "raw_ext", since = "1.1.0")]
+
+pub mod fs;
+pub mod raw;
diff --git a/library/std/src/os/visionos/raw.rs b/library/std/src/os/visionos/raw.rs
new file mode 100644
index 00000000000..2b3eca6f493
--- /dev/null
+++ b/library/std/src/os/visionos/raw.rs
@@ -0,0 +1,83 @@
+//! visionos-specific raw type definitions
+
+#![stable(feature = "raw_ext", since = "1.1.0")]
+#![deprecated(
+    since = "1.8.0",
+    note = "these type aliases are no longer supported by \
+            the standard library, the `libc` crate on \
+            crates.io should be used instead for the correct \
+            definitions"
+)]
+#![allow(deprecated)]
+
+use crate::os::raw::c_long;
+
+#[stable(feature = "raw_ext", since = "1.1.0")]
+pub type blkcnt_t = u64;
+#[stable(feature = "raw_ext", since = "1.1.0")]
+pub type blksize_t = u64;
+#[stable(feature = "raw_ext", since = "1.1.0")]
+pub type dev_t = u64;
+#[stable(feature = "raw_ext", since = "1.1.0")]
+pub type ino_t = u64;
+#[stable(feature = "raw_ext", since = "1.1.0")]
+pub type mode_t = u32;
+#[stable(feature = "raw_ext", since = "1.1.0")]
+pub type nlink_t = u64;
+#[stable(feature = "raw_ext", since = "1.1.0")]
+pub type off_t = u64;
+#[stable(feature = "raw_ext", since = "1.1.0")]
+pub type time_t = i64;
+
+#[stable(feature = "pthread_t", since = "1.8.0")]
+pub type pthread_t = usize;
+
+#[repr(C)]
+#[derive(Clone)]
+#[stable(feature = "raw_ext", since = "1.1.0")]
+pub struct stat {
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_dev: i32,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_mode: u16,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_nlink: u16,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_ino: u64,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_uid: u32,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_gid: u32,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_rdev: i32,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_atime: c_long,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_atime_nsec: c_long,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_mtime: c_long,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_mtime_nsec: c_long,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_ctime: c_long,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_ctime_nsec: c_long,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_birthtime: c_long,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_birthtime_nsec: c_long,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_size: i64,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_blocks: i64,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_blksize: i32,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_flags: u32,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_gen: u32,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_lspare: i32,
+    #[stable(feature = "raw_ext", since = "1.1.0")]
+    pub st_qspare: [i64; 2],
+}
diff --git a/library/std/src/os/windows/process.rs b/library/std/src/os/windows/process.rs
index 1be3acf5d43..15ab2250122 100644
--- a/library/std/src/os/windows/process.rs
+++ b/library/std/src/os/windows/process.rs
@@ -199,8 +199,60 @@ pub trait CommandExt: Sealed {
 
     /// Append literal text to the command line without any quoting or escaping.
     ///
-    /// This is useful for passing arguments to `cmd.exe /c`, which doesn't follow
-    /// `CommandLineToArgvW` escaping rules.
+    /// This is useful for passing arguments to applications which doesn't follow
+    /// the standard C run-time escaping rules, such as `cmd.exe /c`.
+    ///
+    /// # Bat files
+    ///
+    /// Note the `cmd /c` command line has slightly different escaping rules then bat files
+    /// themselves. If possible, it may be better to write complex arguments to a temporary
+    /// .bat file, with appropriate escaping, and simply run that using:
+    ///
+    /// ```no_run
+    /// # use std::process::Command;
+    /// # let temp_bat_file = "";
+    /// # #[allow(unused)]
+    /// let output = Command::new("cmd").args(["/c", &format!("\"{temp_bat_file}\"")]).output();
+    /// ```
+    ///
+    /// # Example
+    ///
+    /// Run a bat script using both trusted and untrusted arguments.
+    ///
+    /// ```no_run
+    /// #[cfg(windows)]
+    /// // `my_script_path` is a path to known bat file.
+    /// // `user_name` is an untrusted name given by the user.
+    /// fn run_script(
+    ///     my_script_path: &str,
+    ///     user_name: &str,
+    /// ) -> Result<std::process::Output, std::io::Error> {
+    ///     use std::io::{Error, ErrorKind};
+    ///     use std::os::windows::process::CommandExt;
+    ///     use std::process::Command;
+    ///
+    ///     // Create the command line, making sure to quote the script path.
+    ///     // This assumes the fixed arguments have been tested to work with the script we're using.
+    ///     let mut cmd_args = format!(r#""{my_script_path}" "--features=[a,b,c]""#);
+    ///
+    ///     // Make sure the user name is safe. In particular we need to be
+    ///     // cautious of ascii symbols that cmd may interpret specially.
+    ///     // Here we only allow alphanumeric characters.
+    ///     if !user_name.chars().all(|c| c.is_alphanumeric()) {
+    ///         return Err(Error::new(ErrorKind::InvalidInput, "invalid user name"));
+    ///     }
+    ///     // now we've checked the user name, let's add that too.
+    ///     cmd_args.push(' ');
+    ///     cmd_args.push_str(&format!("--user {user_name}"));
+    ///
+    ///     // call cmd.exe and return the output
+    ///     Command::new("cmd.exe")
+    ///         .arg("/c")
+    ///         // surround the entire command in an extra pair of quotes, as required by cmd.exe.
+    ///         .raw_arg(&format!("\"{cmd_args}\""))
+    ///         .output()
+    /// }
+    /// ````
     #[stable(feature = "windows_process_extensions_raw_arg", since = "1.62.0")]
     fn raw_arg<S: AsRef<OsStr>>(&mut self, text_to_append_as_is: S) -> &mut process::Command;
 
diff --git a/library/std/src/os/xous/ffi.rs b/library/std/src/os/xous/ffi.rs
index 7fe84db515c..e9a9f533720 100644
--- a/library/std/src/os/xous/ffi.rs
+++ b/library/std/src/os/xous/ffi.rs
@@ -389,7 +389,7 @@ pub(crate) unsafe fn map_memory<T>(
     let result = a0;
 
     if result == SyscallResult::MemoryRange as usize {
-        let start = core::ptr::from_exposed_addr_mut::<T>(a1);
+        let start = core::ptr::with_exposed_provenance_mut::<T>(a1);
         let len = a2 / core::mem::size_of::<T>();
         let end = unsafe { start.add(len) };
         Ok(unsafe { core::slice::from_raw_parts_mut(start, len) })
diff --git a/library/std/src/panic.rs b/library/std/src/panic.rs
index 3d576af681e..e63b46ab705 100644
--- a/library/std/src/panic.rs
+++ b/library/std/src/panic.rs
@@ -126,6 +126,9 @@ where
 /// Also note that unwinding into Rust code with a foreign exception (e.g.
 /// an exception thrown from C++ code) is undefined behavior.
 ///
+/// Finally, be **careful in how you drop the result of this function**.
+/// If it is `Err`, it contains the panic payload, and dropping that may in turn panic!
+///
 /// # Examples
 ///
 /// ```
diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs
index b0bcab7994c..f46e1e171d2 100644
--- a/library/std/src/panicking.rs
+++ b/library/std/src/panicking.rs
@@ -21,7 +21,6 @@ use crate::sync::atomic::{AtomicBool, Ordering};
 use crate::sync::{PoisonError, RwLock};
 use crate::sys::stdio::panic_output;
 use crate::sys_common::backtrace;
-use crate::sys_common::thread_info;
 use crate::thread;
 
 #[cfg(not(test))]
@@ -256,7 +255,7 @@ fn default_hook(info: &PanicInfo<'_>) {
             None => "Box<dyn Any>",
         },
     };
-    let thread = thread_info::current_thread();
+    let thread = thread::try_current();
     let name = thread.as_ref().and_then(|t| t.name()).unwrap_or("<unnamed>");
 
     let write = |err: &mut dyn crate::io::Write| {
@@ -391,6 +390,7 @@ pub mod panic_count {
     pub fn increase(run_panic_hook: bool) -> Option<MustAbort> {
         let global_count = GLOBAL_PANIC_COUNT.fetch_add(1, Ordering::Relaxed);
         if global_count & ALWAYS_ABORT_FLAG != 0 {
+            // Do *not* access thread-local state, we might be after a `fork`.
             return Some(MustAbort::AlwaysAbort);
         }
 
@@ -744,13 +744,22 @@ fn rust_panic_with_hook(
     if let Some(must_abort) = must_abort {
         match must_abort {
             panic_count::MustAbort::PanicInHook => {
-                // Don't try to print the message in this case
-                // - perhaps that is causing the recursive panics.
-                rtprintpanic!("thread panicked while processing panic. aborting.\n");
+                // Don't try to format the message in this case, perhaps that is causing the
+                // recursive panics. However if the message is just a string, no user-defined
+                // code is involved in printing it, so that is risk-free.
+                let msg_str = message.and_then(|m| m.as_str()).map(|m| [m]);
+                let message = msg_str.as_ref().map(|m| fmt::Arguments::new_const(m));
+                let panicinfo = PanicInfo::internal_constructor(
+                    message.as_ref(),
+                    location,
+                    can_unwind,
+                    force_no_backtrace,
+                );
+                rtprintpanic!("{panicinfo}\nthread panicked while processing panic. aborting.\n");
             }
             panic_count::MustAbort::AlwaysAbort => {
                 // Unfortunately, this does not print a backtrace, because creating
-                // a `Backtrace` will allocate, which we must to avoid here.
+                // a `Backtrace` will allocate, which we must avoid here.
                 let panicinfo = PanicInfo::internal_constructor(
                     message,
                     location,
diff --git a/library/std/src/pat.rs b/library/std/src/pat.rs
new file mode 100644
index 00000000000..aeddd84c2cb
--- /dev/null
+++ b/library/std/src/pat.rs
@@ -0,0 +1,3 @@
+//! Helper module for exporting the `pattern_type` macro
+
+pub use core::pattern_type;
diff --git a/library/std/src/prelude/v1.rs b/library/std/src/prelude/common.rs
index 7a7a7737635..f61e04e02b6 100644
--- a/library/std/src/prelude/v1.rs
+++ b/library/std/src/prelude/common.rs
@@ -1,9 +1,7 @@
-//! The first version of the prelude of The Rust Standard Library.
+//! Items common to the prelude of all editions.
 //!
 //! See the [module-level documentation](super) for more.
 
-#![stable(feature = "rust1", since = "1.0.0")]
-
 // Re-exported core operators
 #[stable(feature = "rust1", since = "1.0.0")]
 #[doc(no_inline)]
@@ -52,11 +50,6 @@ pub use core::prelude::v1::{
 #[doc(no_inline)]
 pub use core::prelude::v1::concat_bytes;
 
-// Do not `doc(inline)` these `doc(hidden)` items.
-#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
-#[allow(deprecated)]
-pub use core::prelude::v1::{RustcDecodable, RustcEncodable};
-
 // Do not `doc(no_inline)` so that they become doc items on their own
 // (no public module for them to be re-exported from).
 #[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
@@ -91,6 +84,15 @@ pub use core::prelude::v1::cfg_eval;
 )]
 pub use core::prelude::v1::type_ascribe;
 
+#[cfg(not(bootstrap))]
+// Do not `doc(no_inline)` either.
+#[unstable(
+    feature = "deref_patterns",
+    issue = "87121",
+    reason = "placeholder syntax for deref patterns"
+)]
+pub use core::prelude::v1::deref;
+
 // The file so far is equivalent to core/src/prelude/v1.rs. It is duplicated
 // rather than glob imported because we want docs to show these re-exports as
 // pointing to within `std`.
diff --git a/library/std/src/prelude/mod.rs b/library/std/src/prelude/mod.rs
index 7d44d2e4b5d..0bdbab716ad 100644
--- a/library/std/src/prelude/mod.rs
+++ b/library/std/src/prelude/mod.rs
@@ -93,7 +93,26 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
-pub mod v1;
+mod common;
+
+/// The first version of the prelude of The Rust Standard Library.
+///
+/// See the [module-level documentation](self) for more.
+#[stable(feature = "rust1", since = "1.0.0")]
+pub mod v1 {
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub use super::common::*;
+
+    // Do not `doc(inline)` these `doc(hidden)` items.
+    #[unstable(
+        feature = "rustc_encodable_decodable",
+        issue = "none",
+        soft,
+        reason = "derive macro for `rustc-serialize`; should not be used in new code"
+    )]
+    #[allow(deprecated)]
+    pub use core::prelude::v1::{RustcDecodable, RustcEncodable};
+}
 
 /// The 2015 version of the prelude of The Rust Standard Library.
 ///
@@ -134,9 +153,8 @@ pub mod rust_2021 {
 /// See the [module-level documentation](self) for more.
 #[unstable(feature = "prelude_2024", issue = "121042")]
 pub mod rust_2024 {
-    #[unstable(feature = "prelude_2024", issue = "121042")]
-    #[doc(no_inline)]
-    pub use super::v1::*;
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub use super::common::*;
 
     #[unstable(feature = "prelude_2024", issue = "121042")]
     #[doc(no_inline)]
diff --git a/library/std/src/process.rs b/library/std/src/process.rs
index b84d5f11954..69cc61b30ef 100644
--- a/library/std/src/process.rs
+++ b/library/std/src/process.rs
@@ -88,6 +88,47 @@
 //! assert_eq!(b"test", output.stdout.as_slice());
 //! ```
 //!
+//! # Windows argument splitting
+//!
+//! On Unix systems arguments are passed to a new process as an array of strings
+//! but on Windows arguments are passed as a single commandline string and it's
+//! up to the child process to parse it into an array. Therefore the parent and
+//! child processes must agree on how the commandline string is encoded.
+//!
+//! Most programs use the standard C run-time `argv`, which in practice results
+//! in consistent argument handling. However some programs have their own way of
+//! parsing the commandline string. In these cases using [`arg`] or [`args`] may
+//! result in the child process seeing a different array of arguments then the
+//! parent process intended.
+//!
+//! Two ways of mitigating this are:
+//!
+//! * Validate untrusted input so that only a safe subset is allowed.
+//! * Use [`raw_arg`] to build a custom commandline. This bypasses the escaping
+//!   rules used by [`arg`] so should be used with due caution.
+//!
+//! `cmd.exe` and `.bat` use non-standard argument parsing and are especially
+//! vulnerable to malicious input as they may be used to run arbitrary shell
+//! commands. Untrusted arguments should be restricted as much as possible.
+//! For examples on handling this see [`raw_arg`].
+//!
+//! ### Bat file special handling
+//!
+//! On Windows, `Command` uses the Windows API function [`CreateProcessW`] to
+//! spawn new processes. An undocumented feature of this function is that,
+//! when given a `.bat` file as the application to run, it will automatically
+//! convert that into running `cmd.exe /c` with the bat file as the next argument.
+//!
+//! For historical reasons Rust currently preserves this behaviour when using
+//! [`Command::new`], and escapes the arguments according to `cmd.exe` rules.
+//! Due to the complexity of `cmd.exe` argument handling, it might not be
+//! possible to safely escape some special chars, and using them will result
+//! in an error being returned at process spawn. The set of unescapeable
+//! special chars might change between releases.
+//!
+//! Also note that running `.bat` scripts in this way may be removed in the
+//! future and so should not be relied upon.
+//!
 //! [`spawn`]: Command::spawn
 //! [`output`]: Command::output
 //!
@@ -97,6 +138,12 @@
 //!
 //! [`Write`]: io::Write
 //! [`Read`]: io::Read
+//!
+//! [`arg`]: Command::arg
+//! [`args`]: Command::args
+//! [`raw_arg`]: crate::os::windows::process::CommandExt::raw_arg
+//!
+//! [`CreateProcessW`]: https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessw
 
 #![stable(feature = "process", since = "1.0.0")]
 #![deny(unsafe_op_in_unsafe_fn)]
@@ -611,6 +658,22 @@ impl Command {
     /// escaped characters, word splitting, glob patterns, variable substitution, etc.
     /// have no effect.
     ///
+    /// <div class="warning">
+    ///
+    /// On Windows use caution with untrusted inputs. Most applications use the
+    /// standard convention for decoding arguments passed to them. These are safe to use with `arg`.
+    /// However some applications, such as `cmd.exe` and `.bat` files, use a non-standard way of decoding arguments
+    /// and are therefore vulnerable to malicious input.
+    /// In the case of `cmd.exe` this is especially important because a malicious argument can potentially run arbitrary shell commands.
+    ///
+    /// See [Windows argument splitting][windows-args] for more details
+    /// or [`raw_arg`] for manually implementing non-standard argument encoding.
+    ///
+    /// [`raw_arg`]: crate::os::windows::process::CommandExt::raw_arg
+    /// [windows-args]: crate::process#windows-argument-splitting
+    ///
+    /// </div>
+    ///
     /// # Examples
     ///
     /// Basic usage:
@@ -641,6 +704,22 @@ impl Command {
     /// escaped characters, word splitting, glob patterns, variable substitution, etc.
     /// have no effect.
     ///
+    /// <div class="warning">
+    ///
+    /// On Windows use caution with untrusted inputs. Most applications use the
+    /// standard convention for decoding arguments passed to them. These are safe to use with `args`.
+    /// However some applications, such as `cmd.exe` and `.bat` files, use a non-standard way of decoding arguments
+    /// and are therefore vulnerable to malicious input.
+    /// In the case of `cmd.exe` this is especially important because a malicious argument can potentially run arbitrary shell commands.
+    ///
+    /// See [Windows argument splitting][windows-args] for more details
+    /// or [`raw_arg`] for manually implementing non-standard argument encoding.
+    ///
+    /// [`raw_arg`]: crate::os::windows::process::CommandExt::raw_arg
+    /// [windows-args]: crate::process#windows-argument-splitting
+    ///
+    /// </div>
+    ///
     /// # Examples
     ///
     /// Basic usage:
diff --git a/library/std/src/rt.rs b/library/std/src/rt.rs
index 335944845ae..59e118f81ab 100644
--- a/library/std/src/rt.rs
+++ b/library/std/src/rt.rs
@@ -16,16 +16,13 @@
 #![deny(unsafe_op_in_unsafe_fn)]
 #![allow(unused_macros)]
 
-use crate::ffi::CString;
-
 // Re-export some of our utilities which are expected by other crates.
 pub use crate::panicking::{begin_panic, panic_count};
 pub use core::panicking::{panic_display, panic_fmt};
 
 use crate::sync::Once;
 use crate::sys;
-use crate::sys_common::thread_info;
-use crate::thread::Thread;
+use crate::thread::{self, Thread};
 
 // Prints to the "panic output", depending on the platform this may be:
 // - the standard error output
@@ -96,13 +93,9 @@ unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) {
     unsafe {
         sys::init(argc, argv, sigpipe);
 
-        let main_guard = sys::thread::guard::init();
-        // Next, set up the current Thread with the guard information we just
-        // created. Note that this isn't necessary in general for new threads,
-        // but we just do this to name the main thread and to give it correct
-        // info about the stack bounds.
-        let thread = Thread::new(Some(rtunwrap!(Ok, CString::new("main"))));
-        thread_info::set(main_guard, thread);
+        // Set up the current thread to give it the right name.
+        let thread = Thread::new_main();
+        thread::set_current(thread);
     }
 }
 
diff --git a/library/std/src/sync/mutex.rs b/library/std/src/sync/mutex.rs
index 895fcbd6b7e..d417034f5af 100644
--- a/library/std/src/sync/mutex.rs
+++ b/library/std/src/sync/mutex.rs
@@ -396,7 +396,7 @@ impl<T: ?Sized> Mutex<T> {
         self.poison.get()
     }
 
-    /// Clear the poisoned state from a mutex
+    /// Clear the poisoned state from a mutex.
     ///
     /// If the mutex is poisoned, it will remain poisoned until this function is called. This
     /// allows recovering from a poisoned state and marking that it has recovered. For example, if
diff --git a/library/std/src/sync/once_lock.rs b/library/std/src/sync/once_lock.rs
index 6d068613f8f..fc830bacced 100644
--- a/library/std/src/sync/once_lock.rs
+++ b/library/std/src/sync/once_lock.rs
@@ -252,6 +252,46 @@ impl<T> OnceLock<T> {
         }
     }
 
+    /// Gets the mutable reference of the contents of the cell, initializing
+    /// it with `f` if the cell was empty.
+    ///
+    /// Many threads may call `get_mut_or_init` concurrently with different
+    /// initializing functions, but it is guaranteed that only one function
+    /// will be executed.
+    ///
+    /// # Panics
+    ///
+    /// If `f` panics, the panic is propagated to the caller, and the cell
+    /// remains uninitialized.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(once_cell_get_mut)]
+    ///
+    /// use std::sync::OnceLock;
+    ///
+    /// let mut cell = OnceLock::new();
+    /// let value = cell.get_mut_or_init(|| 92);
+    /// assert_eq!(*value, 92);
+    ///
+    /// *value += 2;
+    /// assert_eq!(*value, 94);
+    ///
+    /// let value = cell.get_mut_or_init(|| unreachable!());
+    /// assert_eq!(*value, 94);
+    /// ```
+    #[inline]
+    #[unstable(feature = "once_cell_get_mut", issue = "121641")]
+    pub fn get_mut_or_init<F>(&mut self, f: F) -> &mut T
+    where
+        F: FnOnce() -> T,
+    {
+        match self.get_mut_or_try_init(|| Ok::<T, !>(f())) {
+            Ok(val) => val,
+        }
+    }
+
     /// Gets the contents of the cell, initializing it with `f` if
     /// the cell was empty. If the cell was empty and `f` failed, an
     /// error is returned.
@@ -303,6 +343,47 @@ impl<T> OnceLock<T> {
         Ok(unsafe { self.get_unchecked() })
     }
 
+    /// Gets the mutable reference of the contents of the cell, initializing
+    /// it with `f` if the cell was empty. If the cell was empty and `f` failed,
+    /// an error is returned.
+    ///
+    /// # Panics
+    ///
+    /// If `f` panics, the panic is propagated to the caller, and
+    /// the cell remains uninitialized.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(once_cell_get_mut)]
+    ///
+    /// use std::sync::OnceLock;
+    ///
+    /// let mut cell: OnceLock<u32> = OnceLock::new();
+    ///
+    /// // Failed initializers do not change the value
+    /// assert!(cell.get_mut_or_try_init(|| "not a number!".parse()).is_err());
+    /// assert!(cell.get().is_none());
+    ///
+    /// let value = cell.get_mut_or_try_init(|| "1234".parse());
+    /// assert_eq!(value, Ok(&mut 1234));
+    /// *value.unwrap() += 2;
+    /// assert_eq!(cell.get(), Some(&1236))
+    /// ```
+    #[inline]
+    #[unstable(feature = "once_cell_get_mut", issue = "121641")]
+    pub fn get_mut_or_try_init<F, E>(&mut self, f: F) -> Result<&mut T, E>
+    where
+        F: FnOnce() -> Result<T, E>,
+    {
+        if self.get().is_none() {
+            self.initialize(f)?;
+        }
+        debug_assert!(self.is_initialized());
+        // SAFETY: The inner value has been initialized
+        Ok(unsafe { self.get_unchecked_mut() })
+    }
+
     /// Consumes the `OnceLock`, returning the wrapped value. Returns
     /// `None` if the cell was empty.
     ///
diff --git a/library/std/src/sync/rwlock.rs b/library/std/src/sync/rwlock.rs
index f7f098c082a..e0a8a7603d7 100644
--- a/library/std/src/sync/rwlock.rs
+++ b/library/std/src/sync/rwlock.rs
@@ -31,13 +31,14 @@ use crate::sys::sync as sys;
 /// <details><summary>Potential deadlock example</summary>
 ///
 /// ```text
-/// // Thread 1             |  // Thread 2
-/// let _rg = lock.read();  |
-///                         |  // will block
-///                         |  let _wg = lock.write();
-/// // may deadlock         |
-/// let _rg = lock.read();  |
+/// // Thread 1              |  // Thread 2
+/// let _rg1 = lock.read();  |
+///                          |  // will block
+///                          |  let _wg = lock.write();
+/// // may deadlock          |
+/// let _rg2 = lock.read();  |
 /// ```
+///
 /// </details>
 ///
 /// The type parameter `T` represents the data that this lock protects. It is
@@ -439,7 +440,7 @@ impl<T: ?Sized> RwLock<T> {
         self.poison.get()
     }
 
-    /// Clear the poisoned state from a lock
+    /// Clear the poisoned state from a lock.
     ///
     /// If the lock is poisoned, it will remain poisoned until this function is called. This allows
     /// recovering from a poisoned state and marking that it has recovered. For example, if the
diff --git a/library/std/src/sys/pal/hermit/fd.rs b/library/std/src/sys/pal/hermit/fd.rs
index 5eb828fea1f..962577bb1ed 100644
--- a/library/std/src/sys/pal/hermit/fd.rs
+++ b/library/std/src/sys/pal/hermit/fd.rs
@@ -48,6 +48,11 @@ impl FileDesc {
     pub fn set_nonblocking(&self, _nonblocking: bool) -> io::Result<()> {
         unsupported()
     }
+
+    pub fn fstat(&self, stat: *mut abi::stat) -> io::Result<()> {
+        cvt(unsafe { abi::fstat(self.fd.as_raw_fd(), stat) })?;
+        Ok(())
+    }
 }
 
 impl<'a> Read for &'a FileDesc {
diff --git a/library/std/src/sys/pal/hermit/fs.rs b/library/std/src/sys/pal/hermit/fs.rs
index d4da53fd3df..6519cc22f1f 100644
--- a/library/std/src/sys/pal/hermit/fs.rs
+++ b/library/std/src/sys/pal/hermit/fs.rs
@@ -1,12 +1,17 @@
-use super::abi::{self, O_APPEND, O_CREAT, O_EXCL, O_RDONLY, O_RDWR, O_TRUNC, O_WRONLY};
+use super::abi::{
+    self, dirent64, stat as stat_struct, DT_DIR, DT_LNK, DT_REG, DT_UNKNOWN, O_APPEND, O_CREAT,
+    O_EXCL, O_RDONLY, O_RDWR, O_TRUNC, O_WRONLY, S_IFDIR, S_IFLNK, S_IFMT, S_IFREG,
+};
 use super::fd::FileDesc;
-use crate::ffi::{CStr, OsString};
+use crate::ffi::{CStr, OsStr, OsString};
 use crate::fmt;
-use crate::hash::{Hash, Hasher};
 use crate::io::{self, Error, ErrorKind};
 use crate::io::{BorrowedCursor, IoSlice, IoSliceMut, SeekFrom};
+use crate::mem;
+use crate::os::hermit::ffi::OsStringExt;
 use crate::os::hermit::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd};
 use crate::path::{Path, PathBuf};
+use crate::sync::Arc;
 use crate::sys::common::small_c_string::run_path_with_cstr;
 use crate::sys::cvt;
 use crate::sys::time::SystemTime;
@@ -14,16 +19,53 @@ use crate::sys::unsupported;
 use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
 
 pub use crate::sys_common::fs::{copy, try_exists};
-//pub use crate::sys_common::fs::remove_dir_all;
 
 #[derive(Debug)]
 pub struct File(FileDesc);
+#[derive(Clone)]
+pub struct FileAttr {
+    stat_val: stat_struct,
+}
 
-pub struct FileAttr(!);
+impl FileAttr {
+    fn from_stat(stat_val: stat_struct) -> Self {
+        Self { stat_val }
+    }
+}
 
-pub struct ReadDir(!);
+// all DirEntry's will have a reference to this struct
+struct InnerReadDir {
+    root: PathBuf,
+    dir: Vec<u8>,
+}
 
-pub struct DirEntry(!);
+impl InnerReadDir {
+    pub fn new(root: PathBuf, dir: Vec<u8>) -> Self {
+        Self { root, dir }
+    }
+}
+
+pub struct ReadDir {
+    inner: Arc<InnerReadDir>,
+    pos: i64,
+}
+
+impl ReadDir {
+    fn new(inner: InnerReadDir) -> Self {
+        Self { inner: Arc::new(inner), pos: 0 }
+    }
+}
+
+pub struct DirEntry {
+    /// path to the entry
+    root: PathBuf,
+    /// 64-bit inode number
+    ino: u64,
+    /// File type
+    type_: u32,
+    /// name of the entry
+    name: OsString,
+}
 
 #[derive(Clone, Debug)]
 pub struct OpenOptions {
@@ -41,72 +83,87 @@ pub struct OpenOptions {
 #[derive(Copy, Clone, Debug, Default)]
 pub struct FileTimes {}
 
-pub struct FilePermissions(!);
-
-pub struct FileType(!);
+#[derive(Clone, PartialEq, Eq, Debug)]
+pub struct FilePermissions {
+    mode: u32,
+}
 
-#[derive(Debug)]
-pub struct DirBuilder {}
+#[derive(Copy, Clone, Eq, Debug)]
+pub struct FileType {
+    mode: u32,
+}
 
-impl FileAttr {
-    pub fn size(&self) -> u64 {
-        self.0
+impl PartialEq for FileType {
+    fn eq(&self, other: &Self) -> bool {
+        self.mode == other.mode
     }
+}
 
-    pub fn perm(&self) -> FilePermissions {
-        self.0
+impl core::hash::Hash for FileType {
+    fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
+        self.mode.hash(state);
     }
+}
 
-    pub fn file_type(&self) -> FileType {
-        self.0
-    }
+#[derive(Debug)]
+pub struct DirBuilder {
+    mode: u32,
+}
 
+impl FileAttr {
     pub fn modified(&self) -> io::Result<SystemTime> {
-        self.0
+        Ok(SystemTime::new(
+            self.stat_val.st_mtime.try_into().unwrap(),
+            self.stat_val.st_mtime_nsec.try_into().unwrap(),
+        ))
     }
 
     pub fn accessed(&self) -> io::Result<SystemTime> {
-        self.0
+        Ok(SystemTime::new(
+            self.stat_val.st_atime.try_into().unwrap(),
+            self.stat_val.st_atime_nsec.try_into().unwrap(),
+        ))
     }
 
     pub fn created(&self) -> io::Result<SystemTime> {
-        self.0
+        Ok(SystemTime::new(
+            self.stat_val.st_ctime.try_into().unwrap(),
+            self.stat_val.st_ctime_nsec.try_into().unwrap(),
+        ))
     }
-}
 
-impl Clone for FileAttr {
-    fn clone(&self) -> FileAttr {
-        self.0
+    pub fn size(&self) -> u64 {
+        self.stat_val.st_size as u64
     }
-}
-
-impl FilePermissions {
-    pub fn readonly(&self) -> bool {
-        self.0
+    pub fn perm(&self) -> FilePermissions {
+        FilePermissions { mode: (self.stat_val.st_mode) }
     }
 
-    pub fn set_readonly(&mut self, _readonly: bool) {
-        self.0
+    pub fn file_type(&self) -> FileType {
+        let masked_mode = self.stat_val.st_mode & S_IFMT;
+        let mode = match masked_mode {
+            S_IFDIR => DT_DIR,
+            S_IFLNK => DT_LNK,
+            S_IFREG => DT_REG,
+            _ => DT_UNKNOWN,
+        };
+        FileType { mode: mode }
     }
 }
 
-impl Clone for FilePermissions {
-    fn clone(&self) -> FilePermissions {
-        self.0
+impl FilePermissions {
+    pub fn readonly(&self) -> bool {
+        // check if any class (owner, group, others) has write permission
+        self.mode & 0o222 == 0
     }
-}
 
-impl PartialEq for FilePermissions {
-    fn eq(&self, _other: &FilePermissions) -> bool {
-        self.0
+    pub fn set_readonly(&mut self, _readonly: bool) {
+        unimplemented!()
     }
-}
-
-impl Eq for FilePermissions {}
 
-impl fmt::Debug for FilePermissions {
-    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        self.0
+    #[allow(dead_code)]
+    pub fn mode(&self) -> u32 {
+        self.mode as u32
     }
 }
 
@@ -117,49 +174,21 @@ impl FileTimes {
 
 impl FileType {
     pub fn is_dir(&self) -> bool {
-        self.0
+        self.mode == DT_DIR
     }
-
     pub fn is_file(&self) -> bool {
-        self.0
+        self.mode == DT_REG
     }
-
     pub fn is_symlink(&self) -> bool {
-        self.0
-    }
-}
-
-impl Clone for FileType {
-    fn clone(&self) -> FileType {
-        self.0
-    }
-}
-
-impl Copy for FileType {}
-
-impl PartialEq for FileType {
-    fn eq(&self, _other: &FileType) -> bool {
-        self.0
-    }
-}
-
-impl Eq for FileType {}
-
-impl Hash for FileType {
-    fn hash<H: Hasher>(&self, _h: &mut H) {
-        self.0
-    }
-}
-
-impl fmt::Debug for FileType {
-    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        self.0
+        self.mode == DT_LNK
     }
 }
 
 impl fmt::Debug for ReadDir {
-    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        self.0
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        // This will only be called from std::fs::ReadDir, which will add a "ReadDir()" frame.
+        // Thus the result will be e.g. 'ReadDir("/home")'
+        fmt::Debug::fmt(&*self.inner.root, f)
     }
 }
 
@@ -167,25 +196,78 @@ impl Iterator for ReadDir {
     type Item = io::Result<DirEntry>;
 
     fn next(&mut self) -> Option<io::Result<DirEntry>> {
-        self.0
+        let mut counter: usize = 0;
+        let mut offset: i64 = 0;
+
+        // loop over all directory entries and search the entry for the current position
+        loop {
+            // leave function, if the loop reaches the of the buffer (with all entries)
+            if offset >= self.inner.dir.len().try_into().unwrap() {
+                return None;
+            }
+
+            let dir = unsafe {
+                &*(self.inner.dir.as_ptr().offset(offset.try_into().unwrap()) as *const dirent64)
+            };
+
+            if counter == self.pos.try_into().unwrap() {
+                self.pos += 1;
+
+                // After dirent64, the file name is stored. d_reclen represents the length of the dirent64
+                // plus the length of the file name. Consequently, file name has a size of d_reclen minus
+                // the size of dirent64. The file name is always a C string and terminated by `\0`.
+                // Consequently, we are able to ignore the last byte.
+                let name_bytes = unsafe {
+                    core::slice::from_raw_parts(
+                        &dir.d_name as *const _ as *const u8,
+                        dir.d_reclen as usize - core::mem::size_of::<dirent64>() - 1,
+                    )
+                    .to_vec()
+                };
+                let entry = DirEntry {
+                    root: self.inner.root.clone(),
+                    ino: dir.d_ino,
+                    type_: dir.d_type as u32,
+                    name: OsString::from_vec(name_bytes),
+                };
+
+                return Some(Ok(entry));
+            }
+
+            counter += 1;
+
+            // move to the next dirent64, which is directly stored after the previous one
+            offset = offset + dir.d_off;
+        }
     }
 }
 
 impl DirEntry {
     pub fn path(&self) -> PathBuf {
-        self.0
+        self.root.join(self.file_name_os_str())
     }
 
     pub fn file_name(&self) -> OsString {
-        self.0
+        self.file_name_os_str().to_os_string()
     }
 
     pub fn metadata(&self) -> io::Result<FileAttr> {
-        self.0
+        let mut path = self.path();
+        path.set_file_name(self.file_name_os_str());
+        lstat(&path)
     }
 
     pub fn file_type(&self) -> io::Result<FileType> {
-        self.0
+        Ok(FileType { mode: self.type_ as u32 })
+    }
+
+    #[allow(dead_code)]
+    pub fn ino(&self) -> u64 {
+        self.ino
+    }
+
+    pub fn file_name_os_str(&self) -> &OsStr {
+        self.name.as_os_str()
     }
 }
 
@@ -288,7 +370,9 @@ impl File {
     }
 
     pub fn file_attr(&self) -> io::Result<FileAttr> {
-        Err(Error::from_raw_os_error(22))
+        let mut stat_val: stat_struct = unsafe { mem::zeroed() };
+        self.0.fstat(&mut stat_val)?;
+        Ok(FileAttr::from_stat(stat_val))
     }
 
     pub fn fsync(&self) -> io::Result<()> {
@@ -357,11 +441,18 @@ impl File {
 
 impl DirBuilder {
     pub fn new() -> DirBuilder {
-        DirBuilder {}
+        DirBuilder { mode: 0o777 }
     }
 
-    pub fn mkdir(&self, _p: &Path) -> io::Result<()> {
-        unsupported()
+    pub fn mkdir(&self, path: &Path) -> io::Result<()> {
+        run_path_with_cstr(path, &|path| {
+            cvt(unsafe { abi::mkdir(path.as_ptr(), self.mode) }).map(|_| ())
+        })
+    }
+
+    #[allow(dead_code)]
+    pub fn set_mode(&mut self, mode: u32) {
+        self.mode = mode as u32;
     }
 }
 
@@ -416,8 +507,43 @@ impl FromRawFd for File {
     }
 }
 
-pub fn readdir(_p: &Path) -> io::Result<ReadDir> {
-    unsupported()
+pub fn readdir(path: &Path) -> io::Result<ReadDir> {
+    let fd_raw = run_path_with_cstr(path, &|path| cvt(unsafe { abi::opendir(path.as_ptr()) }))?;
+    let fd = unsafe { FileDesc::from_raw_fd(fd_raw as i32) };
+    let root = path.to_path_buf();
+
+    // read all director entries
+    let mut vec: Vec<u8> = Vec::new();
+    let mut sz = 512;
+    loop {
+        // reserve memory to receive all directory entries
+        vec.resize(sz, 0);
+
+        let readlen =
+            unsafe { abi::getdents64(fd.as_raw_fd(), vec.as_mut_ptr() as *mut dirent64, sz) };
+        if readlen > 0 {
+            // shrink down to the minimal size
+            vec.resize(readlen.try_into().unwrap(), 0);
+            break;
+        }
+
+        // if the buffer is too small, getdents64 returns EINVAL
+        // otherwise, getdents64 returns an error number
+        if readlen != (-abi::errno::EINVAL).into() {
+            return Err(Error::from_raw_os_error(readlen.try_into().unwrap()));
+        }
+
+        // we don't have enough memory => try to increase the vector size
+        sz = sz * 2;
+
+        // 1 MB for directory entries should be enough
+        // stop here to avoid an endless loop
+        if sz > 0x100000 {
+            return Err(Error::from(ErrorKind::Uncategorized));
+        }
+    }
+
+    Ok(ReadDir::new(InnerReadDir::new(root, vec)))
 }
 
 pub fn unlink(path: &Path) -> io::Result<()> {
@@ -428,17 +554,16 @@ pub fn rename(_old: &Path, _new: &Path) -> io::Result<()> {
     unsupported()
 }
 
-pub fn set_perm(_p: &Path, perm: FilePermissions) -> io::Result<()> {
-    match perm.0 {}
+pub fn set_perm(_p: &Path, _perm: FilePermissions) -> io::Result<()> {
+    Err(Error::from_raw_os_error(22))
 }
 
-pub fn rmdir(_p: &Path) -> io::Result<()> {
-    unsupported()
+pub fn rmdir(path: &Path) -> io::Result<()> {
+    run_path_with_cstr(path, &|path| cvt(unsafe { abi::rmdir(path.as_ptr()) }).map(|_| ()))
 }
 
 pub fn remove_dir_all(_path: &Path) -> io::Result<()> {
-    //unsupported()
-    Ok(())
+    unsupported()
 }
 
 pub fn readlink(_p: &Path) -> io::Result<PathBuf> {
@@ -453,12 +578,20 @@ pub fn link(_original: &Path, _link: &Path) -> io::Result<()> {
     unsupported()
 }
 
-pub fn stat(_p: &Path) -> io::Result<FileAttr> {
-    unsupported()
+pub fn stat(path: &Path) -> io::Result<FileAttr> {
+    run_path_with_cstr(path, &|path| {
+        let mut stat_val: stat_struct = unsafe { mem::zeroed() };
+        cvt(unsafe { abi::stat(path.as_ptr(), &mut stat_val) })?;
+        Ok(FileAttr::from_stat(stat_val))
+    })
 }
 
-pub fn lstat(_p: &Path) -> io::Result<FileAttr> {
-    unsupported()
+pub fn lstat(path: &Path) -> io::Result<FileAttr> {
+    run_path_with_cstr(path, &|path| {
+        let mut stat_val: stat_struct = unsafe { mem::zeroed() };
+        cvt(unsafe { abi::lstat(path.as_ptr(), &mut stat_val) })?;
+        Ok(FileAttr::from_stat(stat_val))
+    })
 }
 
 pub fn canonicalize(_p: &Path) -> io::Result<PathBuf> {
diff --git a/library/std/src/sys/pal/hermit/thread.rs b/library/std/src/sys/pal/hermit/thread.rs
index cf45b9c2396..4fe6b12a95b 100644
--- a/library/std/src/sys/pal/hermit/thread.rs
+++ b/library/std/src/sys/pal/hermit/thread.rs
@@ -2,7 +2,7 @@
 
 use super::abi;
 use super::thread_local_dtor::run_dtors;
-use crate::ffi::{CStr, CString};
+use crate::ffi::CStr;
 use crate::io;
 use crate::mem;
 use crate::num::NonZero;
@@ -29,7 +29,7 @@ impl Thread {
         let p = Box::into_raw(Box::new(p));
         let tid = abi::spawn2(
             thread_start,
-            p.expose_addr(),
+            p.expose_provenance(),
             abi::Priority::into(abi::NORMAL_PRIO),
             stack,
             core_id,
@@ -47,7 +47,7 @@ impl Thread {
         extern "C" fn thread_start(main: usize) {
             unsafe {
                 // Finally, let's run some code.
-                Box::from_raw(ptr::from_exposed_addr::<Box<dyn FnOnce()>>(main).cast_mut())();
+                Box::from_raw(ptr::with_exposed_provenance::<Box<dyn FnOnce()>>(main).cast_mut())();
 
                 // run all destructors
                 run_dtors();
@@ -71,10 +71,6 @@ impl Thread {
         // nope
     }
 
-    pub fn get_name() -> Option<CString> {
-        None
-    }
-
     #[inline]
     pub fn sleep(dur: Duration) {
         unsafe {
@@ -104,13 +100,3 @@ impl Thread {
 pub fn available_parallelism() -> io::Result<NonZero<usize>> {
     unsafe { Ok(NonZero::new_unchecked(abi::get_processor_count())) }
 }
-
-pub mod guard {
-    pub type Guard = !;
-    pub unsafe fn current() -> Option<Guard> {
-        None
-    }
-    pub unsafe fn init() -> Option<Guard> {
-        None
-    }
-}
diff --git a/library/std/src/sys/pal/hermit/time.rs b/library/std/src/sys/pal/hermit/time.rs
index 319b835a768..d6f9e4c1476 100644
--- a/library/std/src/sys/pal/hermit/time.rs
+++ b/library/std/src/sys/pal/hermit/time.rs
@@ -18,6 +18,12 @@ impl Timespec {
         Timespec { t: timespec { tv_sec: 0, tv_nsec: 0 } }
     }
 
+    const fn new(tv_sec: i64, tv_nsec: i64) -> Timespec {
+        assert!(tv_nsec >= 0 && tv_nsec < NSEC_PER_SEC as i64);
+        // SAFETY: The assert above checks tv_nsec is within the valid range
+        Timespec { t: timespec { tv_sec: tv_sec, tv_nsec: tv_nsec } }
+    }
+
     fn sub_timespec(&self, other: &Timespec) -> Result<Duration, Duration> {
         if self >= other {
             Ok(if self.t.tv_nsec >= other.t.tv_nsec {
@@ -195,6 +201,10 @@ pub struct SystemTime(Timespec);
 pub const UNIX_EPOCH: SystemTime = SystemTime(Timespec::zero());
 
 impl SystemTime {
+    pub fn new(tv_sec: i64, tv_nsec: i64) -> SystemTime {
+        SystemTime(Timespec::new(tv_sec, tv_nsec))
+    }
+
     pub fn now() -> SystemTime {
         let mut time: Timespec = Timespec::zero();
         let _ = unsafe { abi::clock_gettime(CLOCK_REALTIME, core::ptr::addr_of_mut!(time.t)) };
diff --git a/library/std/src/sys/pal/itron/thread.rs b/library/std/src/sys/pal/itron/thread.rs
index 814a102dd09..205226ce1da 100644
--- a/library/std/src/sys/pal/itron/thread.rs
+++ b/library/std/src/sys/pal/itron/thread.rs
@@ -8,7 +8,7 @@ use super::{
 };
 use crate::{
     cell::UnsafeCell,
-    ffi::{CStr, CString},
+    ffi::CStr,
     hint, io,
     mem::ManuallyDrop,
     num::NonZero,
@@ -98,7 +98,7 @@ impl Thread {
         });
 
         unsafe extern "C" fn trampoline(exinf: isize) {
-            let p_inner: *mut ThreadInner = crate::ptr::from_exposed_addr_mut(exinf as usize);
+            let p_inner: *mut ThreadInner = crate::ptr::with_exposed_provenance_mut(exinf as usize);
             // Safety: `ThreadInner` is alive at this point
             let inner = unsafe { &*p_inner };
 
@@ -181,7 +181,7 @@ impl Thread {
             abi::acre_tsk(&abi::T_CTSK {
                 // Activate this task immediately
                 tskatr: abi::TA_ACT,
-                exinf: p_inner.as_ptr().expose_addr() as abi::EXINF,
+                exinf: p_inner.as_ptr().expose_provenance() as abi::EXINF,
                 // The entry point
                 task: Some(trampoline),
                 // Inherit the calling task's base priority
@@ -204,10 +204,6 @@ impl Thread {
         // nope
     }
 
-    pub fn get_name() -> Option<CString> {
-        None
-    }
-
     pub fn sleep(dur: Duration) {
         for timeout in dur2reltims(dur) {
             expect_success(unsafe { abi::dly_tsk(timeout) }, &"dly_tsk");
@@ -312,16 +308,6 @@ impl Drop for Thread {
     }
 }
 
-pub mod guard {
-    pub type Guard = !;
-    pub unsafe fn current() -> Option<Guard> {
-        None
-    }
-    pub unsafe fn init() -> Option<Guard> {
-        None
-    }
-}
-
 /// Terminate and delete the specified task.
 ///
 /// This function will abort if `deleted_task` refers to the calling task.
diff --git a/library/std/src/sys/pal/mod.rs b/library/std/src/sys/pal/mod.rs
index 7c87deed371..8c75ac65299 100644
--- a/library/std/src/sys/pal/mod.rs
+++ b/library/std/src/sys/pal/mod.rs
@@ -37,12 +37,12 @@ cfg_if::cfg_if! {
     } else if #[cfg(target_os = "hermit")] {
         mod hermit;
         pub use self::hermit::*;
-    } else if #[cfg(target_os = "wasi")] {
-        mod wasi;
-        pub use self::wasi::*;
     } else if #[cfg(all(target_os = "wasi", target_env = "p2"))] {
         mod wasip2;
         pub use self::wasip2::*;
+    } else if #[cfg(target_os = "wasi")] {
+        mod wasi;
+        pub use self::wasi::*;
     } else if #[cfg(target_family = "wasm")] {
         mod wasm;
         pub use self::wasm::*;
diff --git a/library/std/src/sys/pal/sgx/net.rs b/library/std/src/sys/pal/sgx/net.rs
index c4d5da1627c..edb28e2300f 100644
--- a/library/std/src/sys/pal/sgx/net.rs
+++ b/library/std/src/sys/pal/sgx/net.rs
@@ -524,6 +524,7 @@ pub mod netc {
 
     #[derive(Copy, Clone)]
     pub struct sockaddr_in {
+        #[allow(dead_code)]
         pub sin_family: sa_family_t,
         pub sin_port: u16,
         pub sin_addr: in_addr,
@@ -536,6 +537,7 @@ pub mod netc {
 
     #[derive(Copy, Clone)]
     pub struct sockaddr_in6 {
+        #[allow(dead_code)]
         pub sin6_family: sa_family_t,
         pub sin6_port: u16,
         pub sin6_addr: in6_addr,
diff --git a/library/std/src/sys/pal/sgx/thread.rs b/library/std/src/sys/pal/sgx/thread.rs
index 77f68bf7334..e2df57b1a1f 100644
--- a/library/std/src/sys/pal/sgx/thread.rs
+++ b/library/std/src/sys/pal/sgx/thread.rs
@@ -1,6 +1,6 @@
 #![cfg_attr(test, allow(dead_code))] // why is this necessary?
 use super::unsupported;
-use crate::ffi::{CStr, CString};
+use crate::ffi::CStr;
 use crate::io;
 use crate::num::NonZero;
 use crate::time::Duration;
@@ -133,10 +133,6 @@ impl Thread {
         // which succeeds as-is with the SGX target.
     }
 
-    pub fn get_name() -> Option<CString> {
-        None
-    }
-
     pub fn sleep(dur: Duration) {
         usercalls::wait_timeout(0, dur, || true);
     }
@@ -149,13 +145,3 @@ impl Thread {
 pub fn available_parallelism() -> io::Result<NonZero<usize>> {
     unsupported()
 }
-
-pub mod guard {
-    pub type Guard = !;
-    pub unsafe fn current() -> Option<Guard> {
-        None
-    }
-    pub unsafe fn init() -> Option<Guard> {
-        None
-    }
-}
diff --git a/library/std/src/sys/pal/teeos/thread.rs b/library/std/src/sys/pal/teeos/thread.rs
index b76bcf9bbb0..ae2f58ca08e 100644
--- a/library/std/src/sys/pal/teeos/thread.rs
+++ b/library/std/src/sys/pal/teeos/thread.rs
@@ -1,7 +1,7 @@
 use core::convert::TryInto;
 
 use crate::cmp;
-use crate::ffi::{CStr, CString};
+use crate::ffi::CStr;
 use crate::io;
 use crate::mem;
 use crate::num::NonZero;
@@ -101,10 +101,6 @@ impl Thread {
         // contact the teeos rustzone team.
     }
 
-    pub fn get_name() -> Option<CString> {
-        None
-    }
-
     /// only main thread could wait for sometime in teeos
     pub fn sleep(dur: Duration) {
         let sleep_millis = dur.as_millis();
@@ -151,18 +147,6 @@ pub fn available_parallelism() -> io::Result<NonZero<usize>> {
     ))
 }
 
-// stub
-pub mod guard {
-    use crate::ops::Range;
-    pub type Guard = Range<usize>;
-    pub unsafe fn current() -> Option<Guard> {
-        None
-    }
-    pub unsafe fn init() -> Option<Guard> {
-        None
-    }
-}
-
 fn min_stack_size(_: *const libc::pthread_attr_t) -> usize {
     libc::PTHREAD_STACK_MIN.try_into().expect("Infallible")
 }
diff --git a/library/std/src/sys/pal/uefi/helpers.rs b/library/std/src/sys/pal/uefi/helpers.rs
index ba53ed88f37..23aa4da14a7 100644
--- a/library/std/src/sys/pal/uefi/helpers.rs
+++ b/library/std/src/sys/pal/uefi/helpers.rs
@@ -10,14 +10,16 @@
 //! - More information about protocols can be found [here](https://edk2-docs.gitbook.io/edk-ii-uefi-driver-writer-s-guide/3_foundation/36_protocols_and_handles)
 
 use r_efi::efi::{self, Guid};
+use r_efi::protocols::{device_path, device_path_to_text};
 
+use crate::ffi::OsString;
+use crate::io::{self, const_io_error};
 use crate::mem::{size_of, MaybeUninit};
-use crate::os::uefi;
+use crate::os::uefi::{self, env::boot_services, ffi::OsStringExt};
 use crate::ptr::NonNull;
-use crate::{
-    io::{self, const_io_error},
-    os::uefi::env::boot_services,
-};
+use crate::slice;
+use crate::sync::atomic::{AtomicPtr, Ordering};
+use crate::sys_common::wstr::WStrUnits;
 
 const BOOT_SERVICES_UNAVAILABLE: io::Error =
     const_io_error!(io::ErrorKind::Other, "Boot Services are no longer available");
@@ -142,9 +144,74 @@ pub(crate) unsafe fn close_event(evt: NonNull<crate::ffi::c_void>) -> io::Result
 
 /// Get the Protocol for current system handle.
 /// Note: Some protocols need to be manually freed. It is the callers responsibility to do so.
-pub(crate) fn image_handle_protocol<T>(protocol_guid: Guid) -> Option<NonNull<T>> {
-    let system_handle = uefi::env::try_image_handle()?;
-    open_protocol(system_handle, protocol_guid).ok()
+pub(crate) fn image_handle_protocol<T>(protocol_guid: Guid) -> io::Result<NonNull<T>> {
+    let system_handle = uefi::env::try_image_handle().ok_or(io::const_io_error!(
+        io::ErrorKind::NotFound,
+        "Protocol not found in Image handle"
+    ))?;
+    open_protocol(system_handle, protocol_guid)
+}
+
+pub(crate) fn device_path_to_text(path: NonNull<device_path::Protocol>) -> io::Result<OsString> {
+    fn path_to_text(
+        protocol: NonNull<device_path_to_text::Protocol>,
+        path: NonNull<device_path::Protocol>,
+    ) -> io::Result<OsString> {
+        let path_ptr: *mut r_efi::efi::Char16 = unsafe {
+            ((*protocol.as_ptr()).convert_device_path_to_text)(
+                path.as_ptr(),
+                // DisplayOnly
+                r_efi::efi::Boolean::FALSE,
+                // AllowShortcuts
+                r_efi::efi::Boolean::FALSE,
+            )
+        };
+
+        // SAFETY: `convert_device_path_to_text` returns a pointer to a null-terminated UTF-16
+        // string, and that string cannot be deallocated prior to dropping the `WStrUnits`, so
+        // it's safe for `WStrUnits` to use.
+        let path_len = unsafe {
+            WStrUnits::new(path_ptr)
+                .ok_or(io::const_io_error!(io::ErrorKind::InvalidData, "Invalid path"))?
+                .count()
+        };
+
+        let path = OsString::from_wide(unsafe { slice::from_raw_parts(path_ptr.cast(), path_len) });
+
+        if let Some(boot_services) = crate::os::uefi::env::boot_services() {
+            let boot_services: NonNull<r_efi::efi::BootServices> = boot_services.cast();
+            unsafe {
+                ((*boot_services.as_ptr()).free_pool)(path_ptr.cast());
+            }
+        }
+
+        Ok(path)
+    }
+
+    static LAST_VALID_HANDLE: AtomicPtr<crate::ffi::c_void> =
+        AtomicPtr::new(crate::ptr::null_mut());
+
+    if let Some(handle) = NonNull::new(LAST_VALID_HANDLE.load(Ordering::Acquire)) {
+        if let Ok(protocol) = open_protocol::<device_path_to_text::Protocol>(
+            handle,
+            device_path_to_text::PROTOCOL_GUID,
+        ) {
+            return path_to_text(protocol, path);
+        }
+    }
+
+    let device_path_to_text_handles = locate_handles(device_path_to_text::PROTOCOL_GUID)?;
+    for handle in device_path_to_text_handles {
+        if let Ok(protocol) = open_protocol::<device_path_to_text::Protocol>(
+            handle,
+            device_path_to_text::PROTOCOL_GUID,
+        ) {
+            LAST_VALID_HANDLE.store(handle.as_ptr(), Ordering::Release);
+            return path_to_text(protocol, path);
+        }
+    }
+
+    Err(io::const_io_error!(io::ErrorKind::NotFound, "No device path to text protocol found"))
 }
 
 /// Get RuntimeServices
diff --git a/library/std/src/sys/pal/uefi/os.rs b/library/std/src/sys/pal/uefi/os.rs
index e6693db68e6..58838c5876e 100644
--- a/library/std/src/sys/pal/uefi/os.rs
+++ b/library/std/src/sys/pal/uefi/os.rs
@@ -1,4 +1,4 @@
-use super::{unsupported, RawOsError};
+use super::{helpers, unsupported, RawOsError};
 use crate::error::Error as StdError;
 use crate::ffi::{OsStr, OsString};
 use crate::fmt;
@@ -7,6 +7,7 @@ use crate::marker::PhantomData;
 use crate::os::uefi;
 use crate::path::{self, PathBuf};
 use crate::ptr::NonNull;
+use r_efi::efi::protocols::{device_path, loaded_image_device_path};
 use r_efi::efi::Status;
 
 pub fn errno() -> RawOsError {
@@ -164,7 +165,10 @@ impl fmt::Display for JoinPathsError {
 impl StdError for JoinPathsError {}
 
 pub fn current_exe() -> io::Result<PathBuf> {
-    unsupported()
+    let protocol = helpers::image_handle_protocol::<device_path::Protocol>(
+        loaded_image_device_path::PROTOCOL_GUID,
+    )?;
+    helpers::device_path_to_text(protocol).map(PathBuf::from)
 }
 
 pub struct Env(!);
diff --git a/library/std/src/sys/pal/uefi/thread.rs b/library/std/src/sys/pal/uefi/thread.rs
index b3a4f9c53e3..edc736978a1 100644
--- a/library/std/src/sys/pal/uefi/thread.rs
+++ b/library/std/src/sys/pal/uefi/thread.rs
@@ -1,5 +1,5 @@
 use super::unsupported;
-use crate::ffi::{CStr, CString};
+use crate::ffi::CStr;
 use crate::io;
 use crate::num::NonZero;
 use crate::ptr::NonNull;
@@ -23,10 +23,6 @@ impl Thread {
         // nope
     }
 
-    pub fn get_name() -> Option<CString> {
-        None
-    }
-
     pub fn sleep(dur: Duration) {
         let boot_services: NonNull<r_efi::efi::BootServices> =
             crate::os::uefi::env::boot_services().expect("can't sleep").cast();
@@ -52,13 +48,3 @@ pub fn available_parallelism() -> io::Result<NonZero<usize>> {
     // UEFI is single threaded
     Ok(NonZero::new(1).unwrap())
 }
-
-pub mod guard {
-    pub type Guard = !;
-    pub unsafe fn current() -> Option<Guard> {
-        None
-    }
-    pub unsafe fn init() -> Option<Guard> {
-        None
-    }
-}
diff --git a/library/std/src/sys/pal/unix/args.rs b/library/std/src/sys/pal/unix/args.rs
index 78e82d9c194..acf8100d47f 100644
--- a/library/std/src/sys/pal/unix/args.rs
+++ b/library/std/src/sys/pal/unix/args.rs
@@ -170,7 +170,13 @@ mod imp {
     }
 }
 
-#[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "watchos"))]
+#[cfg(any(
+    target_os = "macos",
+    target_os = "ios",
+    target_os = "watchos",
+    target_os = "visionos",
+    target_os = "tvos"
+))]
 mod imp {
     use super::Args;
     use crate::ffi::CStr;
@@ -211,7 +217,12 @@ mod imp {
     // for i in (0..[args count])
     //      res.push([args objectAtIndex:i])
     // res
-    #[cfg(any(target_os = "ios", target_os = "tvos", target_os = "watchos"))]
+    #[cfg(any(
+        target_os = "ios",
+        target_os = "tvos",
+        target_os = "watchos",
+        target_os = "visionos"
+    ))]
     pub fn args() -> Args {
         use crate::ffi::{c_char, c_void, OsString};
         use crate::mem;
diff --git a/library/std/src/sys/pal/unix/env.rs b/library/std/src/sys/pal/unix/env.rs
index 3d4ba509829..fb1f868644d 100644
--- a/library/std/src/sys/pal/unix/env.rs
+++ b/library/std/src/sys/pal/unix/env.rs
@@ -53,6 +53,17 @@ pub mod os {
     pub const EXE_EXTENSION: &str = "";
 }
 
+#[cfg(target_os = "visionos")]
+pub mod os {
+    pub const FAMILY: &str = "unix";
+    pub const OS: &str = "visionos";
+    pub const DLL_PREFIX: &str = "lib";
+    pub const DLL_SUFFIX: &str = ".dylib";
+    pub const DLL_EXTENSION: &str = "dylib";
+    pub const EXE_SUFFIX: &str = "";
+    pub const EXE_EXTENSION: &str = "";
+}
+
 #[cfg(target_os = "freebsd")]
 pub mod os {
     pub const FAMILY: &str = "unix";
diff --git a/library/std/src/sys/pal/unix/fd.rs b/library/std/src/sys/pal/unix/fd.rs
index a1c0321876f..48e83b04ef4 100644
--- a/library/std/src/sys/pal/unix/fd.rs
+++ b/library/std/src/sys/pal/unix/fd.rs
@@ -51,6 +51,7 @@ const READ_LIMIT: usize = libc::ssize_t::MAX as usize;
     target_os = "netbsd",
     target_os = "openbsd",
     target_os = "watchos",
+    target_os = "visionos",
 ))]
 const fn max_iov() -> usize {
     libc::IOV_MAX as usize
@@ -81,6 +82,7 @@ const fn max_iov() -> usize {
     target_os = "horizon",
     target_os = "vita",
     target_os = "watchos",
+    target_os = "visionos",
 )))]
 const fn max_iov() -> usize {
     16 // The minimum value required by POSIX.
@@ -167,6 +169,8 @@ impl FileDesc {
     }
 
     #[cfg(any(
+        target_os = "aix",
+        target_os = "dragonfly", // DragonFly 1.5
         target_os = "emscripten",
         target_os = "freebsd",
         target_os = "fuchsia",
@@ -174,6 +178,7 @@ impl FileDesc {
         target_os = "illumos",
         target_os = "linux",
         target_os = "netbsd",
+        target_os = "openbsd", // OpenBSD 2.7
     ))]
     pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
         let ret = cvt(unsafe {
@@ -188,7 +193,9 @@ impl FileDesc {
     }
 
     #[cfg(not(any(
+        target_os = "aix",
         target_os = "android",
+        target_os = "dragonfly",
         target_os = "emscripten",
         target_os = "freebsd",
         target_os = "fuchsia",
@@ -199,6 +206,8 @@ impl FileDesc {
         target_os = "linux",
         target_os = "macos",
         target_os = "netbsd",
+        target_os = "openbsd",
+        target_os = "watchos",
     )))]
     pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
         io::default_read_vectored(|b| self.read_at(b, offset), bufs)
@@ -236,9 +245,10 @@ impl FileDesc {
     // no `syscall` possible in these platform.
     #[cfg(any(
         all(target_os = "android", target_pointer_width = "32"),
-        target_os = "ios",
-        target_os = "tvos",
-        target_os = "macos",
+        target_os = "ios", // ios 14.0
+        target_os = "tvos", // tvos 14.0
+        target_os = "macos", // macos 11.0
+        target_os = "watchos", // watchos 7.0
     ))]
     pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
         super::weak::weak!(fn preadv64(libc::c_int, *const libc::iovec, libc::c_int, off64_t) -> isize);
@@ -318,6 +328,8 @@ impl FileDesc {
     }
 
     #[cfg(any(
+        target_os = "aix",
+        target_os = "dragonfly", // DragonFly 1.5
         target_os = "emscripten",
         target_os = "freebsd",
         target_os = "fuchsia",
@@ -325,6 +337,7 @@ impl FileDesc {
         target_os = "illumos",
         target_os = "linux",
         target_os = "netbsd",
+        target_os = "openbsd", // OpenBSD 2.7
     ))]
     pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> {
         let ret = cvt(unsafe {
@@ -339,7 +352,9 @@ impl FileDesc {
     }
 
     #[cfg(not(any(
+        target_os = "aix",
         target_os = "android",
+        target_os = "dragonfly",
         target_os = "emscripten",
         target_os = "freebsd",
         target_os = "fuchsia",
@@ -350,6 +365,8 @@ impl FileDesc {
         target_os = "linux",
         target_os = "macos",
         target_os = "netbsd",
+        target_os = "openbsd",
+        target_os = "watchos",
     )))]
     pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> {
         io::default_write_vectored(|b| self.write_at(b, offset), bufs)
@@ -387,9 +404,10 @@ impl FileDesc {
     // no `syscall` possible in these platform.
     #[cfg(any(
         all(target_os = "android", target_pointer_width = "32"),
-        target_os = "ios",
-        target_os = "tvos",
-        target_os = "macos",
+        target_os = "ios", // ios 14.0
+        target_os = "tvos", // tvos 14.0
+        target_os = "macos", // macos 11.0
+        target_os = "watchos", // watchos 7.0
     ))]
     pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> {
         super::weak::weak!(fn pwritev64(libc::c_int, *const libc::iovec, libc::c_int, off64_t) -> isize);
diff --git a/library/std/src/sys/pal/unix/fs.rs b/library/std/src/sys/pal/unix/fs.rs
index df8a92114ec..e8430b6ae70 100644
--- a/library/std/src/sys/pal/unix/fs.rs
+++ b/library/std/src/sys/pal/unix/fs.rs
@@ -26,6 +26,7 @@ use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
     target_os = "ios",
     target_os = "tvos",
     target_os = "watchos",
+    target_os = "visionos",
 ))]
 use crate::sys::weak::syscall;
 #[cfg(any(target_os = "android", target_os = "macos", target_os = "solaris"))]
@@ -38,6 +39,7 @@ use libc::{c_int, mode_t};
     target_os = "ios",
     target_os = "tvos",
     target_os = "watchos",
+    target_os = "visionos",
     target_os = "solaris",
     all(target_os = "linux", target_env = "gnu")
 ))]
@@ -380,7 +382,13 @@ pub struct FilePermissions {
 pub struct FileTimes {
     accessed: Option<SystemTime>,
     modified: Option<SystemTime>,
-    #[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos", target_os = "tvos"))]
+    #[cfg(any(
+        target_os = "macos",
+        target_os = "ios",
+        target_os = "watchos",
+        target_os = "visionos",
+        target_os = "tvos"
+    ))]
     created: Option<SystemTime>,
 }
 
@@ -522,7 +530,7 @@ impl FileAttr {
 
     #[cfg(any(target_os = "horizon", target_os = "hurd"))]
     pub fn modified(&self) -> io::Result<SystemTime> {
-        Ok(SystemTime::from(self.stat.st_mtim))
+        SystemTime::new(self.stat.st_mtim.tv_sec as i64, self.stat.st_mtim.tv_nsec as i64)
     }
 
     #[cfg(not(any(
@@ -550,7 +558,7 @@ impl FileAttr {
 
     #[cfg(any(target_os = "horizon", target_os = "hurd"))]
     pub fn accessed(&self) -> io::Result<SystemTime> {
-        Ok(SystemTime::from(self.stat.st_atim))
+        SystemTime::new(self.stat.st_atim.tv_sec as i64, self.stat.st_atim.tv_nsec as i64)
     }
 
     #[cfg(any(
@@ -560,6 +568,7 @@ impl FileAttr {
         target_os = "ios",
         target_os = "tvos",
         target_os = "watchos",
+        target_os = "visionos",
     ))]
     pub fn created(&self) -> io::Result<SystemTime> {
         SystemTime::new(self.stat.st_birthtime as i64, self.stat.st_birthtime_nsec as i64)
@@ -572,6 +581,7 @@ impl FileAttr {
         target_os = "ios",
         target_os = "tvos",
         target_os = "watchos",
+        target_os = "visionos",
         target_os = "vita",
     )))]
     pub fn created(&self) -> io::Result<SystemTime> {
@@ -652,7 +662,13 @@ impl FileTimes {
         self.modified = Some(t);
     }
 
-    #[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos", target_os = "tvos"))]
+    #[cfg(any(
+        target_os = "macos",
+        target_os = "ios",
+        target_os = "watchos",
+        target_os = "visionos",
+        target_os = "tvos"
+    ))]
     pub fn set_created(&mut self, t: SystemTime) {
         self.created = Some(t);
     }
@@ -957,6 +973,7 @@ impl DirEntry {
         target_os = "ios",
         target_os = "tvos",
         target_os = "watchos",
+        target_os = "visionos",
         target_os = "linux",
         target_os = "emscripten",
         target_os = "android",
@@ -993,6 +1010,7 @@ impl DirEntry {
         target_os = "ios",
         target_os = "tvos",
         target_os = "watchos",
+        target_os = "visionos",
         target_os = "netbsd",
         target_os = "openbsd",
         target_os = "freebsd",
@@ -1012,6 +1030,7 @@ impl DirEntry {
         target_os = "ios",
         target_os = "tvos",
         target_os = "watchos",
+        target_os = "visionos",
         target_os = "netbsd",
         target_os = "openbsd",
         target_os = "freebsd",
@@ -1198,6 +1217,7 @@ impl File {
             target_os = "ios",
             target_os = "tvos",
             target_os = "watchos",
+            target_os = "visionos",
         ))]
         unsafe fn os_fsync(fd: c_int) -> c_int {
             libc::fcntl(fd, libc::F_FULLFSYNC)
@@ -1207,6 +1227,7 @@ impl File {
             target_os = "ios",
             target_os = "tvos",
             target_os = "watchos",
+            target_os = "visionos",
         )))]
         unsafe fn os_fsync(fd: c_int) -> c_int {
             libc::fsync(fd)
@@ -1222,6 +1243,7 @@ impl File {
             target_os = "ios",
             target_os = "tvos",
             target_os = "watchos",
+            target_os = "visionos",
         ))]
         unsafe fn os_datasync(fd: c_int) -> c_int {
             libc::fcntl(fd, libc::F_FULLFSYNC)
@@ -1248,6 +1270,7 @@ impl File {
             target_os = "netbsd",
             target_os = "openbsd",
             target_os = "watchos",
+            target_os = "visionos",
             target_os = "nto",
             target_os = "hurd",
         )))]
@@ -1358,7 +1381,7 @@ impl File {
                     io::ErrorKind::Unsupported,
                     "setting file times not supported",
                 ))
-            } else if #[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "watchos"))] {
+            } else if #[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "watchos", target_os = "visionos"))] {
                 let mut buf = [mem::MaybeUninit::<libc::timespec>::uninit(); 3];
                 let mut num_times = 0;
                 let mut attrlist: libc::attrlist = unsafe { mem::zeroed() };
@@ -1897,6 +1920,7 @@ fn open_to_and_set_permissions(
     target_os = "ios",
     target_os = "tvos",
     target_os = "watchos",
+    target_os = "visionos",
 )))]
 pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
     let (mut reader, reader_metadata) = open_from(from)?;
@@ -1923,43 +1947,19 @@ pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
     }
 }
 
-#[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "watchos"))]
+#[cfg(any(
+    target_os = "macos",
+    target_os = "ios",
+    target_os = "watchos",
+    target_os = "visionos",
+    target_os = "tvos"
+))]
 pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
     use crate::sync::atomic::{AtomicBool, Ordering};
 
-    const COPYFILE_ACL: u32 = 1 << 0;
-    const COPYFILE_STAT: u32 = 1 << 1;
-    const COPYFILE_XATTR: u32 = 1 << 2;
-    const COPYFILE_DATA: u32 = 1 << 3;
-
-    const COPYFILE_SECURITY: u32 = COPYFILE_STAT | COPYFILE_ACL;
-    const COPYFILE_METADATA: u32 = COPYFILE_SECURITY | COPYFILE_XATTR;
-    const COPYFILE_ALL: u32 = COPYFILE_METADATA | COPYFILE_DATA;
-
-    const COPYFILE_STATE_COPIED: u32 = 8;
-
-    #[allow(non_camel_case_types)]
-    type copyfile_state_t = *mut libc::c_void;
-    #[allow(non_camel_case_types)]
-    type copyfile_flags_t = u32;
-
-    extern "C" {
-        fn fcopyfile(
-            from: libc::c_int,
-            to: libc::c_int,
-            state: copyfile_state_t,
-            flags: copyfile_flags_t,
-        ) -> libc::c_int;
-        fn copyfile_state_alloc() -> copyfile_state_t;
-        fn copyfile_state_free(state: copyfile_state_t) -> libc::c_int;
-        fn copyfile_state_get(
-            state: copyfile_state_t,
-            flag: u32,
-            dst: *mut libc::c_void,
-        ) -> libc::c_int;
-    }
-
-    struct FreeOnDrop(copyfile_state_t);
+    const COPYFILE_ALL: libc::copyfile_flags_t = libc::COPYFILE_METADATA | libc::COPYFILE_DATA;
+
+    struct FreeOnDrop(libc::copyfile_state_t);
     impl Drop for FreeOnDrop {
         fn drop(&mut self) {
             // The code below ensures that `FreeOnDrop` is never a null pointer
@@ -1967,7 +1967,7 @@ pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
                 // `copyfile_state_free` returns -1 if the `to` or `from` files
                 // cannot be closed. However, this is not considered this an
                 // error.
-                copyfile_state_free(self.0);
+                libc::copyfile_state_free(self.0);
             }
         }
     }
@@ -1976,6 +1976,7 @@ pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
     // We store the availability in a global to avoid unnecessary syscalls
     static HAS_FCLONEFILEAT: AtomicBool = AtomicBool::new(true);
     syscall! {
+        // Mirrors `libc::fclonefileat`
         fn fclonefileat(
             srcfd: libc::c_int,
             dst_dirfd: libc::c_int,
@@ -2012,22 +2013,22 @@ pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
     // We ensure that `FreeOnDrop` never contains a null pointer so it is
     // always safe to call `copyfile_state_free`
     let state = unsafe {
-        let state = copyfile_state_alloc();
+        let state = libc::copyfile_state_alloc();
         if state.is_null() {
             return Err(crate::io::Error::last_os_error());
         }
         FreeOnDrop(state)
     };
 
-    let flags = if writer_metadata.is_file() { COPYFILE_ALL } else { COPYFILE_DATA };
+    let flags = if writer_metadata.is_file() { COPYFILE_ALL } else { libc::COPYFILE_DATA };
 
-    cvt(unsafe { fcopyfile(reader.as_raw_fd(), writer.as_raw_fd(), state.0, flags) })?;
+    cvt(unsafe { libc::fcopyfile(reader.as_raw_fd(), writer.as_raw_fd(), state.0, flags) })?;
 
     let mut bytes_copied: libc::off_t = 0;
     cvt(unsafe {
-        copyfile_state_get(
+        libc::copyfile_state_get(
             state.0,
-            COPYFILE_STATE_COPIED,
+            libc::COPYFILE_STATE_COPIED as u32,
             core::ptr::addr_of_mut!(bytes_copied) as *mut libc::c_void,
         )
     })?;
diff --git a/library/std/src/sys/pal/unix/mod.rs b/library/std/src/sys/pal/unix/mod.rs
index f608ae47a21..4ae76518c4f 100644
--- a/library/std/src/sys/pal/unix/mod.rs
+++ b/library/std/src/sys/pal/unix/mod.rs
@@ -83,6 +83,7 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) {
             target_os = "ios",
             target_os = "tvos",
             target_os = "watchos",
+            target_os = "visionos",
             target_os = "redox",
             target_os = "l4re",
             target_os = "horizon",
@@ -405,7 +406,7 @@ cfg_if::cfg_if! {
     } else if #[cfg(target_os = "macos")] {
         #[link(name = "System")]
         extern "C" {}
-    } else if #[cfg(any(target_os = "ios", target_os = "tvos", target_os = "watchos"))] {
+    } else if #[cfg(any(target_os = "ios", target_os = "tvos", target_os = "watchos", target_os = "visionos"))] {
         #[link(name = "System")]
         #[link(name = "objc")]
         #[link(name = "Foundation", kind = "framework")]
diff --git a/library/std/src/sys/pal/unix/net.rs b/library/std/src/sys/pal/unix/net.rs
index 09750b6ffc8..9a0a1b18aee 100644
--- a/library/std/src/sys/pal/unix/net.rs
+++ b/library/std/src/sys/pal/unix/net.rs
@@ -453,6 +453,37 @@ impl Socket {
         Ok(raw as u32)
     }
 
+    #[cfg(any(target_os = "freebsd", target_os = "netbsd"))]
+    pub fn set_acceptfilter(&self, name: &CStr) -> io::Result<()> {
+        if !name.to_bytes().is_empty() {
+            const AF_NAME_MAX: usize = 16;
+            let mut buf = [0; AF_NAME_MAX];
+            for (src, dst) in name.to_bytes().iter().zip(&mut buf[..AF_NAME_MAX - 1]) {
+                *dst = *src as libc::c_char;
+            }
+            let mut arg: libc::accept_filter_arg = unsafe { mem::zeroed() };
+            arg.af_name = buf;
+            setsockopt(self, libc::SOL_SOCKET, libc::SO_ACCEPTFILTER, &mut arg)
+        } else {
+            setsockopt(
+                self,
+                libc::SOL_SOCKET,
+                libc::SO_ACCEPTFILTER,
+                core::ptr::null_mut() as *mut c_void,
+            )
+        }
+    }
+
+    #[cfg(any(target_os = "freebsd", target_os = "netbsd"))]
+    pub fn acceptfilter(&self) -> io::Result<&CStr> {
+        let arg: libc::accept_filter_arg =
+            getsockopt(self, libc::SOL_SOCKET, libc::SO_ACCEPTFILTER)?;
+        let s: &[u8] =
+            unsafe { core::slice::from_raw_parts(arg.af_name.as_ptr() as *const u8, 16) };
+        let name = CStr::from_bytes_with_nul(s).unwrap();
+        Ok(name)
+    }
+
     #[cfg(any(target_os = "android", target_os = "linux",))]
     pub fn set_passcred(&self, passcred: bool) -> io::Result<()> {
         setsockopt(self, libc::SOL_SOCKET, libc::SO_PASSCRED, passcred as libc::c_int)
diff --git a/library/std/src/sys/pal/unix/os.rs b/library/std/src/sys/pal/unix/os.rs
index 0b9c8027e6f..96492fedece 100644
--- a/library/std/src/sys/pal/unix/os.rs
+++ b/library/std/src/sys/pal/unix/os.rs
@@ -69,7 +69,8 @@ extern "C" {
             target_os = "ios",
             target_os = "tvos",
             target_os = "freebsd",
-            target_os = "watchos"
+            target_os = "watchos",
+            target_os = "visionos",
         ),
         link_name = "__error"
     )]
@@ -430,7 +431,13 @@ pub fn current_exe() -> io::Result<PathBuf> {
     Ok(PathBuf::from(OsString::from_vec(e)))
 }
 
-#[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "watchos"))]
+#[cfg(any(
+    target_os = "macos",
+    target_os = "ios",
+    target_os = "watchos",
+    target_os = "visionos",
+    target_os = "tvos"
+))]
 pub fn current_exe() -> io::Result<PathBuf> {
     unsafe {
         let mut sz: u32 = 0;
@@ -699,6 +706,7 @@ pub fn home_dir() -> Option<PathBuf> {
         target_os = "ios",
         target_os = "tvos",
         target_os = "watchos",
+        target_os = "visionos",
         target_os = "emscripten",
         target_os = "redox",
         target_os = "vxworks",
@@ -714,6 +722,7 @@ pub fn home_dir() -> Option<PathBuf> {
         target_os = "ios",
         target_os = "tvos",
         target_os = "watchos",
+        target_os = "visionos",
         target_os = "emscripten",
         target_os = "redox",
         target_os = "vxworks",
diff --git a/library/std/src/sys/pal/unix/process/process_unix.rs b/library/std/src/sys/pal/unix/process/process_unix.rs
index f017d39d804..e798510f9e6 100644
--- a/library/std/src/sys/pal/unix/process/process_unix.rs
+++ b/library/std/src/sys/pal/unix/process/process_unix.rs
@@ -14,6 +14,7 @@ use crate::os::unix::io::AsRawFd;
 #[cfg(any(
     target_os = "macos",
     target_os = "watchos",
+    target_os = "visionos",
     target_os = "tvos",
     target_os = "freebsd",
     all(target_os = "linux", target_env = "gnu"),
diff --git a/library/std/src/sys/pal/unix/rand.rs b/library/std/src/sys/pal/unix/rand.rs
index c9ed6825f6c..de087d98eb8 100644
--- a/library/std/src/sys/pal/unix/rand.rs
+++ b/library/std/src/sys/pal/unix/rand.rs
@@ -16,6 +16,7 @@ pub fn hashmap_random_keys() -> (u64, u64) {
     not(target_os = "ios"),
     not(target_os = "tvos"),
     not(target_os = "watchos"),
+    not(target_os = "visionos"),
     not(target_os = "openbsd"),
     not(target_os = "netbsd"),
     not(target_os = "fuchsia"),
@@ -62,17 +63,23 @@ mod imp {
         unsafe { getrandom(buf.as_mut_ptr().cast(), buf.len(), libc::GRND_NONBLOCK) }
     }
 
-    #[cfg(any(
-        target_os = "espidf",
-        target_os = "horizon",
-        target_os = "freebsd",
-        target_os = "dragonfly",
-        netbsd10
-    ))]
+    #[cfg(any(target_os = "espidf", target_os = "horizon", target_os = "freebsd", netbsd10))]
     fn getrandom(buf: &mut [u8]) -> libc::ssize_t {
         unsafe { libc::getrandom(buf.as_mut_ptr().cast(), buf.len(), 0) }
     }
 
+    #[cfg(target_os = "dragonfly")]
+    fn getrandom(buf: &mut [u8]) -> libc::ssize_t {
+        extern "C" {
+            fn getrandom(
+                buf: *mut libc::c_void,
+                buflen: libc::size_t,
+                flags: libc::c_uint,
+            ) -> libc::ssize_t;
+        }
+        unsafe { getrandom(buf.as_mut_ptr().cast(), buf.len(), 0) }
+    }
+
     #[cfg(not(any(
         target_os = "linux",
         target_os = "android",
diff --git a/library/std/src/sys/pal/unix/stack_overflow.rs b/library/std/src/sys/pal/unix/stack_overflow.rs
index 78a599077c7..26c49257ad0 100644
--- a/library/std/src/sys/pal/unix/stack_overflow.rs
+++ b/library/std/src/sys/pal/unix/stack_overflow.rs
@@ -11,7 +11,7 @@ pub struct Handler {
 
 impl Handler {
     pub unsafe fn new() -> Handler {
-        make_handler()
+        make_handler(false)
     }
 
     fn null() -> Handler {
@@ -29,34 +29,41 @@ impl Drop for Handler {
 
 #[cfg(any(
     target_os = "linux",
-    target_os = "macos",
-    target_os = "dragonfly",
     target_os = "freebsd",
     target_os = "hurd",
-    target_os = "solaris",
-    target_os = "illumos",
+    target_os = "macos",
     target_os = "netbsd",
-    target_os = "openbsd"
+    target_os = "openbsd",
+    target_os = "solaris"
 ))]
 mod imp {
     use super::Handler;
+    use crate::cell::Cell;
     use crate::io;
     use crate::mem;
+    use crate::ops::Range;
     use crate::ptr;
+    use crate::sync::atomic::{AtomicBool, AtomicPtr, AtomicUsize, Ordering};
+    use crate::sys::pal::unix::os;
     use crate::thread;
 
-    use libc::MAP_FAILED;
     #[cfg(not(all(target_os = "linux", target_env = "gnu")))]
-    use libc::{mmap as mmap64, munmap};
+    use libc::{mmap as mmap64, mprotect, munmap};
     #[cfg(all(target_os = "linux", target_env = "gnu"))]
-    use libc::{mmap64, munmap};
-    use libc::{sigaction, sighandler_t, SA_ONSTACK, SA_SIGINFO, SIGBUS, SIG_DFL};
+    use libc::{mmap64, mprotect, munmap};
+    use libc::{sigaction, sighandler_t, SA_ONSTACK, SA_SIGINFO, SIGBUS, SIGSEGV, SIG_DFL};
     use libc::{sigaltstack, SS_DISABLE};
-    use libc::{MAP_ANON, MAP_PRIVATE, PROT_NONE, PROT_READ, PROT_WRITE, SIGSEGV};
+    use libc::{MAP_ANON, MAP_FAILED, MAP_FIXED, MAP_PRIVATE, PROT_NONE, PROT_READ, PROT_WRITE};
 
-    use crate::sync::atomic::{AtomicBool, AtomicPtr, Ordering};
-    use crate::sys::pal::unix::os::page_size;
-    use crate::sys_common::thread_info;
+    // We use a TLS variable to store the address of the guard page. While TLS
+    // variables are not guaranteed to be signal-safe, this works out in practice
+    // since we make sure to write to the variable before the signal stack is
+    // installed, thereby ensuring that the variable is always allocated when
+    // the signal handler is called.
+    thread_local! {
+        // FIXME: use `Range` once that implements `Copy`.
+        static GUARD: Cell<(usize, usize)> = const { Cell::new((0, 0)) };
+    }
 
     // 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
@@ -84,12 +91,12 @@ mod imp {
         info: *mut libc::siginfo_t,
         _data: *mut libc::c_void,
     ) {
-        let guard = thread_info::stack_guard().unwrap_or(0..0);
+        let (start, end) = GUARD.get();
         let addr = (*info).si_addr() as usize;
 
         // If the faulting address is within the guard page, then we print a
         // message saying so and abort.
-        if guard.start <= addr && addr < guard.end {
+        if start <= addr && addr < end {
             rtprintpanic!(
                 "\nthread '{}' has overflowed its stack\n",
                 thread::current().name().unwrap_or("<unknown>")
@@ -105,10 +112,17 @@ mod imp {
         }
     }
 
+    static PAGE_SIZE: AtomicUsize = AtomicUsize::new(0);
     static MAIN_ALTSTACK: AtomicPtr<libc::c_void> = AtomicPtr::new(ptr::null_mut());
     static NEED_ALTSTACK: AtomicBool = AtomicBool::new(false);
 
     pub unsafe fn init() {
+        PAGE_SIZE.store(os::page_size(), Ordering::Relaxed);
+
+        // Always write to GUARD to ensure the TLS variable is allocated.
+        let guard = install_main_guard().unwrap_or(0..0);
+        GUARD.set((guard.start, guard.end));
+
         let mut action: sigaction = mem::zeroed();
         for &signal in &[SIGSEGV, SIGBUS] {
             sigaction(signal, ptr::null_mut(), &mut action);
@@ -121,7 +135,7 @@ mod imp {
             }
         }
 
-        let handler = make_handler();
+        let handler = make_handler(true);
         MAIN_ALTSTACK.store(handler.data, Ordering::Relaxed);
         mem::forget(handler);
     }
@@ -150,7 +164,7 @@ mod imp {
         let flags = MAP_PRIVATE | MAP_ANON;
 
         let sigstack_size = sigstack_size();
-        let page_size = page_size();
+        let page_size = PAGE_SIZE.load(Ordering::Relaxed);
 
         let stackp = mmap64(
             ptr::null_mut(),
@@ -172,10 +186,17 @@ mod imp {
         libc::stack_t { ss_sp: stackp, ss_flags: 0, ss_size: sigstack_size }
     }
 
-    pub unsafe fn make_handler() -> Handler {
+    pub unsafe fn make_handler(main_thread: bool) -> Handler {
         if !NEED_ALTSTACK.load(Ordering::Relaxed) {
             return Handler::null();
         }
+
+        if !main_thread {
+            // Always write to GUARD to ensure the TLS variable is allocated.
+            let guard = current_guard().unwrap_or(0..0);
+            GUARD.set((guard.start, guard.end));
+        }
+
         let mut stack = mem::zeroed();
         sigaltstack(ptr::null(), &mut stack);
         // Configure alternate signal stack, if one is not already set.
@@ -191,7 +212,7 @@ mod imp {
     pub unsafe fn drop_handler(data: *mut libc::c_void) {
         if !data.is_null() {
             let sigstack_size = sigstack_size();
-            let page_size = page_size();
+            let page_size = PAGE_SIZE.load(Ordering::Relaxed);
             let stack = libc::stack_t {
                 ss_sp: ptr::null_mut(),
                 ss_flags: SS_DISABLE,
@@ -225,25 +246,266 @@ mod imp {
     fn sigstack_size() -> usize {
         libc::SIGSTKSZ
     }
+
+    #[cfg(target_os = "solaris")]
+    unsafe fn get_stack_start() -> Option<*mut libc::c_void> {
+        let mut current_stack: libc::stack_t = crate::mem::zeroed();
+        assert_eq!(libc::stack_getbounds(&mut current_stack), 0);
+        Some(current_stack.ss_sp)
+    }
+
+    #[cfg(target_os = "macos")]
+    unsafe fn get_stack_start() -> Option<*mut libc::c_void> {
+        let th = libc::pthread_self();
+        let stackptr = libc::pthread_get_stackaddr_np(th);
+        Some(stackptr.map_addr(|addr| addr - libc::pthread_get_stacksize_np(th)))
+    }
+
+    #[cfg(target_os = "openbsd")]
+    unsafe fn get_stack_start() -> Option<*mut libc::c_void> {
+        let mut current_stack: libc::stack_t = crate::mem::zeroed();
+        assert_eq!(libc::pthread_stackseg_np(libc::pthread_self(), &mut current_stack), 0);
+
+        let stack_ptr = current_stack.ss_sp;
+        let stackaddr = if libc::pthread_main_np() == 1 {
+            // main thread
+            stack_ptr.addr() - current_stack.ss_size + PAGE_SIZE.load(Ordering::Relaxed)
+        } else {
+            // new thread
+            stack_ptr.addr() - current_stack.ss_size
+        };
+        Some(stack_ptr.with_addr(stackaddr))
+    }
+
+    #[cfg(any(
+        target_os = "android",
+        target_os = "freebsd",
+        target_os = "netbsd",
+        target_os = "hurd",
+        target_os = "linux",
+        target_os = "l4re"
+    ))]
+    unsafe fn get_stack_start() -> Option<*mut libc::c_void> {
+        let mut ret = None;
+        let mut attr: libc::pthread_attr_t = crate::mem::zeroed();
+        #[cfg(target_os = "freebsd")]
+        assert_eq!(libc::pthread_attr_init(&mut attr), 0);
+        #[cfg(target_os = "freebsd")]
+        let e = libc::pthread_attr_get_np(libc::pthread_self(), &mut attr);
+        #[cfg(not(target_os = "freebsd"))]
+        let e = libc::pthread_getattr_np(libc::pthread_self(), &mut attr);
+        if e == 0 {
+            let mut stackaddr = crate::ptr::null_mut();
+            let mut stacksize = 0;
+            assert_eq!(libc::pthread_attr_getstack(&attr, &mut stackaddr, &mut stacksize), 0);
+            ret = Some(stackaddr);
+        }
+        if e == 0 || cfg!(target_os = "freebsd") {
+            assert_eq!(libc::pthread_attr_destroy(&mut attr), 0);
+        }
+        ret
+    }
+
+    unsafe fn get_stack_start_aligned() -> Option<*mut libc::c_void> {
+        let page_size = PAGE_SIZE.load(Ordering::Relaxed);
+        let stackptr = get_stack_start()?;
+        let stackaddr = stackptr.addr();
+
+        // Ensure stackaddr is page aligned! A parent process might
+        // have reset RLIMIT_STACK to be non-page aligned. The
+        // pthread_attr_getstack() reports the usable stack area
+        // stackaddr < stackaddr + stacksize, so if stackaddr is not
+        // page-aligned, calculate the fix such that stackaddr <
+        // new_page_aligned_stackaddr < stackaddr + stacksize
+        let remainder = stackaddr % page_size;
+        Some(if remainder == 0 {
+            stackptr
+        } else {
+            stackptr.with_addr(stackaddr + page_size - remainder)
+        })
+    }
+
+    unsafe fn install_main_guard() -> Option<Range<usize>> {
+        let page_size = PAGE_SIZE.load(Ordering::Relaxed);
+        if cfg!(all(target_os = "linux", not(target_env = "musl"))) {
+            // Linux doesn't allocate the whole stack right away, and
+            // the kernel has its own stack-guard mechanism to fault
+            // when growing too close to an existing mapping. If we map
+            // our own guard, then the kernel starts enforcing a rather
+            // large gap above that, rendering much of the possible
+            // stack space useless. See #43052.
+            //
+            // Instead, we'll just note where we expect rlimit to start
+            // faulting, so our handler can report "stack overflow", and
+            // trust that the kernel's own stack guard will work.
+            let stackptr = get_stack_start_aligned()?;
+            let stackaddr = stackptr.addr();
+            Some(stackaddr - page_size..stackaddr)
+        } else if cfg!(all(target_os = "linux", target_env = "musl")) {
+            // For the main thread, the musl's pthread_attr_getstack
+            // returns the current stack size, rather than maximum size
+            // it can eventually grow to. It cannot be used to determine
+            // the position of kernel's stack guard.
+            None
+        } else if cfg!(target_os = "freebsd") {
+            // FreeBSD's stack autogrows, and optionally includes a guard page
+            // at the bottom. If we try to remap the bottom of the stack
+            // ourselves, FreeBSD's guard page moves upwards. So we'll just use
+            // the builtin guard page.
+            let stackptr = get_stack_start_aligned()?;
+            let guardaddr = stackptr.addr();
+            // Technically the number of guard pages is tunable and controlled
+            // by the security.bsd.stack_guard_page sysctl.
+            // By default it is 1, checking once is enough since it is
+            // a boot time config value.
+            static PAGES: crate::sync::OnceLock<usize> = crate::sync::OnceLock::new();
+
+            let pages = PAGES.get_or_init(|| {
+                use crate::sys::weak::dlsym;
+                dlsym!(fn sysctlbyname(*const libc::c_char, *mut libc::c_void, *mut libc::size_t, *const libc::c_void, libc::size_t) -> libc::c_int);
+                let mut guard: usize = 0;
+                let mut size = crate::mem::size_of_val(&guard);
+                let oid = crate::ffi::CStr::from_bytes_with_nul(
+                    b"security.bsd.stack_guard_page\0",
+                )
+                .unwrap();
+                match sysctlbyname.get() {
+                    Some(fcn) => {
+                        if fcn(oid.as_ptr(), core::ptr::addr_of_mut!(guard) as *mut _, core::ptr::addr_of_mut!(size) as *mut _, crate::ptr::null_mut(), 0) == 0 {
+                            guard
+                        } else {
+                            1
+                        }
+                    },
+                    _ => 1,
+                }
+            });
+            Some(guardaddr..guardaddr + pages * page_size)
+        } else if cfg!(any(target_os = "openbsd", target_os = "netbsd")) {
+            // OpenBSD stack already includes a guard page, and stack is
+            // immutable.
+            // NetBSD stack includes the guard page.
+            //
+            // We'll just note where we expect rlimit to start
+            // faulting, so our handler can report "stack overflow", and
+            // trust that the kernel's own stack guard will work.
+            let stackptr = get_stack_start_aligned()?;
+            let stackaddr = stackptr.addr();
+            Some(stackaddr - page_size..stackaddr)
+        } else {
+            // Reallocate the last page of the stack.
+            // This ensures SIGBUS will be raised on
+            // stack overflow.
+            // Systems which enforce strict PAX MPROTECT do not allow
+            // to mprotect() a mapping with less restrictive permissions
+            // than the initial mmap() used, so we mmap() here with
+            // read/write permissions and only then mprotect() it to
+            // no permissions at all. See issue #50313.
+            let stackptr = get_stack_start_aligned()?;
+            let result = mmap64(
+                stackptr,
+                page_size,
+                PROT_READ | PROT_WRITE,
+                MAP_PRIVATE | MAP_ANON | MAP_FIXED,
+                -1,
+                0,
+            );
+            if result != stackptr || result == MAP_FAILED {
+                panic!("failed to allocate a guard page: {}", io::Error::last_os_error());
+            }
+
+            let result = mprotect(stackptr, page_size, PROT_NONE);
+            if result != 0 {
+                panic!("failed to protect the guard page: {}", io::Error::last_os_error());
+            }
+
+            let guardaddr = stackptr.addr();
+
+            Some(guardaddr..guardaddr + page_size)
+        }
+    }
+
+    #[cfg(any(target_os = "macos", target_os = "openbsd", target_os = "solaris"))]
+    unsafe fn current_guard() -> Option<Range<usize>> {
+        let stackptr = get_stack_start()?;
+        let stackaddr = stackptr.addr();
+        Some(stackaddr - PAGE_SIZE.load(Ordering::Relaxed)..stackaddr)
+    }
+
+    #[cfg(any(
+        target_os = "android",
+        target_os = "freebsd",
+        target_os = "hurd",
+        target_os = "linux",
+        target_os = "netbsd",
+        target_os = "l4re"
+    ))]
+    unsafe fn current_guard() -> Option<Range<usize>> {
+        let mut ret = None;
+        let mut attr: libc::pthread_attr_t = crate::mem::zeroed();
+        #[cfg(target_os = "freebsd")]
+        assert_eq!(libc::pthread_attr_init(&mut attr), 0);
+        #[cfg(target_os = "freebsd")]
+        let e = libc::pthread_attr_get_np(libc::pthread_self(), &mut attr);
+        #[cfg(not(target_os = "freebsd"))]
+        let e = libc::pthread_getattr_np(libc::pthread_self(), &mut attr);
+        if e == 0 {
+            let mut guardsize = 0;
+            assert_eq!(libc::pthread_attr_getguardsize(&attr, &mut guardsize), 0);
+            if guardsize == 0 {
+                if cfg!(all(target_os = "linux", target_env = "musl")) {
+                    // musl versions before 1.1.19 always reported guard
+                    // size obtained from pthread_attr_get_np as zero.
+                    // Use page size as a fallback.
+                    guardsize = PAGE_SIZE.load(Ordering::Relaxed);
+                } else {
+                    panic!("there is no guard page");
+                }
+            }
+            let mut stackptr = crate::ptr::null_mut::<libc::c_void>();
+            let mut size = 0;
+            assert_eq!(libc::pthread_attr_getstack(&attr, &mut stackptr, &mut size), 0);
+
+            let stackaddr = stackptr.addr();
+            ret = if cfg!(any(target_os = "freebsd", target_os = "netbsd", target_os = "hurd")) {
+                Some(stackaddr - guardsize..stackaddr)
+            } else if cfg!(all(target_os = "linux", target_env = "musl")) {
+                Some(stackaddr - guardsize..stackaddr)
+            } else if cfg!(all(target_os = "linux", any(target_env = "gnu", target_env = "uclibc")))
+            {
+                // glibc used to include the guard area within the stack, as noted in the BUGS
+                // section of `man pthread_attr_getguardsize`. This has been corrected starting
+                // with glibc 2.27, and in some distro backports, so the guard is now placed at the
+                // end (below) the stack. There's no easy way for us to know which we have at
+                // runtime, so we'll just match any fault in the range right above or below the
+                // stack base to call that fault a stack overflow.
+                Some(stackaddr - guardsize..stackaddr + guardsize)
+            } else {
+                Some(stackaddr..stackaddr + guardsize)
+            };
+        }
+        if e == 0 || cfg!(target_os = "freebsd") {
+            assert_eq!(libc::pthread_attr_destroy(&mut attr), 0);
+        }
+        ret
+    }
 }
 
 #[cfg(not(any(
     target_os = "linux",
-    target_os = "macos",
-    target_os = "dragonfly",
     target_os = "freebsd",
     target_os = "hurd",
-    target_os = "solaris",
-    target_os = "illumos",
+    target_os = "macos",
     target_os = "netbsd",
     target_os = "openbsd",
+    target_os = "solaris"
 )))]
 mod imp {
     pub unsafe fn init() {}
 
     pub unsafe fn cleanup() {}
 
-    pub unsafe fn make_handler() -> super::Handler {
+    pub unsafe fn make_handler(_main_thread: bool) -> super::Handler {
         super::Handler::null()
     }
 
diff --git a/library/std/src/sys/pal/unix/thread.rs b/library/std/src/sys/pal/unix/thread.rs
index 6520ca9fc48..f56e64c3505 100644
--- a/library/std/src/sys/pal/unix/thread.rs
+++ b/library/std/src/sys/pal/unix/thread.rs
@@ -1,5 +1,5 @@
 use crate::cmp;
-use crate::ffi::{CStr, CString};
+use crate::ffi::CStr;
 use crate::io;
 use crate::mem;
 use crate::num::NonZero;
@@ -150,7 +150,13 @@ impl Thread {
         }
     }
 
-    #[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "watchos"))]
+    #[cfg(any(
+        target_os = "macos",
+        target_os = "ios",
+        target_os = "watchos",
+        target_os = "visionos",
+        target_os = "tvos"
+    ))]
     pub fn set_name(name: &CStr) {
         unsafe {
             let name = truncate_cstr::<{ libc::MAXTHREADNAMESIZE }>(name);
@@ -182,8 +188,11 @@ impl Thread {
 
         if let Some(f) = pthread_setname_np.get() {
             #[cfg(target_os = "nto")]
-            let name = truncate_cstr::<{ libc::_NTO_THREAD_NAME_MAX as usize }>(name);
+            const THREAD_NAME_MAX: usize = libc::_NTO_THREAD_NAME_MAX as usize;
+            #[cfg(any(target_os = "solaris", target_os = "illumos"))]
+            const THREAD_NAME_MAX: usize = 32;
 
+            let name = truncate_cstr::<{ THREAD_NAME_MAX }>(name);
             let res = unsafe { f(libc::pthread_self(), name.as_ptr()) };
             debug_assert_eq!(res, 0);
         }
@@ -225,44 +234,6 @@ impl Thread {
         // Newlib, Emscripten, and VxWorks have no way to set a thread name.
     }
 
-    #[cfg(target_os = "linux")]
-    pub fn get_name() -> Option<CString> {
-        const TASK_COMM_LEN: usize = 16;
-        let mut name = vec![0u8; TASK_COMM_LEN];
-        let res = unsafe {
-            libc::pthread_getname_np(libc::pthread_self(), name.as_mut_ptr().cast(), name.len())
-        };
-        if res != 0 {
-            return None;
-        }
-        name.truncate(name.iter().position(|&c| c == 0)?);
-        CString::new(name).ok()
-    }
-
-    #[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "watchos"))]
-    pub fn get_name() -> Option<CString> {
-        let mut name = vec![0u8; libc::MAXTHREADNAMESIZE];
-        let res = unsafe {
-            libc::pthread_getname_np(libc::pthread_self(), name.as_mut_ptr().cast(), name.len())
-        };
-        if res != 0 {
-            return None;
-        }
-        name.truncate(name.iter().position(|&c| c == 0)?);
-        CString::new(name).ok()
-    }
-
-    #[cfg(not(any(
-        target_os = "linux",
-        target_os = "macos",
-        target_os = "ios",
-        target_os = "tvos",
-        target_os = "watchos"
-    )))]
-    pub fn get_name() -> Option<CString> {
-        None
-    }
-
     #[cfg(not(target_os = "espidf"))]
     pub fn sleep(dur: Duration) {
         let mut secs = dur.as_secs();
@@ -334,7 +305,10 @@ impl Drop for Thread {
     target_os = "ios",
     target_os = "tvos",
     target_os = "watchos",
+    target_os = "visionos",
     target_os = "nto",
+    target_os = "solaris",
+    target_os = "illumos",
 ))]
 fn truncate_cstr<const MAX_WITH_NUL: usize>(cstr: &CStr) -> [libc::c_char; MAX_WITH_NUL] {
     let mut result = [0; MAX_WITH_NUL];
@@ -355,8 +329,6 @@ pub fn available_parallelism() -> io::Result<NonZero<usize>> {
             target_os = "tvos",
             target_os = "linux",
             target_os = "macos",
-            target_os = "solaris",
-            target_os = "illumos",
             target_os = "aix",
         ))] {
             #[allow(unused_assignments)]
@@ -426,7 +398,7 @@ pub fn available_parallelism() -> io::Result<NonZero<usize>> {
                     if !set.is_null() {
                         let mut count: usize = 0;
                         if libc::pthread_getaffinity_np(libc::pthread_self(), libc::_cpuset_size(set), set) == 0 {
-                            for i in 0..u64::MAX {
+                            for i in 0..libc::cpuid_t::MAX {
                                 match libc::_cpuset_isset(i, set) {
                                     -1 => break,
                                     0 => continue,
@@ -483,6 +455,12 @@ pub fn available_parallelism() -> io::Result<NonZero<usize>> {
                         .ok_or(io::const_io_error!(io::ErrorKind::NotFound, "The number of hardware threads is not known for the target platform"))
                 }
             }
+        } else if #[cfg(any(target_os = "solaris", target_os = "illumos"))] {
+            let mut cpus = 0u32;
+            if unsafe { libc::pset_info(libc::PS_MYID, core::ptr::null_mut(), &mut cpus, core::ptr::null_mut()) } != 0 {
+                return Err(io::const_io_error!(io::ErrorKind::NotFound, "The number of hardware threads is not known for the target platform"));
+            }
+            Ok(unsafe { NonZero::new_unchecked(cpus as usize) })
         } else if #[cfg(target_os = "haiku")] {
             // system_info cpu_count field gets the static data set at boot time with `smp_set_num_cpus`
             // `get_system_info` calls then `smp_get_num_cpus`
@@ -725,302 +703,6 @@ mod cgroups {
     }
 }
 
-#[cfg(all(
-    not(target_os = "linux"),
-    not(target_os = "freebsd"),
-    not(target_os = "hurd"),
-    not(target_os = "macos"),
-    not(target_os = "netbsd"),
-    not(target_os = "openbsd"),
-    not(target_os = "solaris")
-))]
-#[cfg_attr(test, allow(dead_code))]
-pub mod guard {
-    use crate::ops::Range;
-    pub type Guard = Range<usize>;
-    pub unsafe fn current() -> Option<Guard> {
-        None
-    }
-    pub unsafe fn init() -> Option<Guard> {
-        None
-    }
-}
-
-#[cfg(any(
-    target_os = "linux",
-    target_os = "freebsd",
-    target_os = "hurd",
-    target_os = "macos",
-    target_os = "netbsd",
-    target_os = "openbsd",
-    target_os = "solaris"
-))]
-#[cfg_attr(test, allow(dead_code))]
-pub mod guard {
-    #[cfg(not(all(target_os = "linux", target_env = "gnu")))]
-    use libc::{mmap as mmap64, mprotect};
-    #[cfg(all(target_os = "linux", target_env = "gnu"))]
-    use libc::{mmap64, mprotect};
-    use libc::{MAP_ANON, MAP_FAILED, MAP_FIXED, MAP_PRIVATE, PROT_NONE, PROT_READ, PROT_WRITE};
-
-    use crate::io;
-    use crate::ops::Range;
-    use crate::sync::atomic::{AtomicUsize, Ordering};
-    use crate::sys::os;
-
-    // This is initialized in init() and only read from after
-    static PAGE_SIZE: AtomicUsize = AtomicUsize::new(0);
-
-    pub type Guard = Range<usize>;
-
-    #[cfg(target_os = "solaris")]
-    unsafe fn get_stack_start() -> Option<*mut libc::c_void> {
-        let mut current_stack: libc::stack_t = crate::mem::zeroed();
-        assert_eq!(libc::stack_getbounds(&mut current_stack), 0);
-        Some(current_stack.ss_sp)
-    }
-
-    #[cfg(target_os = "macos")]
-    unsafe fn get_stack_start() -> Option<*mut libc::c_void> {
-        let th = libc::pthread_self();
-        let stackptr = libc::pthread_get_stackaddr_np(th);
-        Some(stackptr.map_addr(|addr| addr - libc::pthread_get_stacksize_np(th)))
-    }
-
-    #[cfg(target_os = "openbsd")]
-    unsafe fn get_stack_start() -> Option<*mut libc::c_void> {
-        let mut current_stack: libc::stack_t = crate::mem::zeroed();
-        assert_eq!(libc::pthread_stackseg_np(libc::pthread_self(), &mut current_stack), 0);
-
-        let stack_ptr = current_stack.ss_sp;
-        let stackaddr = if libc::pthread_main_np() == 1 {
-            // main thread
-            stack_ptr.addr() - current_stack.ss_size + PAGE_SIZE.load(Ordering::Relaxed)
-        } else {
-            // new thread
-            stack_ptr.addr() - current_stack.ss_size
-        };
-        Some(stack_ptr.with_addr(stackaddr))
-    }
-
-    #[cfg(any(
-        target_os = "android",
-        target_os = "freebsd",
-        target_os = "netbsd",
-        target_os = "hurd",
-        target_os = "linux",
-        target_os = "l4re"
-    ))]
-    unsafe fn get_stack_start() -> Option<*mut libc::c_void> {
-        let mut ret = None;
-        let mut attr: libc::pthread_attr_t = crate::mem::zeroed();
-        #[cfg(target_os = "freebsd")]
-        assert_eq!(libc::pthread_attr_init(&mut attr), 0);
-        #[cfg(target_os = "freebsd")]
-        let e = libc::pthread_attr_get_np(libc::pthread_self(), &mut attr);
-        #[cfg(not(target_os = "freebsd"))]
-        let e = libc::pthread_getattr_np(libc::pthread_self(), &mut attr);
-        if e == 0 {
-            let mut stackaddr = crate::ptr::null_mut();
-            let mut stacksize = 0;
-            assert_eq!(libc::pthread_attr_getstack(&attr, &mut stackaddr, &mut stacksize), 0);
-            ret = Some(stackaddr);
-        }
-        if e == 0 || cfg!(target_os = "freebsd") {
-            assert_eq!(libc::pthread_attr_destroy(&mut attr), 0);
-        }
-        ret
-    }
-
-    // Precondition: PAGE_SIZE is initialized.
-    unsafe fn get_stack_start_aligned() -> Option<*mut libc::c_void> {
-        let page_size = PAGE_SIZE.load(Ordering::Relaxed);
-        assert!(page_size != 0);
-        let stackptr = get_stack_start()?;
-        let stackaddr = stackptr.addr();
-
-        // Ensure stackaddr is page aligned! A parent process might
-        // have reset RLIMIT_STACK to be non-page aligned. The
-        // pthread_attr_getstack() reports the usable stack area
-        // stackaddr < stackaddr + stacksize, so if stackaddr is not
-        // page-aligned, calculate the fix such that stackaddr <
-        // new_page_aligned_stackaddr < stackaddr + stacksize
-        let remainder = stackaddr % page_size;
-        Some(if remainder == 0 {
-            stackptr
-        } else {
-            stackptr.with_addr(stackaddr + page_size - remainder)
-        })
-    }
-
-    pub unsafe fn init() -> Option<Guard> {
-        let page_size = os::page_size();
-        PAGE_SIZE.store(page_size, Ordering::Relaxed);
-
-        if cfg!(all(target_os = "linux", not(target_env = "musl"))) {
-            // Linux doesn't allocate the whole stack right away, and
-            // the kernel has its own stack-guard mechanism to fault
-            // when growing too close to an existing mapping. If we map
-            // our own guard, then the kernel starts enforcing a rather
-            // large gap above that, rendering much of the possible
-            // stack space useless. See #43052.
-            //
-            // Instead, we'll just note where we expect rlimit to start
-            // faulting, so our handler can report "stack overflow", and
-            // trust that the kernel's own stack guard will work.
-            let stackptr = get_stack_start_aligned()?;
-            let stackaddr = stackptr.addr();
-            Some(stackaddr - page_size..stackaddr)
-        } else if cfg!(all(target_os = "linux", target_env = "musl")) {
-            // For the main thread, the musl's pthread_attr_getstack
-            // returns the current stack size, rather than maximum size
-            // it can eventually grow to. It cannot be used to determine
-            // the position of kernel's stack guard.
-            None
-        } else if cfg!(target_os = "freebsd") {
-            // FreeBSD's stack autogrows, and optionally includes a guard page
-            // at the bottom. If we try to remap the bottom of the stack
-            // ourselves, FreeBSD's guard page moves upwards. So we'll just use
-            // the builtin guard page.
-            let stackptr = get_stack_start_aligned()?;
-            let guardaddr = stackptr.addr();
-            // Technically the number of guard pages is tunable and controlled
-            // by the security.bsd.stack_guard_page sysctl.
-            // By default it is 1, checking once is enough since it is
-            // a boot time config value.
-            static LOCK: crate::sync::OnceLock<usize> = crate::sync::OnceLock::new();
-            let guard = guardaddr
-                ..guardaddr
-                    + *LOCK.get_or_init(|| {
-                        use crate::sys::weak::dlsym;
-                        dlsym!(fn sysctlbyname(*const libc::c_char, *mut libc::c_void, *mut libc::size_t, *const libc::c_void, libc::size_t) -> libc::c_int);
-                        let mut guard: usize = 0;
-                        let mut size = crate::mem::size_of_val(&guard);
-                        let oid = crate::ffi::CStr::from_bytes_with_nul(
-                            b"security.bsd.stack_guard_page\0",
-                        )
-                        .unwrap();
-                        match sysctlbyname.get() {
-                            Some(fcn) => {
-                                if fcn(oid.as_ptr(), core::ptr::addr_of_mut!(guard) as *mut _, core::ptr::addr_of_mut!(size) as *mut _, crate::ptr::null_mut(), 0) == 0 {
-                                    return guard;
-                                }
-                                return 1;
-                            },
-                            _ => { return 1; }
-                        }
-                    }) * page_size;
-            Some(guard)
-        } else if cfg!(any(target_os = "openbsd", target_os = "netbsd")) {
-            // OpenBSD stack already includes a guard page, and stack is
-            // immutable.
-            // NetBSD stack includes the guard page.
-            //
-            // We'll just note where we expect rlimit to start
-            // faulting, so our handler can report "stack overflow", and
-            // trust that the kernel's own stack guard will work.
-            let stackptr = get_stack_start_aligned()?;
-            let stackaddr = stackptr.addr();
-            Some(stackaddr - page_size..stackaddr)
-        } else {
-            // Reallocate the last page of the stack.
-            // This ensures SIGBUS will be raised on
-            // stack overflow.
-            // Systems which enforce strict PAX MPROTECT do not allow
-            // to mprotect() a mapping with less restrictive permissions
-            // than the initial mmap() used, so we mmap() here with
-            // read/write permissions and only then mprotect() it to
-            // no permissions at all. See issue #50313.
-            let stackptr = get_stack_start_aligned()?;
-            let result = mmap64(
-                stackptr,
-                page_size,
-                PROT_READ | PROT_WRITE,
-                MAP_PRIVATE | MAP_ANON | MAP_FIXED,
-                -1,
-                0,
-            );
-            if result != stackptr || result == MAP_FAILED {
-                panic!("failed to allocate a guard page: {}", io::Error::last_os_error());
-            }
-
-            let result = mprotect(stackptr, page_size, PROT_NONE);
-            if result != 0 {
-                panic!("failed to protect the guard page: {}", io::Error::last_os_error());
-            }
-
-            let guardaddr = stackptr.addr();
-
-            Some(guardaddr..guardaddr + page_size)
-        }
-    }
-
-    #[cfg(any(target_os = "macos", target_os = "openbsd", target_os = "solaris"))]
-    pub unsafe fn current() -> Option<Guard> {
-        let stackptr = get_stack_start()?;
-        let stackaddr = stackptr.addr();
-        Some(stackaddr - PAGE_SIZE.load(Ordering::Relaxed)..stackaddr)
-    }
-
-    #[cfg(any(
-        target_os = "android",
-        target_os = "freebsd",
-        target_os = "hurd",
-        target_os = "linux",
-        target_os = "netbsd",
-        target_os = "l4re"
-    ))]
-    pub unsafe fn current() -> Option<Guard> {
-        let mut ret = None;
-        let mut attr: libc::pthread_attr_t = crate::mem::zeroed();
-        #[cfg(target_os = "freebsd")]
-        assert_eq!(libc::pthread_attr_init(&mut attr), 0);
-        #[cfg(target_os = "freebsd")]
-        let e = libc::pthread_attr_get_np(libc::pthread_self(), &mut attr);
-        #[cfg(not(target_os = "freebsd"))]
-        let e = libc::pthread_getattr_np(libc::pthread_self(), &mut attr);
-        if e == 0 {
-            let mut guardsize = 0;
-            assert_eq!(libc::pthread_attr_getguardsize(&attr, &mut guardsize), 0);
-            if guardsize == 0 {
-                if cfg!(all(target_os = "linux", target_env = "musl")) {
-                    // musl versions before 1.1.19 always reported guard
-                    // size obtained from pthread_attr_get_np as zero.
-                    // Use page size as a fallback.
-                    guardsize = PAGE_SIZE.load(Ordering::Relaxed);
-                } else {
-                    panic!("there is no guard page");
-                }
-            }
-            let mut stackptr = crate::ptr::null_mut::<libc::c_void>();
-            let mut size = 0;
-            assert_eq!(libc::pthread_attr_getstack(&attr, &mut stackptr, &mut size), 0);
-
-            let stackaddr = stackptr.addr();
-            ret = if cfg!(any(target_os = "freebsd", target_os = "netbsd", target_os = "hurd")) {
-                Some(stackaddr - guardsize..stackaddr)
-            } else if cfg!(all(target_os = "linux", target_env = "musl")) {
-                Some(stackaddr - guardsize..stackaddr)
-            } else if cfg!(all(target_os = "linux", any(target_env = "gnu", target_env = "uclibc")))
-            {
-                // glibc used to include the guard area within the stack, as noted in the BUGS
-                // section of `man pthread_attr_getguardsize`. This has been corrected starting
-                // with glibc 2.27, and in some distro backports, so the guard is now placed at the
-                // end (below) the stack. There's no easy way for us to know which we have at
-                // runtime, so we'll just match any fault in the range right above or below the
-                // stack base to call that fault a stack overflow.
-                Some(stackaddr - guardsize..stackaddr + guardsize)
-            } else {
-                Some(stackaddr..stackaddr + guardsize)
-            };
-        }
-        if e == 0 || cfg!(target_os = "freebsd") {
-            assert_eq!(libc::pthread_attr_destroy(&mut attr), 0);
-        }
-        ret
-    }
-}
-
 // glibc >= 2.15 has a __pthread_get_minstack() function that returns
 // PTHREAD_STACK_MIN plus bytes needed for thread-local storage.
 // We need that information to avoid blowing up when a small stack
diff --git a/library/std/src/sys/pal/unix/thread_local_dtor.rs b/library/std/src/sys/pal/unix/thread_local_dtor.rs
index 79b152cece9..1164c1782f4 100644
--- a/library/std/src/sys/pal/unix/thread_local_dtor.rs
+++ b/library/std/src/sys/pal/unix/thread_local_dtor.rs
@@ -35,7 +35,7 @@ pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) {
     #[cfg(not(sanitizer_cfi_normalize_integers))]
     #[cfi_encoding = "i"]
     #[repr(transparent)]
-    pub struct c_int(pub libc::c_int);
+    pub struct c_int(#[allow(dead_code)] pub libc::c_int);
 
     extern "C" {
         #[linkage = "extern_weak"]
@@ -76,7 +76,13 @@ pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) {
 // workaround below is to register, via _tlv_atexit, a custom DTOR list once per
 // thread. thread_local dtors are pushed to the DTOR list without calling
 // _tlv_atexit.
-#[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos", target_os = "tvos"))]
+#[cfg(any(
+    target_os = "macos",
+    target_os = "ios",
+    target_os = "watchos",
+    target_os = "visionos",
+    target_os = "tvos"
+))]
 pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) {
     use crate::cell::{Cell, RefCell};
     use crate::ptr;
diff --git a/library/std/src/sys/pal/unix/thread_parking/mod.rs b/library/std/src/sys/pal/unix/thread_parking/mod.rs
index 185333c072f..3348d4b366d 100644
--- a/library/std/src/sys/pal/unix/thread_parking/mod.rs
+++ b/library/std/src/sys/pal/unix/thread_parking/mod.rs
@@ -16,6 +16,7 @@ cfg_if::cfg_if! {
             target_os = "macos",
             target_os = "ios",
             target_os = "watchos",
+            target_os = "visionos",
             target_os = "tvos",
         ),
         not(miri),
diff --git a/library/std/src/sys/pal/unix/thread_parking/pthread.rs b/library/std/src/sys/pal/unix/thread_parking/pthread.rs
index bb79cf9548e..d0ad3e2ce3e 100644
--- a/library/std/src/sys/pal/unix/thread_parking/pthread.rs
+++ b/library/std/src/sys/pal/unix/thread_parking/pthread.rs
@@ -48,6 +48,7 @@ unsafe fn wait_timeout(
         target_os = "ios",
         target_os = "tvos",
         target_os = "watchos",
+        target_os = "visionos",
         target_os = "espidf",
         target_os = "horizon",
     ))]
@@ -76,6 +77,7 @@ unsafe fn wait_timeout(
         target_os = "ios",
         target_os = "tvos",
         target_os = "watchos",
+        target_os = "visionos",
         target_os = "espidf",
         target_os = "horizon",
     )))]
@@ -124,6 +126,7 @@ impl Parker {
                 target_os = "ios",
                 target_os = "tvos",
                 target_os = "watchos",
+                target_os = "visionos",
                 target_os = "l4re",
                 target_os = "android",
                 target_os = "redox",
diff --git a/library/std/src/sys/pal/unix/time.rs b/library/std/src/sys/pal/unix/time.rs
index 0440f33ded1..e69775be8cf 100644
--- a/library/std/src/sys/pal/unix/time.rs
+++ b/library/std/src/sys/pal/unix/time.rs
@@ -90,7 +90,8 @@ impl Timespec {
             target_os = "macos",
             target_os = "ios",
             target_os = "tvos",
-            target_os = "watchos"
+            target_os = "watchos",
+            target_os = "visionos",
         ))]
         let (tv_sec, tv_nsec) =
             if (tv_sec <= 0 && tv_sec > i64::MIN) && (tv_nsec < 0 && tv_nsec > -1_000_000_000) {
@@ -278,6 +279,7 @@ impl Instant {
             target_os = "macos",
             target_os = "ios",
             target_os = "watchos",
+            target_os = "visionos",
             target_os = "tvos"
         ))]
         const clock_id: libc::clockid_t = libc::CLOCK_UPTIME_RAW;
@@ -285,6 +287,7 @@ impl Instant {
             target_os = "macos",
             target_os = "ios",
             target_os = "watchos",
+            target_os = "visionos",
             target_os = "tvos"
         )))]
         const clock_id: libc::clockid_t = libc::CLOCK_MONOTONIC;
diff --git a/library/std/src/sys/pal/unsupported/net.rs b/library/std/src/sys/pal/unsupported/net.rs
index 931fe9ba246..87e6106468f 100644
--- a/library/std/src/sys/pal/unsupported/net.rs
+++ b/library/std/src/sys/pal/unsupported/net.rs
@@ -346,6 +346,7 @@ pub mod netc {
 
     #[derive(Copy, Clone)]
     pub struct sockaddr_in {
+        #[allow(dead_code)]
         pub sin_family: sa_family_t,
         pub sin_port: u16,
         pub sin_addr: in_addr,
@@ -358,6 +359,7 @@ pub mod netc {
 
     #[derive(Copy, Clone)]
     pub struct sockaddr_in6 {
+        #[allow(dead_code)]
         pub sin6_family: sa_family_t,
         pub sin6_port: u16,
         pub sin6_addr: in6_addr,
diff --git a/library/std/src/sys/pal/unsupported/process.rs b/library/std/src/sys/pal/unsupported/process.rs
index 6a989dd3e76..2445d9073db 100644
--- a/library/std/src/sys/pal/unsupported/process.rs
+++ b/library/std/src/sys/pal/unsupported/process.rs
@@ -1,7 +1,6 @@
-use crate::ffi::OsStr;
+use crate::ffi::{OsStr, OsString};
 use crate::fmt;
 use crate::io;
-use crate::marker::PhantomData;
 use crate::num::NonZero;
 use crate::path::Path;
 use crate::sys::fs::File;
@@ -16,7 +15,14 @@ pub use crate::ffi::OsString as EnvKey;
 ////////////////////////////////////////////////////////////////////////////////
 
 pub struct Command {
+    program: OsString,
+    args: Vec<OsString>,
     env: CommandEnv,
+
+    cwd: Option<OsString>,
+    stdin: Option<Stdio>,
+    stdout: Option<Stdio>,
+    stderr: Option<Stdio>,
 }
 
 // passed back to std::process with the pipes connected to the child, if any
@@ -27,39 +33,62 @@ pub struct StdioPipes {
     pub stderr: Option<AnonPipe>,
 }
 
-// FIXME: This should be a unit struct, so we can always construct it
-// The value here should be never used, since we cannot spawn processes.
+#[derive(Debug)]
 pub enum Stdio {
     Inherit,
     Null,
     MakePipe,
+    ParentStdout,
+    ParentStderr,
+    #[allow(dead_code)] // This variant exists only for the Debug impl
+    InheritFile(File),
 }
 
 impl Command {
-    pub fn new(_program: &OsStr) -> Command {
-        Command { env: Default::default() }
+    pub fn new(program: &OsStr) -> Command {
+        Command {
+            program: program.to_owned(),
+            args: vec![program.to_owned()],
+            env: Default::default(),
+            cwd: None,
+            stdin: None,
+            stdout: None,
+            stderr: None,
+        }
     }
 
-    pub fn arg(&mut self, _arg: &OsStr) {}
+    pub fn arg(&mut self, arg: &OsStr) {
+        self.args.push(arg.to_owned());
+    }
 
     pub fn env_mut(&mut self) -> &mut CommandEnv {
         &mut self.env
     }
 
-    pub fn cwd(&mut self, _dir: &OsStr) {}
+    pub fn cwd(&mut self, dir: &OsStr) {
+        self.cwd = Some(dir.to_owned());
+    }
 
-    pub fn stdin(&mut self, _stdin: Stdio) {}
+    pub fn stdin(&mut self, stdin: Stdio) {
+        self.stdin = Some(stdin);
+    }
 
-    pub fn stdout(&mut self, _stdout: Stdio) {}
+    pub fn stdout(&mut self, stdout: Stdio) {
+        self.stdout = Some(stdout);
+    }
 
-    pub fn stderr(&mut self, _stderr: Stdio) {}
+    pub fn stderr(&mut self, stderr: Stdio) {
+        self.stderr = Some(stderr);
+    }
 
     pub fn get_program(&self) -> &OsStr {
-        panic!("unsupported")
+        &self.program
     }
 
     pub fn get_args(&self) -> CommandArgs<'_> {
-        CommandArgs { _p: PhantomData }
+        let mut iter = self.args.iter();
+        iter.next();
+        CommandArgs { iter }
     }
 
     pub fn get_envs(&self) -> CommandEnvs<'_> {
@@ -67,7 +96,7 @@ impl Command {
     }
 
     pub fn get_current_dir(&self) -> Option<&Path> {
-        None
+        self.cwd.as_ref().map(|cs| Path::new(cs))
     }
 
     pub fn spawn(
@@ -91,31 +120,83 @@ impl From<AnonPipe> for Stdio {
 
 impl From<io::Stdout> for Stdio {
     fn from(_: io::Stdout) -> Stdio {
-        // FIXME: This is wrong.
-        // Instead, the Stdio we have here should be a unit struct.
-        panic!("unsupported")
+        Stdio::ParentStdout
     }
 }
 
 impl From<io::Stderr> for Stdio {
     fn from(_: io::Stderr) -> Stdio {
-        // FIXME: This is wrong.
-        // Instead, the Stdio we have here should be a unit struct.
-        panic!("unsupported")
+        Stdio::ParentStderr
     }
 }
 
 impl From<File> for Stdio {
-    fn from(_file: File) -> Stdio {
-        // FIXME: This is wrong.
-        // Instead, the Stdio we have here should be a unit struct.
-        panic!("unsupported")
+    fn from(file: File) -> Stdio {
+        Stdio::InheritFile(file)
     }
 }
 
 impl fmt::Debug for Command {
-    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        Ok(())
+    // show all attributes
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        if f.alternate() {
+            let mut debug_command = f.debug_struct("Command");
+            debug_command.field("program", &self.program).field("args", &self.args);
+            if !self.env.is_unchanged() {
+                debug_command.field("env", &self.env);
+            }
+
+            if self.cwd.is_some() {
+                debug_command.field("cwd", &self.cwd);
+            }
+
+            if self.stdin.is_some() {
+                debug_command.field("stdin", &self.stdin);
+            }
+            if self.stdout.is_some() {
+                debug_command.field("stdout", &self.stdout);
+            }
+            if self.stderr.is_some() {
+                debug_command.field("stderr", &self.stderr);
+            }
+
+            debug_command.finish()
+        } else {
+            if let Some(ref cwd) = self.cwd {
+                write!(f, "cd {cwd:?} && ")?;
+            }
+            if self.env.does_clear() {
+                write!(f, "env -i ")?;
+                // Altered env vars will be printed next, that should exactly work as expected.
+            } else {
+                // Removed env vars need the command to be wrapped in `env`.
+                let mut any_removed = false;
+                for (key, value_opt) in self.get_envs() {
+                    if value_opt.is_none() {
+                        if !any_removed {
+                            write!(f, "env ")?;
+                            any_removed = true;
+                        }
+                        write!(f, "-u {} ", key.to_string_lossy())?;
+                    }
+                }
+            }
+            // Altered env vars can just be added in front of the program.
+            for (key, value_opt) in self.get_envs() {
+                if let Some(value) = value_opt {
+                    write!(f, "{}={value:?} ", key.to_string_lossy())?;
+                }
+            }
+            if self.program != self.args[0] {
+                write!(f, "[{:?}] ", self.program)?;
+            }
+            write!(f, "{:?}", self.args[0])?;
+
+            for arg in &self.args[1..] {
+                write!(f, " {:?}", arg)?;
+            }
+            Ok(())
+        }
     }
 }
 
@@ -217,23 +298,30 @@ impl Process {
 }
 
 pub struct CommandArgs<'a> {
-    _p: PhantomData<&'a ()>,
+    iter: crate::slice::Iter<'a, OsString>,
 }
 
 impl<'a> Iterator for CommandArgs<'a> {
     type Item = &'a OsStr;
     fn next(&mut self) -> Option<&'a OsStr> {
-        None
+        self.iter.next().map(|os| &**os)
     }
     fn size_hint(&self) -> (usize, Option<usize>) {
-        (0, Some(0))
+        self.iter.size_hint()
     }
 }
 
-impl<'a> ExactSizeIterator for CommandArgs<'a> {}
+impl<'a> ExactSizeIterator for CommandArgs<'a> {
+    fn len(&self) -> usize {
+        self.iter.len()
+    }
+    fn is_empty(&self) -> bool {
+        self.iter.is_empty()
+    }
+}
 
 impl<'a> fmt::Debug for CommandArgs<'a> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_list().finish()
+        f.debug_list().entries(self.iter.clone()).finish()
     }
 }
diff --git a/library/std/src/sys/pal/unsupported/thread.rs b/library/std/src/sys/pal/unsupported/thread.rs
index b3a91ee1d4c..ea939247199 100644
--- a/library/std/src/sys/pal/unsupported/thread.rs
+++ b/library/std/src/sys/pal/unsupported/thread.rs
@@ -1,5 +1,5 @@
 use super::unsupported;
-use crate::ffi::{CStr, CString};
+use crate::ffi::CStr;
 use crate::io;
 use crate::num::NonZero;
 use crate::time::Duration;
@@ -22,10 +22,6 @@ impl Thread {
         // nope
     }
 
-    pub fn get_name() -> Option<CString> {
-        None
-    }
-
     pub fn sleep(_dur: Duration) {
         panic!("can't sleep");
     }
@@ -38,13 +34,3 @@ impl Thread {
 pub fn available_parallelism() -> io::Result<NonZero<usize>> {
     unsupported()
 }
-
-pub mod guard {
-    pub type Guard = !;
-    pub unsafe fn current() -> Option<Guard> {
-        None
-    }
-    pub unsafe fn init() -> Option<Guard> {
-        None
-    }
-}
diff --git a/library/std/src/sys/pal/wasi/net.rs b/library/std/src/sys/pal/wasi/net.rs
index 2098d05db0b..b4cf94c8781 100644
--- a/library/std/src/sys/pal/wasi/net.rs
+++ b/library/std/src/sys/pal/wasi/net.rs
@@ -520,6 +520,7 @@ pub mod netc {
 
     #[derive(Copy, Clone)]
     pub struct sockaddr_in {
+        #[allow(dead_code)]
         pub sin_family: sa_family_t,
         pub sin_port: u16,
         pub sin_addr: in_addr,
@@ -532,6 +533,7 @@ pub mod netc {
 
     #[derive(Copy, Clone)]
     pub struct sockaddr_in6 {
+        #[allow(dead_code)]
         pub sin6_family: sa_family_t,
         pub sin6_port: u16,
         pub sin6_addr: in6_addr,
diff --git a/library/std/src/sys/pal/wasi/thread.rs b/library/std/src/sys/pal/wasi/thread.rs
index 4b116052f8f..d45fb28b67e 100644
--- a/library/std/src/sys/pal/wasi/thread.rs
+++ b/library/std/src/sys/pal/wasi/thread.rs
@@ -1,4 +1,4 @@
-use crate::ffi::{CStr, CString};
+use crate::ffi::CStr;
 use crate::io;
 use crate::mem;
 use crate::num::NonZero;
@@ -134,10 +134,6 @@ impl Thread {
         // nope
     }
 
-    pub fn get_name() -> Option<CString> {
-        None
-    }
-
     pub fn sleep(dur: Duration) {
         let nanos = dur.as_nanos();
         assert!(nanos <= u64::MAX as u128);
@@ -193,13 +189,3 @@ impl Thread {
 pub fn available_parallelism() -> io::Result<NonZero<usize>> {
     unsupported()
 }
-
-pub mod guard {
-    pub type Guard = !;
-    pub unsafe fn current() -> Option<Guard> {
-        None
-    }
-    pub unsafe fn init() -> Option<Guard> {
-        None
-    }
-}
diff --git a/library/std/src/sys/pal/wasip2/cabi_realloc.rs b/library/std/src/sys/pal/wasip2/cabi_realloc.rs
new file mode 100644
index 00000000000..820063173d6
--- /dev/null
+++ b/library/std/src/sys/pal/wasip2/cabi_realloc.rs
@@ -0,0 +1,65 @@
+//! This module contains a canonical definition of the `cabi_realloc` function
+//! for the component model.
+//!
+//! The component model's canonical ABI for representing datatypes in memory
+//! makes use of this function when transferring lists and strings, for example.
+//! This function behaves like C's `realloc` but also takes alignment into
+//! account.
+//!
+//! Components are notably not required to export this function, but nearly
+//! all components end up doing so currently. This definition in the standard
+//! library removes the need for all compilations to define this themselves.
+//!
+//! More information about the canonical ABI can be found at
+//! <https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md>
+//!
+//! Note that the name of this function is not standardized in the canonical ABI
+//! at this time. Instead it's a convention of the "componentization process"
+//! where a core wasm module is converted to a component to use this name.
+//! Additionally this is not the only possible definition of this function, so
+//! this is defined as a "weak" symbol. This means that other definitions are
+//! allowed to overwrite it if they are present in a compilation.
+
+use crate::alloc::{self, Layout};
+use crate::ptr;
+
+#[used]
+static FORCE_CODEGEN_OF_CABI_REALLOC: unsafe extern "C" fn(
+    *mut u8,
+    usize,
+    usize,
+    usize,
+) -> *mut u8 = cabi_realloc;
+
+#[linkage = "weak"]
+#[no_mangle]
+pub unsafe extern "C" fn cabi_realloc(
+    old_ptr: *mut u8,
+    old_len: usize,
+    align: usize,
+    new_len: usize,
+) -> *mut u8 {
+    let layout;
+    let ptr = if old_len == 0 {
+        if new_len == 0 {
+            return ptr::without_provenance_mut(align);
+        }
+        layout = Layout::from_size_align_unchecked(new_len, align);
+        alloc::alloc(layout)
+    } else {
+        debug_assert_ne!(new_len, 0, "non-zero old_len requires non-zero new_len!");
+        layout = Layout::from_size_align_unchecked(old_len, align);
+        alloc::realloc(old_ptr, layout, new_len)
+    };
+    if ptr.is_null() {
+        // Print a nice message in debug mode, but in release mode don't
+        // pull in so many dependencies related to printing so just emit an
+        // `unreachable` instruction.
+        if cfg!(debug_assertions) {
+            alloc::handle_alloc_error(layout);
+        } else {
+            super::abort_internal();
+        }
+    }
+    return ptr;
+}
diff --git a/library/std/src/sys/pal/wasip2/mod.rs b/library/std/src/sys/pal/wasip2/mod.rs
index d1d444d7b79..94aa458d2f9 100644
--- a/library/std/src/sys/pal/wasip2/mod.rs
+++ b/library/std/src/sys/pal/wasip2/mod.rs
@@ -10,8 +10,6 @@
 pub mod alloc;
 #[path = "../wasi/args.rs"]
 pub mod args;
-#[path = "../unix/cmath.rs"]
-pub mod cmath;
 #[path = "../wasi/env.rs"]
 pub mod env;
 #[path = "../wasi/fd.rs"]
@@ -28,10 +26,6 @@ pub mod io;
 pub mod net;
 #[path = "../wasi/os.rs"]
 pub mod os;
-#[path = "../unix/os_str.rs"]
-pub mod os_str;
-#[path = "../unix/path.rs"]
-pub mod path;
 #[path = "../unsupported/pipe.rs"]
 pub mod pipe;
 #[path = "../unsupported/process.rs"]
@@ -72,3 +66,5 @@ pub use helpers::decode_error_kind;
 use helpers::err2io;
 pub use helpers::hashmap_random_keys;
 pub use helpers::is_interrupted;
+
+mod cabi_realloc;
diff --git a/library/std/src/sys/pal/wasm/atomics/thread.rs b/library/std/src/sys/pal/wasm/atomics/thread.rs
index 3923ff821d9..49f936f1449 100644
--- a/library/std/src/sys/pal/wasm/atomics/thread.rs
+++ b/library/std/src/sys/pal/wasm/atomics/thread.rs
@@ -1,5 +1,4 @@
 use crate::ffi::CStr;
-use crate::ffi::CString;
 use crate::io;
 use crate::num::NonZero;
 use crate::sys::unsupported;
@@ -18,9 +17,6 @@ impl Thread {
     pub fn yield_now() {}
 
     pub fn set_name(_name: &CStr) {}
-    pub fn get_name() -> Option<CString> {
-        None
-    }
 
     pub fn sleep(dur: Duration) {
         use crate::arch::wasm32;
diff --git a/library/std/src/sys/pal/windows/args.rs b/library/std/src/sys/pal/windows/args.rs
index 2ecfe088d10..5098c05196e 100644
--- a/library/std/src/sys/pal/windows/args.rs
+++ b/library/std/src/sys/pal/windows/args.rs
@@ -7,7 +7,7 @@
 mod tests;
 
 use super::os::current_exe;
-use crate::ffi::OsString;
+use crate::ffi::{OsStr, OsString};
 use crate::fmt;
 use crate::io;
 use crate::num::NonZero;
@@ -17,6 +17,7 @@ use crate::sys::path::get_long_path;
 use crate::sys::process::ensure_no_nuls;
 use crate::sys::{c, to_u16s};
 use crate::sys_common::wstr::WStrUnits;
+use crate::sys_common::AsInner;
 use crate::vec;
 
 use crate::iter;
@@ -262,16 +263,92 @@ pub(crate) fn append_arg(cmd: &mut Vec<u16>, arg: &Arg, force_quotes: bool) -> i
     Ok(())
 }
 
+fn append_bat_arg(cmd: &mut Vec<u16>, arg: &OsStr, mut quote: bool) -> io::Result<()> {
+    ensure_no_nuls(arg)?;
+    // If an argument has 0 characters then we need to quote it to ensure
+    // that it actually gets passed through on the command line or otherwise
+    // it will be dropped entirely when parsed on the other end.
+    //
+    // We also need to quote the argument if it ends with `\` to guard against
+    // bat usage such as `"%~2"` (i.e. force quote arguments) otherwise a
+    // trailing slash will escape the closing quote.
+    if arg.is_empty() || arg.as_encoded_bytes().last() == Some(&b'\\') {
+        quote = true;
+    }
+    for cp in arg.as_inner().inner.code_points() {
+        if let Some(cp) = cp.to_char() {
+            // Rather than trying to find every ascii symbol that must be quoted,
+            // we assume that all ascii symbols must be quoted unless they're known to be good.
+            // We also quote Unicode control blocks for good measure.
+            // Note an unquoted `\` is fine so long as the argument isn't otherwise quoted.
+            static UNQUOTED: &str = r"#$*+-./:?@\_";
+            let ascii_needs_quotes =
+                cp.is_ascii() && !(cp.is_ascii_alphanumeric() || UNQUOTED.contains(cp));
+            if ascii_needs_quotes || cp.is_control() {
+                quote = true;
+            }
+        }
+    }
+
+    if quote {
+        cmd.push('"' as u16);
+    }
+    // Loop through the string, escaping `\` only if followed by `"`.
+    // And escaping `"` by doubling them.
+    let mut backslashes: usize = 0;
+    for x in arg.encode_wide() {
+        if x == '\\' as u16 {
+            backslashes += 1;
+        } else {
+            if x == '"' as u16 {
+                // Add n backslashes to total 2n before internal `"`.
+                cmd.extend((0..backslashes).map(|_| '\\' as u16));
+                // Appending an additional double-quote acts as an escape.
+                cmd.push(b'"' as u16)
+            } else if x == '%' as u16 || x == '\r' as u16 {
+                // yt-dlp hack: replaces `%` with `%%cd:~,%` to stop %VAR% being expanded as an environment variable.
+                //
+                // # Explanation
+                //
+                // cmd supports extracting a substring from a variable using the following syntax:
+                //     %variable:~start_index,end_index%
+                //
+                // In the above command `cd` is used as the variable and the start_index and end_index are left blank.
+                // `cd` is a built-in variable that dynamically expands to the current directory so it's always available.
+                // Explicitly omitting both the start and end index creates a zero-length substring.
+                //
+                // Therefore it all resolves to nothing. However, by doing this no-op we distract cmd.exe
+                // from potentially expanding %variables% in the argument.
+                cmd.extend_from_slice(&[
+                    '%' as u16, '%' as u16, 'c' as u16, 'd' as u16, ':' as u16, '~' as u16,
+                    ',' as u16,
+                ]);
+            }
+            backslashes = 0;
+        }
+        cmd.push(x);
+    }
+    if quote {
+        // Add n backslashes to total 2n before ending `"`.
+        cmd.extend((0..backslashes).map(|_| '\\' as u16));
+        cmd.push('"' as u16);
+    }
+    Ok(())
+}
+
 pub(crate) fn make_bat_command_line(
     script: &[u16],
     args: &[Arg],
     force_quotes: bool,
 ) -> io::Result<Vec<u16>> {
+    const INVALID_ARGUMENT_ERROR: io::Error =
+        io::const_io_error!(io::ErrorKind::InvalidInput, r#"batch file arguments are invalid"#);
     // Set the start of the command line to `cmd.exe /c "`
     // It is necessary to surround the command in an extra pair of quotes,
     // hence the trailing quote here. It will be closed after all arguments
     // have been added.
-    let mut cmd: Vec<u16> = "cmd.exe /d /c \"".encode_utf16().collect();
+    // Using /e:ON enables "command extensions" which is essential for the `%` hack to work.
+    let mut cmd: Vec<u16> = "cmd.exe /e:ON /v:OFF /d /c \"".encode_utf16().collect();
 
     // Push the script name surrounded by its quote pair.
     cmd.push(b'"' as u16);
@@ -291,18 +368,22 @@ pub(crate) fn make_bat_command_line(
     // reconstructed by the batch script by default.
     for arg in args {
         cmd.push(' ' as u16);
-        // Make sure to always quote special command prompt characters, including:
-        // * Characters `cmd /?` says require quotes.
-        // * `%` for environment variables, as in `%TMP%`.
-        // * `|<>` pipe/redirect characters.
-        const SPECIAL: &[u8] = b"\t &()[]{}^=;!'+,`~%|<>";
-        let force_quotes = match arg {
-            Arg::Regular(arg) if !force_quotes => {
-                arg.as_encoded_bytes().iter().any(|c| SPECIAL.contains(c))
+        match arg {
+            Arg::Regular(arg_os) => {
+                let arg_bytes = arg_os.as_encoded_bytes();
+                // Disallow \r and \n as they may truncate the arguments.
+                const DISALLOWED: &[u8] = b"\r\n";
+                if arg_bytes.iter().any(|c| DISALLOWED.contains(c)) {
+                    return Err(INVALID_ARGUMENT_ERROR);
+                }
+                append_bat_arg(&mut cmd, arg_os, force_quotes)?;
+            }
+            _ => {
+                // Raw arguments are passed on as-is.
+                // It's the user's responsibility to properly handle arguments in this case.
+                append_arg(&mut cmd, arg, force_quotes)?;
             }
-            _ => force_quotes,
         };
-        append_arg(&mut cmd, arg, force_quotes)?;
     }
 
     // Close the quote we left opened earlier.
diff --git a/library/std/src/sys/pal/windows/stack_overflow.rs b/library/std/src/sys/pal/windows/stack_overflow.rs
index 627763da856..f93f31026f8 100644
--- a/library/std/src/sys/pal/windows/stack_overflow.rs
+++ b/library/std/src/sys/pal/windows/stack_overflow.rs
@@ -3,21 +3,12 @@
 use crate::sys::c;
 use crate::thread;
 
-use super::api;
-
-pub struct Handler;
-
-impl Handler {
-    pub unsafe fn new() -> Handler {
-        // This API isn't available on XP, so don't panic in that case and just
-        // pray it works out ok.
-        if c::SetThreadStackGuarantee(&mut 0x5000) == 0
-            && api::get_last_error().code != c::ERROR_CALL_NOT_IMPLEMENTED
-        {
-            panic!("failed to reserve stack space for exception handling");
-        }
-        Handler
-    }
+/// Reserve stack space for use in stack overflow exceptions.
+pub unsafe fn reserve_stack() {
+    let result = c::SetThreadStackGuarantee(&mut 0x5000);
+    // Reserving stack space is not critical so we allow it to fail in the released build of libstd.
+    // We still use debug assert here so that CI will test that we haven't made a mistake calling the function.
+    debug_assert_ne!(result, 0, "failed to reserve stack space for exception handling");
 }
 
 unsafe extern "system" fn vectored_handler(ExceptionInfo: *mut c::EXCEPTION_POINTERS) -> c::LONG {
@@ -36,9 +27,10 @@ unsafe extern "system" fn vectored_handler(ExceptionInfo: *mut c::EXCEPTION_POIN
 }
 
 pub unsafe fn init() {
-    if c::AddVectoredExceptionHandler(0, Some(vectored_handler)).is_null() {
-        panic!("failed to install exception handler");
-    }
+    let result = c::AddVectoredExceptionHandler(0, Some(vectored_handler));
+    // Similar to the above, adding the stack overflow handler is allowed to fail
+    // but a debug assert is used so CI will still test that it normally works.
+    debug_assert!(!result.is_null(), "failed to install exception handler");
     // Set the thread stack guarantee for the main thread.
-    let _h = Handler::new();
+    reserve_stack();
 }
diff --git a/library/std/src/sys/pal/windows/stack_overflow_uwp.rs b/library/std/src/sys/pal/windows/stack_overflow_uwp.rs
index afdf7f566ae..9e9b3efaf1b 100644
--- a/library/std/src/sys/pal/windows/stack_overflow_uwp.rs
+++ b/library/std/src/sys/pal/windows/stack_overflow_uwp.rs
@@ -1,11 +1,4 @@
 #![cfg_attr(test, allow(dead_code))]
 
-pub struct Handler;
-
-impl Handler {
-    pub fn new() -> Handler {
-        Handler
-    }
-}
-
+pub unsafe fn reserve_stack() {}
 pub unsafe fn init() {}
diff --git a/library/std/src/sys/pal/windows/thread.rs b/library/std/src/sys/pal/windows/thread.rs
index 970bd9c6ce7..c0c63c3340f 100644
--- a/library/std/src/sys/pal/windows/thread.rs
+++ b/library/std/src/sys/pal/windows/thread.rs
@@ -9,7 +9,6 @@ use crate::sys::handle::Handle;
 use crate::sys::stack_overflow;
 use crate::sys_common::FromInner;
 use crate::time::Duration;
-use alloc::ffi::CString;
 use core::ffi::c_void;
 
 use super::time::WaitableTimer;
@@ -48,9 +47,8 @@ impl Thread {
 
         extern "system" fn thread_start(main: *mut c_void) -> c::DWORD {
             unsafe {
-                // Next, set up our stack overflow handler which may get triggered if we run
-                // out of stack.
-                let _handler = stack_overflow::Handler::new();
+                // Next, reserve some stack space for if we otherwise run out of stack.
+                stack_overflow::reserve_stack();
                 // Finally, let's run some code.
                 Box::from_raw(main as *mut Box<dyn FnOnce()>)();
             }
@@ -68,29 +66,6 @@ impl Thread {
         };
     }
 
-    pub fn get_name() -> Option<CString> {
-        unsafe {
-            let mut ptr = core::ptr::null_mut();
-            let result = c::GetThreadDescription(c::GetCurrentThread(), &mut ptr);
-            if result < 0 {
-                return None;
-            }
-            let name = String::from_utf16_lossy({
-                let mut len = 0;
-                while *ptr.add(len) != 0 {
-                    len += 1;
-                }
-                core::slice::from_raw_parts(ptr, len)
-            })
-            .into_bytes();
-            // Attempt to free the memory.
-            // This should never fail but if it does then there's not much we can do about it.
-            let result = c::LocalFree(ptr.cast::<c_void>());
-            debug_assert!(result.is_null());
-            if name.is_empty() { None } else { Some(CString::from_vec_unchecked(name)) }
-        }
-    }
-
     pub fn join(self) {
         let rc = unsafe { c::WaitForSingleObject(self.handle.as_raw_handle(), c::INFINITE) };
         if rc == c::WAIT_FAILED {
@@ -144,14 +119,3 @@ pub fn available_parallelism() -> io::Result<NonZero<usize>> {
         cpus => Ok(unsafe { NonZero::new_unchecked(cpus) }),
     }
 }
-
-#[cfg_attr(test, allow(dead_code))]
-pub mod guard {
-    pub type Guard = !;
-    pub unsafe fn current() -> Option<Guard> {
-        None
-    }
-    pub unsafe fn init() -> Option<Guard> {
-        None
-    }
-}
diff --git a/library/std/src/sys/pal/xous/thread.rs b/library/std/src/sys/pal/xous/thread.rs
index f95ceb7343b..da7d722cc70 100644
--- a/library/std/src/sys/pal/xous/thread.rs
+++ b/library/std/src/sys/pal/xous/thread.rs
@@ -1,4 +1,4 @@
-use crate::ffi::{CStr, CString};
+use crate::ffi::CStr;
 use crate::io;
 use crate::num::NonZero;
 use crate::os::xous::ffi::{
@@ -113,10 +113,6 @@ impl Thread {
         // nope
     }
 
-    pub fn get_name() -> Option<CString> {
-        None
-    }
-
     pub fn sleep(dur: Duration) {
         // Because the sleep server works on units of `usized milliseconds`, split
         // the messages up into these chunks. This means we may run into issues
@@ -140,13 +136,3 @@ pub fn available_parallelism() -> io::Result<NonZero<usize>> {
     // We're unicore right now.
     Ok(unsafe { NonZero::new_unchecked(1) })
 }
-
-pub mod guard {
-    pub type Guard = !;
-    pub unsafe fn current() -> Option<Guard> {
-        None
-    }
-    pub unsafe fn init() -> Option<Guard> {
-        None
-    }
-}
diff --git a/library/std/src/sys/pal/xous/thread_local_key.rs b/library/std/src/sys/pal/xous/thread_local_key.rs
index 2aaf46d0244..6c29813c79d 100644
--- a/library/std/src/sys/pal/xous/thread_local_key.rs
+++ b/library/std/src/sys/pal/xous/thread_local_key.rs
@@ -49,7 +49,7 @@ fn tls_ptr_addr() -> *mut *mut u8 {
             out(reg) tp,
         );
     }
-    core::ptr::from_exposed_addr_mut::<*mut u8>(tp)
+    core::ptr::with_exposed_provenance_mut::<*mut u8>(tp)
 }
 
 /// Create an area of memory that's unique per thread. This area will
diff --git a/library/std/src/sys/pal/zkvm/thread_local_key.rs b/library/std/src/sys/pal/zkvm/thread_local_key.rs
index 3ffe6247344..2f67924c618 100644
--- a/library/std/src/sys/pal/zkvm/thread_local_key.rs
+++ b/library/std/src/sys/pal/zkvm/thread_local_key.rs
@@ -9,13 +9,13 @@ pub unsafe fn create(_dtor: Option<unsafe extern "C" fn(*mut u8)>) -> Key {
 
 #[inline]
 pub unsafe fn set(key: Key, value: *mut u8) {
-    let key: *mut *mut u8 = core::ptr::from_exposed_addr_mut(key);
+    let key: *mut *mut u8 = core::ptr::with_exposed_provenance_mut(key);
     *key = value;
 }
 
 #[inline]
 pub unsafe fn get(key: Key) -> *mut u8 {
-    let key: *mut *mut u8 = core::ptr::from_exposed_addr_mut(key);
+    let key: *mut *mut u8 = core::ptr::with_exposed_provenance_mut(key);
     *key
 }
 
diff --git a/library/std/src/sys/personality/dwarf/eh.rs b/library/std/src/sys/personality/dwarf/eh.rs
index a78084de0fa..3f3615ea3e0 100644
--- a/library/std/src/sys/personality/dwarf/eh.rs
+++ b/library/std/src/sys/personality/dwarf/eh.rs
@@ -125,7 +125,7 @@ pub unsafe fn find_eh_action(lsda: *const u8, context: &EHContext<'_>) -> Result
                 // Can never have null landing pad for sjlj -- that would have
                 // been indicated by a -1 call site index.
                 // FIXME(strict provenance)
-                let lpad = ptr::from_exposed_addr((cs_lpad + 1) as usize);
+                let lpad = ptr::with_exposed_provenance((cs_lpad + 1) as usize);
                 return Ok(interpret_cs_action(action_table, cs_action_entry, lpad));
             }
         }
diff --git a/library/std/src/sys/personality/gcc.rs b/library/std/src/sys/personality/gcc.rs
index 6f317131145..b0f744dd966 100644
--- a/library/std/src/sys/personality/gcc.rs
+++ b/library/std/src/sys/personality/gcc.rs
@@ -92,7 +92,7 @@ const UNWIND_DATA_REG: (i32, i32) = (4, 5); // a0, a1
 // https://github.com/gcc-mirror/gcc/blob/trunk/libgcc/unwind-c.c
 
 cfg_if::cfg_if! {
-    if #[cfg(all(target_arch = "arm", not(target_os = "ios"), not(target_os = "tvos"), not(target_os = "watchos"), not(target_os = "netbsd")))] {
+    if #[cfg(all(target_arch = "arm", not(target_os = "ios"), not(target_os = "tvos"), not(target_os = "watchos"), not(target_os = "visionos"), not(target_os = "netbsd")))] {
         // ARM EHABI personality routine.
         // https://web.archive.org/web/20190728160938/https://infocenter.arm.com/help/topic/com.arm.doc.ihi0038b/IHI0038B_ehabi.pdf
         //
diff --git a/library/std/src/sys/sync/condvar/pthread.rs b/library/std/src/sys/sync/condvar/pthread.rs
index 728371685ee..0475f985078 100644
--- a/library/std/src/sys/sync/condvar/pthread.rs
+++ b/library/std/src/sys/sync/condvar/pthread.rs
@@ -34,6 +34,7 @@ impl LazyInit for AllocatedCondvar {
                 target_os = "ios",
                 target_os = "tvos",
                 target_os = "watchos",
+                target_os = "visionos",
                 target_os = "l4re",
                 target_os = "android",
                 target_os = "redox"
@@ -127,6 +128,7 @@ impl Condvar {
         target_os = "ios",
         target_os = "tvos",
         target_os = "watchos",
+        target_os = "visionos",
         target_os = "android",
         target_os = "espidf",
         target_os = "horizon"
@@ -162,6 +164,7 @@ impl Condvar {
         target_os = "ios",
         target_os = "tvos",
         target_os = "watchos",
+        target_os = "visionos",
         target_os = "android",
         target_os = "espidf",
         target_os = "horizon"
diff --git a/library/std/src/sys/sync/rwlock/queue.rs b/library/std/src/sys/sync/rwlock/queue.rs
index dce966086b8..d1918855797 100644
--- a/library/std/src/sys/sync/rwlock/queue.rs
+++ b/library/std/src/sys/sync/rwlock/queue.rs
@@ -115,8 +115,7 @@ use crate::sync::atomic::{
     AtomicBool, AtomicPtr,
     Ordering::{AcqRel, Acquire, Relaxed, Release},
 };
-use crate::sys_common::thread_info;
-use crate::thread::Thread;
+use crate::thread::{self, Thread};
 
 // Locking uses exponential backoff. `SPIN_COUNT` indicates how many times the
 // locking operation will be retried.
@@ -203,8 +202,7 @@ impl Node {
     fn prepare(&mut self) {
         // Fall back to creating an unnamed `Thread` handle to allow locking in
         // TLS destructors.
-        self.thread
-            .get_or_init(|| thread_info::current_thread().unwrap_or_else(|| Thread::new(None)));
+        self.thread.get_or_init(|| thread::try_current().unwrap_or_else(|| Thread::new(None)));
         self.completed = AtomicBool::new(false);
     }
 
diff --git a/library/std/src/sys_common/mod.rs b/library/std/src/sys_common/mod.rs
index 5410f135a73..5abf201aa20 100644
--- a/library/std/src/sys_common/mod.rs
+++ b/library/std/src/sys_common/mod.rs
@@ -26,7 +26,6 @@ pub mod io;
 pub mod lazy_box;
 pub mod process;
 pub mod thread;
-pub mod thread_info;
 pub mod thread_local_dtor;
 pub mod thread_parking;
 pub mod wstr;
diff --git a/library/std/src/sys_common/net.rs b/library/std/src/sys_common/net.rs
index 581c46af0ea..8c9885974b4 100644
--- a/library/std/src/sys_common/net.rs
+++ b/library/std/src/sys_common/net.rs
@@ -18,7 +18,7 @@ use crate::ffi::{c_int, c_void};
 cfg_if::cfg_if! {
     if #[cfg(any(
         target_os = "dragonfly", target_os = "freebsd",
-        target_os = "ios", target_os = "tvos", target_os = "macos", target_os = "watchos",
+        target_os = "ios", target_os = "tvos", target_os = "macos", target_os = "watchos", target_os = "visionos",
         target_os = "openbsd", target_os = "netbsd", target_os = "illumos",
         target_os = "solaris", target_os = "haiku", target_os = "l4re", target_os = "nto"))] {
         use crate::sys::net::netc::IPV6_JOIN_GROUP as IPV6_ADD_MEMBERSHIP;
@@ -107,13 +107,13 @@ where
 pub fn sockaddr_to_addr(storage: &c::sockaddr_storage, len: usize) -> io::Result<SocketAddr> {
     match storage.ss_family as c_int {
         c::AF_INET => {
-            assert!(len as usize >= mem::size_of::<c::sockaddr_in>());
+            assert!(len >= mem::size_of::<c::sockaddr_in>());
             Ok(SocketAddr::V4(FromInner::from_inner(unsafe {
                 *(storage as *const _ as *const c::sockaddr_in)
             })))
         }
         c::AF_INET6 => {
-            assert!(len as usize >= mem::size_of::<c::sockaddr_in6>());
+            assert!(len >= mem::size_of::<c::sockaddr_in6>());
             Ok(SocketAddr::V6(FromInner::from_inner(unsafe {
                 *(storage as *const _ as *const c::sockaddr_in6)
             })))
diff --git a/library/std/src/sys_common/thread_info.rs b/library/std/src/sys_common/thread_info.rs
deleted file mode 100644
index ec1428ea40e..00000000000
--- a/library/std/src/sys_common/thread_info.rs
+++ /dev/null
@@ -1,53 +0,0 @@
-#![allow(dead_code)] // stack_guard isn't used right now on all platforms
-
-use crate::cell::OnceCell;
-use crate::sys;
-use crate::sys::thread::guard::Guard;
-use crate::thread::Thread;
-
-struct ThreadInfo {
-    stack_guard: OnceCell<Guard>,
-    thread: OnceCell<Thread>,
-}
-
-thread_local! {
-   static THREAD_INFO: ThreadInfo = const { ThreadInfo {
-       stack_guard: OnceCell::new(),
-       thread: OnceCell::new()
-   } };
-}
-
-impl ThreadInfo {
-    fn with<R, F>(f: F) -> Option<R>
-    where
-        F: FnOnce(&Thread, &OnceCell<Guard>) -> R,
-    {
-        THREAD_INFO
-            .try_with(move |thread_info| {
-                let thread =
-                    thread_info.thread.get_or_init(|| Thread::new(sys::thread::Thread::get_name()));
-                f(thread, &thread_info.stack_guard)
-            })
-            .ok()
-    }
-}
-
-pub fn current_thread() -> Option<Thread> {
-    ThreadInfo::with(|thread, _| thread.clone())
-}
-
-pub fn stack_guard() -> Option<Guard> {
-    ThreadInfo::with(|_, guard| guard.get().cloned()).flatten()
-}
-
-/// Set new thread info, panicking if it has already been initialized
-#[allow(unreachable_code, unreachable_patterns)] // some platforms don't use stack_guard
-pub fn set(stack_guard: Option<Guard>, thread: Thread) {
-    THREAD_INFO.with(move |thread_info| {
-        rtassert!(thread_info.stack_guard.get().is_none() && thread_info.thread.get().is_none());
-        if let Some(guard) = stack_guard {
-            thread_info.stack_guard.set(guard).unwrap();
-        }
-        thread_info.thread.set(thread).unwrap();
-    });
-}
diff --git a/library/std/src/sys_common/thread_local_key.rs b/library/std/src/sys_common/thread_local_key.rs
index 7dcc1141099..a9cd26389cd 100644
--- a/library/std/src/sys_common/thread_local_key.rs
+++ b/library/std/src/sys_common/thread_local_key.rs
@@ -1,4 +1,4 @@
-//! OS-based thread local storage
+//! OS-based thread local storage for non-Windows systems
 //!
 //! This module provides an implementation of OS-based thread local storage,
 //! using the native OS-provided facilities (think `TlsAlloc` or
@@ -11,6 +11,9 @@
 //! the OS-TLS key. The other is a type which does implement `Drop` and hence
 //! has a safe interface.
 //!
+//! Windows doesn't use this module at all; `sys::pal::windows::thread_local_key`
+//! gets imported in its stead.
+//!
 //! # Usage
 //!
 //! This module should likely not be used directly unless other primitives are
diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs
index 85de2980133..f792a27dd69 100644
--- a/library/std/src/thread/mod.rs
+++ b/library/std/src/thread/mod.rs
@@ -159,7 +159,7 @@
 mod tests;
 
 use crate::any::Any;
-use crate::cell::UnsafeCell;
+use crate::cell::{OnceCell, UnsafeCell};
 use crate::ffi::{CStr, CString};
 use crate::fmt;
 use crate::io;
@@ -174,7 +174,6 @@ use crate::str;
 use crate::sync::Arc;
 use crate::sys::thread as imp;
 use crate::sys_common::thread;
-use crate::sys_common::thread_info;
 use crate::sys_common::thread_parking::Parker;
 use crate::sys_common::{AsInner, IntoInner};
 use crate::time::{Duration, Instant};
@@ -518,12 +517,8 @@ impl Builder {
 
             crate::io::set_output_capture(output_capture);
 
-            // SAFETY: we constructed `f` initialized.
             let f = f.into_inner();
-            // SAFETY: the stack guard passed is the one for the current thread.
-            // This means the current thread's stack and the new thread's stack
-            // are properly set and protected from each other.
-            thread_info::set(unsafe { imp::guard::current() }, their_thread);
+            set_current(their_thread);
             let try_result = panic::catch_unwind(panic::AssertUnwindSafe(|| {
                 crate::sys_common::backtrace::__rust_begin_short_backtrace(f)
             }));
@@ -683,6 +678,25 @@ where
     Builder::new().spawn(f).expect("failed to spawn thread")
 }
 
+thread_local! {
+    static CURRENT: OnceCell<Thread> = const { OnceCell::new() };
+}
+
+/// Sets the thread handle for the current thread.
+///
+/// Panics if the handle has been set already or when called from a TLS destructor.
+pub(crate) fn set_current(thread: Thread) {
+    CURRENT.with(|current| current.set(thread).unwrap());
+}
+
+/// Gets a handle to the thread that invokes it.
+///
+/// In contrast to the public `current` function, this will not panic if called
+/// from inside a TLS destructor.
+pub(crate) fn try_current() -> Option<Thread> {
+    CURRENT.try_with(|current| current.get_or_init(|| Thread::new(None)).clone()).ok()
+}
+
 /// Gets a handle to the thread that invokes it.
 ///
 /// # Examples
@@ -705,7 +719,7 @@ where
 #[must_use]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn current() -> Thread {
-    thread_info::current_thread().expect(
+    try_current().expect(
         "use of std::thread::current() is not possible \
          after the thread's local data has been destroyed",
     )
@@ -1231,9 +1245,16 @@ impl ThreadId {
 // Thread
 ////////////////////////////////////////////////////////////////////////////////
 
+/// The internal representation of a `Thread`'s name.
+enum ThreadName {
+    Main,
+    Other(CString),
+    Unnamed,
+}
+
 /// The internal representation of a `Thread` handle
 struct Inner {
-    name: Option<CString>, // Guaranteed to be UTF-8
+    name: ThreadName, // Guaranteed to be UTF-8
     id: ThreadId,
     parker: Parker,
 }
@@ -1270,8 +1291,20 @@ pub struct Thread {
 
 impl Thread {
     // Used only internally to construct a thread object without spawning
-    // Panics if the name contains nuls.
     pub(crate) fn new(name: Option<CString>) -> Thread {
+        if let Some(name) = name {
+            Self::new_inner(ThreadName::Other(name))
+        } else {
+            Self::new_inner(ThreadName::Unnamed)
+        }
+    }
+
+    // Used in runtime to construct main thread
+    pub(crate) fn new_main() -> Thread {
+        Self::new_inner(ThreadName::Main)
+    }
+
+    fn new_inner(name: ThreadName) -> Thread {
         // We have to use `unsafe` here to construct the `Parker` in-place,
         // which is required for the UNIX implementation.
         //
@@ -1398,7 +1431,11 @@ impl Thread {
     }
 
     fn cname(&self) -> Option<&CStr> {
-        self.inner.name.as_deref()
+        match &self.inner.name {
+            ThreadName::Main => Some(c"main"),
+            ThreadName::Other(other) => Some(&other),
+            ThreadName::Unnamed => None,
+        }
     }
 }
 
diff --git a/library/std/src/thread/tests.rs b/library/std/src/thread/tests.rs
index 589a5fdad1d..494513f2c75 100644
--- a/library/std/src/thread/tests.rs
+++ b/library/std/src/thread/tests.rs
@@ -43,7 +43,8 @@ fn test_named_thread() {
     target_os = "macos",
     target_os = "ios",
     target_os = "tvos",
-    target_os = "watchos"
+    target_os = "watchos",
+    target_os = "visionos",
 ))]
 #[test]
 fn test_named_thread_truncation() {
@@ -69,26 +70,6 @@ fn test_named_thread_truncation() {
     result.unwrap().join().unwrap();
 }
 
-#[cfg(any(
-    all(target_os = "windows", not(target_vendor = "win7")),
-    target_os = "linux",
-    target_os = "macos",
-    target_os = "ios",
-    target_os = "tvos",
-    target_os = "watchos"
-))]
-#[test]
-fn test_get_os_named_thread() {
-    use crate::sys::thread::Thread;
-    // Spawn a new thread to avoid interfering with other tests running on this thread.
-    let handler = thread::spawn(|| {
-        let name = c"test me please";
-        Thread::set_name(name);
-        assert_eq!(name, Thread::get_name().unwrap().as_c_str());
-    });
-    handler.join().unwrap();
-}
-
 #[test]
 #[should_panic]
 fn test_invalid_named_thread() {