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/future.rs2
-rw-r--r--library/std/src/lib.rs1
-rw-r--r--library/std/src/path.rs37
-rw-r--r--library/std/src/process.rs7
-rw-r--r--library/std/src/sys/sgx/fs.rs308
-rw-r--r--library/std/src/sys/sgx/io.rs47
-rw-r--r--library/std/src/sys/sgx/mod.rs4
-rw-r--r--library/std/src/sys/sgx/pipe.rs38
-rw-r--r--library/std/src/sys/sgx/process.rs149
-rw-r--r--library/std/src/sys/unix/alloc.rs86
-rw-r--r--library/std/src/sys/unix/ext/mod.rs12
-rw-r--r--library/std/src/sys/unix/ext/net.rs51
-rw-r--r--library/std/src/sys/unix/ext/ucred.rs97
-rw-r--r--library/std/src/sys/unix/ext/ucred/tests.rs25
-rw-r--r--library/std/src/sys/unix/process/process_fuchsia.rs3
-rw-r--r--library/std/src/sys/unix/process/zircon.rs1
-rw-r--r--library/std/src/sys/unsupported/fs.rs4
-rw-r--r--library/std/src/sys/unsupported/mod.rs1
-rw-r--r--library/std/src/sys/unsupported/path.rs19
-rw-r--r--library/std/src/sys/unsupported/process.rs4
-rw-r--r--library/std/src/sys/wasi/alloc.rs69
-rw-r--r--library/std/src/sys/wasi/mod.rs4
-rw-r--r--library/std/src/sys/wasi/path.rs19
-rw-r--r--library/std/src/sys/wasi/pipe.rs40
-rw-r--r--library/std/src/sys/wasi/process.rs151
-rw-r--r--library/std/src/sys/wasm/mod.rs2
-rw-r--r--library/std/src/sys/windows/mutex.rs84
-rw-r--r--library/std/src/thread/local.rs5
28 files changed, 312 insertions, 958 deletions
diff --git a/library/std/src/future.rs b/library/std/src/future.rs
index 5ff74e55754..9d9c36e9afb 100644
--- a/library/std/src/future.rs
+++ b/library/std/src/future.rs
@@ -9,7 +9,7 @@ pub use core::future::Future;
 pub use core::future::{from_generator, get_context, ResumeTy};
 
 #[doc(inline)]
-#[stable(feature = "future_readiness_fns", since = "1.47.0")]
+#[stable(feature = "future_readiness_fns", since = "1.48.0")]
 pub use core::future::{pending, ready, Pending, Ready};
 
 #[doc(inline)]
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index b834361b750..5333d75ec1b 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -315,6 +315,7 @@
 #![feature(try_reserve)]
 #![feature(unboxed_closures)]
 #![feature(unsafe_block_in_unsafe_fn)]
+#![feature(unsafe_cell_raw_get)]
 #![feature(untagged_unions)]
 #![feature(unwind_attributes)]
 #![feature(vec_into_raw_parts)]
diff --git a/library/std/src/path.rs b/library/std/src/path.rs
index d71e89d0eee..b83c1e9628d 100644
--- a/library/std/src/path.rs
+++ b/library/std/src/path.rs
@@ -58,6 +58,7 @@
 //! [`push`]: PathBuf::push
 
 #![stable(feature = "rust1", since = "1.0.0")]
+#![deny(unsafe_op_in_unsafe_fn)]
 
 #[cfg(test)]
 mod tests;
@@ -294,7 +295,8 @@ fn os_str_as_u8_slice(s: &OsStr) -> &[u8] {
     unsafe { &*(s as *const OsStr as *const [u8]) }
 }
 unsafe fn u8_slice_as_os_str(s: &[u8]) -> &OsStr {
-    &*(s as *const [u8] as *const OsStr)
+    // SAFETY: see the comment of `os_str_as_u8_slice`
+    unsafe { &*(s as *const [u8] as *const OsStr) }
 }
 
 // Detect scheme on Redox
@@ -314,24 +316,21 @@ fn has_physical_root(s: &[u8], prefix: Option<Prefix<'_>>) -> bool {
 
 // basic workhorse for splitting stem and extension
 fn split_file_at_dot(file: &OsStr) -> (Option<&OsStr>, Option<&OsStr>) {
-    unsafe {
-        if os_str_as_u8_slice(file) == b".." {
-            return (Some(file), None);
-        }
-
-        // The unsafety here stems from converting between &OsStr and &[u8]
-        // and back. This is safe to do because (1) we only look at ASCII
-        // contents of the encoding and (2) new &OsStr values are produced
-        // only from ASCII-bounded slices of existing &OsStr values.
+    if os_str_as_u8_slice(file) == b".." {
+        return (Some(file), None);
+    }
 
-        let mut iter = os_str_as_u8_slice(file).rsplitn(2, |b| *b == b'.');
-        let after = iter.next();
-        let before = iter.next();
-        if before == Some(b"") {
-            (Some(file), None)
-        } else {
-            (before.map(|s| u8_slice_as_os_str(s)), after.map(|s| u8_slice_as_os_str(s)))
-        }
+    // The unsafety here stems from converting between &OsStr and &[u8]
+    // and back. This is safe to do because (1) we only look at ASCII
+    // contents of the encoding and (2) new &OsStr values are produced
+    // only from ASCII-bounded slices of existing &OsStr values.
+    let mut iter = os_str_as_u8_slice(file).rsplitn(2, |b| *b == b'.');
+    let after = iter.next();
+    let before = iter.next();
+    if before == Some(b"") {
+        (Some(file), None)
+    } else {
+        unsafe { (before.map(|s| u8_slice_as_os_str(s)), after.map(|s| u8_slice_as_os_str(s))) }
     }
 }
 
@@ -1702,7 +1701,7 @@ impl Path {
     // The following (private!) function allows construction of a path from a u8
     // slice, which is only safe when it is known to follow the OsStr encoding.
     unsafe fn from_u8_slice(s: &[u8]) -> &Path {
-        Path::new(u8_slice_as_os_str(s))
+        unsafe { Path::new(u8_slice_as_os_str(s)) }
     }
     // The following (private!) function reveals the byte encoding used for OsStr.
     fn as_u8_slice(&self) -> &[u8] {
diff --git a/library/std/src/process.rs b/library/std/src/process.rs
index d1960a049d9..00e2dbc9c1d 100644
--- a/library/std/src/process.rs
+++ b/library/std/src/process.rs
@@ -95,6 +95,7 @@
 //! [`Read`]: io::Read
 
 #![stable(feature = "process", since = "1.0.0")]
+#![deny(unsafe_op_in_unsafe_fn)]
 
 #[cfg(all(test, not(any(target_os = "cloudabi", target_os = "emscripten", target_env = "sgx"))))]
 mod tests;
@@ -321,7 +322,8 @@ impl Read for ChildStdout {
 
     #[inline]
     unsafe fn initializer(&self) -> Initializer {
-        Initializer::nop()
+        // SAFETY: Read is guaranteed to work on uninitialized memory
+        unsafe { Initializer::nop() }
     }
 }
 
@@ -381,7 +383,8 @@ impl Read for ChildStderr {
 
     #[inline]
     unsafe fn initializer(&self) -> Initializer {
-        Initializer::nop()
+        // SAFETY: Read is guaranteed to work on uninitialized memory
+        unsafe { Initializer::nop() }
     }
 }
 
diff --git a/library/std/src/sys/sgx/fs.rs b/library/std/src/sys/sgx/fs.rs
deleted file mode 100644
index ecb5b51cccd..00000000000
--- a/library/std/src/sys/sgx/fs.rs
+++ /dev/null
@@ -1,308 +0,0 @@
-use crate::ffi::OsString;
-use crate::fmt;
-use crate::hash::{Hash, Hasher};
-use crate::io::{self, IoSlice, IoSliceMut, SeekFrom};
-use crate::path::{Path, PathBuf};
-use crate::sys::time::SystemTime;
-use crate::sys::{unsupported, Void};
-
-pub struct File(Void);
-
-pub struct FileAttr(Void);
-
-pub struct ReadDir(Void);
-
-pub struct DirEntry(Void);
-
-#[derive(Clone, Debug)]
-pub struct OpenOptions {}
-
-pub struct FilePermissions(Void);
-
-pub struct FileType(Void);
-
-#[derive(Debug)]
-pub struct DirBuilder {}
-
-impl FileAttr {
-    pub fn size(&self) -> u64 {
-        match self.0 {}
-    }
-
-    pub fn perm(&self) -> FilePermissions {
-        match self.0 {}
-    }
-
-    pub fn file_type(&self) -> FileType {
-        match self.0 {}
-    }
-
-    pub fn modified(&self) -> io::Result<SystemTime> {
-        match self.0 {}
-    }
-
-    pub fn accessed(&self) -> io::Result<SystemTime> {
-        match self.0 {}
-    }
-
-    pub fn created(&self) -> io::Result<SystemTime> {
-        match self.0 {}
-    }
-}
-
-impl Clone for FileAttr {
-    fn clone(&self) -> FileAttr {
-        match self.0 {}
-    }
-}
-
-impl FilePermissions {
-    pub fn readonly(&self) -> bool {
-        match self.0 {}
-    }
-
-    pub fn set_readonly(&mut self, _readonly: bool) {
-        match self.0 {}
-    }
-}
-
-impl Clone for FilePermissions {
-    fn clone(&self) -> FilePermissions {
-        match self.0 {}
-    }
-}
-
-impl PartialEq for FilePermissions {
-    fn eq(&self, _other: &FilePermissions) -> bool {
-        match self.0 {}
-    }
-}
-
-impl Eq for FilePermissions {}
-
-impl fmt::Debug for FilePermissions {
-    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self.0 {}
-    }
-}
-
-impl FileType {
-    pub fn is_dir(&self) -> bool {
-        match self.0 {}
-    }
-
-    pub fn is_file(&self) -> bool {
-        match self.0 {}
-    }
-
-    pub fn is_symlink(&self) -> bool {
-        match self.0 {}
-    }
-}
-
-impl Clone for FileType {
-    fn clone(&self) -> FileType {
-        match self.0 {}
-    }
-}
-
-impl Copy for FileType {}
-
-impl PartialEq for FileType {
-    fn eq(&self, _other: &FileType) -> bool {
-        match self.0 {}
-    }
-}
-
-impl Eq for FileType {}
-
-impl Hash for FileType {
-    fn hash<H: Hasher>(&self, _h: &mut H) {
-        match self.0 {}
-    }
-}
-
-impl fmt::Debug for FileType {
-    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self.0 {}
-    }
-}
-
-impl fmt::Debug for ReadDir {
-    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self.0 {}
-    }
-}
-
-impl Iterator for ReadDir {
-    type Item = io::Result<DirEntry>;
-
-    fn next(&mut self) -> Option<io::Result<DirEntry>> {
-        match self.0 {}
-    }
-}
-
-impl DirEntry {
-    pub fn path(&self) -> PathBuf {
-        match self.0 {}
-    }
-
-    pub fn file_name(&self) -> OsString {
-        match self.0 {}
-    }
-
-    pub fn metadata(&self) -> io::Result<FileAttr> {
-        match self.0 {}
-    }
-
-    pub fn file_type(&self) -> io::Result<FileType> {
-        match self.0 {}
-    }
-}
-
-impl OpenOptions {
-    pub fn new() -> OpenOptions {
-        OpenOptions {}
-    }
-
-    pub fn read(&mut self, _read: bool) {}
-    pub fn write(&mut self, _write: bool) {}
-    pub fn append(&mut self, _append: bool) {}
-    pub fn truncate(&mut self, _truncate: bool) {}
-    pub fn create(&mut self, _create: bool) {}
-    pub fn create_new(&mut self, _create_new: bool) {}
-}
-
-impl File {
-    pub fn open(_path: &Path, _opts: &OpenOptions) -> io::Result<File> {
-        unsupported()
-    }
-
-    pub fn file_attr(&self) -> io::Result<FileAttr> {
-        match self.0 {}
-    }
-
-    pub fn fsync(&self) -> io::Result<()> {
-        match self.0 {}
-    }
-
-    pub fn datasync(&self) -> io::Result<()> {
-        match self.0 {}
-    }
-
-    pub fn truncate(&self, _size: u64) -> io::Result<()> {
-        match self.0 {}
-    }
-
-    pub fn read(&self, _buf: &mut [u8]) -> io::Result<usize> {
-        match self.0 {}
-    }
-
-    pub fn read_vectored(&self, _bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
-        match self.0 {}
-    }
-
-    pub fn is_read_vectored(&self) -> bool {
-        match self.0 {}
-    }
-
-    pub fn write(&self, _buf: &[u8]) -> io::Result<usize> {
-        match self.0 {}
-    }
-
-    pub fn write_vectored(&self, _bufs: &[IoSlice<'_>]) -> io::Result<usize> {
-        match self.0 {}
-    }
-
-    pub fn is_write_vectored(&self) -> bool {
-        match self.0 {}
-    }
-
-    pub fn flush(&self) -> io::Result<()> {
-        match self.0 {}
-    }
-
-    pub fn seek(&self, _pos: SeekFrom) -> io::Result<u64> {
-        match self.0 {}
-    }
-
-    pub fn duplicate(&self) -> io::Result<File> {
-        match self.0 {}
-    }
-
-    pub fn set_permissions(&self, _perm: FilePermissions) -> io::Result<()> {
-        match self.0 {}
-    }
-
-    pub fn diverge(&self) -> ! {
-        match self.0 {}
-    }
-}
-
-impl DirBuilder {
-    pub fn new() -> DirBuilder {
-        DirBuilder {}
-    }
-
-    pub fn mkdir(&self, _p: &Path) -> io::Result<()> {
-        unsupported()
-    }
-}
-
-impl fmt::Debug for File {
-    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self.0 {}
-    }
-}
-
-pub fn readdir(_p: &Path) -> io::Result<ReadDir> {
-    unsupported()
-}
-
-pub fn unlink(_p: &Path) -> io::Result<()> {
-    unsupported()
-}
-
-pub fn rename(_old: &Path, _new: &Path) -> io::Result<()> {
-    unsupported()
-}
-
-pub fn set_perm(_p: &Path, perm: FilePermissions) -> io::Result<()> {
-    match perm.0 {}
-}
-
-pub fn rmdir(_p: &Path) -> io::Result<()> {
-    unsupported()
-}
-
-pub fn remove_dir_all(_path: &Path) -> io::Result<()> {
-    unsupported()
-}
-
-pub fn readlink(_p: &Path) -> io::Result<PathBuf> {
-    unsupported()
-}
-
-pub fn symlink(_src: &Path, _dst: &Path) -> io::Result<()> {
-    unsupported()
-}
-
-pub fn link(_src: &Path, _dst: &Path) -> io::Result<()> {
-    unsupported()
-}
-
-pub fn stat(_p: &Path) -> io::Result<FileAttr> {
-    unsupported()
-}
-
-pub fn lstat(_p: &Path) -> io::Result<FileAttr> {
-    unsupported()
-}
-
-pub fn canonicalize(_p: &Path) -> io::Result<PathBuf> {
-    unsupported()
-}
-
-pub fn copy(_from: &Path, _to: &Path) -> io::Result<u64> {
-    unsupported()
-}
diff --git a/library/std/src/sys/sgx/io.rs b/library/std/src/sys/sgx/io.rs
deleted file mode 100644
index d5f475b4310..00000000000
--- a/library/std/src/sys/sgx/io.rs
+++ /dev/null
@@ -1,47 +0,0 @@
-use crate::mem;
-
-#[derive(Copy, Clone)]
-pub struct IoSlice<'a>(&'a [u8]);
-
-impl<'a> IoSlice<'a> {
-    #[inline]
-    pub fn new(buf: &'a [u8]) -> IoSlice<'a> {
-        IoSlice(buf)
-    }
-
-    #[inline]
-    pub fn advance(&mut self, n: usize) {
-        self.0 = &self.0[n..]
-    }
-
-    #[inline]
-    pub fn as_slice(&self) -> &[u8] {
-        self.0
-    }
-}
-
-pub struct IoSliceMut<'a>(&'a mut [u8]);
-
-impl<'a> IoSliceMut<'a> {
-    #[inline]
-    pub fn new(buf: &'a mut [u8]) -> IoSliceMut<'a> {
-        IoSliceMut(buf)
-    }
-
-    #[inline]
-    pub fn advance(&mut self, n: usize) {
-        let slice = mem::replace(&mut self.0, &mut []);
-        let (_, remaining) = slice.split_at_mut(n);
-        self.0 = remaining;
-    }
-
-    #[inline]
-    pub fn as_slice(&self) -> &[u8] {
-        self.0
-    }
-
-    #[inline]
-    pub fn as_mut_slice(&mut self) -> &mut [u8] {
-        self.0
-    }
-}
diff --git a/library/std/src/sys/sgx/mod.rs b/library/std/src/sys/sgx/mod.rs
index 1d32eb25424..1abd91e75e8 100644
--- a/library/std/src/sys/sgx/mod.rs
+++ b/library/std/src/sys/sgx/mod.rs
@@ -17,14 +17,18 @@ pub mod condvar;
 pub mod env;
 pub mod ext;
 pub mod fd;
+#[path = "../unsupported/fs.rs"]
 pub mod fs;
+#[path = "../unsupported/io.rs"]
 pub mod io;
 pub mod memchr;
 pub mod mutex;
 pub mod net;
 pub mod os;
 pub mod path;
+#[path = "../unsupported/pipe.rs"]
 pub mod pipe;
+#[path = "../unsupported/process.rs"]
 pub mod process;
 pub mod rwlock;
 pub mod stack_overflow;
diff --git a/library/std/src/sys/sgx/pipe.rs b/library/std/src/sys/sgx/pipe.rs
deleted file mode 100644
index 10d0925823e..00000000000
--- a/library/std/src/sys/sgx/pipe.rs
+++ /dev/null
@@ -1,38 +0,0 @@
-use crate::io::{self, IoSlice, IoSliceMut};
-use crate::sys::Void;
-
-pub struct AnonPipe(Void);
-
-impl AnonPipe {
-    pub fn read(&self, _buf: &mut [u8]) -> io::Result<usize> {
-        match self.0 {}
-    }
-
-    pub fn read_vectored(&self, _bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
-        match self.0 {}
-    }
-
-    pub fn is_read_vectored(&self) -> bool {
-        match self.0 {}
-    }
-
-    pub fn write(&self, _buf: &[u8]) -> io::Result<usize> {
-        match self.0 {}
-    }
-
-    pub fn write_vectored(&self, _bufs: &[IoSlice<'_>]) -> io::Result<usize> {
-        match self.0 {}
-    }
-
-    pub fn is_write_vectored(&self) -> bool {
-        match self.0 {}
-    }
-
-    pub fn diverge(&self) -> ! {
-        match self.0 {}
-    }
-}
-
-pub fn read2(p1: AnonPipe, _v1: &mut Vec<u8>, _p2: AnonPipe, _v2: &mut Vec<u8>) -> io::Result<()> {
-    match p1.0 {}
-}
diff --git a/library/std/src/sys/sgx/process.rs b/library/std/src/sys/sgx/process.rs
deleted file mode 100644
index 4702e5c5492..00000000000
--- a/library/std/src/sys/sgx/process.rs
+++ /dev/null
@@ -1,149 +0,0 @@
-use crate::ffi::OsStr;
-use crate::fmt;
-use crate::io;
-use crate::sys::fs::File;
-use crate::sys::pipe::AnonPipe;
-use crate::sys::{unsupported, Void};
-use crate::sys_common::process::CommandEnv;
-
-pub use crate::ffi::OsString as EnvKey;
-
-////////////////////////////////////////////////////////////////////////////////
-// Command
-////////////////////////////////////////////////////////////////////////////////
-
-pub struct Command {
-    env: CommandEnv,
-}
-
-// passed back to std::process with the pipes connected to the child, if any
-// were requested
-pub struct StdioPipes {
-    pub stdin: Option<AnonPipe>,
-    pub stdout: Option<AnonPipe>,
-    pub stderr: Option<AnonPipe>,
-}
-
-pub enum Stdio {
-    Inherit,
-    Null,
-    MakePipe,
-}
-
-impl Command {
-    pub fn new(_program: &OsStr) -> Command {
-        Command { env: Default::default() }
-    }
-
-    pub fn arg(&mut self, _arg: &OsStr) {}
-
-    pub fn env_mut(&mut self) -> &mut CommandEnv {
-        &mut self.env
-    }
-
-    pub fn cwd(&mut self, _dir: &OsStr) {}
-
-    pub fn stdin(&mut self, _stdin: Stdio) {}
-
-    pub fn stdout(&mut self, _stdout: Stdio) {}
-
-    pub fn stderr(&mut self, _stderr: Stdio) {}
-
-    pub fn spawn(
-        &mut self,
-        _default: Stdio,
-        _needs_stdin: bool,
-    ) -> io::Result<(Process, StdioPipes)> {
-        unsupported()
-    }
-}
-
-impl From<AnonPipe> for Stdio {
-    fn from(pipe: AnonPipe) -> Stdio {
-        pipe.diverge()
-    }
-}
-
-impl From<File> for Stdio {
-    fn from(file: File) -> Stdio {
-        file.diverge()
-    }
-}
-
-impl fmt::Debug for Command {
-    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        Ok(())
-    }
-}
-
-pub struct ExitStatus(Void);
-
-impl ExitStatus {
-    pub fn success(&self) -> bool {
-        match self.0 {}
-    }
-
-    pub fn code(&self) -> Option<i32> {
-        match self.0 {}
-    }
-}
-
-impl Clone for ExitStatus {
-    fn clone(&self) -> ExitStatus {
-        match self.0 {}
-    }
-}
-
-impl Copy for ExitStatus {}
-
-impl PartialEq for ExitStatus {
-    fn eq(&self, _other: &ExitStatus) -> bool {
-        match self.0 {}
-    }
-}
-
-impl Eq for ExitStatus {}
-
-impl fmt::Debug for ExitStatus {
-    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self.0 {}
-    }
-}
-
-impl fmt::Display for ExitStatus {
-    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self.0 {}
-    }
-}
-
-#[derive(PartialEq, Eq, Clone, Copy, Debug)]
-pub struct ExitCode(bool);
-
-impl ExitCode {
-    pub const SUCCESS: ExitCode = ExitCode(false);
-    pub const FAILURE: ExitCode = ExitCode(true);
-
-    pub fn as_i32(&self) -> i32 {
-        self.0 as i32
-    }
-}
-
-pub struct Process(Void);
-
-impl Process {
-    pub fn id(&self) -> u32 {
-        match self.0 {}
-    }
-
-    pub fn kill(&mut self) -> io::Result<()> {
-        match self.0 {}
-    }
-
-    pub fn wait(&mut self) -> io::Result<ExitStatus> {
-        match self.0 {}
-    }
-
-    pub fn try_wait(&mut self) -> io::Result<Option<ExitStatus>> {
-        match self.0 {}
-    }
-}
diff --git a/library/std/src/sys/unix/alloc.rs b/library/std/src/sys/unix/alloc.rs
index 8e193935460..964abe8b8c9 100644
--- a/library/std/src/sys/unix/alloc.rs
+++ b/library/std/src/sys/unix/alloc.rs
@@ -52,46 +52,48 @@ unsafe impl GlobalAlloc for System {
     }
 }
 
-#[cfg(any(
-    target_os = "android",
-    target_os = "illumos",
-    target_os = "redox",
-    target_os = "solaris"
-))]
-#[inline]
-unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 {
-    // On android we currently target API level 9 which unfortunately
-    // doesn't have the `posix_memalign` API used below. Instead we use
-    // `memalign`, but this unfortunately has the property on some systems
-    // where the memory returned cannot be deallocated by `free`!
-    //
-    // Upon closer inspection, however, this appears to work just fine with
-    // Android, so for this platform we should be fine to call `memalign`
-    // (which is present in API level 9). Some helpful references could
-    // possibly be chromium using memalign [1], attempts at documenting that
-    // memalign + free is ok [2] [3], or the current source of chromium
-    // which still uses memalign on android [4].
-    //
-    // [1]: https://codereview.chromium.org/10796020/
-    // [2]: https://code.google.com/p/android/issues/detail?id=35391
-    // [3]: https://bugs.chromium.org/p/chromium/issues/detail?id=138579
-    // [4]: https://chromium.googlesource.com/chromium/src/base/+/master/
-    //                                       /memory/aligned_memory.cc
-    libc::memalign(layout.align(), layout.size()) as *mut u8
-}
-
-#[cfg(not(any(
-    target_os = "android",
-    target_os = "illumos",
-    target_os = "redox",
-    target_os = "solaris"
-)))]
-#[inline]
-unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 {
-    let mut out = ptr::null_mut();
-    // posix_memalign requires that the alignment be a multiple of `sizeof(void*)`.
-    // Since these are all powers of 2, we can just use max.
-    let align = layout.align().max(crate::mem::size_of::<usize>());
-    let ret = libc::posix_memalign(&mut out, align, layout.size());
-    if ret != 0 { ptr::null_mut() } else { out as *mut u8 }
+cfg_if::cfg_if! {
+    if #[cfg(any(
+        target_os = "android",
+        target_os = "illumos",
+        target_os = "redox",
+        target_os = "solaris"
+    ))] {
+        #[inline]
+        unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 {
+            // On android we currently target API level 9 which unfortunately
+            // doesn't have the `posix_memalign` API used below. Instead we use
+            // `memalign`, but this unfortunately has the property on some systems
+            // where the memory returned cannot be deallocated by `free`!
+            //
+            // Upon closer inspection, however, this appears to work just fine with
+            // Android, so for this platform we should be fine to call `memalign`
+            // (which is present in API level 9). Some helpful references could
+            // possibly be chromium using memalign [1], attempts at documenting that
+            // memalign + free is ok [2] [3], or the current source of chromium
+            // which still uses memalign on android [4].
+            //
+            // [1]: https://codereview.chromium.org/10796020/
+            // [2]: https://code.google.com/p/android/issues/detail?id=35391
+            // [3]: https://bugs.chromium.org/p/chromium/issues/detail?id=138579
+            // [4]: https://chromium.googlesource.com/chromium/src/base/+/master/
+            //                                       /memory/aligned_memory.cc
+            libc::memalign(layout.align(), layout.size()) as *mut u8
+        }
+    } else if #[cfg(target_os = "wasi")] {
+        #[inline]
+        unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 {
+            libc::aligned_alloc(layout.align(), layout.size()) as *mut u8
+        }
+    } else {
+        #[inline]
+        unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 {
+            let mut out = ptr::null_mut();
+            // posix_memalign requires that the alignment be a multiple of `sizeof(void*)`.
+            // Since these are all powers of 2, we can just use max.
+            let align = layout.align().max(crate::mem::size_of::<usize>());
+            let ret = libc::posix_memalign(&mut out, align, layout.size());
+            if ret != 0 { ptr::null_mut() } else { out as *mut u8 }
+        }
+    }
 }
diff --git a/library/std/src/sys/unix/ext/mod.rs b/library/std/src/sys/unix/ext/mod.rs
index cbdb1c10049..f4354688098 100644
--- a/library/std/src/sys/unix/ext/mod.rs
+++ b/library/std/src/sys/unix/ext/mod.rs
@@ -37,6 +37,18 @@ pub mod process;
 pub mod raw;
 pub mod thread;
 
+#[unstable(feature = "peer_credentials_unix_socket", issue = "42839", reason = "unstable")]
+#[cfg(any(
+    target_os = "android",
+    target_os = "linux",
+    target_os = "dragonfly",
+    target_os = "freebsd",
+    target_os = "ios",
+    target_os = "macos",
+    target_os = "openbsd"
+))]
+pub mod ucred;
+
 /// A prelude for conveniently writing platform-specific code.
 ///
 /// Includes all extension traits, and some important type definitions.
diff --git a/library/std/src/sys/unix/ext/net.rs b/library/std/src/sys/unix/ext/net.rs
index 320378e30cc..f3da8f9f584 100644
--- a/library/std/src/sys/unix/ext/net.rs
+++ b/library/std/src/sys/unix/ext/net.rs
@@ -31,6 +31,29 @@ use crate::sys_common::{self, AsInner, FromInner, IntoInner};
 use crate::time::Duration;
 
 #[cfg(any(
+    target_os = "android",
+    target_os = "linux",
+    target_os = "dragonfly",
+    target_os = "freebsd",
+    target_os = "ios",
+    target_os = "macos",
+    target_os = "openbsd"
+))]
+use crate::os::unix::ucred;
+
+#[unstable(feature = "peer_credentials_unix_socket", issue = "42839", reason = "unstable")]
+#[cfg(any(
+    target_os = "android",
+    target_os = "linux",
+    target_os = "dragonfly",
+    target_os = "freebsd",
+    target_os = "ios",
+    target_os = "macos",
+    target_os = "openbsd"
+))]
+pub use ucred::UCred;
+
+#[cfg(any(
     target_os = "linux",
     target_os = "android",
     target_os = "dragonfly",
@@ -405,6 +428,34 @@ impl UnixStream {
         SocketAddr::new(|addr, len| unsafe { libc::getpeername(*self.0.as_inner(), addr, len) })
     }
 
+    /// Gets the peer credentials for this Unix domain socket.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// #![feature(peer_credentials_unix_socket)]
+    /// use std::os::unix::net::UnixStream;
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     let socket = UnixStream::connect("/tmp/sock")?;
+    ///     let peer_cred = socket.peer_cred().expect("Couldn't get peer credentials");
+    ///     Ok(())
+    /// }
+    /// ```
+    #[unstable(feature = "peer_credentials_unix_socket", issue = "42839", reason = "unstable")]
+    #[cfg(any(
+        target_os = "android",
+        target_os = "linux",
+        target_os = "dragonfly",
+        target_os = "freebsd",
+        target_os = "ios",
+        target_os = "macos",
+        target_os = "openbsd"
+    ))]
+    pub fn peer_cred(&self) -> io::Result<UCred> {
+        ucred::peer_cred(self)
+    }
+
     /// Sets the read timeout for the socket.
     ///
     /// If the provided value is [`None`], then [`read`] calls will block
diff --git a/library/std/src/sys/unix/ext/ucred.rs b/library/std/src/sys/unix/ext/ucred.rs
new file mode 100644
index 00000000000..ed7516c7f28
--- /dev/null
+++ b/library/std/src/sys/unix/ext/ucred.rs
@@ -0,0 +1,97 @@
+//! Unix peer credentials.
+
+// NOTE: Code in this file is heavily based on work done in PR 13 from the tokio-uds repository on
+//       GitHub.
+//
+//       For reference, the link is here: https://github.com/tokio-rs/tokio-uds/pull/13
+//       Credit to Martin Habovštiak (GitHub username Kixunil) and contributors for this work.
+
+use libc::{gid_t, pid_t, uid_t};
+
+/// Credentials for a UNIX process for credentials passing.
+#[unstable(feature = "peer_credentials_unix_socket", issue = "42839", reason = "unstable")]
+#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
+pub struct UCred {
+    /// The UID part of the peer credential. This is the effective UID of the process at the domain
+    /// socket's endpoint.
+    pub uid: uid_t,
+    /// The GID part of the peer credential. This is the effective GID of the process at the domain
+    /// socket's endpoint.
+    pub gid: gid_t,
+    /// The PID part of the peer credential. This field is optional because the PID part of the
+    /// peer credentials is not supported on every platform. On platforms where the mechanism to
+    /// discover the PID exists, this field will be populated to the PID of the process at the
+    /// domain socket's endpoint. Otherwise, it will be set to None.
+    pub pid: Option<pid_t>,
+}
+
+#[cfg(any(target_os = "android", target_os = "linux"))]
+pub use self::impl_linux::peer_cred;
+
+#[cfg(any(
+    target_os = "dragonfly",
+    target_os = "freebsd",
+    target_os = "ios",
+    target_os = "macos",
+    target_os = "openbsd"
+))]
+pub use self::impl_bsd::peer_cred;
+
+#[cfg(any(target_os = "linux", target_os = "android"))]
+pub mod impl_linux {
+    use super::UCred;
+    use crate::os::unix::io::AsRawFd;
+    use crate::os::unix::net::UnixStream;
+    use crate::{io, mem};
+    use libc::{c_void, getsockopt, socklen_t, ucred, SOL_SOCKET, SO_PEERCRED};
+
+    pub fn peer_cred(socket: &UnixStream) -> io::Result<UCred> {
+        let ucred_size = mem::size_of::<ucred>();
+
+        // Trivial sanity checks.
+        assert!(mem::size_of::<u32>() <= mem::size_of::<usize>());
+        assert!(ucred_size <= u32::MAX as usize);
+
+        let mut ucred_size = ucred_size as socklen_t;
+        let mut ucred: ucred = ucred { pid: 1, uid: 1, gid: 1 };
+
+        unsafe {
+            let ret = getsockopt(
+                socket.as_raw_fd(),
+                SOL_SOCKET,
+                SO_PEERCRED,
+                &mut ucred as *mut ucred as *mut c_void,
+                &mut ucred_size,
+            );
+
+            if ret == 0 && ucred_size as usize == mem::size_of::<ucred>() {
+                Ok(UCred { uid: ucred.uid, gid: ucred.gid, pid: Some(ucred.pid) })
+            } else {
+                Err(io::Error::last_os_error())
+            }
+        }
+    }
+}
+
+#[cfg(any(
+    target_os = "dragonfly",
+    target_os = "macos",
+    target_os = "ios",
+    target_os = "freebsd",
+    target_os = "openbsd"
+))]
+pub mod impl_bsd {
+    use super::UCred;
+    use crate::io;
+    use crate::os::unix::io::AsRawFd;
+    use crate::os::unix::net::UnixStream;
+
+    pub fn peer_cred(socket: &UnixStream) -> io::Result<UCred> {
+        let mut cred = UCred { uid: 1, gid: 1, pid: None };
+        unsafe {
+            let ret = libc::getpeereid(socket.as_raw_fd(), &mut cred.uid, &mut cred.gid);
+
+            if ret == 0 { Ok(cred) } else { Err(io::Error::last_os_error()) }
+        }
+    }
+}
diff --git a/library/std/src/sys/unix/ext/ucred/tests.rs b/library/std/src/sys/unix/ext/ucred/tests.rs
new file mode 100644
index 00000000000..451b534b266
--- /dev/null
+++ b/library/std/src/sys/unix/ext/ucred/tests.rs
@@ -0,0 +1,25 @@
+use crate::os::unix::net::UnixStream;
+use libc::{getegid, geteuid};
+
+#[test]
+#[cfg(any(
+    target_os = "android",
+    target_os = "linux",
+    target_os = "dragonfly",
+    target_os = "freebsd",
+    target_os = "ios",
+    target_os = "macos",
+    target_os = "openbsd"
+))]
+fn test_socket_pair() {
+    // Create two connected sockets and get their peer credentials. They should be equal.
+    let (sock_a, sock_b) = UnixStream::pair().unwrap();
+    let (cred_a, cred_b) = (sock_a.peer_cred().unwrap(), sock_b.peer_cred().unwrap());
+    assert_eq!(cred_a, cred_b);
+
+    // Check that the UID and GIDs match up.
+    let uid = unsafe { geteuid() };
+    let gid = unsafe { getegid() };
+    assert_eq!(cred_a.uid, uid);
+    assert_eq!(cred_a.gid, gid);
+}
diff --git a/library/std/src/sys/unix/process/process_fuchsia.rs b/library/std/src/sys/unix/process/process_fuchsia.rs
index 6daf2885bae..fab27cd9f70 100644
--- a/library/std/src/sys/unix/process/process_fuchsia.rs
+++ b/library/std/src/sys/unix/process/process_fuchsia.rs
@@ -118,7 +118,8 @@ impl Command {
             FDIO_SPAWN_CLONE_JOB
                 | FDIO_SPAWN_CLONE_LDSVC
                 | FDIO_SPAWN_CLONE_NAMESPACE
-                | FDIO_SPAWN_CLONE_ENVIRON, // this is ignored when envp is non-null
+                | FDIO_SPAWN_CLONE_ENVIRON // this is ignored when envp is non-null
+                | FDIO_SPAWN_CLONE_UTC_CLOCK,
             self.get_program().as_ptr(),
             self.get_argv().as_ptr(),
             envp,
diff --git a/library/std/src/sys/unix/process/zircon.rs b/library/std/src/sys/unix/process/zircon.rs
index 750b8f0762a..69ec275c2b3 100644
--- a/library/std/src/sys/unix/process/zircon.rs
+++ b/library/std/src/sys/unix/process/zircon.rs
@@ -138,6 +138,7 @@ pub const FDIO_SPAWN_CLONE_LDSVC: u32 = 0x0002;
 pub const FDIO_SPAWN_CLONE_NAMESPACE: u32 = 0x0004;
 pub const FDIO_SPAWN_CLONE_STDIO: u32 = 0x0008;
 pub const FDIO_SPAWN_CLONE_ENVIRON: u32 = 0x0010;
+pub const FDIO_SPAWN_CLONE_UTC_CLOCK: u32 = 0x0020;
 pub const FDIO_SPAWN_CLONE_ALL: u32 = 0xFFFF;
 
 // fdio_spawn_etc actions
diff --git a/library/std/src/sys/unsupported/fs.rs b/library/std/src/sys/unsupported/fs.rs
index ecb5b51cccd..faa53b6a744 100644
--- a/library/std/src/sys/unsupported/fs.rs
+++ b/library/std/src/sys/unsupported/fs.rs
@@ -233,10 +233,6 @@ impl File {
     pub fn set_permissions(&self, _perm: FilePermissions) -> io::Result<()> {
         match self.0 {}
     }
-
-    pub fn diverge(&self) -> ! {
-        match self.0 {}
-    }
 }
 
 impl DirBuilder {
diff --git a/library/std/src/sys/unsupported/mod.rs b/library/std/src/sys/unsupported/mod.rs
index 87f655eecd5..8ba870c5dbc 100644
--- a/library/std/src/sys/unsupported/mod.rs
+++ b/library/std/src/sys/unsupported/mod.rs
@@ -8,6 +8,7 @@ pub mod io;
 pub mod mutex;
 pub mod net;
 pub mod os;
+#[path = "../unix/path.rs"]
 pub mod path;
 pub mod pipe;
 pub mod process;
diff --git a/library/std/src/sys/unsupported/path.rs b/library/std/src/sys/unsupported/path.rs
deleted file mode 100644
index 840a7ae0426..00000000000
--- a/library/std/src/sys/unsupported/path.rs
+++ /dev/null
@@ -1,19 +0,0 @@
-use crate::ffi::OsStr;
-use crate::path::Prefix;
-
-#[inline]
-pub fn is_sep_byte(b: u8) -> bool {
-    b == b'/'
-}
-
-#[inline]
-pub fn is_verbatim_sep(b: u8) -> bool {
-    b == b'/'
-}
-
-pub fn parse_prefix(_: &OsStr) -> Option<Prefix<'_>> {
-    None
-}
-
-pub const MAIN_SEP_STR: &str = "/";
-pub const MAIN_SEP: char = '/';
diff --git a/library/std/src/sys/unsupported/process.rs b/library/std/src/sys/unsupported/process.rs
index 4702e5c5492..7156c9ab92f 100644
--- a/library/std/src/sys/unsupported/process.rs
+++ b/library/std/src/sys/unsupported/process.rs
@@ -65,8 +65,8 @@ impl From<AnonPipe> for Stdio {
 }
 
 impl From<File> for Stdio {
-    fn from(file: File) -> Stdio {
-        file.diverge()
+    fn from(_file: File) -> Stdio {
+        panic!("unsupported")
     }
 }
 
diff --git a/library/std/src/sys/wasi/alloc.rs b/library/std/src/sys/wasi/alloc.rs
deleted file mode 100644
index 4d0afe27bb8..00000000000
--- a/library/std/src/sys/wasi/alloc.rs
+++ /dev/null
@@ -1,69 +0,0 @@
-#![deny(unsafe_op_in_unsafe_fn)]
-
-use crate::alloc::{GlobalAlloc, Layout, System};
-use crate::ptr;
-use crate::sys_common::alloc::{realloc_fallback, MIN_ALIGN};
-
-// SAFETY: All methods implemented follow the contract rules defined
-// in `GlobalAlloc`.
-#[stable(feature = "alloc_system_type", since = "1.28.0")]
-unsafe impl GlobalAlloc for System {
-    #[inline]
-    unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
-        if layout.align() <= MIN_ALIGN && layout.align() <= layout.size() {
-            // SAFETY: `libc::malloc` is guaranteed to be safe, it will allocate
-            // `layout.size()` bytes of memory and return a pointer to it
-            unsafe { libc::malloc(layout.size()) as *mut u8 }
-        } else {
-            // SAFETY: `libc::aligned_alloc` is guaranteed to be safe if
-            // `layout.size()` is a multiple of `layout.align()`. This
-            // constraint can be satisfied if `pad_to_align` is called,
-            // which creates a layout by rounding the size of this layout up
-            // to a multiple of the layout's alignment
-            let aligned_layout = layout.pad_to_align();
-            unsafe { libc::aligned_alloc(aligned_layout.align(), aligned_layout.size()) as *mut u8 }
-        }
-    }
-
-    #[inline]
-    unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
-        if layout.align() <= MIN_ALIGN && layout.align() <= layout.size() {
-            // SAFETY: `libc::calloc` is safe as long that `layout.size() * 1`
-            // would not result in integer overflow which cannot happen,
-            // multiplying by one never overflows
-            unsafe { libc::calloc(layout.size(), 1) as *mut u8 }
-        } else {
-            // SAFETY: The safety contract for `alloc` must be upheld by the caller
-            let ptr = unsafe { self.alloc(layout.clone()) };
-            if !ptr.is_null() {
-                // SAFETY: in the case of the `ptr` being not null
-                // it will be properly aligned and a valid ptr
-                // which satisfies `ptr::write_bytes` safety constrains
-                unsafe { ptr::write_bytes(ptr, 0, layout.size()) };
-            }
-            ptr
-        }
-    }
-
-    #[inline]
-    unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) {
-        // SAFETY: `libc::free` is guaranteed to be safe if `ptr` is allocated
-        // by this allocator or if `ptr` is NULL
-        unsafe { libc::free(ptr as *mut libc::c_void) }
-    }
-
-    #[inline]
-    unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
-        if layout.align() <= MIN_ALIGN && layout.align() <= new_size {
-            // SAFETY: `libc::realloc` is safe if `ptr` is allocated by this
-            // allocator or NULL
-            // - If `new_size` is 0 and `ptr` is not NULL, it will act as `libc::free`
-            // - If `new_size` is not 0 and `ptr` is NULL, it will act as `libc::malloc`
-            // - Else, it will resize the block accordingly
-            unsafe { libc::realloc(ptr as *mut libc::c_void, new_size) as *mut u8 }
-        } else {
-            // SAFETY: The safety contract for `realloc_fallback` must be upheld by the caller
-            unsafe { realloc_fallback(self, ptr, layout, new_size) }
-        }
-    }
-}
diff --git a/library/std/src/sys/wasi/mod.rs b/library/std/src/sys/wasi/mod.rs
index 2704ff484f9..a7a4407ac38 100644
--- a/library/std/src/sys/wasi/mod.rs
+++ b/library/std/src/sys/wasi/mod.rs
@@ -17,6 +17,7 @@
 use crate::io as std_io;
 use crate::mem;
 
+#[path = "../unix/alloc.rs"]
 pub mod alloc;
 pub mod args;
 #[path = "../unsupported/cmath.rs"]
@@ -33,8 +34,11 @@ pub mod net;
 pub mod os;
 pub use crate::sys_common::os_str_bytes as os_str;
 pub mod ext;
+#[path = "../unix/path.rs"]
 pub mod path;
+#[path = "../unsupported/pipe.rs"]
 pub mod pipe;
+#[path = "../unsupported/process.rs"]
 pub mod process;
 #[path = "../unsupported/rwlock.rs"]
 pub mod rwlock;
diff --git a/library/std/src/sys/wasi/path.rs b/library/std/src/sys/wasi/path.rs
deleted file mode 100644
index 840a7ae0426..00000000000
--- a/library/std/src/sys/wasi/path.rs
+++ /dev/null
@@ -1,19 +0,0 @@
-use crate::ffi::OsStr;
-use crate::path::Prefix;
-
-#[inline]
-pub fn is_sep_byte(b: u8) -> bool {
-    b == b'/'
-}
-
-#[inline]
-pub fn is_verbatim_sep(b: u8) -> bool {
-    b == b'/'
-}
-
-pub fn parse_prefix(_: &OsStr) -> Option<Prefix<'_>> {
-    None
-}
-
-pub const MAIN_SEP_STR: &str = "/";
-pub const MAIN_SEP: char = '/';
diff --git a/library/std/src/sys/wasi/pipe.rs b/library/std/src/sys/wasi/pipe.rs
deleted file mode 100644
index 180fc114d86..00000000000
--- a/library/std/src/sys/wasi/pipe.rs
+++ /dev/null
@@ -1,40 +0,0 @@
-#![deny(unsafe_op_in_unsafe_fn)]
-
-use crate::io::{self, IoSlice, IoSliceMut};
-use crate::sys::Void;
-
-pub struct AnonPipe(Void);
-
-impl AnonPipe {
-    pub fn read(&self, _buf: &mut [u8]) -> io::Result<usize> {
-        match self.0 {}
-    }
-
-    pub fn read_vectored(&self, _bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
-        match self.0 {}
-    }
-
-    pub fn is_read_vectored(&self) -> bool {
-        match self.0 {}
-    }
-
-    pub fn write(&self, _buf: &[u8]) -> io::Result<usize> {
-        match self.0 {}
-    }
-
-    pub fn write_vectored(&self, _bufs: &[IoSlice<'_>]) -> io::Result<usize> {
-        match self.0 {}
-    }
-
-    pub fn is_write_vectored(&self) -> bool {
-        match self.0 {}
-    }
-
-    pub fn diverge(&self) -> ! {
-        match self.0 {}
-    }
-}
-
-pub fn read2(p1: AnonPipe, _v1: &mut Vec<u8>, _p2: AnonPipe, _v2: &mut Vec<u8>) -> io::Result<()> {
-    match p1.0 {}
-}
diff --git a/library/std/src/sys/wasi/process.rs b/library/std/src/sys/wasi/process.rs
deleted file mode 100644
index c69d6376b01..00000000000
--- a/library/std/src/sys/wasi/process.rs
+++ /dev/null
@@ -1,151 +0,0 @@
-#![deny(unsafe_op_in_unsafe_fn)]
-
-use crate::ffi::OsStr;
-use crate::fmt;
-use crate::io;
-use crate::sys::fs::File;
-use crate::sys::pipe::AnonPipe;
-use crate::sys::{unsupported, Void};
-use crate::sys_common::process::CommandEnv;
-
-pub use crate::ffi::OsString as EnvKey;
-
-////////////////////////////////////////////////////////////////////////////////
-// Command
-////////////////////////////////////////////////////////////////////////////////
-
-pub struct Command {
-    env: CommandEnv,
-}
-
-// passed back to std::process with the pipes connected to the child, if any
-// were requested
-pub struct StdioPipes {
-    pub stdin: Option<AnonPipe>,
-    pub stdout: Option<AnonPipe>,
-    pub stderr: Option<AnonPipe>,
-}
-
-pub enum Stdio {
-    Inherit,
-    Null,
-    MakePipe,
-}
-
-impl Command {
-    pub fn new(_program: &OsStr) -> Command {
-        Command { env: Default::default() }
-    }
-
-    pub fn arg(&mut self, _arg: &OsStr) {}
-
-    pub fn env_mut(&mut self) -> &mut CommandEnv {
-        &mut self.env
-    }
-
-    pub fn cwd(&mut self, _dir: &OsStr) {}
-
-    pub fn stdin(&mut self, _stdin: Stdio) {}
-
-    pub fn stdout(&mut self, _stdout: Stdio) {}
-
-    pub fn stderr(&mut self, _stderr: Stdio) {}
-
-    pub fn spawn(
-        &mut self,
-        _default: Stdio,
-        _needs_stdin: bool,
-    ) -> io::Result<(Process, StdioPipes)> {
-        unsupported()
-    }
-}
-
-impl From<AnonPipe> for Stdio {
-    fn from(pipe: AnonPipe) -> Stdio {
-        pipe.diverge()
-    }
-}
-
-impl From<File> for Stdio {
-    fn from(_file: File) -> Stdio {
-        panic!("unsupported")
-    }
-}
-
-impl fmt::Debug for Command {
-    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        Ok(())
-    }
-}
-
-pub struct ExitStatus(Void);
-
-impl ExitStatus {
-    pub fn success(&self) -> bool {
-        match self.0 {}
-    }
-
-    pub fn code(&self) -> Option<i32> {
-        match self.0 {}
-    }
-}
-
-impl Clone for ExitStatus {
-    fn clone(&self) -> ExitStatus {
-        match self.0 {}
-    }
-}
-
-impl Copy for ExitStatus {}
-
-impl PartialEq for ExitStatus {
-    fn eq(&self, _other: &ExitStatus) -> bool {
-        match self.0 {}
-    }
-}
-
-impl Eq for ExitStatus {}
-
-impl fmt::Debug for ExitStatus {
-    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self.0 {}
-    }
-}
-
-impl fmt::Display for ExitStatus {
-    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self.0 {}
-    }
-}
-
-#[derive(PartialEq, Eq, Clone, Copy, Debug)]
-pub struct ExitCode(bool);
-
-impl ExitCode {
-    pub const SUCCESS: ExitCode = ExitCode(false);
-    pub const FAILURE: ExitCode = ExitCode(true);
-
-    pub fn as_i32(&self) -> i32 {
-        self.0 as i32
-    }
-}
-
-pub struct Process(Void);
-
-impl Process {
-    pub fn id(&self) -> u32 {
-        match self.0 {}
-    }
-
-    pub fn kill(&mut self) -> io::Result<()> {
-        match self.0 {}
-    }
-
-    pub fn wait(&mut self) -> io::Result<ExitStatus> {
-        match self.0 {}
-    }
-
-    pub fn try_wait(&mut self) -> io::Result<Option<ExitStatus>> {
-        match self.0 {}
-    }
-}
diff --git a/library/std/src/sys/wasm/mod.rs b/library/std/src/sys/wasm/mod.rs
index 3de58904043..2934ea59ab5 100644
--- a/library/std/src/sys/wasm/mod.rs
+++ b/library/std/src/sys/wasm/mod.rs
@@ -27,7 +27,7 @@ pub mod io;
 pub mod net;
 #[path = "../unsupported/os.rs"]
 pub mod os;
-#[path = "../unsupported/path.rs"]
+#[path = "../unix/path.rs"]
 pub mod path;
 #[path = "../unsupported/pipe.rs"]
 pub mod pipe;
diff --git a/library/std/src/sys/windows/mutex.rs b/library/std/src/sys/windows/mutex.rs
index 63dfc640908..1e09b95c872 100644
--- a/library/std/src/sys/windows/mutex.rs
+++ b/library/std/src/sys/windows/mutex.rs
@@ -19,20 +19,25 @@
 //! CriticalSection is used and we keep track of who's holding the mutex to
 //! detect recursive locks.
 
-use crate::cell::UnsafeCell;
+use crate::cell::{Cell, UnsafeCell};
 use crate::mem::{self, MaybeUninit};
 use crate::sync::atomic::{AtomicUsize, Ordering};
 use crate::sys::c;
 use crate::sys::compat;
 
 pub struct Mutex {
+    // This is either directly an SRWLOCK (if supported), or a Box<Inner> otherwise.
     lock: AtomicUsize,
-    held: UnsafeCell<bool>,
 }
 
 unsafe impl Send for Mutex {}
 unsafe impl Sync for Mutex {}
 
+struct Inner {
+    remutex: ReentrantMutex,
+    held: Cell<bool>,
+}
+
 #[derive(Clone, Copy)]
 enum Kind {
     SRWLock = 1,
@@ -51,7 +56,6 @@ impl Mutex {
             // This works because SRWLOCK_INIT is 0 (wrapped in a struct), so we are also properly
             // initializing an SRWLOCK here.
             lock: AtomicUsize::new(0),
-            held: UnsafeCell::new(false),
         }
     }
     #[inline]
@@ -60,10 +64,11 @@ impl Mutex {
         match kind() {
             Kind::SRWLock => c::AcquireSRWLockExclusive(raw(self)),
             Kind::CriticalSection => {
-                let re = self.remutex();
-                (*re).lock();
-                if !self.flag_locked() {
-                    (*re).unlock();
+                let inner = &*self.inner();
+                inner.remutex.lock();
+                if inner.held.replace(true) {
+                    // It was already locked, so we got a recursive lock which we do not want.
+                    inner.remutex.unlock();
                     panic!("cannot recursively lock a mutex");
                 }
             }
@@ -73,23 +78,27 @@ impl Mutex {
         match kind() {
             Kind::SRWLock => c::TryAcquireSRWLockExclusive(raw(self)) != 0,
             Kind::CriticalSection => {
-                let re = self.remutex();
-                if !(*re).try_lock() {
+                let inner = &*self.inner();
+                if !inner.remutex.try_lock() {
                     false
-                } else if self.flag_locked() {
-                    true
-                } else {
-                    (*re).unlock();
+                } else if inner.held.replace(true) {
+                    // It was already locked, so we got a recursive lock which we do not want.
+                    inner.remutex.unlock();
                     false
+                } else {
+                    true
                 }
             }
         }
     }
     pub unsafe fn unlock(&self) {
-        *self.held.get() = false;
         match kind() {
             Kind::SRWLock => c::ReleaseSRWLockExclusive(raw(self)),
-            Kind::CriticalSection => (*self.remutex()).unlock(),
+            Kind::CriticalSection => {
+                let inner = &*(self.lock.load(Ordering::SeqCst) as *const Inner);
+                inner.held.set(false);
+                inner.remutex.unlock();
+            }
         }
     }
     pub unsafe fn destroy(&self) {
@@ -97,38 +106,27 @@ impl Mutex {
             Kind::SRWLock => {}
             Kind::CriticalSection => match self.lock.load(Ordering::SeqCst) {
                 0 => {}
-                n => {
-                    Box::from_raw(n as *mut ReentrantMutex).destroy();
-                }
+                n => Box::from_raw(n as *mut Inner).remutex.destroy(),
             },
         }
     }
 
-    unsafe fn remutex(&self) -> *mut ReentrantMutex {
+    unsafe fn inner(&self) -> *const Inner {
         match self.lock.load(Ordering::SeqCst) {
             0 => {}
-            n => return n as *mut _,
+            n => return n as *const _,
         }
-        let re = box ReentrantMutex::uninitialized();
-        re.init();
-        let re = Box::into_raw(re);
-        match self.lock.compare_and_swap(0, re as usize, Ordering::SeqCst) {
-            0 => re,
+        let inner = box Inner { remutex: ReentrantMutex::uninitialized(), held: Cell::new(false) };
+        inner.remutex.init();
+        let inner = Box::into_raw(inner);
+        match self.lock.compare_and_swap(0, inner as usize, Ordering::SeqCst) {
+            0 => inner,
             n => {
-                Box::from_raw(re).destroy();
-                n as *mut _
+                Box::from_raw(inner).remutex.destroy();
+                n as *const _
             }
         }
     }
-
-    unsafe fn flag_locked(&self) -> bool {
-        if *self.held.get() {
-            false
-        } else {
-            *self.held.get() = true;
-            true
-        }
-    }
 }
 
 fn kind() -> Kind {
@@ -150,7 +148,7 @@ fn kind() -> Kind {
 }
 
 pub struct ReentrantMutex {
-    inner: UnsafeCell<MaybeUninit<c::CRITICAL_SECTION>>,
+    inner: MaybeUninit<UnsafeCell<c::CRITICAL_SECTION>>,
 }
 
 unsafe impl Send for ReentrantMutex {}
@@ -158,27 +156,27 @@ unsafe impl Sync for ReentrantMutex {}
 
 impl ReentrantMutex {
     pub const fn uninitialized() -> ReentrantMutex {
-        ReentrantMutex { inner: UnsafeCell::new(MaybeUninit::uninit()) }
+        ReentrantMutex { inner: MaybeUninit::uninit() }
     }
 
     pub unsafe fn init(&self) {
-        c::InitializeCriticalSection((&mut *self.inner.get()).as_mut_ptr());
+        c::InitializeCriticalSection(UnsafeCell::raw_get(self.inner.as_ptr()));
     }
 
     pub unsafe fn lock(&self) {
-        c::EnterCriticalSection((&mut *self.inner.get()).as_mut_ptr());
+        c::EnterCriticalSection(UnsafeCell::raw_get(self.inner.as_ptr()));
     }
 
     #[inline]
     pub unsafe fn try_lock(&self) -> bool {
-        c::TryEnterCriticalSection((&mut *self.inner.get()).as_mut_ptr()) != 0
+        c::TryEnterCriticalSection(UnsafeCell::raw_get(self.inner.as_ptr())) != 0
     }
 
     pub unsafe fn unlock(&self) {
-        c::LeaveCriticalSection((&mut *self.inner.get()).as_mut_ptr());
+        c::LeaveCriticalSection(UnsafeCell::raw_get(self.inner.as_ptr()));
     }
 
     pub unsafe fn destroy(&self) {
-        c::DeleteCriticalSection((&mut *self.inner.get()).as_mut_ptr());
+        c::DeleteCriticalSection(UnsafeCell::raw_get(self.inner.as_ptr()));
     }
 }
diff --git a/library/std/src/thread/local.rs b/library/std/src/thread/local.rs
index 9d8c6f1815e..60a05dc5d54 100644
--- a/library/std/src/thread/local.rs
+++ b/library/std/src/thread/local.rs
@@ -424,10 +424,9 @@ pub mod fast {
         // thread_local's, or it is being recursively initialized.
         //
         // Macos: Inlining this function can cause two `tlv_get_addr` calls to
-        // be performed for every call to `Key::get`. The #[cold] hint makes
-        // that less likely.
+        // be performed for every call to `Key::get`.
         // LLVM issue: https://bugs.llvm.org/show_bug.cgi?id=41722
-        #[cold]
+        #[inline(never)]
         unsafe fn try_initialize<F: FnOnce() -> T>(&self, init: F) -> Option<&'static T> {
             if !mem::needs_drop::<T>() || self.try_register_dtor() {
                 Some(self.inner.initialize(init))