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/alloc.rs1
-rw-r--r--library/std/src/backtrace.rs58
-rw-r--r--library/std/src/backtrace/tests.rs6
-rw-r--r--library/std/src/ffi/os_str.rs65
-rw-r--r--library/std/src/fs/tests.rs2
-rw-r--r--library/std/src/io/util.rs100
-rw-r--r--library/std/src/io/util/tests.rs13
-rw-r--r--library/std/src/lib.rs3
-rw-r--r--library/std/src/os/android/raw.rs2
-rw-r--r--library/std/src/os/raw/mod.rs5
-rw-r--r--library/std/src/os/unix/fs.rs40
-rw-r--r--library/std/src/os/unix/net/tests.rs18
-rw-r--r--library/std/src/panicking.rs2
-rw-r--r--library/std/src/path.rs24
-rw-r--r--library/std/src/path/tests.rs50
-rw-r--r--library/std/src/sync/condvar.rs18
-rw-r--r--library/std/src/sync/lazy_lock.rs29
-rw-r--r--library/std/src/sys/common/thread_local/fast_local.rs4
-rw-r--r--library/std/src/sys/common/thread_local/os_local.rs5
-rw-r--r--library/std/src/sys/common/thread_local/static_local.rs4
-rw-r--r--library/std/src/sys/sgx/thread.rs10
-rw-r--r--library/std/src/sys/unix/mod.rs14
-rw-r--r--library/std/src/sys/unix/os_str.rs10
-rw-r--r--library/std/src/sys/unix/rand.rs22
-rw-r--r--library/std/src/sys/windows/compat.rs5
-rw-r--r--library/std/src/sys/windows/os_str.rs10
-rw-r--r--library/std/src/sys/windows/thread_local_dtor.rs27
-rw-r--r--library/std/src/sys/windows/thread_local_key.rs46
-rw-r--r--library/std/src/sys/windows/thread_local_key/tests.rs4
-rw-r--r--library/std/src/sys_common/backtrace.rs19
-rw-r--r--library/std/src/sys_common/thread_info.rs1
-rw-r--r--library/std/src/sys_common/wtf8.rs15
32 files changed, 471 insertions, 161 deletions
diff --git a/library/std/src/alloc.rs b/library/std/src/alloc.rs
index ec774e62deb..1eae7fa6a95 100644
--- a/library/std/src/alloc.rs
+++ b/library/std/src/alloc.rs
@@ -336,7 +336,6 @@ fn default_alloc_error_hook(layout: Layout) {
         static __rust_alloc_error_handler_should_panic: u8;
     }
 
-    #[allow(unused_unsafe)]
     if unsafe { __rust_alloc_error_handler_should_panic != 0 } {
         panic!("memory allocation of {} bytes failed", layout.size());
     } else {
diff --git a/library/std/src/backtrace.rs b/library/std/src/backtrace.rs
index 7543ffadd41..f0e199fac73 100644
--- a/library/std/src/backtrace.rs
+++ b/library/std/src/backtrace.rs
@@ -89,12 +89,11 @@ mod tests;
 // a backtrace or actually symbolizing it.
 
 use crate::backtrace_rs::{self, BytesOrWideString};
-use crate::cell::UnsafeCell;
 use crate::env;
 use crate::ffi::c_void;
 use crate::fmt;
 use crate::sync::atomic::{AtomicUsize, Ordering::Relaxed};
-use crate::sync::Once;
+use crate::sync::LazyLock;
 use crate::sys_common::backtrace::{lock, output_filename};
 use crate::vec::Vec;
 
@@ -133,12 +132,11 @@ pub enum BacktraceStatus {
 enum Inner {
     Unsupported,
     Disabled,
-    Captured(LazilyResolvedCapture),
+    Captured(LazyLock<Capture, LazyResolve>),
 }
 
 struct Capture {
     actual_start: usize,
-    resolved: bool,
     frames: Vec<BacktraceFrame>,
 }
 
@@ -179,7 +177,7 @@ impl fmt::Debug for Backtrace {
         let capture = match &self.inner {
             Inner::Unsupported => return fmt.write_str("<unsupported>"),
             Inner::Disabled => return fmt.write_str("<disabled>"),
-            Inner::Captured(c) => c.force(),
+            Inner::Captured(c) => &**c,
         };
 
         let frames = &capture.frames[capture.actual_start..];
@@ -347,11 +345,10 @@ impl Backtrace {
         let inner = if frames.is_empty() {
             Inner::Unsupported
         } else {
-            Inner::Captured(LazilyResolvedCapture::new(Capture {
+            Inner::Captured(LazyLock::new(lazy_resolve(Capture {
                 actual_start: actual_start.unwrap_or(0),
                 frames,
-                resolved: false,
-            }))
+            })))
         };
 
         Backtrace { inner }
@@ -376,7 +373,7 @@ impl<'a> Backtrace {
     #[must_use]
     #[unstable(feature = "backtrace_frames", issue = "79676")]
     pub fn frames(&'a self) -> &'a [BacktraceFrame] {
-        if let Inner::Captured(c) = &self.inner { &c.force().frames } else { &[] }
+        if let Inner::Captured(c) = &self.inner { &c.frames } else { &[] }
     }
 }
 
@@ -386,7 +383,7 @@ impl fmt::Display for Backtrace {
         let capture = match &self.inner {
             Inner::Unsupported => return fmt.write_str("unsupported backtrace"),
             Inner::Disabled => return fmt.write_str("disabled backtrace"),
-            Inner::Captured(c) => c.force(),
+            Inner::Captured(c) => &**c,
         };
 
         let full = fmt.alternate();
@@ -430,46 +427,15 @@ impl fmt::Display for Backtrace {
     }
 }
 
-struct LazilyResolvedCapture {
-    sync: Once,
-    capture: UnsafeCell<Capture>,
-}
-
-impl LazilyResolvedCapture {
-    fn new(capture: Capture) -> Self {
-        LazilyResolvedCapture { sync: Once::new(), capture: UnsafeCell::new(capture) }
-    }
-
-    fn force(&self) -> &Capture {
-        self.sync.call_once(|| {
-            // SAFETY: This exclusive reference can't overlap with any others
-            // `Once` guarantees callers will block until this closure returns
-            // `Once` also guarantees only a single caller will enter this closure
-            unsafe { &mut *self.capture.get() }.resolve();
-        });
-
-        // SAFETY: This shared reference can't overlap with the exclusive reference above
-        unsafe { &*self.capture.get() }
-    }
-}
-
-// SAFETY: Access to the inner value is synchronized using a thread-safe `Once`
-// So long as `Capture` is `Sync`, `LazilyResolvedCapture` is too
-unsafe impl Sync for LazilyResolvedCapture where Capture: Sync {}
-
-impl Capture {
-    fn resolve(&mut self) {
-        // If we're already resolved, nothing to do!
-        if self.resolved {
-            return;
-        }
-        self.resolved = true;
+type LazyResolve = impl (FnOnce() -> Capture) + Send + Sync;
 
+fn lazy_resolve(mut capture: Capture) -> LazyResolve {
+    move || {
         // Use the global backtrace lock to synchronize this as it's a
         // requirement of the `backtrace` crate, and then actually resolve
         // everything.
         let _lock = lock();
-        for frame in self.frames.iter_mut() {
+        for frame in capture.frames.iter_mut() {
             let symbols = &mut frame.symbols;
             let frame = match &frame.frame {
                 RawFrame::Actual(frame) => frame,
@@ -490,6 +456,8 @@ impl Capture {
                 });
             }
         }
+
+        capture
     }
 }
 
diff --git a/library/std/src/backtrace/tests.rs b/library/std/src/backtrace/tests.rs
index 4dfbf88e83e..ef419806dcc 100644
--- a/library/std/src/backtrace/tests.rs
+++ b/library/std/src/backtrace/tests.rs
@@ -43,9 +43,8 @@ fn generate_fake_frames() -> Vec<BacktraceFrame> {
 #[test]
 fn test_debug() {
     let backtrace = Backtrace {
-        inner: Inner::Captured(LazilyResolvedCapture::new(Capture {
+        inner: Inner::Captured(LazyLock::preinit(Capture {
             actual_start: 1,
-            resolved: true,
             frames: generate_fake_frames(),
         })),
     };
@@ -66,9 +65,8 @@ fn test_debug() {
 #[test]
 fn test_frames() {
     let backtrace = Backtrace {
-        inner: Inner::Captured(LazilyResolvedCapture::new(Capture {
+        inner: Inner::Captured(LazyLock::preinit(Capture {
             actual_start: 1,
-            resolved: true,
             frames: generate_fake_frames(),
         })),
     };
diff --git a/library/std/src/ffi/os_str.rs b/library/std/src/ffi/os_str.rs
index e7bad9d542c..67e58fd1b86 100644
--- a/library/std/src/ffi/os_str.rs
+++ b/library/std/src/ffi/os_str.rs
@@ -141,6 +141,51 @@ impl OsString {
         OsString { inner: Buf::from_string(String::new()) }
     }
 
+    /// Converts bytes to an `OsString` without checking that the bytes contains
+    /// valid [`OsStr`]-encoded data.
+    ///
+    /// The byte encoding is an unspecified, platform-specific, self-synchronizing superset of UTF-8.
+    /// By being a self-synchronizing superset of UTF-8, this encoding is also a superset of 7-bit
+    /// ASCII.
+    ///
+    /// See the [module's toplevel documentation about conversions][conversions] for safe,
+    /// cross-platform [conversions] from/to native representations.
+    ///
+    /// # Safety
+    ///
+    /// As the encoding is unspecified, callers must pass in bytes that originated as a mixture of
+    /// validated UTF-8 and bytes from [`OsStr::as_os_str_bytes`] from within the same rust version
+    /// built for the same target platform.  For example, reconstructing an `OsString` from bytes sent
+    /// over the network or stored in a file will likely violate these safety rules.
+    ///
+    /// Due to the encoding being self-synchronizing, the bytes from [`OsStr::as_os_str_bytes`] can be
+    /// split either immediately before or immediately after any valid non-empty UTF-8 substring.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// #![feature(os_str_bytes)]
+    ///
+    /// use std::ffi::OsStr;
+    ///
+    /// let os_str = OsStr::new("Mary had a little lamb");
+    /// let bytes = os_str.as_os_str_bytes();
+    /// let words = bytes.split(|b| *b == b' ');
+    /// let words: Vec<&OsStr> = words.map(|word| {
+    ///     // SAFETY:
+    ///     // - Each `word` only contains content that originated from `OsStr::as_os_str_bytes`
+    ///     // - Only split with ASCII whitespace which is a non-empty UTF-8 substring
+    ///     unsafe { OsStr::from_os_str_bytes_unchecked(word) }
+    /// }).collect();
+    /// ```
+    ///
+    /// [conversions]: super#conversions
+    #[inline]
+    #[unstable(feature = "os_str_bytes", issue = "111544")]
+    pub unsafe fn from_os_str_bytes_unchecked(bytes: Vec<u8>) -> Self {
+        OsString { inner: Buf::from_os_str_bytes_unchecked(bytes) }
+    }
+
     /// Converts to an [`OsStr`] slice.
     ///
     /// # Examples
@@ -159,6 +204,26 @@ impl OsString {
         self
     }
 
+    /// Converts the `OsString` into a byte slice.  To convert the byte slice back into an
+    /// `OsString`, use the [`OsStr::from_os_str_bytes_unchecked`] function.
+    ///
+    /// The byte encoding is an unspecified, platform-specific, self-synchronizing superset of UTF-8.
+    /// By being a self-synchronizing superset of UTF-8, this encoding is also a superset of 7-bit
+    /// ASCII.
+    ///
+    /// Note: As the encoding is unspecified, any sub-slice of bytes that is not valid UTF-8 should
+    /// be treated as opaque and only comparable within the same rust version built for the same
+    /// target platform.  For example, sending the bytes over the network or storing it in a file
+    /// will likely result in incompatible data.  See [`OsString`] for more encoding details
+    /// and [`std::ffi`] for platform-specific, specified conversions.
+    ///
+    /// [`std::ffi`]: crate::ffi
+    #[inline]
+    #[unstable(feature = "os_str_bytes", issue = "111544")]
+    pub fn into_os_str_bytes(self) -> Vec<u8> {
+        self.inner.into_os_str_bytes()
+    }
+
     /// Converts the `OsString` into a [`String`] if it contains valid Unicode data.
     ///
     /// On failure, ownership of the original `OsString` is returned.
diff --git a/library/std/src/fs/tests.rs b/library/std/src/fs/tests.rs
index 9ff01b9c35d..d74f0f00e46 100644
--- a/library/std/src/fs/tests.rs
+++ b/library/std/src/fs/tests.rs
@@ -957,6 +957,7 @@ fn readlink_not_symlink() {
 }
 
 #[test]
+#[cfg_attr(target_os = "android", ignore)] // Android SELinux rules prevent creating hardlinks
 fn links_work() {
     let tmpdir = tmpdir();
     let input = tmpdir.join("in.txt");
@@ -1453,6 +1454,7 @@ fn metadata_access_times() {
 
 /// Test creating hard links to symlinks.
 #[test]
+#[cfg_attr(target_os = "android", ignore)] // Android SELinux rules prevent creating hardlinks
 fn symlink_hard_link() {
     let tmpdir = tmpdir();
     if !got_symlink_permission(&tmpdir) {
diff --git a/library/std/src/io/util.rs b/library/std/src/io/util.rs
index f076ee0923c..3840ffe7eec 100644
--- a/library/std/src/io/util.rs
+++ b/library/std/src/io/util.rs
@@ -8,24 +8,41 @@ use crate::io::{
     self, BorrowedCursor, BufRead, IoSlice, IoSliceMut, Read, Seek, SeekFrom, SizeHint, Write,
 };
 
-/// A reader which is always at EOF.
+/// `Empty` ignores any data written via [`Write`], and will always be empty
+/// (returning zero bytes) when read via [`Read`].
 ///
-/// This struct is generally created by calling [`empty()`]. Please see
-/// the documentation of [`empty()`] for more details.
+/// This struct is generally created by calling [`empty()`]. Please
+/// see the documentation of [`empty()`] for more details.
 #[stable(feature = "rust1", since = "1.0.0")]
 #[non_exhaustive]
-#[derive(Copy, Clone, Default)]
+#[derive(Copy, Clone, Debug, Default)]
 pub struct Empty;
 
-/// Constructs a new handle to an empty reader.
+/// Creates a value that is always at EOF for reads, and ignores all data written.
 ///
-/// All reads from the returned reader will return <code>[Ok]\(0)</code>.
+/// All calls to [`write`] on the returned instance will return [`Ok(buf.len())`]
+/// and the contents of the buffer will not be inspected.
+///
+/// All calls to [`read`] from the returned reader will return [`Ok(0)`].
+///
+/// [`Ok(buf.len())`]: Ok
+/// [`Ok(0)`]: Ok
+///
+/// [`write`]: Write::write
+/// [`read`]: Read::read
 ///
 /// # Examples
 ///
-/// A slightly sad example of not reading anything into a buffer:
+/// ```rust
+/// use std::io::{self, Write};
 ///
+/// let buffer = vec![1, 2, 3, 5, 8];
+/// let num_bytes = io::empty().write(&buffer).unwrap();
+/// assert_eq!(num_bytes, 5);
 /// ```
+///
+///
+/// ```rust
 /// use std::io::{self, Read};
 ///
 /// let mut buffer = String::new();
@@ -76,13 +93,6 @@ impl Seek for Empty {
     }
 }
 
-#[stable(feature = "std_debug", since = "1.16.0")]
-impl fmt::Debug for Empty {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_struct("Empty").finish_non_exhaustive()
-    }
-}
-
 impl SizeHint for Empty {
     #[inline]
     fn upper_bound(&self) -> Option<usize> {
@@ -90,6 +100,54 @@ impl SizeHint for Empty {
     }
 }
 
+#[stable(feature = "empty_write", since = "CURRENT_RUSTC_VERSION")]
+impl Write for Empty {
+    #[inline]
+    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
+        Ok(buf.len())
+    }
+
+    #[inline]
+    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
+        let total_len = bufs.iter().map(|b| b.len()).sum();
+        Ok(total_len)
+    }
+
+    #[inline]
+    fn is_write_vectored(&self) -> bool {
+        true
+    }
+
+    #[inline]
+    fn flush(&mut self) -> io::Result<()> {
+        Ok(())
+    }
+}
+
+#[stable(feature = "empty_write", since = "CURRENT_RUSTC_VERSION")]
+impl Write for &Empty {
+    #[inline]
+    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
+        Ok(buf.len())
+    }
+
+    #[inline]
+    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
+        let total_len = bufs.iter().map(|b| b.len()).sum();
+        Ok(total_len)
+    }
+
+    #[inline]
+    fn is_write_vectored(&self) -> bool {
+        true
+    }
+
+    #[inline]
+    fn flush(&mut self) -> io::Result<()> {
+        Ok(())
+    }
+}
+
 /// A reader which yields one byte over and over and over and over and over and...
 ///
 /// This struct is generally created by calling [`repeat()`]. Please
@@ -182,19 +240,20 @@ impl fmt::Debug for Repeat {
 
 /// A writer which will move data into the void.
 ///
-/// This struct is generally created by calling [`sink`]. Please
+/// This struct is generally created by calling [`sink()`]. Please
 /// see the documentation of [`sink()`] for more details.
 #[stable(feature = "rust1", since = "1.0.0")]
 #[non_exhaustive]
-#[derive(Copy, Clone, Default)]
+#[derive(Copy, Clone, Debug, Default)]
 pub struct Sink;
 
 /// Creates an instance of a writer which will successfully consume all data.
 ///
-/// All calls to [`write`] on the returned instance will return `Ok(buf.len())`
+/// All calls to [`write`] on the returned instance will return [`Ok(buf.len())`]
 /// and the contents of the buffer will not be inspected.
 ///
 /// [`write`]: Write::write
+/// [`Ok(buf.len())`]: Ok
 ///
 /// # Examples
 ///
@@ -259,10 +318,3 @@ impl Write for &Sink {
         Ok(())
     }
 }
-
-#[stable(feature = "std_debug", since = "1.16.0")]
-impl fmt::Debug for Sink {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_struct("Sink").finish_non_exhaustive()
-    }
-}
diff --git a/library/std/src/io/util/tests.rs b/library/std/src/io/util/tests.rs
index 1baa94e64c9..6de91e29c77 100644
--- a/library/std/src/io/util/tests.rs
+++ b/library/std/src/io/util/tests.rs
@@ -18,7 +18,7 @@ fn empty_reads() {
     assert_eq!(e.read(&mut []).unwrap(), 0);
     assert_eq!(e.read(&mut [0]).unwrap(), 0);
     assert_eq!(e.read(&mut [0; 1024]).unwrap(), 0);
-    assert_eq!(e.by_ref().read(&mut [0; 1024]).unwrap(), 0);
+    assert_eq!(Read::by_ref(&mut e).read(&mut [0; 1024]).unwrap(), 0);
 
     let buf: &mut [MaybeUninit<_>] = &mut [];
     let mut buf: BorrowedBuf<'_> = buf.into();
@@ -40,7 +40,7 @@ fn empty_reads() {
 
     let buf: &mut [_] = &mut [MaybeUninit::uninit(); 1024];
     let mut buf: BorrowedBuf<'_> = buf.into();
-    e.by_ref().read_buf(buf.unfilled()).unwrap();
+    Read::by_ref(&mut e).read_buf(buf.unfilled()).unwrap();
     assert_eq!(buf.len(), 0);
     assert_eq!(buf.init_len(), 0);
 }
@@ -66,6 +66,15 @@ fn empty_seeks() {
 }
 
 #[test]
+fn empty_sinks() {
+    let mut e = empty();
+    assert_eq!(e.write(&[]).unwrap(), 0);
+    assert_eq!(e.write(&[0]).unwrap(), 1);
+    assert_eq!(e.write(&[0; 1024]).unwrap(), 1024);
+    assert_eq!(Write::by_ref(&mut e).write(&[0; 1024]).unwrap(), 1024);
+}
+
+#[test]
 fn repeat_repeats() {
     let mut r = repeat(4);
     let mut b = [0; 1024];
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index 5bf66850f03..238c74229cc 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -272,6 +272,7 @@
 #![feature(staged_api)]
 #![feature(thread_local)]
 #![feature(try_blocks)]
+#![feature(type_alias_impl_trait)]
 #![feature(utf8_chunks)]
 // tidy-alphabetical-end
 //
@@ -542,7 +543,7 @@ pub mod time;
 // Pull in `std_float` crate  into std. The contents of
 // `std_float` are in a different repository: rust-lang/portable-simd.
 #[path = "../../portable-simd/crates/std_float/src/lib.rs"]
-#[allow(missing_debug_implementations, dead_code, unsafe_op_in_unsafe_fn, unused_unsafe)]
+#[allow(missing_debug_implementations, dead_code, unsafe_op_in_unsafe_fn)]
 #[allow(rustdoc::bare_urls)]
 #[unstable(feature = "portable_simd", issue = "86656")]
 mod std_float;
diff --git a/library/std/src/os/android/raw.rs b/library/std/src/os/android/raw.rs
index daaf3d3eac6..175f8eac971 100644
--- a/library/std/src/os/android/raw.rs
+++ b/library/std/src/os/android/raw.rs
@@ -89,7 +89,7 @@ mod arch {
     }
 }
 
-#[cfg(target_arch = "aarch64")]
+#[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
 mod arch {
     use crate::os::raw::{c_int, c_long, c_uint, c_ulong};
     use crate::os::unix::raw::{gid_t, uid_t};
diff --git a/library/std/src/os/raw/mod.rs b/library/std/src/os/raw/mod.rs
index 19d0ffb2e39..5b302e3c2c8 100644
--- a/library/std/src/os/raw/mod.rs
+++ b/library/std/src/os/raw/mod.rs
@@ -9,11 +9,6 @@ macro_rules! alias_core_ffi {
     ($($t:ident)*) => {$(
         #[stable(feature = "raw_os", since = "1.1.0")]
         #[doc = include_str!(concat!("../../../../core/src/ffi/", stringify!($t), ".md"))]
-        // Make this type alias appear cfg-dependent so that Clippy does not suggest
-        // replacing expressions like `0 as c_char` with `0_i8`/`0_u8`. This #[cfg(all())] can be
-        // removed after the false positive in https://github.com/rust-lang/rust-clippy/issues/8093
-        // is fixed.
-        #[cfg(all())]
         #[doc(cfg(all()))]
         pub type $t = core::ffi::$t;
     )*}
diff --git a/library/std/src/os/unix/fs.rs b/library/std/src/os/unix/fs.rs
index 1e1c3693105..88326aaf295 100644
--- a/library/std/src/os/unix/fs.rs
+++ b/library/std/src/os/unix/fs.rs
@@ -149,7 +149,36 @@ pub trait FileExt {
     /// Note that similar to [`File::write`], it is not an error to return a
     /// short write.
     ///
+    /// # Bug
+    /// On some systems, `write_at` utilises [`pwrite64`] to write to files.
+    /// However, this syscall has a [bug] where files opened with the `O_APPEND`
+    /// flag fail to respect the offset parameter, always appending to the end
+    /// of the file instead.
+    ///
+    /// It is possible to inadvertantly set this flag, like in the example below.
+    /// Therefore, it is important to be vigilant while changing options to mitigate
+    /// unexpected behaviour.
+    ///
+    /// ```no_run
+    /// use std::fs::File;
+    /// use std::io;
+    /// use std::os::unix::prelude::FileExt;
+    ///
+    /// fn main() -> io::Result<()> {
+    ///     // Open a file with the append option (sets the `O_APPEND` flag)
+    ///     let file = File::options().append(true).open("foo.txt")?;
+    ///
+    ///     // We attempt to write at offset 10; instead appended to EOF
+    ///     file.write_at(b"sushi", 10)?;
+    ///
+    ///     // foo.txt is 5 bytes long instead of 15
+    ///     Ok(())
+    /// }
+    /// ```
+    ///
     /// [`File::write`]: fs::File::write
+    /// [`pwrite64`]: https://man7.org/linux/man-pages/man2/pwrite.2.html
+    /// [bug]: https://man7.org/linux/man-pages/man2/pwrite.2.html#BUGS
     ///
     /// # Examples
     ///
@@ -159,7 +188,7 @@ pub trait FileExt {
     /// use std::os::unix::prelude::FileExt;
     ///
     /// fn main() -> io::Result<()> {
-    ///     let file = File::open("foo.txt")?;
+    ///     let file = File::create("foo.txt")?;
     ///
     ///     // We now write at the offset 10.
     ///     file.write_at(b"sushi", 10)?;
@@ -971,7 +1000,6 @@ impl DirBuilderExt for fs::DirBuilder {
 /// # Examples
 ///
 /// ```no_run
-/// #![feature(unix_chown)]
 /// use std::os::unix::fs;
 ///
 /// fn main() -> std::io::Result<()> {
@@ -979,7 +1007,7 @@ impl DirBuilderExt for fs::DirBuilder {
 ///     Ok(())
 /// }
 /// ```
-#[unstable(feature = "unix_chown", issue = "88989")]
+#[stable(feature = "unix_chown", since = "CURRENT_RUSTC_VERSION")]
 pub fn chown<P: AsRef<Path>>(dir: P, uid: Option<u32>, gid: Option<u32>) -> io::Result<()> {
     sys::fs::chown(dir.as_ref(), uid.unwrap_or(u32::MAX), gid.unwrap_or(u32::MAX))
 }
@@ -991,7 +1019,6 @@ pub fn chown<P: AsRef<Path>>(dir: P, uid: Option<u32>, gid: Option<u32>) -> io::
 /// # Examples
 ///
 /// ```no_run
-/// #![feature(unix_chown)]
 /// use std::os::unix::fs;
 ///
 /// fn main() -> std::io::Result<()> {
@@ -1000,7 +1027,7 @@ pub fn chown<P: AsRef<Path>>(dir: P, uid: Option<u32>, gid: Option<u32>) -> io::
 ///     Ok(())
 /// }
 /// ```
-#[unstable(feature = "unix_chown", issue = "88989")]
+#[stable(feature = "unix_chown", since = "CURRENT_RUSTC_VERSION")]
 pub fn fchown<F: AsFd>(fd: F, uid: Option<u32>, gid: Option<u32>) -> io::Result<()> {
     sys::fs::fchown(fd.as_fd().as_raw_fd(), uid.unwrap_or(u32::MAX), gid.unwrap_or(u32::MAX))
 }
@@ -1013,7 +1040,6 @@ pub fn fchown<F: AsFd>(fd: F, uid: Option<u32>, gid: Option<u32>) -> io::Result<
 /// # Examples
 ///
 /// ```no_run
-/// #![feature(unix_chown)]
 /// use std::os::unix::fs;
 ///
 /// fn main() -> std::io::Result<()> {
@@ -1021,7 +1047,7 @@ pub fn fchown<F: AsFd>(fd: F, uid: Option<u32>, gid: Option<u32>) -> io::Result<
 ///     Ok(())
 /// }
 /// ```
-#[unstable(feature = "unix_chown", issue = "88989")]
+#[stable(feature = "unix_chown", since = "CURRENT_RUSTC_VERSION")]
 pub fn lchown<P: AsRef<Path>>(dir: P, uid: Option<u32>, gid: Option<u32>) -> io::Result<()> {
     sys::fs::lchown(dir.as_ref(), uid.unwrap_or(u32::MAX), gid.unwrap_or(u32::MAX))
 }
diff --git a/library/std/src/os/unix/net/tests.rs b/library/std/src/os/unix/net/tests.rs
index 39f10c50dc4..3d4302e665c 100644
--- a/library/std/src/os/unix/net/tests.rs
+++ b/library/std/src/os/unix/net/tests.rs
@@ -23,6 +23,7 @@ macro_rules! or_panic {
 }
 
 #[test]
+#[cfg_attr(target_os = "android", ignore)] // Android SELinux rules prevent creating Unix sockets
 fn basic() {
     let dir = tmpdir();
     let socket_path = dir.path().join("sock");
@@ -93,6 +94,7 @@ fn pair() {
 }
 
 #[test]
+#[cfg_attr(target_os = "android", ignore)] // Android SELinux rules prevent creating Unix sockets
 fn try_clone() {
     let dir = tmpdir();
     let socket_path = dir.path().join("sock");
@@ -119,6 +121,7 @@ fn try_clone() {
 }
 
 #[test]
+#[cfg_attr(target_os = "android", ignore)] // Android SELinux rules prevent creating Unix sockets
 fn iter() {
     let dir = tmpdir();
     let socket_path = dir.path().join("sock");
@@ -168,6 +171,7 @@ fn long_path() {
 
 #[test]
 #[cfg(not(target_os = "nto"))]
+#[cfg_attr(target_os = "android", ignore)] // Android SELinux rules prevent creating Unix sockets
 fn timeouts() {
     let dir = tmpdir();
     let socket_path = dir.path().join("sock");
@@ -195,6 +199,7 @@ fn timeouts() {
 }
 
 #[test]
+#[cfg_attr(target_os = "android", ignore)] // Android SELinux rules prevent creating Unix sockets
 fn test_read_timeout() {
     let dir = tmpdir();
     let socket_path = dir.path().join("sock");
@@ -214,6 +219,7 @@ fn test_read_timeout() {
 }
 
 #[test]
+#[cfg_attr(target_os = "android", ignore)] // Android SELinux rules prevent creating Unix sockets
 fn test_read_with_timeout() {
     let dir = tmpdir();
     let socket_path = dir.path().join("sock");
@@ -241,6 +247,7 @@ fn test_read_with_timeout() {
 // Ensure the `set_read_timeout` and `set_write_timeout` calls return errors
 // when passed zero Durations
 #[test]
+#[cfg_attr(target_os = "android", ignore)] // Android SELinux rules prevent creating Unix sockets
 fn test_unix_stream_timeout_zero_duration() {
     let dir = tmpdir();
     let socket_path = dir.path().join("sock");
@@ -260,6 +267,7 @@ fn test_unix_stream_timeout_zero_duration() {
 }
 
 #[test]
+#[cfg_attr(target_os = "android", ignore)] // Android SELinux rules prevent creating Unix sockets
 fn test_unix_datagram() {
     let dir = tmpdir();
     let path1 = dir.path().join("sock1");
@@ -276,6 +284,7 @@ fn test_unix_datagram() {
 }
 
 #[test]
+#[cfg_attr(target_os = "android", ignore)] // Android SELinux rules prevent creating Unix sockets
 fn test_unnamed_unix_datagram() {
     let dir = tmpdir();
     let path1 = dir.path().join("sock1");
@@ -293,6 +302,7 @@ fn test_unnamed_unix_datagram() {
 }
 
 #[test]
+#[cfg_attr(target_os = "android", ignore)] // Android SELinux rules prevent creating Unix sockets
 fn test_unix_datagram_connect_to_recv_addr() {
     let dir = tmpdir();
     let path1 = dir.path().join("sock1");
@@ -317,6 +327,7 @@ fn test_unix_datagram_connect_to_recv_addr() {
 }
 
 #[test]
+#[cfg_attr(target_os = "android", ignore)] // Android SELinux rules prevent creating Unix sockets
 fn test_connect_unix_datagram() {
     let dir = tmpdir();
     let path1 = dir.path().join("sock1");
@@ -343,6 +354,7 @@ fn test_connect_unix_datagram() {
 }
 
 #[test]
+#[cfg_attr(target_os = "android", ignore)] // Android SELinux rules prevent creating Unix sockets
 fn test_unix_datagram_recv() {
     let dir = tmpdir();
     let path1 = dir.path().join("sock1");
@@ -385,6 +397,7 @@ fn datagram_pair() {
 // Ensure the `set_read_timeout` and `set_write_timeout` calls return errors
 // when passed zero Durations
 #[test]
+#[cfg_attr(target_os = "android", ignore)] // Android SELinux rules prevent creating Unix sockets
 fn test_unix_datagram_timeout_zero_duration() {
     let dir = tmpdir();
     let path = dir.path().join("sock");
@@ -529,6 +542,7 @@ fn test_abstract_no_pathname_and_not_unnamed() {
 }
 
 #[test]
+#[cfg_attr(target_os = "android", ignore)] // Android SELinux rules prevent creating Unix sockets
 fn test_unix_stream_peek() {
     let (txdone, rxdone) = crate::sync::mpsc::channel();
 
@@ -561,6 +575,7 @@ fn test_unix_stream_peek() {
 }
 
 #[test]
+#[cfg_attr(target_os = "android", ignore)] // Android SELinux rules prevent creating Unix sockets
 fn test_unix_datagram_peek() {
     let dir = tmpdir();
     let path1 = dir.path().join("sock");
@@ -585,6 +600,7 @@ fn test_unix_datagram_peek() {
 }
 
 #[test]
+#[cfg_attr(target_os = "android", ignore)] // Android SELinux rules prevent creating Unix sockets
 fn test_unix_datagram_peek_from() {
     let dir = tmpdir();
     let path1 = dir.path().join("sock");
@@ -648,6 +664,7 @@ fn test_send_vectored_fds_unix_stream() {
 
 #[cfg(any(target_os = "android", target_os = "linux", target_os = "freebsd"))]
 #[test]
+#[cfg_attr(target_os = "android", ignore)] // Android SELinux rules prevent creating Unix sockets
 fn test_send_vectored_with_ancillary_to_unix_datagram() {
     fn getpid() -> libc::pid_t {
         unsafe { libc::getpid() }
@@ -715,6 +732,7 @@ fn test_send_vectored_with_ancillary_to_unix_datagram() {
 
 #[cfg(any(target_os = "android", target_os = "linux"))]
 #[test]
+#[cfg_attr(target_os = "android", ignore)] // Android SELinux rules prevent creating Unix sockets
 fn test_send_vectored_with_ancillary_unix_datagram() {
     let dir = tmpdir();
     let path1 = dir.path().join("sock1");
diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs
index 0e90d618ad4..15285465c71 100644
--- a/library/std/src/panicking.rs
+++ b/library/std/src/panicking.rs
@@ -300,7 +300,7 @@ pub fn panic_hook_with_disk_dump(info: &PanicInfo<'_>, path: Option<&crate::path
     };
 
     if let Some(path) = path
-        && let Ok(mut out) = crate::fs::File::options().create(true).write(true).open(&path)
+        && let Ok(mut out) = crate::fs::File::options().create(true).append(true).open(&path)
     {
         write(&mut out, BacktraceStyle::full());
     }
diff --git a/library/std/src/path.rs b/library/std/src/path.rs
index 28cd3c4e4db..99f7a60f8ab 100644
--- a/library/std/src/path.rs
+++ b/library/std/src/path.rs
@@ -2608,9 +2608,27 @@ impl Path {
     }
 
     fn _with_extension(&self, extension: &OsStr) -> PathBuf {
-        let mut buf = self.to_path_buf();
-        buf.set_extension(extension);
-        buf
+        let self_len = self.as_os_str().len();
+        let self_bytes = self.as_os_str().as_os_str_bytes();
+
+        let (new_capacity, slice_to_copy) = match self.extension() {
+            None => {
+                // Enough capacity for the extension and the dot
+                let capacity = self_len + extension.len() + 1;
+                let whole_path = self_bytes.iter();
+                (capacity, whole_path)
+            }
+            Some(previous_extension) => {
+                let capacity = self_len + extension.len() - previous_extension.len();
+                let path_till_dot = self_bytes[..self_len - previous_extension.len()].iter();
+                (capacity, path_till_dot)
+            }
+        };
+
+        let mut new_path = PathBuf::with_capacity(new_capacity);
+        new_path.as_mut_vec().extend(slice_to_copy);
+        new_path.set_extension(extension);
+        new_path
     }
 
     /// Produces an iterator over the [`Component`]s of the path.
diff --git a/library/std/src/path/tests.rs b/library/std/src/path/tests.rs
index dd307022c6d..f12ffbf2e01 100644
--- a/library/std/src/path/tests.rs
+++ b/library/std/src/path/tests.rs
@@ -1183,7 +1183,7 @@ pub fn test_prefix_ext() {
 #[test]
 pub fn test_push() {
     macro_rules! tp (
-        ($path:expr, $push:expr, $expected:expr) => ( {
+        ($path:expr, $push:expr, $expected:expr) => ({
             let mut actual = PathBuf::from($path);
             actual.push($push);
             assert!(actual.to_str() == Some($expected),
@@ -1281,7 +1281,7 @@ pub fn test_push() {
 #[test]
 pub fn test_pop() {
     macro_rules! tp (
-        ($path:expr, $expected:expr, $output:expr) => ( {
+        ($path:expr, $expected:expr, $output:expr) => ({
             let mut actual = PathBuf::from($path);
             let output = actual.pop();
             assert!(actual.to_str() == Some($expected) && output == $output,
@@ -1335,7 +1335,7 @@ pub fn test_pop() {
 #[test]
 pub fn test_set_file_name() {
     macro_rules! tfn (
-            ($path:expr, $file:expr, $expected:expr) => ( {
+        ($path:expr, $file:expr, $expected:expr) => ({
             let mut p = PathBuf::from($path);
             p.set_file_name($file);
             assert!(p.to_str() == Some($expected),
@@ -1369,7 +1369,7 @@ pub fn test_set_file_name() {
 #[test]
 pub fn test_set_extension() {
     macro_rules! tfe (
-            ($path:expr, $ext:expr, $expected:expr, $output:expr) => ( {
+        ($path:expr, $ext:expr, $expected:expr, $output:expr) => ({
             let mut p = PathBuf::from($path);
             let output = p.set_extension($ext);
             assert!(p.to_str() == Some($expected) && output == $output,
@@ -1395,6 +1395,46 @@ pub fn test_set_extension() {
 }
 
 #[test]
+pub fn test_with_extension() {
+    macro_rules! twe (
+        ($input:expr, $extension:expr, $expected:expr) => ({
+            let input = Path::new($input);
+            let output = input.with_extension($extension);
+
+            assert!(
+                output.to_str() == Some($expected),
+                "calling Path::new({:?}).with_extension({:?}): Expected {:?}, got {:?}",
+                $input, $extension, $expected, output,
+            );
+        });
+    );
+
+    twe!("foo", "txt", "foo.txt");
+    twe!("foo.bar", "txt", "foo.txt");
+    twe!("foo.bar.baz", "txt", "foo.bar.txt");
+    twe!(".test", "txt", ".test.txt");
+    twe!("foo.txt", "", "foo");
+    twe!("foo", "", "foo");
+    twe!("", "foo", "");
+    twe!(".", "foo", ".");
+    twe!("foo/", "bar", "foo.bar");
+    twe!("foo/.", "bar", "foo.bar");
+    twe!("..", "foo", "..");
+    twe!("foo/..", "bar", "foo/..");
+    twe!("/", "foo", "/");
+
+    // New extension is smaller than file name
+    twe!("aaa_aaa_aaa", "bbb_bbb", "aaa_aaa_aaa.bbb_bbb");
+    // New extension is greater than file name
+    twe!("bbb_bbb", "aaa_aaa_aaa", "bbb_bbb.aaa_aaa_aaa");
+
+    // New extension is smaller than previous extension
+    twe!("ccc.aaa_aaa_aaa", "bbb_bbb", "ccc.bbb_bbb");
+    // New extension is greater than previous extension
+    twe!("ccc.bbb_bbb", "aaa_aaa_aaa", "ccc.aaa_aaa_aaa");
+}
+
+#[test]
 fn test_eq_receivers() {
     use crate::borrow::Cow;
 
@@ -1669,7 +1709,7 @@ fn into_rc() {
 #[test]
 fn test_ord() {
     macro_rules! ord(
-        ($ord:ident, $left:expr, $right:expr) => ( {
+        ($ord:ident, $left:expr, $right:expr) => ({
             use core::cmp::Ordering;
 
             let left = Path::new($left);
diff --git a/library/std/src/sync/condvar.rs b/library/std/src/sync/condvar.rs
index 76a1b4a2a86..9c4b926b7ec 100644
--- a/library/std/src/sync/condvar.rs
+++ b/library/std/src/sync/condvar.rs
@@ -21,11 +21,11 @@ impl WaitTimeoutResult {
     ///
     /// # Examples
     ///
-    /// This example spawns a thread which will update the boolean value and
-    /// then wait 100 milliseconds before notifying the condvar.
+    /// This example spawns a thread which will sleep 20 milliseconds before
+    /// updating a boolean value and then notifying the condvar.
     ///
-    /// The main thread will wait with a timeout on the condvar and then leave
-    /// once the boolean has been updated and notified.
+    /// The main thread will wait with a 10 millisecond timeout on the condvar
+    /// and will leave the loop upon timeout.
     ///
     /// ```
     /// use std::sync::{Arc, Condvar, Mutex};
@@ -49,14 +49,12 @@ impl WaitTimeoutResult {
     ///
     /// // Wait for the thread to start up.
     /// let (lock, cvar) = &*pair;
-    /// let mut started = lock.lock().unwrap();
     /// loop {
     ///     // Let's put a timeout on the condvar's wait.
-    ///     let result = cvar.wait_timeout(started, Duration::from_millis(10)).unwrap();
-    ///     // 10 milliseconds have passed, or maybe the value changed!
-    ///     started = result.0;
-    ///     if *started == true {
-    ///         // We received the notification and the value has been updated, we can leave.
+    ///     let result = cvar.wait_timeout(lock.lock().unwrap(), Duration::from_millis(10)).unwrap();
+    ///     // 10 milliseconds have passed.
+    ///     if result.1.timed_out() {
+    ///         // timed out now and we can leave.
     ///         break
     ///     }
     /// }
diff --git a/library/std/src/sync/lazy_lock.rs b/library/std/src/sync/lazy_lock.rs
index a6bc468b092..1aeed406562 100644
--- a/library/std/src/sync/lazy_lock.rs
+++ b/library/std/src/sync/lazy_lock.rs
@@ -25,6 +25,8 @@ union Data<T, F> {
 ///
 /// # Examples
 ///
+/// Initialize static variables with `LazyLock`.
+///
 /// ```
 /// #![feature(lazy_cell)]
 ///
@@ -54,6 +56,24 @@ union Data<T, F> {
 ///     //   Some("Hoyten")
 /// }
 /// ```
+/// Initialize fields with `LazyLock`.
+/// ```
+/// #![feature(lazy_cell)]
+///
+/// use std::sync::LazyLock;
+///
+/// #[derive(Debug)]
+/// struct UseCellLock {
+///     number: LazyLock<u32>,
+/// }
+/// fn main() {
+///     let lock: LazyLock<u32> = LazyLock::new(|| 0u32);
+///
+///     let data = UseCellLock { number: lock };
+///     println!("{}", *data.number);
+/// }
+/// ```
+
 #[unstable(feature = "lazy_cell", issue = "109736")]
 pub struct LazyLock<T, F = fn() -> T> {
     once: Once,
@@ -69,6 +89,15 @@ impl<T, F: FnOnce() -> T> LazyLock<T, F> {
         LazyLock { once: Once::new(), data: UnsafeCell::new(Data { f: ManuallyDrop::new(f) }) }
     }
 
+    /// Creates a new lazy value that is already initialized.
+    #[inline]
+    #[cfg(test)]
+    pub(crate) fn preinit(value: T) -> LazyLock<T, F> {
+        let once = Once::new();
+        once.call_once(|| {});
+        LazyLock { once, data: UnsafeCell::new(Data { value: ManuallyDrop::new(value) }) }
+    }
+
     /// Consumes this `LazyLock` returning the stored value.
     ///
     /// Returns `Ok(value)` if `Lazy` is initialized and `Err(f)` otherwise.
diff --git a/library/std/src/sys/common/thread_local/fast_local.rs b/library/std/src/sys/common/thread_local/fast_local.rs
index bc5da1a1896..c0a9619bf7b 100644
--- a/library/std/src/sys/common/thread_local/fast_local.rs
+++ b/library/std/src/sys/common/thread_local/fast_local.rs
@@ -87,10 +87,6 @@ pub macro thread_local_inner {
                 static __KEY: $crate::thread::local_impl::Key<$t> =
                     $crate::thread::local_impl::Key::<$t>::new();
 
-                // FIXME: remove the #[allow(...)] marker when macros don't
-                // raise warning for missing/extraneous unsafe blocks anymore.
-                // See https://github.com/rust-lang/rust/issues/74838.
-                #[allow(unused_unsafe)]
                 unsafe {
                     __KEY.get(move || {
                         if let $crate::option::Option::Some(init) = init {
diff --git a/library/std/src/sys/common/thread_local/os_local.rs b/library/std/src/sys/common/thread_local/os_local.rs
index 5d48ce1e03b..7cf29192122 100644
--- a/library/std/src/sys/common/thread_local/os_local.rs
+++ b/library/std/src/sys/common/thread_local/os_local.rs
@@ -24,7 +24,6 @@ pub macro thread_local_inner {
             const fn __init() -> $t { INIT_EXPR }
             static __KEY: $crate::thread::local_impl::Key<$t> =
                 $crate::thread::local_impl::Key::new();
-            #[allow(unused_unsafe)]
             unsafe {
                 __KEY.get(move || {
                     if let $crate::option::Option::Some(init) = _init {
@@ -59,10 +58,6 @@ pub macro thread_local_inner {
                 static __KEY: $crate::thread::local_impl::Key<$t> =
                     $crate::thread::local_impl::Key::new();
 
-                // FIXME: remove the #[allow(...)] marker when macros don't
-                // raise warning for missing/extraneous unsafe blocks anymore.
-                // See https://github.com/rust-lang/rust/issues/74838.
-                #[allow(unused_unsafe)]
                 unsafe {
                     __KEY.get(move || {
                         if let $crate::option::Option::Some(init) = init {
diff --git a/library/std/src/sys/common/thread_local/static_local.rs b/library/std/src/sys/common/thread_local/static_local.rs
index 80322a97864..5cb6c541a0e 100644
--- a/library/std/src/sys/common/thread_local/static_local.rs
+++ b/library/std/src/sys/common/thread_local/static_local.rs
@@ -43,10 +43,6 @@ pub macro thread_local_inner {
                 static __KEY: $crate::thread::local_impl::Key<$t> =
                     $crate::thread::local_impl::Key::new();
 
-                // FIXME: remove the #[allow(...)] marker when macros don't
-                // raise warning for missing/extraneous unsafe blocks anymore.
-                // See https://github.com/rust-lang/rust/issues/74838.
-                #[allow(unused_unsafe)]
                 unsafe {
                     __KEY.get(move || {
                         if let $crate::option::Option::Some(init) = init {
diff --git a/library/std/src/sys/sgx/thread.rs b/library/std/src/sys/sgx/thread.rs
index 1608b8cb642..7ac9d1d64b4 100644
--- a/library/std/src/sys/sgx/thread.rs
+++ b/library/std/src/sys/sgx/thread.rs
@@ -121,8 +121,16 @@ impl Thread {
         rtassert!(wait_error.kind() == io::ErrorKind::WouldBlock);
     }
 
+    /// SGX should protect in-enclave data from the outside (attacker),
+    /// so there should be no data leakage to the OS,
+    /// and therefore also no 1-1 mapping between SGX thread names and OS thread names.
+    ///
+    /// This is why the method is intentionally No-Op.
     pub fn set_name(_name: &CStr) {
-        // FIXME: could store this pointer in TLS somewhere
+        // Note that the internally visible SGX thread name is already provided
+        // by the platform-agnostic (target-agnostic) Rust thread code.
+        // This can be observed in the [`std::thread::tests::test_named_thread`] test,
+        // which succeeds as-is with the SGX target.
     }
 
     pub fn sleep(dur: Duration) {
diff --git a/library/std/src/sys/unix/mod.rs b/library/std/src/sys/unix/mod.rs
index 326f1481e19..77ef086f29b 100644
--- a/library/std/src/sys/unix/mod.rs
+++ b/library/std/src/sys/unix/mod.rs
@@ -110,6 +110,11 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) {
             while libc::poll(pfds.as_mut_ptr(), 3, 0) == -1 {
                 match errno() {
                     libc::EINTR => continue,
+                    #[cfg(target_vendor = "unikraft")]
+                    libc::ENOSYS => {
+                        // Not all configurations of Unikraft enable `LIBPOSIX_EVENT`.
+                        break 'poll;
+                    }
                     libc::EINVAL | libc::EAGAIN | libc::ENOMEM => {
                         // RLIMIT_NOFILE or temporary allocation failures
                         // may be preventing use of poll(), fall back to fcntl
@@ -165,7 +170,14 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) {
     }
 
     unsafe fn reset_sigpipe(#[allow(unused_variables)] sigpipe: u8) {
-        #[cfg(not(any(target_os = "emscripten", target_os = "fuchsia", target_os = "horizon")))]
+        #[cfg(not(any(
+            target_os = "emscripten",
+            target_os = "fuchsia",
+            target_os = "horizon",
+            // Unikraft's `signal` implementation is currently broken:
+            // https://github.com/unikraft/lib-musl/issues/57
+            target_vendor = "unikraft",
+        )))]
         {
             // We don't want to add this as a public type to std, nor do we
             // want to `include!` a file from the compiler (which would break
diff --git a/library/std/src/sys/unix/os_str.rs b/library/std/src/sys/unix/os_str.rs
index f7333fd5a1f..463b0a27515 100644
--- a/library/std/src/sys/unix/os_str.rs
+++ b/library/std/src/sys/unix/os_str.rs
@@ -96,6 +96,16 @@ impl AsInner<[u8]> for Buf {
 }
 
 impl Buf {
+    #[inline]
+    pub fn into_os_str_bytes(self) -> Vec<u8> {
+        self.inner
+    }
+
+    #[inline]
+    pub unsafe fn from_os_str_bytes_unchecked(s: Vec<u8>) -> Self {
+        Self { inner: s }
+    }
+
     pub fn from_string(s: String) -> Buf {
         Buf { inner: s.into_bytes() }
     }
diff --git a/library/std/src/sys/unix/rand.rs b/library/std/src/sys/unix/rand.rs
index d471be33ed5..fbf158f56fc 100644
--- a/library/std/src/sys/unix/rand.rs
+++ b/library/std/src/sys/unix/rand.rs
@@ -17,7 +17,6 @@ pub fn hashmap_random_keys() -> (u64, u64) {
     not(target_os = "tvos"),
     not(target_os = "watchos"),
     not(target_os = "openbsd"),
-    not(target_os = "freebsd"),
     not(target_os = "netbsd"),
     not(target_os = "fuchsia"),
     not(target_os = "redox"),
@@ -68,11 +67,25 @@ mod imp {
         unsafe { libc::getrandom(buf.as_mut_ptr().cast(), buf.len(), 0) }
     }
 
+    #[cfg(target_os = "freebsd")]
+    fn getrandom(buf: &mut [u8]) -> libc::ssize_t {
+        // FIXME: using the above when libary std's libc is updated
+        extern "C" {
+            fn getrandom(
+                buffer: *mut libc::c_void,
+                length: 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",
         target_os = "espidf",
-        target_os = "horizon"
+        target_os = "horizon",
+        target_os = "freebsd"
     )))]
     fn getrandom_fill_bytes(_buf: &mut [u8]) -> bool {
         false
@@ -82,7 +95,8 @@ mod imp {
         target_os = "linux",
         target_os = "android",
         target_os = "espidf",
-        target_os = "horizon"
+        target_os = "horizon",
+        target_os = "freebsd"
     ))]
     fn getrandom_fill_bytes(v: &mut [u8]) -> bool {
         use crate::sync::atomic::{AtomicBool, Ordering};
@@ -222,7 +236,7 @@ mod imp {
     }
 }
 
-#[cfg(any(target_os = "freebsd", target_os = "netbsd"))]
+#[cfg(target_os = "netbsd")]
 mod imp {
     use crate::ptr;
 
diff --git a/library/std/src/sys/windows/compat.rs b/library/std/src/sys/windows/compat.rs
index 4fe95d41116..e28dd493536 100644
--- a/library/std/src/sys/windows/compat.rs
+++ b/library/std/src/sys/windows/compat.rs
@@ -69,10 +69,7 @@ unsafe extern "C" fn init() {
 
 /// Helper macro for creating CStrs from literals and symbol names.
 macro_rules! ansi_str {
-    (sym $ident:ident) => {{
-        #[allow(unused_unsafe)]
-        crate::sys::compat::const_cstr_from_bytes(concat!(stringify!($ident), "\0").as_bytes())
-    }};
+    (sym $ident:ident) => {{ crate::sys::compat::const_cstr_from_bytes(concat!(stringify!($ident), "\0").as_bytes()) }};
     ($lit:literal) => {{ crate::sys::compat::const_cstr_from_bytes(concat!($lit, "\0").as_bytes()) }};
 }
 
diff --git a/library/std/src/sys/windows/os_str.rs b/library/std/src/sys/windows/os_str.rs
index 16c4f55c687..4708657a907 100644
--- a/library/std/src/sys/windows/os_str.rs
+++ b/library/std/src/sys/windows/os_str.rs
@@ -63,6 +63,16 @@ impl fmt::Display for Slice {
 }
 
 impl Buf {
+    #[inline]
+    pub fn into_os_str_bytes(self) -> Vec<u8> {
+        self.inner.into_bytes()
+    }
+
+    #[inline]
+    pub unsafe fn from_os_str_bytes_unchecked(s: Vec<u8>) -> Self {
+        Self { inner: Wtf8Buf::from_bytes_unchecked(s) }
+    }
+
     pub fn with_capacity(capacity: usize) -> Buf {
         Buf { inner: Wtf8Buf::with_capacity(capacity) }
     }
diff --git a/library/std/src/sys/windows/thread_local_dtor.rs b/library/std/src/sys/windows/thread_local_dtor.rs
index 9707a95dff2..cf542d2bfb8 100644
--- a/library/std/src/sys/windows/thread_local_dtor.rs
+++ b/library/std/src/sys/windows/thread_local_dtor.rs
@@ -4,29 +4,4 @@
 #![unstable(feature = "thread_local_internals", issue = "none")]
 #![cfg(target_thread_local)]
 
-// Using a per-thread list avoids the problems in synchronizing global state.
-#[thread_local]
-static mut DESTRUCTORS: Vec<(*mut u8, unsafe extern "C" fn(*mut u8))> = Vec::new();
-
-// Ensure this can never be inlined because otherwise this may break in dylibs.
-// See #44391.
-#[inline(never)]
-pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) {
-    DESTRUCTORS.push((t, dtor));
-}
-
-#[inline(never)] // See comment above
-/// Runs destructors. This should not be called until thread exit.
-pub unsafe fn run_keyless_dtors() {
-    // Drop all the destructors.
-    //
-    // Note: While this is potentially an infinite loop, it *should* be
-    // the case that this loop always terminates because we provide the
-    // guarantee that a TLS key cannot be set after it is flagged for
-    // destruction.
-    while let Some((ptr, dtor)) = DESTRUCTORS.pop() {
-        (dtor)(ptr);
-    }
-    // We're done so free the memory.
-    DESTRUCTORS = Vec::new();
-}
+pub use super::thread_local_key::register_keyless_dtor as register_dtor;
diff --git a/library/std/src/sys/windows/thread_local_key.rs b/library/std/src/sys/windows/thread_local_key.rs
index 17628b7579b..036d96596e9 100644
--- a/library/std/src/sys/windows/thread_local_key.rs
+++ b/library/std/src/sys/windows/thread_local_key.rs
@@ -1,7 +1,7 @@
 use crate::cell::UnsafeCell;
 use crate::ptr;
 use crate::sync::atomic::{
-    AtomicPtr, AtomicU32,
+    AtomicBool, AtomicPtr, AtomicU32,
     Ordering::{AcqRel, Acquire, Relaxed, Release},
 };
 use crate::sys::c;
@@ -9,6 +9,41 @@ use crate::sys::c;
 #[cfg(test)]
 mod tests;
 
+/// An optimization hint. The compiler is often smart enough to know if an atomic
+/// is never set and can remove dead code based on that fact.
+static HAS_DTORS: AtomicBool = AtomicBool::new(false);
+
+// Using a per-thread list avoids the problems in synchronizing global state.
+#[thread_local]
+#[cfg(target_thread_local)]
+static mut DESTRUCTORS: Vec<(*mut u8, unsafe extern "C" fn(*mut u8))> = Vec::new();
+
+// Ensure this can never be inlined because otherwise this may break in dylibs.
+// See #44391.
+#[inline(never)]
+#[cfg(target_thread_local)]
+pub unsafe fn register_keyless_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) {
+    DESTRUCTORS.push((t, dtor));
+    HAS_DTORS.store(true, Relaxed);
+}
+
+#[inline(never)] // See comment above
+#[cfg(target_thread_local)]
+/// Runs destructors. This should not be called until thread exit.
+unsafe fn run_keyless_dtors() {
+    // Drop all the destructors.
+    //
+    // Note: While this is potentially an infinite loop, it *should* be
+    // the case that this loop always terminates because we provide the
+    // guarantee that a TLS key cannot be set after it is flagged for
+    // destruction.
+    while let Some((ptr, dtor)) = DESTRUCTORS.pop() {
+        (dtor)(ptr);
+    }
+    // We're done so free the memory.
+    DESTRUCTORS = Vec::new();
+}
+
 type Key = c::DWORD;
 type Dtor = unsafe extern "C" fn(*mut u8);
 
@@ -156,6 +191,8 @@ static DTORS: AtomicPtr<StaticKey> = AtomicPtr::new(ptr::null_mut());
 /// Should only be called once per key, otherwise loops or breaks may occur in
 /// the linked list.
 unsafe fn register_dtor(key: &'static StaticKey) {
+    // Ensure this is never run when native thread locals are available.
+    assert_eq!(false, cfg!(target_thread_local));
     let this = <*const StaticKey>::cast_mut(key);
     // Use acquire ordering to pass along the changes done by the previously
     // registered keys when we store the new head with release ordering.
@@ -167,6 +204,7 @@ unsafe fn register_dtor(key: &'static StaticKey) {
             Err(new) => head = new,
         }
     }
+    HAS_DTORS.store(true, Release);
 }
 
 // -------------------------------------------------------------------------
@@ -240,10 +278,14 @@ pub static p_thread_callback: unsafe extern "system" fn(c::LPVOID, c::DWORD, c::
 
 #[allow(dead_code, unused_variables)]
 unsafe extern "system" fn on_tls_callback(h: c::LPVOID, dwReason: c::DWORD, pv: c::LPVOID) {
+    if !HAS_DTORS.load(Acquire) {
+        return;
+    }
     if dwReason == c::DLL_THREAD_DETACH || dwReason == c::DLL_PROCESS_DETACH {
+        #[cfg(not(target_thread_local))]
         run_dtors();
         #[cfg(target_thread_local)]
-        super::thread_local_dtor::run_keyless_dtors();
+        run_keyless_dtors();
     }
 
     // See comments above for what this is doing. Note that we don't need this
diff --git a/library/std/src/sys/windows/thread_local_key/tests.rs b/library/std/src/sys/windows/thread_local_key/tests.rs
index c95f383fb90..c739f0caf3e 100644
--- a/library/std/src/sys/windows/thread_local_key/tests.rs
+++ b/library/std/src/sys/windows/thread_local_key/tests.rs
@@ -1,3 +1,7 @@
+// This file only tests the thread local key fallback.
+// Windows targets with native thread local support do not use this.
+#![cfg(not(target_thread_local))]
+
 use super::StaticKey;
 use crate::ptr;
 
diff --git a/library/std/src/sys_common/backtrace.rs b/library/std/src/sys_common/backtrace.rs
index 6f020940df1..84e2c5d8d7f 100644
--- a/library/std/src/sys_common/backtrace.rs
+++ b/library/std/src/sys_common/backtrace.rs
@@ -60,6 +60,8 @@ unsafe fn _print_fmt(fmt: &mut fmt::Formatter<'_>, print_fmt: PrintFmt) -> fmt::
     bt_fmt.add_context()?;
     let mut idx = 0;
     let mut res = Ok(());
+    let mut omitted_count: usize = 0;
+    let mut first_omit = true;
     // Start immediately if we're not using a short backtrace.
     let mut start = print_fmt != PrintFmt::Short;
     backtrace_rs::trace_unsynchronized(|frame| {
@@ -85,10 +87,27 @@ unsafe fn _print_fmt(fmt: &mut fmt::Formatter<'_>, print_fmt: PrintFmt) -> fmt::
                         start = true;
                         return;
                     }
+                    if !start {
+                        omitted_count += 1;
+                    }
                 }
             }
 
             if start {
+                if omitted_count > 0 {
+                    debug_assert!(print_fmt == PrintFmt::Short);
+                    // only print the message between the middle of frames
+                    if !first_omit {
+                        let _ = writeln!(
+                            bt_fmt.formatter(),
+                            "      [... omitted {} frame{} ...]",
+                            omitted_count,
+                            if omitted_count > 1 { "s" } else { "" }
+                        );
+                    }
+                    first_omit = false;
+                    omitted_count = 0;
+                }
                 res = bt_fmt.frame().symbol(frame, symbol);
             }
         });
diff --git a/library/std/src/sys_common/thread_info.rs b/library/std/src/sys_common/thread_info.rs
index 38c9e50009a..88d937a7db1 100644
--- a/library/std/src/sys_common/thread_info.rs
+++ b/library/std/src/sys_common/thread_info.rs
@@ -1,5 +1,4 @@
 #![allow(dead_code)] // stack_guard isn't used right now on all platforms
-#![allow(unused_unsafe)] // thread_local with `const {}` triggers this liny
 
 use crate::cell::RefCell;
 use crate::sys::thread::guard::Guard;
diff --git a/library/std/src/sys_common/wtf8.rs b/library/std/src/sys_common/wtf8.rs
index c9d3e13cf0c..195d175cc9b 100644
--- a/library/std/src/sys_common/wtf8.rs
+++ b/library/std/src/sys_common/wtf8.rs
@@ -182,6 +182,15 @@ impl Wtf8Buf {
         Wtf8Buf { bytes: Vec::with_capacity(capacity), is_known_utf8: true }
     }
 
+    /// Creates a WTF-8 string from a WTF-8 byte vec.
+    ///
+    /// Since the byte vec is not checked for valid WTF-8, this functions is
+    /// marked unsafe.
+    #[inline]
+    pub unsafe fn from_bytes_unchecked(value: Vec<u8>) -> Wtf8Buf {
+        Wtf8Buf { bytes: value, is_known_utf8: false }
+    }
+
     /// Creates a WTF-8 string from a UTF-8 `String`.
     ///
     /// This takes ownership of the `String` and does not copy.
@@ -402,6 +411,12 @@ impl Wtf8Buf {
         self.bytes.truncate(new_len)
     }
 
+    /// Consumes the WTF-8 string and tries to convert it to a vec of bytes.
+    #[inline]
+    pub fn into_bytes(self) -> Vec<u8> {
+        self.bytes
+    }
+
     /// Consumes the WTF-8 string and tries to convert it to UTF-8.
     ///
     /// This does not copy the data.