about summary refs log tree commit diff
path: root/library/std
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-03-06 18:51:11 +0000
committerbors <bors@rust-lang.org>2024-03-06 18:51:11 +0000
commit305d2b0f5c7e8081ab21f78e2d53ed8f84aebecd (patch)
treee8c9415143a6307f929727db3da941edda124d78 /library/std
parent033c1e00b0fda6616c1442ecf40bb79da8c5db20 (diff)
parent3c2318c0b21e2f4473c2465a4d9481ccd21906dd (diff)
Auto merge of #3363 - RalfJung:rustup, r=RalfJung
Rustup

This should finally work again :)
Diffstat (limited to 'library/std')
-rw-r--r--library/std/src/env.rs2
-rw-r--r--library/std/src/f32.rs24
-rw-r--r--library/std/src/f64.rs24
-rw-r--r--library/std/src/fs.rs9
-rw-r--r--library/std/src/io/buffered/linewritershim.rs2
-rw-r--r--library/std/src/io/mod.rs2
-rw-r--r--library/std/src/sync/mutex.rs20
-rw-r--r--library/std/src/sys/locks/condvar/mod.rs7
-rw-r--r--library/std/src/sys/locks/condvar/windows7.rs (renamed from library/std/src/sys/locks/condvar/windows.rs)0
-rw-r--r--library/std/src/sys/locks/mutex/futex.rs54
-rw-r--r--library/std/src/sys/locks/mutex/mod.rs7
-rw-r--r--library/std/src/sys/locks/mutex/windows7.rs (renamed from library/std/src/sys/locks/mutex/windows.rs)0
-rw-r--r--library/std/src/sys/locks/rwlock/mod.rs7
-rw-r--r--library/std/src/sys/locks/rwlock/windows7.rs (renamed from library/std/src/sys/locks/rwlock/windows.rs)0
-rw-r--r--library/std/src/sys/mod.rs3
-rw-r--r--library/std/src/sys/pal/common/mod.rs2
-rw-r--r--library/std/src/sys/pal/hermit/memchr.rs1
-rw-r--r--library/std/src/sys/pal/hermit/mod.rs1
-rw-r--r--library/std/src/sys/pal/hermit/os.rs2
-rw-r--r--library/std/src/sys/pal/hermit/thread.rs6
-rw-r--r--library/std/src/sys/pal/itron/thread.rs6
-rw-r--r--library/std/src/sys/pal/sgx/memchr.rs1
-rw-r--r--library/std/src/sys/pal/sgx/mod.rs1
-rw-r--r--library/std/src/sys/pal/sgx/thread.rs6
-rw-r--r--library/std/src/sys/pal/solid/memchr.rs21
-rw-r--r--library/std/src/sys/pal/solid/mod.rs1
-rw-r--r--library/std/src/sys/pal/solid/os.rs4
-rw-r--r--library/std/src/sys/pal/teeos/mod.rs2
-rw-r--r--library/std/src/sys/pal/teeos/thread.rs6
-rw-r--r--library/std/src/sys/pal/uefi/mod.rs4
-rw-r--r--library/std/src/sys/pal/uefi/thread.rs6
-rw-r--r--library/std/src/sys/pal/unix/memchr.rs40
-rw-r--r--library/std/src/sys/pal/unix/mod.rs1
-rw-r--r--library/std/src/sys/pal/unix/os.rs2
-rw-r--r--library/std/src/sys/pal/unix/thread.rs40
-rw-r--r--library/std/src/sys/pal/unsupported/common.rs4
-rw-r--r--library/std/src/sys/pal/unsupported/thread.rs6
-rw-r--r--library/std/src/sys/pal/wasi/os.rs2
-rw-r--r--library/std/src/sys/pal/wasi/thread.rs6
-rw-r--r--library/std/src/sys/pal/wasm/atomics/thread.rs4
-rw-r--r--library/std/src/sys/pal/windows/c.rs10
-rw-r--r--library/std/src/sys/pal/windows/c/bindings.txt2
-rw-r--r--library/std/src/sys/pal/windows/c/windows_sys.rs6
-rw-r--r--library/std/src/sys/pal/windows/futex.rs85
-rw-r--r--library/std/src/sys/pal/windows/memchr.rs5
-rw-r--r--library/std/src/sys/pal/windows/mod.rs24
-rw-r--r--library/std/src/sys/pal/windows/thread.rs25
-rw-r--r--library/std/src/sys/pal/xous/thread.rs6
-rw-r--r--library/std/src/sys/pal/zkvm/mod.rs4
-rw-r--r--library/std/src/sys/thread_local/fast_local.rs (renamed from library/std/src/sys/pal/common/thread_local/fast_local.rs)0
-rw-r--r--library/std/src/sys/thread_local/mod.rs (renamed from library/std/src/sys/pal/common/thread_local/mod.rs)0
-rw-r--r--library/std/src/sys/thread_local/os_local.rs (renamed from library/std/src/sys/pal/common/thread_local/os_local.rs)0
-rw-r--r--library/std/src/sys/thread_local/static_local.rs (renamed from library/std/src/sys/pal/common/thread_local/static_local.rs)0
-rw-r--r--library/std/src/sys_common/memchr.rs51
-rw-r--r--library/std/src/sys_common/memchr/tests.rs86
-rw-r--r--library/std/src/sys_common/mod.rs1
-rw-r--r--library/std/src/sys_common/thread_info.rs4
-rw-r--r--library/std/src/thread/mod.rs2
-rw-r--r--library/std/src/thread/tests.rs19
59 files changed, 332 insertions, 334 deletions
diff --git a/library/std/src/env.rs b/library/std/src/env.rs
index 1f2b8d3007d..6f8ac17f12c 100644
--- a/library/std/src/env.rs
+++ b/library/std/src/env.rs
@@ -469,7 +469,6 @@ pub struct SplitPaths<'a> {
 ///     None => println!("{key} is not defined in the environment.")
 /// }
 /// ```
-#[doc(alias = "PATH")]
 #[stable(feature = "env", since = "1.0.0")]
 pub fn split_paths<T: AsRef<OsStr> + ?Sized>(unparsed: &T) -> SplitPaths<'_> {
     SplitPaths { inner: os_imp::split_paths(unparsed.as_ref()) }
@@ -565,7 +564,6 @@ pub struct JoinPathsError {
 /// ```
 ///
 /// [`env::split_paths()`]: split_paths
-#[doc(alias = "PATH")]
 #[stable(feature = "env", since = "1.0.0")]
 pub fn join_paths<I, T>(paths: I) -> Result<OsString, JoinPathsError>
 where
diff --git a/library/std/src/f32.rs b/library/std/src/f32.rs
index 6ec389400ae..de9bde51f2a 100644
--- a/library/std/src/f32.rs
+++ b/library/std/src/f32.rs
@@ -186,11 +186,8 @@ impl f32 {
     /// let x = 3.5_f32;
     /// let y = -3.5_f32;
     ///
-    /// let abs_difference_x = (x.abs() - x).abs();
-    /// let abs_difference_y = (y.abs() - (-y)).abs();
-    ///
-    /// assert!(abs_difference_x <= f32::EPSILON);
-    /// assert!(abs_difference_y <= f32::EPSILON);
+    /// assert_eq!(x.abs(), x);
+    /// assert_eq!(y.abs(), -y);
     ///
     /// assert!(f32::NAN.abs().is_nan());
     /// ```
@@ -276,10 +273,17 @@ impl f32 {
     /// let x = 4.0_f32;
     /// let b = 60.0_f32;
     ///
-    /// // 100.0
-    /// let abs_difference = (m.mul_add(x, b) - ((m * x) + b)).abs();
+    /// assert_eq!(m.mul_add(x, b), 100.0);
+    /// assert_eq!(m * x + b, 100.0);
     ///
-    /// assert!(abs_difference <= f32::EPSILON);
+    /// let one_plus_eps = 1.0_f32 + f32::EPSILON;
+    /// let one_minus_eps = 1.0_f32 - f32::EPSILON;
+    /// let minus_one = -1.0_f32;
+    ///
+    /// // The exact result (1 + eps) * (1 - eps) = 1 - eps * eps.
+    /// assert_eq!(one_plus_eps.mul_add(one_minus_eps, minus_one), -f32::EPSILON * f32::EPSILON);
+    /// // Different rounding with the non-fused multiply and add.
+    /// assert_eq!(one_plus_eps * one_minus_eps + minus_one, 0.0);
     /// ```
     #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
@@ -426,9 +430,7 @@ impl f32 {
     /// let negative = -4.0_f32;
     /// let negative_zero = -0.0_f32;
     ///
-    /// let abs_difference = (positive.sqrt() - 2.0).abs();
-    ///
-    /// assert!(abs_difference <= f32::EPSILON);
+    /// assert_eq!(positive.sqrt(), 2.0);
     /// assert!(negative.sqrt().is_nan());
     /// assert!(negative_zero.sqrt() == negative_zero);
     /// ```
diff --git a/library/std/src/f64.rs b/library/std/src/f64.rs
index 7385576c337..944186d602c 100644
--- a/library/std/src/f64.rs
+++ b/library/std/src/f64.rs
@@ -186,11 +186,8 @@ impl f64 {
     /// let x = 3.5_f64;
     /// let y = -3.5_f64;
     ///
-    /// let abs_difference_x = (x.abs() - x).abs();
-    /// let abs_difference_y = (y.abs() - (-y)).abs();
-    ///
-    /// assert!(abs_difference_x < 1e-10);
-    /// assert!(abs_difference_y < 1e-10);
+    /// assert_eq!(x.abs(), x);
+    /// assert_eq!(y.abs(), -y);
     ///
     /// assert!(f64::NAN.abs().is_nan());
     /// ```
@@ -276,10 +273,17 @@ impl f64 {
     /// let x = 4.0_f64;
     /// let b = 60.0_f64;
     ///
-    /// // 100.0
-    /// let abs_difference = (m.mul_add(x, b) - ((m * x) + b)).abs();
+    /// assert_eq!(m.mul_add(x, b), 100.0);
+    /// assert_eq!(m * x + b, 100.0);
     ///
-    /// assert!(abs_difference < 1e-10);
+    /// let one_plus_eps = 1.0_f64 + f64::EPSILON;
+    /// let one_minus_eps = 1.0_f64 - f64::EPSILON;
+    /// let minus_one = -1.0_f64;
+    ///
+    /// // The exact result (1 + eps) * (1 - eps) = 1 - eps * eps.
+    /// assert_eq!(one_plus_eps.mul_add(one_minus_eps, minus_one), -f64::EPSILON * f64::EPSILON);
+    /// // Different rounding with the non-fused multiply and add.
+    /// assert_eq!(one_plus_eps * one_minus_eps + minus_one, 0.0);
     /// ```
     #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
@@ -426,9 +430,7 @@ impl f64 {
     /// let negative = -4.0_f64;
     /// let negative_zero = -0.0_f64;
     ///
-    /// let abs_difference = (positive.sqrt() - 2.0).abs();
-    ///
-    /// assert!(abs_difference < 1e-10);
+    /// assert_eq!(positive.sqrt(), 2.0);
     /// assert!(negative.sqrt().is_nan());
     /// assert!(negative_zero.sqrt() == negative_zero);
     /// ```
diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs
index 6b1dd1b5af4..694cc34cdc1 100644
--- a/library/std/src/fs.rs
+++ b/library/std/src/fs.rs
@@ -1476,11 +1476,10 @@ impl Permissions {
     /// On Unix-based platforms this checks if *any* of the owner, group or others
     /// write permission bits are set. It does not check if the current
     /// user is in the file's assigned group. It also does not check ACLs.
-    /// Therefore even if this returns true you may not be able to write to the
-    /// file, and vice versa. The [`PermissionsExt`] trait gives direct access
-    /// to the permission bits but also does not read ACLs. If you need to
-    /// accurately know whether or not a file is writable use the `access()`
-    /// function from libc.
+    /// Therefore the return value of this function cannot be relied upon
+    /// to predict whether attempts to read or write the file will actually succeed.
+    /// The [`PermissionsExt`] trait gives direct access to the permission bits but
+    /// also does not read ACLs.
     ///
     /// [`PermissionsExt`]: crate::os::unix::fs::PermissionsExt
     ///
diff --git a/library/std/src/io/buffered/linewritershim.rs b/library/std/src/io/buffered/linewritershim.rs
index f2a55da05b2..7eadfd41366 100644
--- a/library/std/src/io/buffered/linewritershim.rs
+++ b/library/std/src/io/buffered/linewritershim.rs
@@ -1,5 +1,5 @@
 use crate::io::{self, BufWriter, IoSlice, Write};
-use crate::sys_common::memchr;
+use core::slice::memchr;
 
 /// Private helper struct for implementing the line-buffered writing logic.
 /// This shim temporarily wraps a BufWriter, and uses its internals to
diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs
index 102db62fced..f35bffd6a3c 100644
--- a/library/std/src/io/mod.rs
+++ b/library/std/src/io/mod.rs
@@ -304,7 +304,7 @@ use crate::ops::{Deref, DerefMut};
 use crate::slice;
 use crate::str;
 use crate::sys;
-use crate::sys_common::memchr;
+use core::slice::memchr;
 
 #[stable(feature = "bufwriter_into_parts", since = "1.56.0")]
 pub use self::buffered::WriterPanicked;
diff --git a/library/std/src/sync/mutex.rs b/library/std/src/sync/mutex.rs
index fa91f9d907a..65ff10e02d4 100644
--- a/library/std/src/sync/mutex.rs
+++ b/library/std/src/sync/mutex.rs
@@ -369,26 +369,6 @@ impl<T: ?Sized> Mutex<T> {
         }
     }
 
-    /// Immediately drops the guard, and consequently unlocks the mutex.
-    ///
-    /// This function is equivalent to calling [`drop`] on the guard but is more self-documenting.
-    /// Alternately, the guard will be automatically dropped when it goes out of scope.
-    ///
-    /// ```
-    /// #![feature(mutex_unlock)]
-    ///
-    /// use std::sync::Mutex;
-    /// let mutex = Mutex::new(0);
-    ///
-    /// let mut guard = mutex.lock().unwrap();
-    /// *guard += 20;
-    /// Mutex::unlock(guard);
-    /// ```
-    #[unstable(feature = "mutex_unlock", issue = "81872")]
-    pub fn unlock(guard: MutexGuard<'_, T>) {
-        drop(guard);
-    }
-
     /// Determines whether the mutex is poisoned.
     ///
     /// If another thread is active, the mutex can still become poisoned at any
diff --git a/library/std/src/sys/locks/condvar/mod.rs b/library/std/src/sys/locks/condvar/mod.rs
index 126a42a2a4c..6849cacf88e 100644
--- a/library/std/src/sys/locks/condvar/mod.rs
+++ b/library/std/src/sys/locks/condvar/mod.rs
@@ -1,5 +1,6 @@
 cfg_if::cfg_if! {
     if #[cfg(any(
+        all(target_os = "windows", not(target_vendor="win7")),
         target_os = "linux",
         target_os = "android",
         target_os = "freebsd",
@@ -14,9 +15,9 @@ cfg_if::cfg_if! {
     } else if #[cfg(target_family = "unix")] {
         mod pthread;
         pub use pthread::Condvar;
-    } else if #[cfg(target_os = "windows")] {
-        mod windows;
-        pub use windows::Condvar;
+    } else if #[cfg(all(target_os = "windows", target_vendor = "win7"))] {
+        mod windows7;
+        pub use windows7::Condvar;
     } else if #[cfg(all(target_vendor = "fortanix", target_env = "sgx"))] {
         mod sgx;
         pub use sgx::Condvar;
diff --git a/library/std/src/sys/locks/condvar/windows.rs b/library/std/src/sys/locks/condvar/windows7.rs
index 28a288335d2..28a288335d2 100644
--- a/library/std/src/sys/locks/condvar/windows.rs
+++ b/library/std/src/sys/locks/condvar/windows7.rs
diff --git a/library/std/src/sys/locks/mutex/futex.rs b/library/std/src/sys/locks/mutex/futex.rs
index c01229586c3..7427cae94d6 100644
--- a/library/std/src/sys/locks/mutex/futex.rs
+++ b/library/std/src/sys/locks/mutex/futex.rs
@@ -1,30 +1,42 @@
 use crate::sync::atomic::{
-    AtomicU32,
+    self,
     Ordering::{Acquire, Relaxed, Release},
 };
 use crate::sys::futex::{futex_wait, futex_wake};
 
+cfg_if::cfg_if! {
+if #[cfg(windows)] {
+    // On Windows we can have a smol futex
+    type Atomic = atomic::AtomicU8;
+    type State = u8;
+} else {
+    type Atomic = atomic::AtomicU32;
+    type State = u32;
+}
+}
+
 pub struct Mutex {
-    /// 0: unlocked
-    /// 1: locked, no other threads waiting
-    /// 2: locked, and other threads waiting (contended)
-    futex: AtomicU32,
+    futex: Atomic,
 }
 
+const UNLOCKED: State = 0;
+const LOCKED: State = 1; // locked, no other threads waiting
+const CONTENDED: State = 2; // locked, and other threads waiting (contended)
+
 impl Mutex {
     #[inline]
     pub const fn new() -> Self {
-        Self { futex: AtomicU32::new(0) }
+        Self { futex: Atomic::new(UNLOCKED) }
     }
 
     #[inline]
     pub fn try_lock(&self) -> bool {
-        self.futex.compare_exchange(0, 1, Acquire, Relaxed).is_ok()
+        self.futex.compare_exchange(UNLOCKED, LOCKED, Acquire, Relaxed).is_ok()
     }
 
     #[inline]
     pub fn lock(&self) {
-        if self.futex.compare_exchange(0, 1, Acquire, Relaxed).is_err() {
+        if self.futex.compare_exchange(UNLOCKED, LOCKED, Acquire, Relaxed).is_err() {
             self.lock_contended();
         }
     }
@@ -36,8 +48,8 @@ impl Mutex {
 
         // If it's unlocked now, attempt to take the lock
         // without marking it as contended.
-        if state == 0 {
-            match self.futex.compare_exchange(0, 1, Acquire, Relaxed) {
+        if state == UNLOCKED {
+            match self.futex.compare_exchange(UNLOCKED, LOCKED, Acquire, Relaxed) {
                 Ok(_) => return, // Locked!
                 Err(s) => state = s,
             }
@@ -45,31 +57,31 @@ impl Mutex {
 
         loop {
             // Put the lock in contended state.
-            // We avoid an unnecessary write if it as already set to 2,
+            // We avoid an unnecessary write if it as already set to CONTENDED,
             // to be friendlier for the caches.
-            if state != 2 && self.futex.swap(2, Acquire) == 0 {
-                // We changed it from 0 to 2, so we just successfully locked it.
+            if state != CONTENDED && self.futex.swap(CONTENDED, Acquire) == UNLOCKED {
+                // We changed it from UNLOCKED to CONTENDED, so we just successfully locked it.
                 return;
             }
 
-            // Wait for the futex to change state, assuming it is still 2.
-            futex_wait(&self.futex, 2, None);
+            // Wait for the futex to change state, assuming it is still CONTENDED.
+            futex_wait(&self.futex, CONTENDED, None);
 
             // Spin again after waking up.
             state = self.spin();
         }
     }
 
-    fn spin(&self) -> u32 {
+    fn spin(&self) -> State {
         let mut spin = 100;
         loop {
             // We only use `load` (and not `swap` or `compare_exchange`)
             // while spinning, to be easier on the caches.
             let state = self.futex.load(Relaxed);
 
-            // We stop spinning when the mutex is unlocked (0),
-            // but also when it's contended (2).
-            if state != 1 || spin == 0 {
+            // We stop spinning when the mutex is UNLOCKED,
+            // but also when it's CONTENDED.
+            if state != LOCKED || spin == 0 {
                 return state;
             }
 
@@ -80,9 +92,9 @@ impl Mutex {
 
     #[inline]
     pub unsafe fn unlock(&self) {
-        if self.futex.swap(0, Release) == 2 {
+        if self.futex.swap(UNLOCKED, Release) == CONTENDED {
             // We only wake up one thread. When that thread locks the mutex, it
-            // will mark the mutex as contended (2) (see lock_contended above),
+            // will mark the mutex as CONTENDED (see lock_contended above),
             // which makes sure that any other waiting threads will also be
             // woken up eventually.
             self.wake();
diff --git a/library/std/src/sys/locks/mutex/mod.rs b/library/std/src/sys/locks/mutex/mod.rs
index 710cb91fb14..73d9bd273de 100644
--- a/library/std/src/sys/locks/mutex/mod.rs
+++ b/library/std/src/sys/locks/mutex/mod.rs
@@ -1,5 +1,6 @@
 cfg_if::cfg_if! {
     if #[cfg(any(
+        all(target_os = "windows", not(target_vendor = "win7")),
         target_os = "linux",
         target_os = "android",
         target_os = "freebsd",
@@ -19,9 +20,9 @@ cfg_if::cfg_if! {
     ))] {
         mod pthread;
         pub use pthread::{Mutex, raw};
-    } else if #[cfg(target_os = "windows")] {
-        mod windows;
-        pub use windows::{Mutex, raw};
+    } else if #[cfg(all(target_os = "windows", target_vendor = "win7"))] {
+        mod windows7;
+        pub use windows7::{Mutex, raw};
     } else if #[cfg(all(target_vendor = "fortanix", target_env = "sgx"))] {
         mod sgx;
         pub use sgx::Mutex;
diff --git a/library/std/src/sys/locks/mutex/windows.rs b/library/std/src/sys/locks/mutex/windows7.rs
index ef2f84082cd..ef2f84082cd 100644
--- a/library/std/src/sys/locks/mutex/windows.rs
+++ b/library/std/src/sys/locks/mutex/windows7.rs
diff --git a/library/std/src/sys/locks/rwlock/mod.rs b/library/std/src/sys/locks/rwlock/mod.rs
index 0564f1fe6fa..675931c64bd 100644
--- a/library/std/src/sys/locks/rwlock/mod.rs
+++ b/library/std/src/sys/locks/rwlock/mod.rs
@@ -1,5 +1,6 @@
 cfg_if::cfg_if! {
     if #[cfg(any(
+        all(target_os = "windows", not(target_vendor = "win7")),
         target_os = "linux",
         target_os = "android",
         target_os = "freebsd",
@@ -14,9 +15,9 @@ cfg_if::cfg_if! {
     } else if #[cfg(target_family = "unix")] {
         mod queue;
         pub use queue::RwLock;
-    } else if #[cfg(target_os = "windows")] {
-        mod windows;
-        pub use windows::RwLock;
+    } else if #[cfg(all(target_os = "windows", target_vendor = "win7"))] {
+        mod windows7;
+        pub use windows7::RwLock;
     } else if #[cfg(all(target_vendor = "fortanix", target_env = "sgx"))] {
         mod sgx;
         pub use sgx::RwLock;
diff --git a/library/std/src/sys/locks/rwlock/windows.rs b/library/std/src/sys/locks/rwlock/windows7.rs
index e69415baac4..e69415baac4 100644
--- a/library/std/src/sys/locks/rwlock/windows.rs
+++ b/library/std/src/sys/locks/rwlock/windows7.rs
diff --git a/library/std/src/sys/mod.rs b/library/std/src/sys/mod.rs
index d77ac7eb027..81200e0061e 100644
--- a/library/std/src/sys/mod.rs
+++ b/library/std/src/sys/mod.rs
@@ -9,6 +9,9 @@ pub mod cmath;
 pub mod locks;
 pub mod os_str;
 pub mod path;
+#[allow(dead_code)]
+#[allow(unused_imports)]
+pub mod thread_local;
 
 // FIXME(117276): remove this, move feature implementations into individual
 //                submodules.
diff --git a/library/std/src/sys/pal/common/mod.rs b/library/std/src/sys/pal/common/mod.rs
index b35c5d30b41..29fc0835d76 100644
--- a/library/std/src/sys/pal/common/mod.rs
+++ b/library/std/src/sys/pal/common/mod.rs
@@ -12,8 +12,6 @@
 
 pub mod alloc;
 pub mod small_c_string;
-#[allow(unused_imports)]
-pub mod thread_local;
 
 #[cfg(test)]
 mod tests;
diff --git a/library/std/src/sys/pal/hermit/memchr.rs b/library/std/src/sys/pal/hermit/memchr.rs
deleted file mode 100644
index 9967482197e..00000000000
--- a/library/std/src/sys/pal/hermit/memchr.rs
+++ /dev/null
@@ -1 +0,0 @@
-pub use core::slice::memchr::{memchr, memrchr};
diff --git a/library/std/src/sys/pal/hermit/mod.rs b/library/std/src/sys/pal/hermit/mod.rs
index ada408107dc..910935541bd 100644
--- a/library/std/src/sys/pal/hermit/mod.rs
+++ b/library/std/src/sys/pal/hermit/mod.rs
@@ -25,7 +25,6 @@ pub mod fs;
 pub mod futex;
 #[path = "../unsupported/io.rs"]
 pub mod io;
-pub mod memchr;
 pub mod net;
 pub mod os;
 #[path = "../unsupported/pipe.rs"]
diff --git a/library/std/src/sys/pal/hermit/os.rs b/library/std/src/sys/pal/hermit/os.rs
index 645f0dc1e31..1f9affbf773 100644
--- a/library/std/src/sys/pal/hermit/os.rs
+++ b/library/std/src/sys/pal/hermit/os.rs
@@ -9,9 +9,9 @@ use crate::os::hermit::ffi::OsStringExt;
 use crate::path::{self, PathBuf};
 use crate::str;
 use crate::sync::Mutex;
-use crate::sys::memchr;
 use crate::sys::unsupported;
 use crate::vec;
+use core::slice::memchr;
 
 pub fn errno() -> i32 {
     unsafe { abi::get_errno() }
diff --git a/library/std/src/sys/pal/hermit/thread.rs b/library/std/src/sys/pal/hermit/thread.rs
index fee80c02d4a..cf45b9c2396 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;
+use crate::ffi::{CStr, CString};
 use crate::io;
 use crate::mem;
 use crate::num::NonZero;
@@ -71,6 +71,10 @@ impl Thread {
         // nope
     }
 
+    pub fn get_name() -> Option<CString> {
+        None
+    }
+
     #[inline]
     pub fn sleep(dur: Duration) {
         unsafe {
diff --git a/library/std/src/sys/pal/itron/thread.rs b/library/std/src/sys/pal/itron/thread.rs
index 9c1387bf408..814a102dd09 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,
+    ffi::{CStr, CString},
     hint, io,
     mem::ManuallyDrop,
     num::NonZero,
@@ -204,6 +204,10 @@ 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");
diff --git a/library/std/src/sys/pal/sgx/memchr.rs b/library/std/src/sys/pal/sgx/memchr.rs
deleted file mode 100644
index 9967482197e..00000000000
--- a/library/std/src/sys/pal/sgx/memchr.rs
+++ /dev/null
@@ -1 +0,0 @@
-pub use core::slice::memchr::{memchr, memrchr};
diff --git a/library/std/src/sys/pal/sgx/mod.rs b/library/std/src/sys/pal/sgx/mod.rs
index 8ef3495884f..76f930b86f2 100644
--- a/library/std/src/sys/pal/sgx/mod.rs
+++ b/library/std/src/sys/pal/sgx/mod.rs
@@ -17,7 +17,6 @@ pub mod fd;
 pub mod fs;
 #[path = "../unsupported/io.rs"]
 pub mod io;
-pub mod memchr;
 pub mod net;
 pub mod os;
 #[path = "../unsupported/pipe.rs"]
diff --git a/library/std/src/sys/pal/sgx/thread.rs b/library/std/src/sys/pal/sgx/thread.rs
index c797fde7fbd..77f68bf7334 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;
+use crate::ffi::{CStr, CString};
 use crate::io;
 use crate::num::NonZero;
 use crate::time::Duration;
@@ -133,6 +133,10 @@ 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);
     }
diff --git a/library/std/src/sys/pal/solid/memchr.rs b/library/std/src/sys/pal/solid/memchr.rs
deleted file mode 100644
index 452b7a3de1b..00000000000
--- a/library/std/src/sys/pal/solid/memchr.rs
+++ /dev/null
@@ -1,21 +0,0 @@
-pub fn memchr(needle: u8, haystack: &[u8]) -> Option<usize> {
-    let p = unsafe {
-        libc::memchr(
-            haystack.as_ptr() as *const libc::c_void,
-            needle as libc::c_int,
-            haystack.len(),
-        )
-    };
-    if p.is_null() { None } else { Some(p as usize - (haystack.as_ptr() as usize)) }
-}
-
-pub fn memrchr(needle: u8, haystack: &[u8]) -> Option<usize> {
-    let p = unsafe {
-        libc::memrchr(
-            haystack.as_ptr() as *const libc::c_void,
-            needle as libc::c_int,
-            haystack.len(),
-        )
-    };
-    if p.is_null() { None } else { Some(p as usize - (haystack.as_ptr() as usize)) }
-}
diff --git a/library/std/src/sys/pal/solid/mod.rs b/library/std/src/sys/pal/solid/mod.rs
index 9ada7d130f0..109ee1a0ab6 100644
--- a/library/std/src/sys/pal/solid/mod.rs
+++ b/library/std/src/sys/pal/solid/mod.rs
@@ -33,7 +33,6 @@ pub mod pipe;
 pub mod process;
 pub mod stdio;
 pub use self::itron::thread;
-pub mod memchr;
 pub mod thread_local_dtor;
 pub mod thread_local_key;
 pub use self::itron::thread_parking;
diff --git a/library/std/src/sys/pal/solid/os.rs b/library/std/src/sys/pal/solid/os.rs
index 5ceab3b27e0..ef35d8788a2 100644
--- a/library/std/src/sys/pal/solid/os.rs
+++ b/library/std/src/sys/pal/solid/os.rs
@@ -12,7 +12,9 @@ use crate::sync::{PoisonError, RwLock};
 use crate::sys::common::small_c_string::run_with_cstr;
 use crate::vec;
 
-use super::{error, itron, memchr};
+use super::{error, itron};
+
+use core::slice::memchr;
 
 // `solid` directly maps `errno`s to μITRON error codes.
 impl itron::error::ItronError {
diff --git a/library/std/src/sys/pal/teeos/mod.rs b/library/std/src/sys/pal/teeos/mod.rs
index 51ef96a69a0..1fb9d5438de 100644
--- a/library/std/src/sys/pal/teeos/mod.rs
+++ b/library/std/src/sys/pal/teeos/mod.rs
@@ -18,8 +18,6 @@ pub mod env;
 pub mod fs;
 #[path = "../unsupported/io.rs"]
 pub mod io;
-#[path = "../unix/memchr.rs"]
-pub mod memchr;
 pub mod net;
 #[path = "../unsupported/once.rs"]
 pub mod once;
diff --git a/library/std/src/sys/pal/teeos/thread.rs b/library/std/src/sys/pal/teeos/thread.rs
index 77f9040ead5..b76bcf9bbb0 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;
+use crate::ffi::{CStr, CString};
 use crate::io;
 use crate::mem;
 use crate::num::NonZero;
@@ -101,6 +101,10 @@ 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();
diff --git a/library/std/src/sys/pal/uefi/mod.rs b/library/std/src/sys/pal/uefi/mod.rs
index ff8e3bd32ad..7c5b37fb490 100644
--- a/library/std/src/sys/pal/uefi/mod.rs
+++ b/library/std/src/sys/pal/uefi/mod.rs
@@ -48,10 +48,6 @@ use crate::os::uefi;
 use crate::ptr::NonNull;
 use crate::sync::atomic::{AtomicPtr, Ordering};
 
-pub mod memchr {
-    pub use core::slice::memchr::{memchr, memrchr};
-}
-
 static EXIT_BOOT_SERVICE_EVENT: AtomicPtr<crate::ffi::c_void> =
     AtomicPtr::new(crate::ptr::null_mut());
 
diff --git a/library/std/src/sys/pal/uefi/thread.rs b/library/std/src/sys/pal/uefi/thread.rs
index 3d8fa27251f..b3a4f9c53e3 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;
+use crate::ffi::{CStr, CString};
 use crate::io;
 use crate::num::NonZero;
 use crate::ptr::NonNull;
@@ -23,6 +23,10 @@ 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();
diff --git a/library/std/src/sys/pal/unix/memchr.rs b/library/std/src/sys/pal/unix/memchr.rs
deleted file mode 100644
index 73ba604eccb..00000000000
--- a/library/std/src/sys/pal/unix/memchr.rs
+++ /dev/null
@@ -1,40 +0,0 @@
-// Original implementation taken from rust-memchr.
-// Copyright 2015 Andrew Gallant, bluss and Nicolas Koch
-
-pub fn memchr(needle: u8, haystack: &[u8]) -> Option<usize> {
-    let p = unsafe {
-        libc::memchr(
-            haystack.as_ptr() as *const libc::c_void,
-            needle as libc::c_int,
-            haystack.len(),
-        )
-    };
-    if p.is_null() { None } else { Some(p.addr() - haystack.as_ptr().addr()) }
-}
-
-pub fn memrchr(needle: u8, haystack: &[u8]) -> Option<usize> {
-    #[cfg(target_os = "linux")]
-    fn memrchr_specific(needle: u8, haystack: &[u8]) -> Option<usize> {
-        // GNU's memrchr() will - unlike memchr() - error if haystack is empty.
-        if haystack.is_empty() {
-            return None;
-        }
-        let p = unsafe {
-            libc::memrchr(
-                haystack.as_ptr() as *const libc::c_void,
-                needle as libc::c_int,
-                haystack.len(),
-            )
-        };
-        // FIXME: this should *likely* use `offset_from`, but more
-        // investigation is needed (including running tests in miri).
-        if p.is_null() { None } else { Some(p.addr() - haystack.as_ptr().addr()) }
-    }
-
-    #[cfg(not(target_os = "linux"))]
-    fn memrchr_specific(needle: u8, haystack: &[u8]) -> Option<usize> {
-        core::slice::memchr::memrchr(needle, haystack)
-    }
-
-    memrchr_specific(needle, haystack)
-}
diff --git a/library/std/src/sys/pal/unix/mod.rs b/library/std/src/sys/pal/unix/mod.rs
index 23287258f2f..f608ae47a21 100644
--- a/library/std/src/sys/pal/unix/mod.rs
+++ b/library/std/src/sys/pal/unix/mod.rs
@@ -20,7 +20,6 @@ pub mod io;
 pub mod kernel_copy;
 #[cfg(target_os = "l4re")]
 mod l4re;
-pub mod memchr;
 #[cfg(not(target_os = "l4re"))]
 pub mod net;
 #[cfg(target_os = "l4re")]
diff --git a/library/std/src/sys/pal/unix/os.rs b/library/std/src/sys/pal/unix/os.rs
index af2b9db4685..0b9c8027e6f 100644
--- a/library/std/src/sys/pal/unix/os.rs
+++ b/library/std/src/sys/pal/unix/os.rs
@@ -21,8 +21,8 @@ use crate::sync::{PoisonError, RwLock};
 use crate::sys::common::small_c_string::{run_path_with_cstr, run_with_cstr};
 use crate::sys::cvt;
 use crate::sys::fd;
-use crate::sys::memchr;
 use crate::vec;
+use core::slice::memchr;
 
 #[cfg(all(target_env = "gnu", not(target_os = "vxworks")))]
 use crate::sys::weak::weak;
diff --git a/library/std/src/sys/pal/unix/thread.rs b/library/std/src/sys/pal/unix/thread.rs
index 864de31c6eb..2af6382f3da 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;
+use crate::ffi::{CStr, CString};
 use crate::io;
 use crate::mem;
 use crate::num::NonZero;
@@ -225,6 +225,44 @@ 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();
diff --git a/library/std/src/sys/pal/unsupported/common.rs b/library/std/src/sys/pal/unsupported/common.rs
index 5c379992b20..4f44db610af 100644
--- a/library/std/src/sys/pal/unsupported/common.rs
+++ b/library/std/src/sys/pal/unsupported/common.rs
@@ -1,9 +1,5 @@
 use crate::io as std_io;
 
-pub mod memchr {
-    pub use core::slice::memchr::{memchr, memrchr};
-}
-
 // SAFETY: must be called only once during runtime initialization.
 // NOTE: this is not guaranteed to run, for example when Rust code is called externally.
 pub unsafe fn init(_argc: isize, _argv: *const *const u8, _sigpipe: u8) {}
diff --git a/library/std/src/sys/pal/unsupported/thread.rs b/library/std/src/sys/pal/unsupported/thread.rs
index cd1ae7f7d11..b3a91ee1d4c 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;
+use crate::ffi::{CStr, CString};
 use crate::io;
 use crate::num::NonZero;
 use crate::time::Duration;
@@ -22,6 +22,10 @@ impl Thread {
         // nope
     }
 
+    pub fn get_name() -> Option<CString> {
+        None
+    }
+
     pub fn sleep(_dur: Duration) {
         panic!("can't sleep");
     }
diff --git a/library/std/src/sys/pal/wasi/os.rs b/library/std/src/sys/pal/wasi/os.rs
index d62ff8a2f18..ee377b6ef79 100644
--- a/library/std/src/sys/pal/wasi/os.rs
+++ b/library/std/src/sys/pal/wasi/os.rs
@@ -10,9 +10,9 @@ use crate::os::wasi::prelude::*;
 use crate::path::{self, PathBuf};
 use crate::str;
 use crate::sys::common::small_c_string::{run_path_with_cstr, run_with_cstr};
-use crate::sys::memchr;
 use crate::sys::unsupported;
 use crate::vec;
+use core::slice::memchr;
 
 // Add a few symbols not in upstream `libc` just yet.
 mod libc {
diff --git a/library/std/src/sys/pal/wasi/thread.rs b/library/std/src/sys/pal/wasi/thread.rs
index 77d8b4378e7..4b116052f8f 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;
+use crate::ffi::{CStr, CString};
 use crate::io;
 use crate::mem;
 use crate::num::NonZero;
@@ -134,6 +134,10 @@ 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);
diff --git a/library/std/src/sys/pal/wasm/atomics/thread.rs b/library/std/src/sys/pal/wasm/atomics/thread.rs
index 49f936f1449..3923ff821d9 100644
--- a/library/std/src/sys/pal/wasm/atomics/thread.rs
+++ b/library/std/src/sys/pal/wasm/atomics/thread.rs
@@ -1,4 +1,5 @@
 use crate::ffi::CStr;
+use crate::ffi::CString;
 use crate::io;
 use crate::num::NonZero;
 use crate::sys::unsupported;
@@ -17,6 +18,9 @@ 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/c.rs b/library/std/src/sys/pal/windows/c.rs
index b007796722b..584e17cd196 100644
--- a/library/std/src/sys/pal/windows/c.rs
+++ b/library/std/src/sys/pal/windows/c.rs
@@ -36,6 +36,7 @@ pub type LPVOID = *mut c_void;
 pub type LPWCH = *mut WCHAR;
 pub type LPWSTR = *mut WCHAR;
 
+#[cfg(target_vendor = "win7")]
 pub type PSRWLOCK = *mut SRWLOCK;
 
 pub type socklen_t = c_int;
@@ -50,7 +51,9 @@ pub const INVALID_HANDLE_VALUE: HANDLE = ::core::ptr::without_provenance_mut(-1i
 pub const EXIT_SUCCESS: u32 = 0;
 pub const EXIT_FAILURE: u32 = 1;
 
+#[cfg(target_vendor = "win7")]
 pub const CONDITION_VARIABLE_INIT: CONDITION_VARIABLE = CONDITION_VARIABLE { Ptr: ptr::null_mut() };
+#[cfg(target_vendor = "win7")]
 pub const SRWLOCK_INIT: SRWLOCK = SRWLOCK { Ptr: ptr::null_mut() };
 pub const INIT_ONCE_STATIC_INIT: INIT_ONCE = INIT_ONCE { Ptr: ptr::null_mut() };
 
@@ -344,6 +347,12 @@ compat_fn_with_fallback! {
         SetLastError(ERROR_CALL_NOT_IMPLEMENTED as DWORD); E_NOTIMPL
     }
 
+    // >= Win10 1607
+    // https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-getthreaddescription
+    pub fn GetThreadDescription(hthread: HANDLE, lpthreaddescription: *mut PWSTR) -> HRESULT {
+        SetLastError(ERROR_CALL_NOT_IMPLEMENTED as DWORD); E_NOTIMPL
+    }
+
     // >= Win8 / Server 2012
     // https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getsystemtimepreciseasfiletime
     pub fn GetSystemTimePreciseAsFileTime(lpsystemtimeasfiletime: *mut FILETIME) -> () {
@@ -367,6 +376,7 @@ extern "system" {
         dwmilliseconds: u32,
     ) -> BOOL;
     pub fn WakeByAddressSingle(address: *const c_void);
+    pub fn WakeByAddressAll(address: *const c_void);
 }
 
 #[cfg(target_vendor = "win7")]
diff --git a/library/std/src/sys/pal/windows/c/bindings.txt b/library/std/src/sys/pal/windows/c/bindings.txt
index ab2a8caf5df..7667f761106 100644
--- a/library/std/src/sys/pal/windows/c/bindings.txt
+++ b/library/std/src/sys/pal/windows/c/bindings.txt
@@ -1923,6 +1923,7 @@ Windows.Win32.Foundation.HANDLE_FLAG_INHERIT
 Windows.Win32.Foundation.HANDLE_FLAG_PROTECT_FROM_CLOSE
 Windows.Win32.Foundation.HANDLE_FLAGS
 Windows.Win32.Foundation.HMODULE
+Windows.Win32.Foundation.LocalFree
 Windows.Win32.Foundation.MAX_PATH
 Windows.Win32.Foundation.NO_ERROR
 Windows.Win32.Foundation.NTSTATUS
@@ -2481,6 +2482,7 @@ Windows.Win32.System.SystemInformation.SYSTEM_INFO
 Windows.Win32.System.SystemServices.DLL_PROCESS_DETACH
 Windows.Win32.System.SystemServices.DLL_THREAD_DETACH
 Windows.Win32.System.SystemServices.EXCEPTION_MAXIMUM_PARAMETERS
+Windows.Win32.System.SystemServices.FAST_FAIL_FATAL_APP_EXIT
 Windows.Win32.System.SystemServices.IO_REPARSE_TAG_MOUNT_POINT
 Windows.Win32.System.SystemServices.IO_REPARSE_TAG_SYMLINK
 Windows.Win32.System.Threading.ABOVE_NORMAL_PRIORITY_CLASS
diff --git a/library/std/src/sys/pal/windows/c/windows_sys.rs b/library/std/src/sys/pal/windows/c/windows_sys.rs
index 8eb779373f7..7b751079afb 100644
--- a/library/std/src/sys/pal/windows/c/windows_sys.rs
+++ b/library/std/src/sys/pal/windows/c/windows_sys.rs
@@ -380,6 +380,10 @@ extern "system" {
 }
 #[link(name = "kernel32")]
 extern "system" {
+    pub fn LocalFree(hmem: HLOCAL) -> HLOCAL;
+}
+#[link(name = "kernel32")]
+extern "system" {
     pub fn MoveFileExW(
         lpexistingfilename: PCWSTR,
         lpnewfilename: PCWSTR,
@@ -3086,6 +3090,7 @@ pub type FACILITY_CODE = u32;
 pub const FACILITY_NT_BIT: FACILITY_CODE = 268435456u32;
 pub const FALSE: BOOL = 0i32;
 pub type FARPROC = ::core::option::Option<unsafe extern "system" fn() -> isize>;
+pub const FAST_FAIL_FATAL_APP_EXIT: u32 = 7u32;
 #[repr(C)]
 pub struct FD_SET {
     pub fd_count: u32,
@@ -3441,6 +3446,7 @@ pub type HANDLE_FLAGS = u32;
 pub const HANDLE_FLAG_INHERIT: HANDLE_FLAGS = 1u32;
 pub const HANDLE_FLAG_PROTECT_FROM_CLOSE: HANDLE_FLAGS = 2u32;
 pub const HIGH_PRIORITY_CLASS: PROCESS_CREATION_FLAGS = 128u32;
+pub type HLOCAL = *mut ::core::ffi::c_void;
 pub type HMODULE = *mut ::core::ffi::c_void;
 pub type HRESULT = i32;
 pub const IDLE_PRIORITY_CLASS: PROCESS_CREATION_FLAGS = 64u32;
diff --git a/library/std/src/sys/pal/windows/futex.rs b/library/std/src/sys/pal/windows/futex.rs
new file mode 100644
index 00000000000..bc19c402d9c
--- /dev/null
+++ b/library/std/src/sys/pal/windows/futex.rs
@@ -0,0 +1,85 @@
+use super::api;
+use crate::sys::c;
+use crate::sys::dur2timeout;
+use core::ffi::c_void;
+use core::mem;
+use core::ptr;
+use core::sync::atomic::{
+    AtomicBool, AtomicI16, AtomicI32, AtomicI64, AtomicI8, AtomicIsize, AtomicPtr, AtomicU16,
+    AtomicU32, AtomicU64, AtomicU8, AtomicUsize,
+};
+use core::time::Duration;
+
+pub unsafe trait Waitable {
+    type Atomic;
+}
+macro_rules! unsafe_waitable_int {
+    ($(($int:ty, $atomic:ty)),*$(,)?) => {
+        $(
+            unsafe impl Waitable for $int {
+                type Atomic = $atomic;
+            }
+        )*
+    };
+}
+unsafe_waitable_int! {
+    (bool, AtomicBool),
+    (i8, AtomicI8),
+    (i16, AtomicI16),
+    (i32, AtomicI32),
+    (i64, AtomicI64),
+    (isize, AtomicIsize),
+    (u8, AtomicU8),
+    (u16, AtomicU16),
+    (u32, AtomicU32),
+    (u64, AtomicU64),
+    (usize, AtomicUsize),
+}
+unsafe impl<T> Waitable for *const T {
+    type Atomic = AtomicPtr<T>;
+}
+unsafe impl<T> Waitable for *mut T {
+    type Atomic = AtomicPtr<T>;
+}
+
+pub fn wait_on_address<W: Waitable>(
+    address: &W::Atomic,
+    compare: W,
+    timeout: Option<Duration>,
+) -> bool {
+    unsafe {
+        let addr = ptr::from_ref(address).cast::<c_void>();
+        let size = mem::size_of::<W>();
+        let compare_addr = ptr::addr_of!(compare).cast::<c_void>();
+        let timeout = timeout.map(dur2timeout).unwrap_or(c::INFINITE);
+        c::WaitOnAddress(addr, compare_addr, size, timeout) == c::TRUE
+    }
+}
+
+pub fn wake_by_address_single<T>(address: &T) {
+    unsafe {
+        let addr = ptr::from_ref(address).cast::<c_void>();
+        c::WakeByAddressSingle(addr);
+    }
+}
+
+pub fn wake_by_address_all<T>(address: &T) {
+    unsafe {
+        let addr = ptr::from_ref(address).cast::<c_void>();
+        c::WakeByAddressAll(addr);
+    }
+}
+
+pub fn futex_wait<W: Waitable>(futex: &W::Atomic, expected: W, timeout: Option<Duration>) -> bool {
+    // return false only on timeout
+    wait_on_address(futex, expected, timeout) || api::get_last_error().code != c::ERROR_TIMEOUT
+}
+
+pub fn futex_wake<T>(futex: &T) -> bool {
+    wake_by_address_single(futex);
+    false
+}
+
+pub fn futex_wake_all<T>(futex: &T) {
+    wake_by_address_all(futex)
+}
diff --git a/library/std/src/sys/pal/windows/memchr.rs b/library/std/src/sys/pal/windows/memchr.rs
deleted file mode 100644
index b9e5bcc1b4b..00000000000
--- a/library/std/src/sys/pal/windows/memchr.rs
+++ /dev/null
@@ -1,5 +0,0 @@
-// Original implementation taken from rust-memchr.
-// Copyright 2015 Andrew Gallant, bluss and Nicolas Koch
-
-// Fallback memchr is fastest on Windows.
-pub use core::slice::memchr::{memchr, memrchr};
diff --git a/library/std/src/sys/pal/windows/mod.rs b/library/std/src/sys/pal/windows/mod.rs
index b47d213df34..6a561518fad 100644
--- a/library/std/src/sys/pal/windows/mod.rs
+++ b/library/std/src/sys/pal/windows/mod.rs
@@ -17,9 +17,10 @@ pub mod args;
 pub mod c;
 pub mod env;
 pub mod fs;
+#[cfg(not(target_vendor = "win7"))]
+pub mod futex;
 pub mod handle;
 pub mod io;
-pub mod memchr;
 pub mod net;
 pub mod os;
 pub mod pipe;
@@ -322,25 +323,26 @@ pub fn dur2timeout(dur: Duration) -> c::DWORD {
 ///
 /// This is the same implementation as in libpanic_abort's `__rust_start_panic`. See
 /// that function for more information on `__fastfail`
-#[allow(unreachable_code)]
+#[cfg(not(miri))] // inline assembly does not work in Miri
 pub fn abort_internal() -> ! {
-    #[allow(unused)]
-    const FAST_FAIL_FATAL_APP_EXIT: usize = 7;
-    #[cfg(not(miri))] // inline assembly does not work in Miri
     unsafe {
         cfg_if::cfg_if! {
             if #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] {
-                core::arch::asm!("int $$0x29", in("ecx") FAST_FAIL_FATAL_APP_EXIT);
-                crate::intrinsics::unreachable();
+                core::arch::asm!("int $$0x29", in("ecx") c::FAST_FAIL_FATAL_APP_EXIT, options(noreturn, nostack));
             } else if #[cfg(all(target_arch = "arm", target_feature = "thumb-mode"))] {
-                core::arch::asm!(".inst 0xDEFB", in("r0") FAST_FAIL_FATAL_APP_EXIT);
-                crate::intrinsics::unreachable();
+                core::arch::asm!(".inst 0xDEFB", in("r0") c::FAST_FAIL_FATAL_APP_EXIT, options(noreturn, nostack));
             } else if #[cfg(target_arch = "aarch64")] {
-                core::arch::asm!("brk 0xF003", in("x0") FAST_FAIL_FATAL_APP_EXIT);
-                crate::intrinsics::unreachable();
+                core::arch::asm!("brk 0xF003", in("x0") c::FAST_FAIL_FATAL_APP_EXIT, options(noreturn, nostack));
+            } else {
+                core::intrinsics::abort();
             }
         }
     }
+}
+
+// miri is sensitive to changes here so check that miri is happy if touching this
+#[cfg(miri)]
+pub fn abort_internal() -> ! {
     crate::intrinsics::abort();
 }
 
diff --git a/library/std/src/sys/pal/windows/thread.rs b/library/std/src/sys/pal/windows/thread.rs
index 0f709e2ec7b..a8f1e9b726b 100644
--- a/library/std/src/sys/pal/windows/thread.rs
+++ b/library/std/src/sys/pal/windows/thread.rs
@@ -9,7 +9,7 @@ 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;
@@ -71,6 +71,29 @@ 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 {
diff --git a/library/std/src/sys/pal/xous/thread.rs b/library/std/src/sys/pal/xous/thread.rs
index 21f5954d6e2..f95ceb7343b 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;
+use crate::ffi::{CStr, CString};
 use crate::io;
 use crate::num::NonZero;
 use crate::os::xous::ffi::{
@@ -113,6 +113,10 @@ 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
diff --git a/library/std/src/sys/pal/zkvm/mod.rs b/library/std/src/sys/pal/zkvm/mod.rs
index 016c977dc33..6c714f76309 100644
--- a/library/std/src/sys/pal/zkvm/mod.rs
+++ b/library/std/src/sys/pal/zkvm/mod.rs
@@ -43,10 +43,6 @@ mod abi;
 
 use crate::io as std_io;
 
-pub mod memchr {
-    pub use core::slice::memchr::{memchr, memrchr};
-}
-
 // SAFETY: must be called only once during runtime initialization.
 // NOTE: this is not guaranteed to run, for example when Rust code is called externally.
 pub unsafe fn init(_argc: isize, _argv: *const *const u8, _sigpipe: u8) {}
diff --git a/library/std/src/sys/pal/common/thread_local/fast_local.rs b/library/std/src/sys/thread_local/fast_local.rs
index 646dcd7f3a3..646dcd7f3a3 100644
--- a/library/std/src/sys/pal/common/thread_local/fast_local.rs
+++ b/library/std/src/sys/thread_local/fast_local.rs
diff --git a/library/std/src/sys/pal/common/thread_local/mod.rs b/library/std/src/sys/thread_local/mod.rs
index 8b2c839f837..8b2c839f837 100644
--- a/library/std/src/sys/pal/common/thread_local/mod.rs
+++ b/library/std/src/sys/thread_local/mod.rs
diff --git a/library/std/src/sys/pal/common/thread_local/os_local.rs b/library/std/src/sys/thread_local/os_local.rs
index 3edffd7e443..3edffd7e443 100644
--- a/library/std/src/sys/pal/common/thread_local/os_local.rs
+++ b/library/std/src/sys/thread_local/os_local.rs
diff --git a/library/std/src/sys/pal/common/thread_local/static_local.rs b/library/std/src/sys/thread_local/static_local.rs
index 4f2b6868962..4f2b6868962 100644
--- a/library/std/src/sys/pal/common/thread_local/static_local.rs
+++ b/library/std/src/sys/thread_local/static_local.rs
diff --git a/library/std/src/sys_common/memchr.rs b/library/std/src/sys_common/memchr.rs
deleted file mode 100644
index b219e878912..00000000000
--- a/library/std/src/sys_common/memchr.rs
+++ /dev/null
@@ -1,51 +0,0 @@
-// Original implementation taken from rust-memchr.
-// Copyright 2015 Andrew Gallant, bluss and Nicolas Koch
-
-use crate::sys::memchr as sys;
-
-#[cfg(test)]
-mod tests;
-
-/// A safe interface to `memchr`.
-///
-/// Returns the index corresponding to the first occurrence of `needle` in
-/// `haystack`, or `None` if one is not found.
-///
-/// memchr reduces to super-optimized machine code at around an order of
-/// magnitude faster than `haystack.iter().position(|&b| b == needle)`.
-/// (See benchmarks.)
-///
-/// # Examples
-///
-/// This shows how to find the first position of a byte in a byte string.
-///
-/// ```ignore (cannot-doctest-private-modules)
-/// use memchr::memchr;
-///
-/// let haystack = b"the quick brown fox";
-/// assert_eq!(memchr(b'k', haystack), Some(8));
-/// ```
-#[inline]
-pub fn memchr(needle: u8, haystack: &[u8]) -> Option<usize> {
-    sys::memchr(needle, haystack)
-}
-
-/// A safe interface to `memrchr`.
-///
-/// Returns the index corresponding to the last occurrence of `needle` in
-/// `haystack`, or `None` if one is not found.
-///
-/// # Examples
-///
-/// This shows how to find the last position of a byte in a byte string.
-///
-/// ```ignore (cannot-doctest-private-modules)
-/// use memchr::memrchr;
-///
-/// let haystack = b"the quick brown fox";
-/// assert_eq!(memrchr(b'o', haystack), Some(17));
-/// ```
-#[inline]
-pub fn memrchr(needle: u8, haystack: &[u8]) -> Option<usize> {
-    sys::memrchr(needle, haystack)
-}
diff --git a/library/std/src/sys_common/memchr/tests.rs b/library/std/src/sys_common/memchr/tests.rs
deleted file mode 100644
index 557d749c7f6..00000000000
--- a/library/std/src/sys_common/memchr/tests.rs
+++ /dev/null
@@ -1,86 +0,0 @@
-// Original implementation taken from rust-memchr.
-// Copyright 2015 Andrew Gallant, bluss and Nicolas Koch
-
-// test the implementations for the current platform
-use super::{memchr, memrchr};
-
-#[test]
-fn matches_one() {
-    assert_eq!(Some(0), memchr(b'a', b"a"));
-}
-
-#[test]
-fn matches_begin() {
-    assert_eq!(Some(0), memchr(b'a', b"aaaa"));
-}
-
-#[test]
-fn matches_end() {
-    assert_eq!(Some(4), memchr(b'z', b"aaaaz"));
-}
-
-#[test]
-fn matches_nul() {
-    assert_eq!(Some(4), memchr(b'\x00', b"aaaa\x00"));
-}
-
-#[test]
-fn matches_past_nul() {
-    assert_eq!(Some(5), memchr(b'z', b"aaaa\x00z"));
-}
-
-#[test]
-fn no_match_empty() {
-    assert_eq!(None, memchr(b'a', b""));
-}
-
-#[test]
-fn no_match() {
-    assert_eq!(None, memchr(b'a', b"xyz"));
-}
-
-#[test]
-fn matches_one_reversed() {
-    assert_eq!(Some(0), memrchr(b'a', b"a"));
-}
-
-#[test]
-fn matches_begin_reversed() {
-    assert_eq!(Some(3), memrchr(b'a', b"aaaa"));
-}
-
-#[test]
-fn matches_end_reversed() {
-    assert_eq!(Some(0), memrchr(b'z', b"zaaaa"));
-}
-
-#[test]
-fn matches_nul_reversed() {
-    assert_eq!(Some(4), memrchr(b'\x00', b"aaaa\x00"));
-}
-
-#[test]
-fn matches_past_nul_reversed() {
-    assert_eq!(Some(0), memrchr(b'z', b"z\x00aaaa"));
-}
-
-#[test]
-fn no_match_empty_reversed() {
-    assert_eq!(None, memrchr(b'a', b""));
-}
-
-#[test]
-fn no_match_reversed() {
-    assert_eq!(None, memrchr(b'a', b"xyz"));
-}
-
-#[test]
-fn each_alignment() {
-    let mut data = [1u8; 64];
-    let needle = 2;
-    let pos = 40;
-    data[pos] = needle;
-    for start in 0..16 {
-        assert_eq!(Some(pos - start), memchr(needle, &data[start..]));
-    }
-}
diff --git a/library/std/src/sys_common/mod.rs b/library/std/src/sys_common/mod.rs
index 01f83ecb414..c9025a81bf3 100644
--- a/library/std/src/sys_common/mod.rs
+++ b/library/std/src/sys_common/mod.rs
@@ -24,7 +24,6 @@ pub mod backtrace;
 pub mod fs;
 pub mod io;
 pub mod lazy_box;
-pub mod memchr;
 pub mod once;
 pub mod process;
 pub mod thread;
diff --git a/library/std/src/sys_common/thread_info.rs b/library/std/src/sys_common/thread_info.rs
index 8d51732e035..ec1428ea40e 100644
--- a/library/std/src/sys_common/thread_info.rs
+++ b/library/std/src/sys_common/thread_info.rs
@@ -1,6 +1,7 @@
 #![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;
 
@@ -23,7 +24,8 @@ impl ThreadInfo {
     {
         THREAD_INFO
             .try_with(move |thread_info| {
-                let thread = thread_info.thread.get_or_init(|| Thread::new(None));
+                let thread =
+                    thread_info.thread.get_or_init(|| Thread::new(sys::thread::Thread::get_name()));
                 f(thread, &thread_info.stack_guard)
             })
             .ok()
diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs
index 76af7fec926..85de2980133 100644
--- a/library/std/src/thread/mod.rs
+++ b/library/std/src/thread/mod.rs
@@ -205,7 +205,7 @@ cfg_if::cfg_if! {
         #[doc(hidden)]
         #[unstable(feature = "thread_local_internals", issue = "none")]
         pub mod local_impl {
-            pub use crate::sys::common::thread_local::{thread_local_inner, Key, abort_on_dtor_unwind};
+            pub use crate::sys::thread_local::{thread_local_inner, Key, abort_on_dtor_unwind};
         }
     }
 }
diff --git a/library/std/src/thread/tests.rs b/library/std/src/thread/tests.rs
index 5d6b9e94ee9..813ede06415 100644
--- a/library/std/src/thread/tests.rs
+++ b/library/std/src/thread/tests.rs
@@ -69,6 +69,25 @@ 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;
+    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() {