about summary refs log tree commit diff
path: root/library/std/src
diff options
context:
space:
mode:
Diffstat (limited to 'library/std/src')
-rw-r--r--library/std/src/alloc.rs20
-rw-r--r--library/std/src/backtrace.rs11
-rw-r--r--library/std/src/backtrace/tests.rs4
-rw-r--r--library/std/src/f32.rs9
-rw-r--r--library/std/src/f64.rs9
-rw-r--r--library/std/src/ffi/c_str.rs2
-rw-r--r--library/std/src/fs.rs26
-rw-r--r--library/std/src/io/buffered/bufwriter.rs59
-rw-r--r--library/std/src/io/buffered/linewritershim.rs8
-rw-r--r--library/std/src/io/buffered/mod.rs45
-rw-r--r--library/std/src/io/impls.rs4
-rw-r--r--library/std/src/io/mod.rs4
-rw-r--r--library/std/src/io/stdio.rs64
-rw-r--r--library/std/src/keyword_docs.rs33
-rw-r--r--library/std/src/lazy.rs55
-rw-r--r--library/std/src/lib.rs14
-rw-r--r--library/std/src/macros.rs1
-rw-r--r--library/std/src/net/ip.rs9
-rw-r--r--library/std/src/net/ip/tests.rs6
-rw-r--r--library/std/src/net/tcp.rs2
-rw-r--r--library/std/src/net/udp.rs2
-rw-r--r--library/std/src/num/tests.rs6
-rw-r--r--library/std/src/primitive_docs.rs8
-rw-r--r--library/std/src/process.rs3
-rw-r--r--library/std/src/sys/cloudabi/abi/bitflags.rs47
-rw-r--r--library/std/src/sys/cloudabi/abi/cloudabi.rs2954
-rw-r--r--library/std/src/sys/cloudabi/abi/mod.rs3
-rw-r--r--library/std/src/sys/cloudabi/args.rs7
-rw-r--r--library/std/src/sys/cloudabi/condvar.rs149
-rw-r--r--library/std/src/sys/cloudabi/io.rs47
-rw-r--r--library/std/src/sys/cloudabi/mod.rs73
-rw-r--r--library/std/src/sys/cloudabi/mutex.rs153
-rw-r--r--library/std/src/sys/cloudabi/os.rs26
-rw-r--r--library/std/src/sys/cloudabi/rwlock.rs215
-rw-r--r--library/std/src/sys/cloudabi/shims/args.rs35
-rw-r--r--library/std/src/sys/cloudabi/shims/env.rs9
-rw-r--r--library/std/src/sys/cloudabi/shims/fs.rs308
-rw-r--r--library/std/src/sys/cloudabi/shims/mod.rs19
-rw-r--r--library/std/src/sys/cloudabi/shims/net.rs326
-rw-r--r--library/std/src/sys/cloudabi/shims/os.rs86
-rw-r--r--library/std/src/sys/cloudabi/shims/pipe.rs38
-rw-r--r--library/std/src/sys/cloudabi/shims/process.rs149
-rw-r--r--library/std/src/sys/cloudabi/stack_overflow.rs5
-rw-r--r--library/std/src/sys/cloudabi/stdio.rs66
-rw-r--r--library/std/src/sys/cloudabi/thread.rs118
-rw-r--r--library/std/src/sys/cloudabi/time.rs82
-rw-r--r--library/std/src/sys/hermit/fs.rs4
-rw-r--r--library/std/src/sys/mod.rs13
-rw-r--r--library/std/src/sys/sgx/ext/io.rs39
-rw-r--r--library/std/src/sys/sgx/net.rs6
-rw-r--r--library/std/src/sys/unix/ext/fs.rs6
-rw-r--r--library/std/src/sys/unix/ext/net.rs1768
-rw-r--r--library/std/src/sys/unix/ext/net/addr.rs226
-rw-r--r--library/std/src/sys/unix/ext/net/ancillary.rs660
-rw-r--r--library/std/src/sys/unix/ext/net/datagram.rs897
-rw-r--r--library/std/src/sys/unix/ext/net/listener.rs319
-rw-r--r--library/std/src/sys/unix/ext/net/mod.rs54
-rw-r--r--library/std/src/sys/unix/ext/net/raw_fd.rs40
-rw-r--r--library/std/src/sys/unix/ext/net/stream.rs673
-rw-r--r--library/std/src/sys/unix/ext/net/tests.rs192
-rw-r--r--library/std/src/sys/unix/ext/ucred.rs57
-rw-r--r--library/std/src/sys/unix/ext/ucred/tests.rs15
-rw-r--r--library/std/src/sys/unix/fs.rs21
-rw-r--r--library/std/src/sys/unix/kernel_copy.rs187
-rw-r--r--library/std/src/sys/unix/kernel_copy/tests.rs59
-rw-r--r--library/std/src/sys/unix/net.rs39
-rw-r--r--library/std/src/sys/unix/rand.rs15
-rw-r--r--library/std/src/sys/unix/weak.rs66
-rw-r--r--library/std/src/sys/unsupported/fs.rs2
-rw-r--r--library/std/src/sys/wasi/fs.rs20
-rw-r--r--library/std/src/sys/windows/c.rs47
-rw-r--r--library/std/src/sys/windows/compat.rs2
-rw-r--r--library/std/src/sys/windows/ext/fs.rs12
-rw-r--r--library/std/src/sys/windows/fs.rs39
-rw-r--r--library/std/src/sys/windows/mod.rs1
-rw-r--r--library/std/src/sys/windows/thread_local_key.rs24
-rw-r--r--library/std/src/sys/windows/thread_parker.rs250
-rw-r--r--library/std/src/sys_common/mod.rs3
-rw-r--r--library/std/src/sys_common/net.rs5
-rw-r--r--library/std/src/sys_common/remutex.rs55
-rw-r--r--library/std/src/sys_common/remutex/tests.rs35
-rw-r--r--library/std/src/sys_common/thread_parker/mod.rs2
-rw-r--r--library/std/src/thread/available_concurrency.rs1
-rw-r--r--library/std/src/time.rs4
84 files changed, 4140 insertions, 7037 deletions
diff --git a/library/std/src/alloc.rs b/library/std/src/alloc.rs
index 375b015ccc8..819d57a934d 100644
--- a/library/std/src/alloc.rs
+++ b/library/std/src/alloc.rs
@@ -149,7 +149,7 @@ impl System {
         }
     }
 
-    // SAFETY: Same as `AllocRef::grow`
+    // SAFETY: Same as `Allocator::grow`
     #[inline]
     unsafe fn grow_impl(
         &self,
@@ -190,29 +190,29 @@ impl System {
             old_size => unsafe {
                 let new_ptr = self.alloc_impl(new_layout, zeroed)?;
                 ptr::copy_nonoverlapping(ptr.as_ptr(), new_ptr.as_mut_ptr(), old_size);
-                AllocRef::dealloc(&self, ptr, old_layout);
+                Allocator::deallocate(&self, ptr, old_layout);
                 Ok(new_ptr)
             },
         }
     }
 }
 
-// The AllocRef impl checks the layout size to be non-zero and forwards to the GlobalAlloc impl,
+// The Allocator impl checks the layout size to be non-zero and forwards to the GlobalAlloc impl,
 // which is in `std::sys::*::alloc`.
 #[unstable(feature = "allocator_api", issue = "32838")]
-unsafe impl AllocRef for System {
+unsafe impl Allocator for System {
     #[inline]
-    fn alloc(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
+    fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
         self.alloc_impl(layout, false)
     }
 
     #[inline]
-    fn alloc_zeroed(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
+    fn allocate_zeroed(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
         self.alloc_impl(layout, true)
     }
 
     #[inline]
-    unsafe fn dealloc(&self, ptr: NonNull<u8>, layout: Layout) {
+    unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
         if layout.size() != 0 {
             // SAFETY: `layout` is non-zero in size,
             // other conditions must be upheld by the caller
@@ -257,7 +257,7 @@ unsafe impl AllocRef for System {
         match new_layout.size() {
             // SAFETY: conditions must be upheld by the caller
             0 => unsafe {
-                AllocRef::dealloc(&self, ptr, old_layout);
+                Allocator::deallocate(&self, ptr, old_layout);
                 Ok(NonNull::slice_from_raw_parts(new_layout.dangling(), 0))
             },
 
@@ -277,9 +277,9 @@ unsafe impl AllocRef for System {
             // `new_ptr`. Thus, the call to `copy_nonoverlapping` is safe. The safety contract
             // for `dealloc` must be upheld by the caller.
             new_size => unsafe {
-                let new_ptr = AllocRef::alloc(&self, new_layout)?;
+                let new_ptr = Allocator::allocate(&self, new_layout)?;
                 ptr::copy_nonoverlapping(ptr.as_ptr(), new_ptr.as_mut_ptr(), new_size);
-                AllocRef::dealloc(&self, ptr, old_layout);
+                Allocator::deallocate(&self, ptr, old_layout);
                 Ok(new_ptr)
             },
         }
diff --git a/library/std/src/backtrace.rs b/library/std/src/backtrace.rs
index a9d8a4e2a81..7e8e0a621e3 100644
--- a/library/std/src/backtrace.rs
+++ b/library/std/src/backtrace.rs
@@ -161,6 +161,7 @@ struct BacktraceSymbol {
     name: Option<Vec<u8>>,
     filename: Option<BytesOrWide>,
     lineno: Option<u32>,
+    colno: Option<u32>,
 }
 
 enum BytesOrWide {
@@ -197,6 +198,10 @@ impl fmt::Debug for Backtrace {
 
 impl fmt::Debug for BacktraceSymbol {
     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        // FIXME: improve formatting: https://github.com/rust-lang/rust/issues/65280
+        // FIXME: Also, include column numbers into the debug format as Display already has them.
+        // Until there are stable per-frame accessors, the format shouldn't be changed:
+        // https://github.com/rust-lang/rust/issues/65280#issuecomment-638966585
         write!(fmt, "{{ ")?;
 
         if let Some(fn_name) = self.name.as_ref().map(|b| backtrace_rs::SymbolName::new(b)) {
@@ -209,7 +214,7 @@ impl fmt::Debug for BacktraceSymbol {
             write!(fmt, ", file: \"{:?}\"", fname)?;
         }
 
-        if let Some(line) = self.lineno.as_ref() {
+        if let Some(line) = self.lineno {
             write!(fmt, ", line: {:?}", line)?;
         }
 
@@ -381,7 +386,7 @@ impl fmt::Display for Backtrace {
                 f.print_raw(frame.frame.ip(), None, None, None)?;
             } else {
                 for symbol in frame.symbols.iter() {
-                    f.print_raw(
+                    f.print_raw_with_column(
                         frame.frame.ip(),
                         symbol.name.as_ref().map(|b| backtrace_rs::SymbolName::new(b)),
                         symbol.filename.as_ref().map(|b| match b {
@@ -389,6 +394,7 @@ impl fmt::Display for Backtrace {
                             BytesOrWide::Wide(w) => BytesOrWideString::Wide(w),
                         }),
                         symbol.lineno,
+                        symbol.colno,
                     )?;
                 }
             }
@@ -427,6 +433,7 @@ impl Capture {
                             BytesOrWideString::Wide(b) => BytesOrWide::Wide(b.to_owned()),
                         }),
                         lineno: symbol.lineno(),
+                        colno: symbol.colno(),
                     });
                 });
             }
diff --git a/library/std/src/backtrace/tests.rs b/library/std/src/backtrace/tests.rs
index 287359cd545..f5f74d1eb9a 100644
--- a/library/std/src/backtrace/tests.rs
+++ b/library/std/src/backtrace/tests.rs
@@ -13,6 +13,7 @@ fn test_debug() {
                         name: Some(b"std::backtrace::Backtrace::create".to_vec()),
                         filename: Some(BytesOrWide::Bytes(b"rust/backtrace.rs".to_vec())),
                         lineno: Some(100),
+                        colno: None,
                     }],
                 },
                 BacktraceFrame {
@@ -21,6 +22,7 @@ fn test_debug() {
                         name: Some(b"__rust_maybe_catch_panic".to_vec()),
                         filename: None,
                         lineno: None,
+                        colno: None,
                     }],
                 },
                 BacktraceFrame {
@@ -30,11 +32,13 @@ fn test_debug() {
                             name: Some(b"std::rt::lang_start_internal".to_vec()),
                             filename: Some(BytesOrWide::Bytes(b"rust/rt.rs".to_vec())),
                             lineno: Some(300),
+                            colno: Some(5),
                         },
                         BacktraceSymbol {
                             name: Some(b"std::rt::lang_start".to_vec()),
                             filename: Some(BytesOrWide::Bytes(b"rust/rt.rs".to_vec())),
                             lineno: Some(400),
+                            colno: None,
                         },
                     ],
                 },
diff --git a/library/std/src/f32.rs b/library/std/src/f32.rs
index 2a54b117ff4..48c77bd13e0 100644
--- a/library/std/src/f32.rs
+++ b/library/std/src/f32.rs
@@ -206,8 +206,10 @@ impl f32 {
     /// Fused multiply-add. Computes `(self * a) + b` with only one rounding
     /// error, yielding a more accurate result than an unfused multiply-add.
     ///
-    /// Using `mul_add` can be more performant than an unfused multiply-add if
-    /// the target architecture has a dedicated `fma` CPU instruction.
+    /// Using `mul_add` *may* be more performant than an unfused multiply-add if
+    /// the target architecture has a dedicated `fma` CPU instruction. However,
+    /// this is not always true, and will be heavily dependant on designing
+    /// algorithms with specific target hardware in mind.
     ///
     /// # Examples
     ///
@@ -893,14 +895,13 @@ impl f32 {
     /// # Examples
     ///
     /// ```
-    /// #![feature(clamp)]
     /// assert!((-3.0f32).clamp(-2.0, 1.0) == -2.0);
     /// assert!((0.0f32).clamp(-2.0, 1.0) == 0.0);
     /// assert!((2.0f32).clamp(-2.0, 1.0) == 1.0);
     /// assert!((f32::NAN).clamp(-2.0, 1.0).is_nan());
     /// ```
     #[must_use = "method returns a new number and does not mutate the original value"]
-    #[unstable(feature = "clamp", issue = "44095")]
+    #[stable(feature = "clamp", since = "1.50.0")]
     #[inline]
     pub fn clamp(self, min: f32, max: f32) -> f32 {
         assert!(min <= max);
diff --git a/library/std/src/f64.rs b/library/std/src/f64.rs
index 363d1a00476..e823ac43fdd 100644
--- a/library/std/src/f64.rs
+++ b/library/std/src/f64.rs
@@ -206,8 +206,10 @@ impl f64 {
     /// Fused multiply-add. Computes `(self * a) + b` with only one rounding
     /// error, yielding a more accurate result than an unfused multiply-add.
     ///
-    /// Using `mul_add` can be more performant than an unfused multiply-add if
-    /// the target architecture has a dedicated `fma` CPU instruction.
+    /// Using `mul_add` *may* be more performant than an unfused multiply-add if
+    /// the target architecture has a dedicated `fma` CPU instruction. However,
+    /// this is not always true, and will be heavily dependant on designing
+    /// algorithms with specific target hardware in mind.
     ///
     /// # Examples
     ///
@@ -895,14 +897,13 @@ impl f64 {
     /// # Examples
     ///
     /// ```
-    /// #![feature(clamp)]
     /// assert!((-3.0f64).clamp(-2.0, 1.0) == -2.0);
     /// assert!((0.0f64).clamp(-2.0, 1.0) == 0.0);
     /// assert!((2.0f64).clamp(-2.0, 1.0) == 1.0);
     /// assert!((f64::NAN).clamp(-2.0, 1.0).is_nan());
     /// ```
     #[must_use = "method returns a new number and does not mutate the original value"]
-    #[unstable(feature = "clamp", issue = "44095")]
+    #[stable(feature = "clamp", since = "1.50.0")]
     #[inline]
     pub fn clamp(self, min: f64, max: f64) -> f64 {
         assert!(min <= max);
diff --git a/library/std/src/ffi/c_str.rs b/library/std/src/ffi/c_str.rs
index 8c6d6c80402..60b642a6dba 100644
--- a/library/std/src/ffi/c_str.rs
+++ b/library/std/src/ffi/c_str.rs
@@ -1266,7 +1266,7 @@ impl CStr {
     /// behavior when `ptr` is used inside the `unsafe` block:
     ///
     /// ```no_run
-    /// # #![allow(unused_must_use)] #![cfg_attr(not(bootstrap), allow(temporary_cstring_as_ptr))]
+    /// # #![allow(unused_must_use)] #![allow(temporary_cstring_as_ptr)]
     /// use std::ffi::CString;
     ///
     /// let ptr = CString::new("Hello").expect("CString::new failed").as_ptr();
diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs
index a4123cc15b8..e2d4f2e6a56 100644
--- a/library/std/src/fs.rs
+++ b/library/std/src/fs.rs
@@ -8,7 +8,7 @@
 #![stable(feature = "rust1", since = "1.0.0")]
 #![deny(unsafe_op_in_unsafe_fn)]
 
-#[cfg(all(test, not(any(target_os = "cloudabi", target_os = "emscripten", target_env = "sgx"))))]
+#[cfg(all(test, not(any(target_os = "emscripten", target_env = "sgx"))))]
 mod tests;
 
 use crate::ffi::OsString;
@@ -1698,12 +1698,14 @@ pub fn copy<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> io::Result<u64> {
 
 /// Creates a new hard link on the filesystem.
 ///
-/// The `dst` path will be a link pointing to the `src` path. Note that systems
-/// often require these two paths to both be located on the same filesystem.
+/// The `link` path will be a link pointing to the `original` path. Note that
+/// systems often require these two paths to both be located on the same
+/// filesystem.
 ///
-/// If `src` names a symbolic link, it is platform-specific whether the symbolic
-/// link is followed. On platforms where it's possible to not follow it, it is
-/// not followed, and the created hard link points to the symbolic link itself.
+/// If `original` names a symbolic link, it is platform-specific whether the
+/// symbolic link is followed. On platforms where it's possible to not follow
+/// it, it is not followed, and the created hard link points to the symbolic
+/// link itself.
 ///
 /// # Platform-specific behavior
 ///
@@ -1718,7 +1720,7 @@ pub fn copy<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> io::Result<u64> {
 /// This function will return an error in the following situations, but is not
 /// limited to just these cases:
 ///
-/// * The `src` path is not a file or doesn't exist.
+/// * The `original` path is not a file or doesn't exist.
 ///
 /// # Examples
 ///
@@ -1731,13 +1733,13 @@ pub fn copy<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> io::Result<u64> {
 /// }
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
-pub fn hard_link<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> io::Result<()> {
-    fs_imp::link(src.as_ref(), dst.as_ref())
+pub fn hard_link<P: AsRef<Path>, Q: AsRef<Path>>(original: P, link: Q) -> io::Result<()> {
+    fs_imp::link(original.as_ref(), link.as_ref())
 }
 
 /// Creates a new symbolic link on the filesystem.
 ///
-/// The `dst` path will be a symbolic link pointing to the `src` path.
+/// The `link` path will be a symbolic link pointing to the `original` path.
 /// On Windows, this will be a file symlink, not a directory symlink;
 /// for this reason, the platform-specific [`std::os::unix::fs::symlink`]
 /// and [`std::os::windows::fs::symlink_file`] or [`symlink_dir`] should be
@@ -1763,8 +1765,8 @@ pub fn hard_link<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> io::Result<(
     reason = "replaced with std::os::unix::fs::symlink and \
               std::os::windows::fs::{symlink_file, symlink_dir}"
 )]
-pub fn soft_link<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> io::Result<()> {
-    fs_imp::symlink(src.as_ref(), dst.as_ref())
+pub fn soft_link<P: AsRef<Path>, Q: AsRef<Path>>(original: P, link: Q) -> io::Result<()> {
+    fs_imp::symlink(original.as_ref(), link.as_ref())
 }
 
 /// Reads a symbolic link, returning the file that the link points to.
diff --git a/library/std/src/io/buffered/bufwriter.rs b/library/std/src/io/buffered/bufwriter.rs
index 067ed6ba7ff..3b3399860ba 100644
--- a/library/std/src/io/buffered/bufwriter.rs
+++ b/library/std/src/io/buffered/bufwriter.rs
@@ -328,24 +328,57 @@ impl<W: Write> Write for BufWriter<W> {
     }
 
     fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
-        let total_len = bufs.iter().map(|b| b.len()).sum::<usize>();
-        if self.buf.len() + total_len > self.buf.capacity() {
-            self.flush_buf()?;
-        }
-        // FIXME: Why no len > capacity? Why not buffer len == capacity? #72919
-        if total_len >= self.buf.capacity() {
-            self.panicked = true;
-            let r = self.get_mut().write_vectored(bufs);
-            self.panicked = false;
-            r
+        if self.get_ref().is_write_vectored() {
+            let total_len = bufs.iter().map(|b| b.len()).sum::<usize>();
+            if self.buf.len() + total_len > self.buf.capacity() {
+                self.flush_buf()?;
+            }
+            if total_len >= self.buf.capacity() {
+                self.panicked = true;
+                let r = self.get_mut().write_vectored(bufs);
+                self.panicked = false;
+                r
+            } else {
+                bufs.iter().for_each(|b| self.buf.extend_from_slice(b));
+                Ok(total_len)
+            }
         } else {
-            bufs.iter().for_each(|b| self.buf.extend_from_slice(b));
-            Ok(total_len)
+            let mut iter = bufs.iter();
+            let mut total_written = if let Some(buf) = iter.by_ref().find(|&buf| !buf.is_empty()) {
+                // This is the first non-empty slice to write, so if it does
+                // not fit in the buffer, we still get to flush and proceed.
+                if self.buf.len() + buf.len() > self.buf.capacity() {
+                    self.flush_buf()?;
+                }
+                if buf.len() >= self.buf.capacity() {
+                    // The slice is at least as large as the buffering capacity,
+                    // so it's better to write it directly, bypassing the buffer.
+                    self.panicked = true;
+                    let r = self.get_mut().write(buf);
+                    self.panicked = false;
+                    return r;
+                } else {
+                    self.buf.extend_from_slice(buf);
+                    buf.len()
+                }
+            } else {
+                return Ok(0);
+            };
+            debug_assert!(total_written != 0);
+            for buf in iter {
+                if self.buf.len() + buf.len() > self.buf.capacity() {
+                    break;
+                } else {
+                    self.buf.extend_from_slice(buf);
+                    total_written += buf.len();
+                }
+            }
+            Ok(total_written)
         }
     }
 
     fn is_write_vectored(&self) -> bool {
-        self.get_ref().is_write_vectored()
+        true
     }
 
     fn flush(&mut self) -> io::Result<()> {
diff --git a/library/std/src/io/buffered/linewritershim.rs b/library/std/src/io/buffered/linewritershim.rs
index a80d08db869..d0c859d2e0c 100644
--- a/library/std/src/io/buffered/linewritershim.rs
+++ b/library/std/src/io/buffered/linewritershim.rs
@@ -20,6 +20,12 @@ impl<'a, W: Write> LineWriterShim<'a, W> {
         Self { buffer }
     }
 
+    /// Get a reference to the inner writer (that is, the writer
+    /// wrapped by the BufWriter).
+    fn inner(&self) -> &W {
+        self.buffer.get_ref()
+    }
+
     /// Get a mutable reference to the inner writer (that is, the writer
     /// wrapped by the BufWriter). Be careful with this writer, as writes to
     /// it will bypass the buffer.
@@ -227,7 +233,7 @@ impl<'a, W: Write> Write for LineWriterShim<'a, W> {
     }
 
     fn is_write_vectored(&self) -> bool {
-        self.buffer.is_write_vectored()
+        self.inner().is_write_vectored()
     }
 
     /// Write some data into this BufReader with line buffering. This means
diff --git a/library/std/src/io/buffered/mod.rs b/library/std/src/io/buffered/mod.rs
index f9caeaf98e2..65497817f81 100644
--- a/library/std/src/io/buffered/mod.rs
+++ b/library/std/src/io/buffered/mod.rs
@@ -126,6 +126,51 @@ impl<W> IntoInnerError<W> {
     pub fn into_inner(self) -> W {
         self.0
     }
+
+    /// Consumes the [`IntoInnerError`] and returns the error which caused the call to
+    /// [`BufWriter::into_inner()`] to fail.  Unlike `error`, this can be used to
+    /// obtain ownership of the underlying error.
+    ///
+    /// # Example
+    /// ```
+    /// #![feature(io_into_inner_error_parts)]
+    /// use std::io::{BufWriter, ErrorKind, Write};
+    ///
+    /// let mut not_enough_space = [0u8; 10];
+    /// let mut stream = BufWriter::new(not_enough_space.as_mut());
+    /// write!(stream, "this cannot be actually written").unwrap();
+    /// let into_inner_err = stream.into_inner().expect_err("now we discover it's too small");
+    /// let err = into_inner_err.into_error();
+    /// assert_eq!(err.kind(), ErrorKind::WriteZero);
+    /// ```
+    #[unstable(feature = "io_into_inner_error_parts", issue = "79704")]
+    pub fn into_error(self) -> Error {
+        self.1
+    }
+
+    /// Consumes the [`IntoInnerError`] and returns the error which caused the call to
+    /// [`BufWriter::into_inner()`] to fail, and the underlying writer.
+    ///
+    /// This can be used to simply obtain ownership of the underlying error; it can also be used for
+    /// advanced error recovery.
+    ///
+    /// # Example
+    /// ```
+    /// #![feature(io_into_inner_error_parts)]
+    /// use std::io::{BufWriter, ErrorKind, Write};
+    ///
+    /// let mut not_enough_space = [0u8; 10];
+    /// let mut stream = BufWriter::new(not_enough_space.as_mut());
+    /// write!(stream, "this cannot be actually written").unwrap();
+    /// let into_inner_err = stream.into_inner().expect_err("now we discover it's too small");
+    /// let (err, recovered_writer) = into_inner_err.into_parts();
+    /// assert_eq!(err.kind(), ErrorKind::WriteZero);
+    /// assert_eq!(recovered_writer.buffer(), b"t be actually written");
+    /// ```
+    #[unstable(feature = "io_into_inner_error_parts", issue = "79704")]
+    pub fn into_parts(self) -> (Error, W) {
+        (self.1, self.0)
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/library/std/src/io/impls.rs b/library/std/src/io/impls.rs
index 6b3c86cb0df..00bf8b9af73 100644
--- a/library/std/src/io/impls.rs
+++ b/library/std/src/io/impls.rs
@@ -306,6 +306,10 @@ impl BufRead for &[u8] {
 ///
 /// Note that writing updates the slice to point to the yet unwritten part.
 /// The slice will be empty when it has been completely overwritten.
+///
+/// If the number of bytes to be written exceeds the size of the slice, write operations will
+/// return short writes: ultimately, `Ok(0)`; in this situation, `write_all` returns an error of
+/// kind `ErrorKind::WriteZero`.
 #[stable(feature = "rust1", since = "1.0.0")]
 impl Write for &mut [u8] {
     #[inline]
diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs
index 703c3755b63..dfbf6c3f244 100644
--- a/library/std/src/io/mod.rs
+++ b/library/std/src/io/mod.rs
@@ -1307,10 +1307,10 @@ pub trait Write {
         default_write_vectored(|b| self.write(b), bufs)
     }
 
-    /// Determines if this `Write`er has an efficient [`write_vectored`]
+    /// Determines if this `Write`r has an efficient [`write_vectored`]
     /// implementation.
     ///
-    /// If a `Write`er does not override the default [`write_vectored`]
+    /// If a `Write`r does not override the default [`write_vectored`]
     /// implementation, code using it may want to avoid the method all together
     /// and coalesce writes into a single buffer for higher performance.
     ///
diff --git a/library/std/src/io/stdio.rs b/library/std/src/io/stdio.rs
index 6ea7704d422..1160011f352 100644
--- a/library/std/src/io/stdio.rs
+++ b/library/std/src/io/stdio.rs
@@ -9,6 +9,7 @@ use crate::cell::{Cell, RefCell};
 use crate::fmt;
 use crate::io::{self, BufReader, Initializer, IoSlice, IoSliceMut, LineWriter};
 use crate::lazy::SyncOnceCell;
+use crate::pin::Pin;
 use crate::sync::atomic::{AtomicBool, Ordering};
 use crate::sync::{Arc, Mutex, MutexGuard};
 use crate::sys::stdio;
@@ -490,7 +491,7 @@ pub struct Stdout {
     // FIXME: this should be LineWriter or BufWriter depending on the state of
     //        stdout (tty or not). Note that if this is not line buffered it
     //        should also flush-on-panic or some form of flush-on-abort.
-    inner: &'static ReentrantMutex<RefCell<LineWriter<StdoutRaw>>>,
+    inner: Pin<&'static ReentrantMutex<RefCell<LineWriter<StdoutRaw>>>>,
 }
 
 /// A locked reference to the `Stdout` handle.
@@ -550,25 +551,29 @@ pub struct StdoutLock<'a> {
 pub fn stdout() -> Stdout {
     static INSTANCE: SyncOnceCell<ReentrantMutex<RefCell<LineWriter<StdoutRaw>>>> =
         SyncOnceCell::new();
+
+    fn cleanup() {
+        if let Some(instance) = INSTANCE.get() {
+            // Flush the data and disable buffering during shutdown
+            // by replacing the line writer by one with zero
+            // buffering capacity.
+            // We use try_lock() instead of lock(), because someone
+            // might have leaked a StdoutLock, which would
+            // otherwise cause a deadlock here.
+            if let Some(lock) = Pin::static_ref(instance).try_lock() {
+                *lock.borrow_mut() = LineWriter::with_capacity(0, stdout_raw());
+            }
+        }
+    }
+
     Stdout {
-        inner: INSTANCE.get_or_init(|| unsafe {
-            let _ = sys_common::at_exit(|| {
-                if let Some(instance) = INSTANCE.get() {
-                    // Flush the data and disable buffering during shutdown
-                    // by replacing the line writer by one with zero
-                    // buffering capacity.
-                    // We use try_lock() instead of lock(), because someone
-                    // might have leaked a StdoutLock, which would
-                    // otherwise cause a deadlock here.
-                    if let Some(lock) = instance.try_lock() {
-                        *lock.borrow_mut() = LineWriter::with_capacity(0, stdout_raw());
-                    }
-                }
-            });
-            let r = ReentrantMutex::new(RefCell::new(LineWriter::new(stdout_raw())));
-            r.init();
-            r
-        }),
+        inner: Pin::static_ref(&INSTANCE).get_or_init_pin(
+            || unsafe {
+                let _ = sys_common::at_exit(cleanup);
+                ReentrantMutex::new(RefCell::new(LineWriter::new(stdout_raw())))
+            },
+            |mutex| unsafe { mutex.init() },
+        ),
     }
 }
 
@@ -700,7 +705,7 @@ impl fmt::Debug for StdoutLock<'_> {
 /// an error.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Stderr {
-    inner: &'static ReentrantMutex<RefCell<StderrRaw>>,
+    inner: Pin<&'static ReentrantMutex<RefCell<StderrRaw>>>,
 }
 
 /// A locked reference to the `Stderr` handle.
@@ -756,21 +761,16 @@ pub struct StderrLock<'a> {
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn stderr() -> Stderr {
-    // Note that unlike `stdout()` we don't use `Lazy` here which registers a
-    // destructor. Stderr is not buffered nor does the `stderr_raw` type consume
-    // any owned resources, so there's no need to run any destructors at some
-    // point in the future.
-    //
-    // This has the added benefit of allowing `stderr` to be usable during
-    // process shutdown as well!
+    // Note that unlike `stdout()` we don't use `at_exit` here to register a
+    // destructor. Stderr is not buffered , so there's no need to run a
+    // destructor for flushing the buffer
     static INSTANCE: SyncOnceCell<ReentrantMutex<RefCell<StderrRaw>>> = SyncOnceCell::new();
 
     Stderr {
-        inner: INSTANCE.get_or_init(|| unsafe {
-            let r = ReentrantMutex::new(RefCell::new(stderr_raw()));
-            r.init();
-            r
-        }),
+        inner: Pin::static_ref(&INSTANCE).get_or_init_pin(
+            || unsafe { ReentrantMutex::new(RefCell::new(stderr_raw())) },
+            |mutex| unsafe { mutex.init() },
+        ),
     }
 }
 
diff --git a/library/std/src/keyword_docs.rs b/library/std/src/keyword_docs.rs
index b990b785703..8174cf5c373 100644
--- a/library/std/src/keyword_docs.rs
+++ b/library/std/src/keyword_docs.rs
@@ -20,19 +20,30 @@
 /// explicitly using `as` allows a few more coercions that aren't allowed implicitly, such as
 /// changing the type of a raw pointer or turning closures into raw pointers.
 ///
-/// `as` is also used to rename imports in [`use`] and [`extern crate`] statements:
+/// `as` can be seen as the primitive for `From` and `Into`: `as` only works  with primitives
+/// (`u8`, `bool`, `str`, pointers, ...) whereas `From` and `Into`  also works with types like
+/// `String` or `Vec`.
+///
+/// `as` can also be used with the `_` placeholder when the destination type can be inferred. Note
+/// that this can cause inference breakage and usually such code should use an explicit type for
+/// both clarity and stability. This is most useful when converting pointers using `as *const _` or
+/// `as *mut _` though the [`cast`][const-cast] method is recommended over `as *const _` and it is
+/// [the same][mut-cast] for `as *mut _`: those methods make the intent clearer.
+///
+/// `as` is also used to rename imports in [`use`] and [`extern crate`][`crate`] statements:
 ///
 /// ```
 /// # #[allow(unused_imports)]
 /// use std::{mem as memory, net as network};
 /// // Now you can use the names `memory` and `network` to refer to `std::mem` and `std::net`.
 /// ```
-///
 /// For more information on what `as` is capable of, see the [Reference].
 ///
 /// [Reference]: ../reference/expressions/operator-expr.html#type-cast-expressions
+/// [`crate`]: keyword.crate.html
 /// [`use`]: keyword.use.html
-/// [`extern crate`]: keyword.crate.html
+/// [const-cast]: primitive.pointer.html#method.cast
+/// [mut-cast]: primitive.pointer.html#method.cast-1
 mod as_keyword {}
 
 #[doc(keyword = "break")]
@@ -554,8 +565,12 @@ mod fn_keyword {}
 ///
 /// For more information on for-loops, see the [Rust book] or the [Reference].
 ///
+/// See also, [`loop`], [`while`].
+///
 /// [`in`]: keyword.in.html
 /// [`impl`]: keyword.impl.html
+/// [`loop`]: keyword.loop.html
+/// [`while`]: keyword.while.html
 /// [higher-ranked trait bounds]: ../reference/trait-bounds.html#higher-ranked-trait-bounds
 /// [Rust book]:
 /// ../book/ch03-05-control-flow.html#looping-through-a-collection-with-for
@@ -707,8 +722,8 @@ mod impl_keyword {}
 ///
 /// ## Literal Examples:
 ///
-///    * `for _ **in** 1..3 {}` - Iterate over an exclusive range up to but excluding 3.
-///    * `for _ **in** 1..=3 {}` - Iterate over an inclusive range up to and including 3.
+///    * `for _ in 1..3 {}` - Iterate over an exclusive range up to but excluding 3.
+///    * `for _ in 1..=3 {}` - Iterate over an inclusive range up to and including 3.
 ///
 /// (Read more about [range patterns])
 ///
@@ -831,6 +846,8 @@ mod let_keyword {}
 ///
 /// For more information on `while` and loops in general, see the [reference].
 ///
+/// See also, [`for`], [`loop`].
+///
 /// [`for`]: keyword.for.html
 /// [`loop`]: keyword.loop.html
 /// [reference]: ../reference/expressions/loop-expr.html#predicate-loops
@@ -879,6 +896,10 @@ mod while_keyword {}
 ///
 /// For more information on `loop` and loops in general, see the [Reference].
 ///
+/// See also, [`for`], [`while`].
+///
+/// [`for`]: keyword.for.html
+/// [`while`]: keyword.while.html
 /// [Reference]: ../reference/expressions/loop-expr.html
 mod loop_keyword {}
 
@@ -1739,7 +1760,7 @@ mod super_keyword {}
 ///
 /// # Differences between the 2015 and 2018 editions
 ///
-/// In the 2015 edition parameters pattern where not needed for traits:
+/// In the 2015 edition the parameters pattern was not needed for traits:
 ///
 /// ```rust,edition2015
 /// trait Tr {
diff --git a/library/std/src/lazy.rs b/library/std/src/lazy.rs
index e0095e64faf..68f57958bb2 100644
--- a/library/std/src/lazy.rs
+++ b/library/std/src/lazy.rs
@@ -10,6 +10,7 @@ use crate::{
     mem::MaybeUninit,
     ops::{Deref, Drop},
     panic::{RefUnwindSafe, UnwindSafe},
+    pin::Pin,
     sync::Once,
 };
 
@@ -297,6 +298,60 @@ impl<T> SyncOnceCell<T> {
         Ok(unsafe { self.get_unchecked() })
     }
 
+    /// Internal-only API that gets the contents of the cell, initializing it
+    /// in two steps with `f` and `g` if the cell was empty.
+    ///
+    /// `f` is called to construct the value, which is then moved into the cell
+    /// and given as a (pinned) mutable reference to `g` to finish
+    /// initialization.
+    ///
+    /// This allows `g` to inspect an manipulate the value after it has been
+    /// moved into its final place in the cell, but before the cell is
+    /// considered initialized.
+    ///
+    /// # Panics
+    ///
+    /// If `f` or `g` panics, the panic is propagated to the caller, and the
+    /// cell remains uninitialized.
+    ///
+    /// With the current implementation, if `g` panics, the value from `f` will
+    /// not be dropped. This should probably be fixed if this is ever used for
+    /// a type where this matters.
+    ///
+    /// It is an error to reentrantly initialize the cell from `f`. The exact
+    /// outcome is unspecified. Current implementation deadlocks, but this may
+    /// be changed to a panic in the future.
+    pub(crate) fn get_or_init_pin<F, G>(self: Pin<&Self>, f: F, g: G) -> Pin<&T>
+    where
+        F: FnOnce() -> T,
+        G: FnOnce(Pin<&mut T>),
+    {
+        if let Some(value) = self.get_ref().get() {
+            // SAFETY: The inner value was already initialized, and will not be
+            // moved anymore.
+            return unsafe { Pin::new_unchecked(value) };
+        }
+
+        let slot = &self.value;
+
+        // Ignore poisoning from other threads
+        // If another thread panics, then we'll be able to run our closure
+        self.once.call_once_force(|_| {
+            let value = f();
+            // SAFETY: We use the Once (self.once) to guarantee unique access
+            // to the UnsafeCell (slot).
+            let value: &mut T = unsafe { (&mut *slot.get()).write(value) };
+            // SAFETY: The value has been written to its final place in
+            // self.value. We do not to move it anymore, which we promise here
+            // with a Pin<&mut T>.
+            g(unsafe { Pin::new_unchecked(value) });
+        });
+
+        // SAFETY: The inner value has been initialized, and will not be moved
+        // anymore.
+        unsafe { Pin::new_unchecked(self.get_ref().get_unchecked()) }
+    }
+
     /// Consumes the `SyncOnceCell`, returning the wrapped value. Returns
     /// `None` if the cell was empty.
     ///
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index db523f05e01..fc48997f1bb 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -206,12 +206,13 @@
 #![needs_panic_runtime]
 // std may use features in a platform-specific way
 #![allow(unused_features)]
-#![cfg_attr(not(bootstrap), feature(rustc_allow_const_fn_unstable))]
+#![feature(rustc_allow_const_fn_unstable)]
 #![cfg_attr(test, feature(internal_output_capture, print_internals, update_panic_count))]
 #![cfg_attr(
     all(target_vendor = "fortanix", target_env = "sgx"),
     feature(slice_index_methods, coerce_unsized, sgx_platform)
 )]
+#![deny(rustc::existing_doc_keyword)]
 #![cfg_attr(all(test, target_vendor = "fortanix", target_env = "sgx"), feature(fixed_size_array))]
 // std is implemented with unstable features, many of which are internal
 // compiler details that will never be stable
@@ -227,7 +228,6 @@
 #![feature(asm)]
 #![feature(associated_type_bounds)]
 #![feature(atomic_mut_ptr)]
-#![feature(bool_to_option)]
 #![feature(box_syntax)]
 #![feature(c_variadic)]
 #![feature(cfg_accessible)]
@@ -235,7 +235,6 @@
 #![feature(cfg_target_thread_local)]
 #![feature(char_error_internals)]
 #![feature(char_internals)]
-#![feature(clamp)]
 #![feature(concat_idents)]
 #![feature(const_cstr_unchecked)]
 #![feature(const_fn_floating_point_arithmetic)]
@@ -267,6 +266,7 @@
 #![feature(format_args_nl)]
 #![feature(gen_future)]
 #![feature(generator_trait)]
+#![feature(get_mut_unchecked)]
 #![feature(global_asm)]
 #![feature(hashmap_internals)]
 #![feature(int_error_internals)]
@@ -288,21 +288,23 @@
 #![feature(nll)]
 #![feature(nonnull_slice_from_raw_parts)]
 #![feature(once_cell)]
-#![feature(optin_builtin_traits)]
+#![cfg_attr(bootstrap, feature(optin_builtin_traits))]
+#![cfg_attr(not(bootstrap), feature(auto_traits))]
 #![feature(or_patterns)]
 #![feature(panic_info_message)]
 #![feature(panic_internals)]
 #![feature(panic_unwind)]
+#![feature(pin_static_ref)]
 #![feature(prelude_import)]
 #![feature(ptr_internals)]
 #![feature(raw)]
 #![feature(raw_ref_macros)]
 #![feature(ready_macro)]
-#![feature(refcell_take)]
 #![feature(rustc_attrs)]
 #![feature(rustc_private)]
 #![feature(shrink_to)]
 #![feature(slice_concat_ext)]
+#![feature(slice_fill)]
 #![feature(slice_internals)]
 #![feature(slice_ptr_get)]
 #![feature(slice_ptr_len)]
@@ -312,6 +314,7 @@
 #![feature(stdsimd)]
 #![feature(stmt_expr_attributes)]
 #![feature(str_internals)]
+#![feature(str_split_once)]
 #![feature(test)]
 #![feature(thread_local)]
 #![feature(thread_local_internals)]
@@ -324,7 +327,6 @@
 #![feature(unsafe_block_in_unsafe_fn)]
 #![feature(unsafe_cell_get_mut)]
 #![feature(unsafe_cell_raw_get)]
-#![cfg_attr(bootstrap, feature(untagged_unions))]
 #![feature(unwind_attributes)]
 #![feature(vec_into_raw_parts)]
 #![feature(wake_trait)]
diff --git a/library/std/src/macros.rs b/library/std/src/macros.rs
index 57649d6f8f2..de072e83dfc 100644
--- a/library/std/src/macros.rs
+++ b/library/std/src/macros.rs
@@ -8,6 +8,7 @@
 #[macro_export]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[allow_internal_unstable(libstd_sys_internals)]
+#[cfg_attr(not(any(bootstrap, test)), rustc_diagnostic_item = "std_panic_macro")]
 macro_rules! panic {
     () => ({ $crate::panic!("explicit panic") });
     ($msg:expr $(,)?) => ({ $crate::rt::begin_panic($msg) });
diff --git a/library/std/src/net/ip.rs b/library/std/src/net/ip.rs
index bb3ece4c273..87bbd33bc01 100644
--- a/library/std/src/net/ip.rs
+++ b/library/std/src/net/ip.rs
@@ -263,8 +263,9 @@ impl IpAddr {
     /// assert_eq!(IpAddr::V4(Ipv4Addr::new(203, 0, 113, 6)).is_ipv4(), true);
     /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0)).is_ipv4(), false);
     /// ```
+    #[rustc_const_stable(feature = "const_ip", since = "1.50.0")]
     #[stable(feature = "ipaddr_checker", since = "1.16.0")]
-    pub fn is_ipv4(&self) -> bool {
+    pub const fn is_ipv4(&self) -> bool {
         matches!(self, IpAddr::V4(_))
     }
 
@@ -281,8 +282,9 @@ impl IpAddr {
     /// assert_eq!(IpAddr::V4(Ipv4Addr::new(203, 0, 113, 6)).is_ipv6(), false);
     /// assert_eq!(IpAddr::V6(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0)).is_ipv6(), true);
     /// ```
+    #[rustc_const_stable(feature = "const_ip", since = "1.50.0")]
     #[stable(feature = "ipaddr_checker", since = "1.16.0")]
-    pub fn is_ipv6(&self) -> bool {
+    pub const fn is_ipv6(&self) -> bool {
         matches!(self, IpAddr::V6(_))
     }
 }
@@ -1043,8 +1045,7 @@ impl Ipv6Addr {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_stable(feature = "const_ipv6", since = "1.32.0")]
-    #[cfg_attr(not(bootstrap), rustc_allow_const_fn_unstable(const_fn_transmute))]
-    #[cfg_attr(bootstrap, allow_internal_unstable(const_fn_transmute))]
+    #[rustc_allow_const_fn_unstable(const_fn_transmute)]
     pub const fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> Ipv6Addr {
         let addr16 = [
             a.to_be(),
diff --git a/library/std/src/net/ip/tests.rs b/library/std/src/net/ip/tests.rs
index d9fbdd1b5e7..44fb3adf070 100644
--- a/library/std/src/net/ip/tests.rs
+++ b/library/std/src/net/ip/tests.rs
@@ -936,4 +936,10 @@ fn ip_const() {
 
     const IS_MULTICAST: bool = IP_ADDRESS.is_multicast();
     assert!(!IS_MULTICAST);
+
+    const IS_IP_V4: bool = IP_ADDRESS.is_ipv4();
+    assert!(IS_IP_V4);
+
+    const IS_IP_V6: bool = IP_ADDRESS.is_ipv6();
+    assert!(!IS_IP_V6);
 }
diff --git a/library/std/src/net/tcp.rs b/library/std/src/net/tcp.rs
index 58c6343ea34..325acf0b979 100644
--- a/library/std/src/net/tcp.rs
+++ b/library/std/src/net/tcp.rs
@@ -1,6 +1,6 @@
 #![deny(unsafe_op_in_unsafe_fn)]
 
-#[cfg(all(test, not(any(target_os = "cloudabi", target_os = "emscripten"))))]
+#[cfg(all(test, not(target_os = "emscripten")))]
 mod tests;
 
 use crate::io::prelude::*;
diff --git a/library/std/src/net/udp.rs b/library/std/src/net/udp.rs
index 17e3e4497c4..2377a76a33d 100644
--- a/library/std/src/net/udp.rs
+++ b/library/std/src/net/udp.rs
@@ -1,4 +1,4 @@
-#[cfg(all(test, not(any(target_os = "cloudabi", target_os = "emscripten", target_env = "sgx"))))]
+#[cfg(all(test, not(any(target_os = "emscripten", target_env = "sgx"))))]
 mod tests;
 
 use crate::fmt;
diff --git a/library/std/src/num/tests.rs b/library/std/src/num/tests.rs
index 2f50b73f490..df0df3f23f7 100644
--- a/library/std/src/num/tests.rs
+++ b/library/std/src/num/tests.rs
@@ -75,8 +75,8 @@ fn test_checked_mul() {
 
 macro_rules! test_is_power_of_two {
     ($test_name:ident, $T:ident) => {
+        #[test]
         fn $test_name() {
-            #![test]
             assert_eq!((0 as $T).is_power_of_two(), false);
             assert_eq!((1 as $T).is_power_of_two(), true);
             assert_eq!((2 as $T).is_power_of_two(), true);
@@ -96,8 +96,8 @@ test_is_power_of_two! { test_is_power_of_two_uint, usize }
 
 macro_rules! test_next_power_of_two {
     ($test_name:ident, $T:ident) => {
+        #[test]
         fn $test_name() {
-            #![test]
             assert_eq!((0 as $T).next_power_of_two(), 1);
             let mut next_power = 1;
             for i in 1 as $T..40 {
@@ -118,8 +118,8 @@ test_next_power_of_two! { test_next_power_of_two_uint, usize }
 
 macro_rules! test_checked_next_power_of_two {
     ($test_name:ident, $T:ident) => {
+        #[test]
         fn $test_name() {
-            #![test]
             assert_eq!((0 as $T).checked_next_power_of_two(), Some(1));
             let smax = $T::MAX >> 1;
             assert_eq!(smax.checked_next_power_of_two(), Some(smax + 1));
diff --git a/library/std/src/primitive_docs.rs b/library/std/src/primitive_docs.rs
index 83a282c8cd6..7aca5451ebc 100644
--- a/library/std/src/primitive_docs.rs
+++ b/library/std/src/primitive_docs.rs
@@ -198,7 +198,7 @@ mod prim_bool {}
 /// words, they can't return `!` from every code path. As an example, this code doesn't compile:
 ///
 /// ```compile_fail
-/// use core::ops::Add;
+/// use std::ops::Add;
 ///
 /// fn foo() -> impl Add<u32> {
 ///     unimplemented!()
@@ -208,7 +208,7 @@ mod prim_bool {}
 /// But this code does:
 ///
 /// ```
-/// use core::ops::Add;
+/// use std::ops::Add;
 ///
 /// fn foo() -> impl Add<u32> {
 ///     if true {
@@ -489,6 +489,10 @@ mod prim_pointer {}
 /// * A repeat expression `[x; N]`, which produces an array with `N` copies of `x`.
 ///   The type of `x` must be [`Copy`].
 ///
+/// Note that `[expr; 0]` is allowed, and produces an empty array.
+/// This will still evaluate `expr`, however, and immediately drop the resulting value, so
+/// be mindful of side effects.
+///
 /// Arrays of *any* size implement the following traits if the element type allows it:
 ///
 /// - [`Copy`]
diff --git a/library/std/src/process.rs b/library/std/src/process.rs
index 2c7ed4614bc..fb78e62834a 100644
--- a/library/std/src/process.rs
+++ b/library/std/src/process.rs
@@ -97,7 +97,7 @@
 #![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"))))]
+#[cfg(all(test, not(any(target_os = "emscripten", target_env = "sgx"))))]
 mod tests;
 
 use crate::io::prelude::*;
@@ -1779,6 +1779,7 @@ pub fn exit(code: i32) -> ! {
 ///
 /// [panic hook]: crate::panic::set_hook
 #[stable(feature = "process_abort", since = "1.17.0")]
+#[cold]
 pub fn abort() -> ! {
     crate::sys::abort_internal();
 }
diff --git a/library/std/src/sys/cloudabi/abi/bitflags.rs b/library/std/src/sys/cloudabi/abi/bitflags.rs
deleted file mode 100644
index 2383277ad72..00000000000
--- a/library/std/src/sys/cloudabi/abi/bitflags.rs
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright (c) 2018 Nuxi (https://nuxi.nl/) and contributors.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions
-// are met:
-// 1. Redistributions of source code must retain the above copyright
-//    notice, this list of conditions and the following disclaimer.
-// 2. Redistributions in binary form must reproduce the above copyright
-//    notice, this list of conditions and the following disclaimer in the
-//    documentation and/or other materials provided with the distribution.
-//
-// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-// ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-// SUCH DAMAGE.
-
-#[cfg(feature = "bitflags")]
-use bitflags::bitflags;
-
-// Minimal implementation of bitflags! in case we can't depend on the bitflags
-// crate. Only implements `bits()` and a `from_bits_truncate()` that doesn't
-// actually truncate.
-#[cfg(not(feature = "bitflags"))]
-macro_rules! bitflags {
-  (
-    $(#[$attr:meta])*
-    pub struct $name:ident: $type:ty {
-      $($(#[$const_attr:meta])* const $const:ident = $val:expr;)*
-    }
-  ) => {
-    $(#[$attr])*
-    #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
-    pub struct $name { bits: $type }
-    impl $name {
-      $($(#[$const_attr])* pub const $const: $name = $name{ bits: $val };)*
-      pub fn bits(&self) -> $type { self.bits }
-      pub fn from_bits_truncate(bits: $type) -> Self { $name{ bits } }
-    }
-  }
-}
diff --git a/library/std/src/sys/cloudabi/abi/cloudabi.rs b/library/std/src/sys/cloudabi/abi/cloudabi.rs
deleted file mode 100644
index d67f0f81a9f..00000000000
--- a/library/std/src/sys/cloudabi/abi/cloudabi.rs
+++ /dev/null
@@ -1,2954 +0,0 @@
-// Copyright (c) 2016-2017 Nuxi <https://nuxi.nl/> and contributors.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions
-// are met:
-// 1. Redistributions of source code must retain the above copyright
-//    notice, this list of conditions and the following disclaimer.
-// 2. Redistributions in binary form must reproduce the above copyright
-//    notice, this list of conditions and the following disclaimer in the
-//    documentation and/or other materials provided with the distribution.
-//
-// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-// ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
-// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-// SUCH DAMAGE.
-//
-// This file is automatically generated. Do not edit.
-//
-// Source: https://github.com/NuxiNL/cloudabi
-
-// Appease Rust's tidy.
-// ignore-tidy-linelength
-
-//! **PLEASE NOTE: This entire crate including this
-//! documentation is automatically generated from
-//! [`cloudabi.txt`](https://github.com/NuxiNL/cloudabi/blob/master/cloudabi.txt)**
-//!
-//! # Nuxi CloudABI
-//!
-//! CloudABI is what you get if you take POSIX, add capability-based
-//! security, and remove everything that's incompatible with that. The
-//! result is a minimal ABI consisting of only 49 syscalls.
-//!
-//! CloudABI doesn't have its own kernel, but instead is implemented in existing
-//! kernels: FreeBSD has CloudABI support for x86-64 and arm64, and [a patch-set
-//! for NetBSD](https://github.com/NuxiNL/netbsd) and [a patch-set for
-//! Linux](https://github.com/NuxiNL/linux) are available as well. This means that
-//! CloudABI binaries can be executed on different operating systems, without any
-//! modification.
-//!
-//! ## Capability-Based Security
-//!
-//! Capability-based security means that processes can only perform
-//! actions that have no global impact. Processes cannot open files by
-//! their absolute path, cannot open network connections, and cannot
-//! observe global system state such as the process table.
-//!
-//! The capabilities of a process are fully determined by its set of open
-//! file descriptors (fds). For example, files can only be opened if the
-//! process already has a file descriptor to a directory the file is in.
-//!
-//! Unlike in POSIX, where processes are normally started with file
-//! descriptors 0, 1, and 2 reserved for standard input, output, and
-//! error, CloudABI does not reserve any file descriptor numbers for
-//! specific purposes.
-//!
-//! In CloudABI, a process depends on its parent process to launch it with
-//! the right set of resources, since the process will not be able to open
-//! any new resources. For example, a simple static web server would need
-//! to be started with a file descriptor to a [TCP
-//! listener](https://github.com/NuxiNL/flower), and a file descriptor to
-//! the directory for which to serve files. The web server will then be
-//! unable to do anything other than reading files in that directory, and
-//! process incoming network connections.
-//!
-//! So, unknown CloudABI binaries can safely be executed without the need
-//! for containers, virtual machines, or other sandboxing technologies.
-//!
-//! Watch [Ed Schouten's Talk at
-//! 32C3](https://www.youtube.com/watch?v=3N29vrPoDv8) for more
-//! information about what capability-based security for UNIX means.
-//!
-//! ## Cloudlibc
-//!
-//! [Cloudlibc](https://github.com/NuxiNL/cloudlibc) is an implementation
-//! of the C standard library, without all CloudABI-incompatible
-//! functions. For example, Cloudlibc does not have `printf`, but does
-//! have `fprintf`. It does not have `open`, but does have `openat`.
-//!
-//! ## CloudABI-Ports
-//!
-//! [CloudABI-Ports](https://github.com/NuxiNL/cloudabi-ports) is a
-//! collection of ports of commonly used libraries and applications to
-//! CloudABI. It contains software such as `zlib`, `libpng`, `boost`,
-//! `memcached`, and much more. The software is patched to not depend on
-//! any global state, such as files in `/etc` or `/dev`, using `open()`,
-//! etc.
-//!
-//! ## Using CloudABI
-//!
-//! Instructions for using CloudABI (including kernel modules/patches,
-//! toolchain, and ports) are available for several operating systems:
-//!
-//! - [Arch Linux](https://nuxi.nl/cloudabi/archlinux/)
-//! - [Debian, Ubuntu, and other Debian derivatives](https://nuxi.nl/cloudabi/debian/)
-//! - [FreeBSD, PC-BSD and DragonFly BSD](https://nuxi.nl/cloudabi/freebsd/)
-//! - [Mac OS X](https://nuxi.nl/cloudabi/mac/)
-//! - [NetBSD](https://nuxi.nl/cloudabi/netbsd/)
-//!
-//! ## Specification of the ABI
-//!
-//! The entire ABI is specified in a file called
-//! [`cloudabi.txt`](https://github.com/NuxiNL/cloudabi/blob/master/cloudabi.txt),
-//! from which all
-//! [headers](https://github.com/NuxiNL/cloudabi/tree/master/headers)
-//! and documentation (including the one you're reading now) is generated.
-
-#![no_std]
-#![allow(non_camel_case_types)]
-#![allow(deprecated)] // FIXME: using `mem::uninitialized()`
-
-include!("bitflags.rs");
-
-/// File or memory access pattern advisory information.
-#[repr(u8)]
-#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
-#[non_exhaustive]
-pub enum advice {
-    /// The application expects that it will not access the
-    /// specified data in the near future.
-    DONTNEED = 1,
-    /// The application expects to access the specified data
-    /// once and then not reuse it thereafter.
-    NOREUSE = 2,
-    /// The application has no advice to give on its behavior
-    /// with respect to the specified data.
-    NORMAL = 3,
-    /// The application expects to access the specified data
-    /// in a random order.
-    RANDOM = 4,
-    /// The application expects to access the specified data
-    /// sequentially from lower offsets to higher offsets.
-    SEQUENTIAL = 5,
-    /// The application expects to access the specified data
-    /// in the near future.
-    WILLNEED = 6,
-}
-
-/// Enumeration describing the kind of value stored in [`auxv`].
-#[repr(u32)]
-#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
-#[non_exhaustive]
-pub enum auxtype {
-    /// Base address of the binary argument data provided to
-    /// [`proc_exec()`](fn.proc_exec.html).
-    ARGDATA = 256,
-    /// Length of the binary argument data provided to
-    /// [`proc_exec()`](fn.proc_exec.html).
-    ARGDATALEN = 257,
-    /// Base address at which the executable is placed in
-    /// memory.
-    BASE = 7,
-    /// Base address of a buffer of random data that may be
-    /// used for non-cryptographic purposes, for example as a
-    /// canary for stack smashing protection.
-    CANARY = 258,
-    /// Length of a buffer of random data that may be used
-    /// for non-cryptographic purposes, for example as a
-    /// canary for stack smashing protection.
-    CANARYLEN = 259,
-    /// Number of CPUs that the system this process is running
-    /// on has.
-    NCPUS = 260,
-    /// Terminator of the auxiliary vector.
-    NULL = 0,
-    /// Smallest memory object size for which individual
-    /// memory protection controls can be configured.
-    PAGESZ = 6,
-    /// Address of the first ELF program header of the
-    /// executable.
-    PHDR = 3,
-    /// Number of ELF program headers of the executable.
-    PHNUM = 4,
-    /// Identifier of the process.
-    ///
-    /// This environment does not provide any simple numerical
-    /// process identifiers, for the reason that these are not
-    /// useful in distributed contexts. Instead, processes are
-    /// identified by a UUID.
-    ///
-    /// This record should point to sixteen bytes of binary
-    /// data, containing a version 4 UUID (fully random).
-    PID = 263,
-    /// Address of the ELF header of the vDSO.
-    ///
-    /// The vDSO is a shared library that is mapped in the
-    /// address space of the process. It provides entry points
-    /// for every system call supported by the environment,
-    /// all having a corresponding symbol that is prefixed
-    /// with `cloudabi_sys_`. System calls should be invoked
-    /// through these entry points.
-    ///
-    /// The first advantage of letting processes call into a
-    /// vDSO to perform system calls instead of raising
-    /// hardware traps is that it allows for easy emulation of
-    /// executables on top of existing operating systems. The
-    /// second advantage is that in cases where an operating
-    /// system provides native support for CloudABI executables,
-    /// it may still implement partial userspace
-    /// implementations of these system calls to improve
-    /// performance (e.g., [`clock_time_get()`](fn.clock_time_get.html)). It also provides
-    /// a more dynamic way of adding, removing or replacing
-    /// system calls.
-    SYSINFO_EHDR = 262,
-    /// Thread ID of the initial thread of the process.
-    TID = 261,
-}
-
-/// Identifiers for clocks.
-#[repr(u32)]
-#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
-#[non_exhaustive]
-pub enum clockid {
-    /// The system-wide monotonic clock, which is defined as a
-    /// clock measuring real time, whose value cannot be
-    /// adjusted and which cannot have negative clock jumps.
-    ///
-    /// The epoch of this clock is undefined. The absolute
-    /// time value of this clock therefore has no meaning.
-    MONOTONIC = 1,
-    /// The CPU-time clock associated with the current
-    /// process.
-    PROCESS_CPUTIME_ID = 2,
-    /// The system-wide clock measuring real time. Time value
-    /// zero corresponds with 1970-01-01T00:00:00Z.
-    REALTIME = 3,
-    /// The CPU-time clock associated with the current thread.
-    THREAD_CPUTIME_ID = 4,
-}
-
-/// A userspace condition variable.
-#[repr(C)]
-#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
-pub struct condvar(pub u32);
-/// The condition variable is in its initial state. There
-/// are no threads waiting to be woken up. If the
-/// condition variable has any other value, the kernel
-/// must be called to wake up any sleeping threads.
-pub const CONDVAR_HAS_NO_WAITERS: condvar = condvar(0);
-
-/// Identifier for a device containing a file system. Can be used
-/// in combination with [`inode`] to uniquely identify a file on the
-/// local system.
-#[repr(C)]
-#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
-pub struct device(pub u64);
-
-/// A reference to the offset of a directory entry.
-#[repr(C)]
-#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
-pub struct dircookie(pub u64);
-/// Permanent reference to the first directory entry
-/// within a directory.
-pub const DIRCOOKIE_START: dircookie = dircookie(0);
-
-/// Error codes returned by system calls.
-///
-/// Not all of these error codes are returned by the system calls
-/// provided by this environment, but are either used in userspace
-/// exclusively or merely provided for alignment with POSIX.
-#[repr(u16)]
-#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
-#[non_exhaustive]
-pub enum errno {
-    /// No error occurred. System call completed successfully.
-    SUCCESS = 0,
-    /// Argument list too long.
-    TOOBIG = 1,
-    /// Permission denied.
-    ACCES = 2,
-    /// Address in use.
-    ADDRINUSE = 3,
-    /// Address not available.
-    ADDRNOTAVAIL = 4,
-    /// Address family not supported.
-    AFNOSUPPORT = 5,
-    /// Resource unavailable, or operation would block.
-    AGAIN = 6,
-    /// Connection already in progress.
-    ALREADY = 7,
-    /// Bad file descriptor.
-    BADF = 8,
-    /// Bad message.
-    BADMSG = 9,
-    /// Device or resource busy.
-    BUSY = 10,
-    /// Operation canceled.
-    CANCELED = 11,
-    /// No child processes.
-    CHILD = 12,
-    /// Connection aborted.
-    CONNABORTED = 13,
-    /// Connection refused.
-    CONNREFUSED = 14,
-    /// Connection reset.
-    CONNRESET = 15,
-    /// Resource deadlock would occur.
-    DEADLK = 16,
-    /// Destination address required.
-    DESTADDRREQ = 17,
-    /// Mathematics argument out of domain of function.
-    DOM = 18,
-    /// Reserved.
-    DQUOT = 19,
-    /// File exists.
-    EXIST = 20,
-    /// Bad address.
-    FAULT = 21,
-    /// File too large.
-    FBIG = 22,
-    /// Host is unreachable.
-    HOSTUNREACH = 23,
-    /// Identifier removed.
-    IDRM = 24,
-    /// Illegal byte sequence.
-    ILSEQ = 25,
-    /// Operation in progress.
-    INPROGRESS = 26,
-    /// Interrupted function.
-    INTR = 27,
-    /// Invalid argument.
-    INVAL = 28,
-    /// I/O error.
-    IO = 29,
-    /// Socket is connected.
-    ISCONN = 30,
-    /// Is a directory.
-    ISDIR = 31,
-    /// Too many levels of symbolic links.
-    LOOP = 32,
-    /// File descriptor value too large.
-    MFILE = 33,
-    /// Too many links.
-    MLINK = 34,
-    /// Message too large.
-    MSGSIZE = 35,
-    /// Reserved.
-    MULTIHOP = 36,
-    /// Filename too long.
-    NAMETOOLONG = 37,
-    /// Network is down.
-    NETDOWN = 38,
-    /// Connection aborted by network.
-    NETRESET = 39,
-    /// Network unreachable.
-    NETUNREACH = 40,
-    /// Too many files open in system.
-    NFILE = 41,
-    /// No buffer space available.
-    NOBUFS = 42,
-    /// No such device.
-    NODEV = 43,
-    /// No such file or directory.
-    NOENT = 44,
-    /// Executable file format error.
-    NOEXEC = 45,
-    /// No locks available.
-    NOLCK = 46,
-    /// Reserved.
-    NOLINK = 47,
-    /// Not enough space.
-    NOMEM = 48,
-    /// No message of the desired type.
-    NOMSG = 49,
-    /// Protocol not available.
-    NOPROTOOPT = 50,
-    /// No space left on device.
-    NOSPC = 51,
-    /// Function not supported.
-    NOSYS = 52,
-    /// The socket is not connected.
-    NOTCONN = 53,
-    /// Not a directory or a symbolic link to a directory.
-    NOTDIR = 54,
-    /// Directory not empty.
-    NOTEMPTY = 55,
-    /// State not recoverable.
-    NOTRECOVERABLE = 56,
-    /// Not a socket.
-    NOTSOCK = 57,
-    /// Not supported, or operation not supported on socket.
-    NOTSUP = 58,
-    /// Inappropriate I/O control operation.
-    NOTTY = 59,
-    /// No such device or address.
-    NXIO = 60,
-    /// Value too large to be stored in data type.
-    OVERFLOW = 61,
-    /// Previous owner died.
-    OWNERDEAD = 62,
-    /// Operation not permitted.
-    PERM = 63,
-    /// Broken pipe.
-    PIPE = 64,
-    /// Protocol error.
-    PROTO = 65,
-    /// Protocol not supported.
-    PROTONOSUPPORT = 66,
-    /// Protocol wrong type for socket.
-    PROTOTYPE = 67,
-    /// Result too large.
-    RANGE = 68,
-    /// Read-only file system.
-    ROFS = 69,
-    /// Invalid seek.
-    SPIPE = 70,
-    /// No such process.
-    SRCH = 71,
-    /// Reserved.
-    STALE = 72,
-    /// Connection timed out.
-    TIMEDOUT = 73,
-    /// Text file busy.
-    TXTBSY = 74,
-    /// Cross-device link.
-    XDEV = 75,
-    /// Extension: Capabilities insufficient.
-    NOTCAPABLE = 76,
-}
-
-bitflags! {
-  /// The state of the file descriptor subscribed to with
-  /// [`FD_READ`](enum.eventtype.html#variant.FD_READ) or [`FD_WRITE`](enum.eventtype.html#variant.FD_WRITE).
-  #[repr(C)]
-  pub struct eventrwflags: u16 {
-    /// The peer of this socket has closed or disconnected.
-    const HANGUP = 0x0001;
-  }
-}
-
-/// Type of a subscription to an event or its occurrence.
-#[repr(u8)]
-#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
-#[non_exhaustive]
-pub enum eventtype {
-    /// The time value of clock [`subscription.union.clock.clock_id`](struct.subscription_clock.html#structfield.clock_id)
-    /// has reached timestamp [`subscription.union.clock.timeout`](struct.subscription_clock.html#structfield.timeout).
-    CLOCK = 1,
-    /// Condition variable [`subscription.union.condvar.condvar`](struct.subscription_condvar.html#structfield.condvar) has
-    /// been woken up and [`subscription.union.condvar.lock`](struct.subscription_condvar.html#structfield.lock) has been
-    /// acquired for writing.
-    CONDVAR = 2,
-    /// File descriptor [`subscription.union.fd_readwrite.fd`](struct.subscription_fd_readwrite.html#structfield.fd) has
-    /// data available for reading. This event always triggers
-    /// for regular files.
-    FD_READ = 3,
-    /// File descriptor [`subscription.union.fd_readwrite.fd`](struct.subscription_fd_readwrite.html#structfield.fd) has
-    /// capacity available for writing. This event always
-    /// triggers for regular files.
-    FD_WRITE = 4,
-    /// Lock [`subscription.union.lock.lock`](struct.subscription_lock.html#structfield.lock) has been acquired for
-    /// reading.
-    LOCK_RDLOCK = 5,
-    /// Lock [`subscription.union.lock.lock`](struct.subscription_lock.html#structfield.lock) has been acquired for
-    /// writing.
-    LOCK_WRLOCK = 6,
-    /// The process associated with process descriptor
-    /// [`subscription.union.proc_terminate.fd`](struct.subscription_proc_terminate.html#structfield.fd) has terminated.
-    PROC_TERMINATE = 7,
-}
-
-/// Exit code generated by a process when exiting.
-pub type exitcode = u32;
-
-/// A file descriptor number.
-///
-/// Unlike on POSIX-compliant systems, none of the file descriptor
-/// numbers are reserved for a purpose (e.g., stdin, stdout,
-/// stderr). Operating systems are not required to allocate new
-/// file descriptors in ascending order.
-#[repr(C)]
-#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
-pub struct fd(pub u32);
-/// Returned to the child process by [`proc_fork()`](fn.proc_fork.html).
-pub const PROCESS_CHILD: fd = fd(0xffffffff);
-/// Passed to [`mem_map()`](fn.mem_map.html) when creating a mapping to
-/// anonymous memory.
-pub const MAP_ANON_FD: fd = fd(0xffffffff);
-
-bitflags! {
-  /// File descriptor flags.
-  #[repr(C)]
-  pub struct fdflags: u16 {
-    /// Append mode: Data written to the file is always
-    /// appended to the file's end.
-    const APPEND   = 0x0001;
-    /// Write according to synchronized I/O data integrity
-    /// completion. Only the data stored in the file is
-    /// synchronized.
-    const DSYNC    = 0x0002;
-    /// Non-blocking mode.
-    const NONBLOCK = 0x0004;
-    /// Synchronized read I/O operations.
-    const RSYNC    = 0x0008;
-    /// Write according to synchronized I/O file integrity
-    /// completion. In addition to synchronizing the data
-    /// stored in the file, the system may also synchronously
-    /// update the file's metadata.
-    const SYNC     = 0x0010;
-  }
-}
-
-bitflags! {
-  /// Which file descriptor attributes to adjust.
-  #[repr(C)]
-  pub struct fdsflags: u16 {
-    /// Adjust the file descriptor flags stored in
-    /// [`fdstat.fs_flags`](struct.fdstat.html#structfield.fs_flags).
-    const FLAGS  = 0x0001;
-    /// Restrict the rights of the file descriptor to the
-    /// rights stored in [`fdstat.fs_rights_base`](struct.fdstat.html#structfield.fs_rights_base) and
-    /// [`fdstat.fs_rights_inheriting`](struct.fdstat.html#structfield.fs_rights_inheriting).
-    const RIGHTS = 0x0002;
-  }
-}
-
-/// Relative offset within a file.
-pub type filedelta = i64;
-
-/// Non-negative file size or length of a region within a file.
-pub type filesize = u64;
-
-/// The type of a file descriptor or file.
-#[repr(u8)]
-#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
-#[non_exhaustive]
-pub enum filetype {
-    /// The type of the file descriptor or file is unknown or
-    /// is different from any of the other types specified.
-    UNKNOWN = 0,
-    /// The file descriptor or file refers to a block device
-    /// inode.
-    BLOCK_DEVICE = 16,
-    /// The file descriptor or file refers to a character
-    /// device inode.
-    CHARACTER_DEVICE = 17,
-    /// The file descriptor or file refers to a directory
-    /// inode.
-    DIRECTORY = 32,
-    /// The file descriptor refers to a process handle.
-    PROCESS = 80,
-    /// The file descriptor or file refers to a regular file
-    /// inode.
-    REGULAR_FILE = 96,
-    /// The file descriptor refers to a shared memory object.
-    SHARED_MEMORY = 112,
-    /// The file descriptor or file refers to a datagram
-    /// socket.
-    SOCKET_DGRAM = 128,
-    /// The file descriptor or file refers to a byte-stream
-    /// socket.
-    SOCKET_STREAM = 130,
-    /// The file refers to a symbolic link inode.
-    SYMBOLIC_LINK = 144,
-}
-
-bitflags! {
-  /// Which file attributes to adjust.
-  #[repr(C)]
-  pub struct fsflags: u16 {
-    /// Adjust the last data access timestamp to the value
-    /// stored in [`filestat.st_atim`](struct.filestat.html#structfield.st_atim).
-    const ATIM     = 0x0001;
-    /// Adjust the last data access timestamp to the time
-    /// of clock [`REALTIME`](enum.clockid.html#variant.REALTIME).
-    const ATIM_NOW = 0x0002;
-    /// Adjust the last data modification timestamp to the
-    /// value stored in [`filestat.st_mtim`](struct.filestat.html#structfield.st_mtim).
-    const MTIM     = 0x0004;
-    /// Adjust the last data modification timestamp to the
-    /// time of clock [`REALTIME`](enum.clockid.html#variant.REALTIME).
-    const MTIM_NOW = 0x0008;
-    /// Truncate or extend the file to the size stored in
-    /// [`filestat.st_size`](struct.filestat.html#structfield.st_size).
-    const SIZE     = 0x0010;
-  }
-}
-
-/// File serial number that is unique within its file system.
-#[repr(C)]
-#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
-pub struct inode(pub u64);
-
-/// Number of hard links to an inode.
-pub type linkcount = u32;
-
-/// A userspace read-recursive readers-writer lock, similar to a
-/// Linux futex or a FreeBSD umtx.
-#[repr(C)]
-#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
-pub struct lock(pub u32);
-/// Value indicating that the lock is in its initial
-/// unlocked state.
-pub const LOCK_UNLOCKED: lock = lock(0x00000000);
-/// Bitmask indicating that the lock is write-locked. If
-/// set, the lower 30 bits of the lock contain the
-/// identifier of the thread that owns the write lock.
-/// Otherwise, the lower 30 bits of the lock contain the
-/// number of acquired read locks.
-pub const LOCK_WRLOCKED: lock = lock(0x40000000);
-/// Bitmask indicating that the lock is either read locked
-/// or write locked, and that one or more threads have
-/// their execution suspended, waiting to acquire the
-/// lock. The last owner of the lock must call the
-/// kernel to unlock.
-///
-/// When the lock is acquired for reading and this bit is
-/// set, it means that one or more threads are attempting
-/// to acquire this lock for writing. In that case, other
-/// threads should only acquire additional read locks if
-/// suspending execution would cause a deadlock. It is
-/// preferred to suspend execution, as this prevents
-/// starvation of writers.
-pub const LOCK_KERNEL_MANAGED: lock = lock(0x80000000);
-/// Value indicating that the lock is in an incorrect
-/// state. A lock cannot be in its initial unlocked state,
-/// while also managed by the kernel.
-pub const LOCK_BOGUS: lock = lock(0x80000000);
-
-bitflags! {
-  /// Flags determining the method of how paths are resolved.
-  #[repr(C)]
-  pub struct lookupflags: u32 {
-    /// As long as the resolved path corresponds to a symbolic
-    /// link, it is expanded.
-    const SYMLINK_FOLLOW = 0x00000001;
-  }
-}
-
-bitflags! {
-  /// Memory mapping flags.
-  #[repr(C)]
-  pub struct mflags: u8 {
-    /// Instead of mapping the contents of the file provided,
-    /// create a mapping to anonymous memory. The file
-    /// descriptor argument must be set to [`MAP_ANON_FD`](constant.MAP_ANON_FD.html),
-    /// and the offset must be set to zero.
-    const ANON    = 0x01;
-    /// Require that the mapping is performed at the base
-    /// address provided.
-    const FIXED   = 0x02;
-    /// Changes are private.
-    const PRIVATE = 0x04;
-    /// Changes are shared.
-    const SHARED  = 0x08;
-  }
-}
-
-bitflags! {
-  /// Memory page protection options.
-  ///
-  /// This implementation enforces the `W^X` property: Pages cannot be
-  /// mapped for execution while also mapped for writing.
-  #[repr(C)]
-  pub struct mprot: u8 {
-    /// Page can be executed.
-    const EXEC  = 0x01;
-    /// Page can be written.
-    const WRITE = 0x02;
-    /// Page can be read.
-    const READ  = 0x04;
-  }
-}
-
-bitflags! {
-  /// Methods of synchronizing memory with physical storage.
-  #[repr(C)]
-  pub struct msflags: u8 {
-    /// Performs asynchronous writes.
-    const ASYNC      = 0x01;
-    /// Invalidates cached data.
-    const INVALIDATE = 0x02;
-    /// Performs synchronous writes.
-    const SYNC       = 0x04;
-  }
-}
-
-/// Specifies the number of threads sleeping on a condition
-/// variable that should be woken up.
-pub type nthreads = u32;
-
-bitflags! {
-  /// Open flags used by [`file_open()`](fn.file_open.html).
-  #[repr(C)]
-  pub struct oflags: u16 {
-    /// Create file if it does not exist.
-    const CREAT     = 0x0001;
-    /// Fail if not a directory.
-    const DIRECTORY = 0x0002;
-    /// Fail if file already exists.
-    const EXCL      = 0x0004;
-    /// Truncate file to size 0.
-    const TRUNC     = 0x0008;
-  }
-}
-
-bitflags! {
-  /// Flags provided to [`sock_recv()`](fn.sock_recv.html).
-  #[repr(C)]
-  pub struct riflags: u16 {
-    /// Returns the message without removing it from the
-    /// socket's receive queue.
-    const PEEK    = 0x0004;
-    /// On byte-stream sockets, block until the full amount
-    /// of data can be returned.
-    const WAITALL = 0x0010;
-  }
-}
-
-bitflags! {
-  /// File descriptor rights, determining which actions may be
-  /// performed.
-  #[repr(C)]
-  pub struct rights: u64 {
-    /// The right to invoke [`fd_datasync()`](fn.fd_datasync.html).
-    ///
-    /// If [`FILE_OPEN`](struct.rights.html#associatedconstant.FILE_OPEN) is set, includes the right to
-    /// invoke [`file_open()`](fn.file_open.html) with [`DSYNC`](struct.fdflags.html#associatedconstant.DSYNC).
-    const FD_DATASYNC           = 0x0000000000000001;
-    /// The right to invoke [`fd_read()`](fn.fd_read.html) and [`sock_recv()`](fn.sock_recv.html).
-    ///
-    /// If [`MEM_MAP`](struct.rights.html#associatedconstant.MEM_MAP) is set, includes the right to
-    /// invoke [`mem_map()`](fn.mem_map.html) with memory protection option
-    /// [`READ`](struct.mprot.html#associatedconstant.READ).
-    ///
-    /// If [`FD_SEEK`](struct.rights.html#associatedconstant.FD_SEEK) is set, includes the right to invoke
-    /// [`fd_pread()`](fn.fd_pread.html).
-    const FD_READ               = 0x0000000000000002;
-    /// The right to invoke [`fd_seek()`](fn.fd_seek.html). This flag implies
-    /// [`FD_TELL`](struct.rights.html#associatedconstant.FD_TELL).
-    const FD_SEEK               = 0x0000000000000004;
-    /// The right to invoke [`fd_stat_put()`](fn.fd_stat_put.html) with
-    /// [`FLAGS`](struct.fdsflags.html#associatedconstant.FLAGS).
-    const FD_STAT_PUT_FLAGS     = 0x0000000000000008;
-    /// The right to invoke [`fd_sync()`](fn.fd_sync.html).
-    ///
-    /// If [`FILE_OPEN`](struct.rights.html#associatedconstant.FILE_OPEN) is set, includes the right to
-    /// invoke [`file_open()`](fn.file_open.html) with [`RSYNC`](struct.fdflags.html#associatedconstant.RSYNC) and
-    /// [`DSYNC`](struct.fdflags.html#associatedconstant.DSYNC).
-    const FD_SYNC               = 0x0000000000000010;
-    /// The right to invoke [`fd_seek()`](fn.fd_seek.html) in such a way that the
-    /// file offset remains unaltered (i.e., [`CUR`](enum.whence.html#variant.CUR) with
-    /// offset zero).
-    const FD_TELL               = 0x0000000000000020;
-    /// The right to invoke [`fd_write()`](fn.fd_write.html) and [`sock_send()`](fn.sock_send.html).
-    ///
-    /// If [`MEM_MAP`](struct.rights.html#associatedconstant.MEM_MAP) is set, includes the right to
-    /// invoke [`mem_map()`](fn.mem_map.html) with memory protection option
-    /// [`WRITE`](struct.mprot.html#associatedconstant.WRITE).
-    ///
-    /// If [`FD_SEEK`](struct.rights.html#associatedconstant.FD_SEEK) is set, includes the right to
-    /// invoke [`fd_pwrite()`](fn.fd_pwrite.html).
-    const FD_WRITE              = 0x0000000000000040;
-    /// The right to invoke [`file_advise()`](fn.file_advise.html).
-    const FILE_ADVISE           = 0x0000000000000080;
-    /// The right to invoke [`file_allocate()`](fn.file_allocate.html).
-    const FILE_ALLOCATE         = 0x0000000000000100;
-    /// The right to invoke [`file_create()`](fn.file_create.html) with
-    /// [`DIRECTORY`](enum.filetype.html#variant.DIRECTORY).
-    const FILE_CREATE_DIRECTORY = 0x0000000000000200;
-    /// If [`FILE_OPEN`](struct.rights.html#associatedconstant.FILE_OPEN) is set, the right to invoke
-    /// [`file_open()`](fn.file_open.html) with [`CREAT`](struct.oflags.html#associatedconstant.CREAT).
-    const FILE_CREATE_FILE      = 0x0000000000000400;
-    /// The right to invoke [`file_link()`](fn.file_link.html) with the file
-    /// descriptor as the source directory.
-    const FILE_LINK_SOURCE      = 0x0000000000001000;
-    /// The right to invoke [`file_link()`](fn.file_link.html) with the file
-    /// descriptor as the target directory.
-    const FILE_LINK_TARGET      = 0x0000000000002000;
-    /// The right to invoke [`file_open()`](fn.file_open.html).
-    const FILE_OPEN             = 0x0000000000004000;
-    /// The right to invoke [`file_readdir()`](fn.file_readdir.html).
-    const FILE_READDIR          = 0x0000000000008000;
-    /// The right to invoke [`file_readlink()`](fn.file_readlink.html).
-    const FILE_READLINK         = 0x0000000000010000;
-    /// The right to invoke [`file_rename()`](fn.file_rename.html) with the file
-    /// descriptor as the source directory.
-    const FILE_RENAME_SOURCE    = 0x0000000000020000;
-    /// The right to invoke [`file_rename()`](fn.file_rename.html) with the file
-    /// descriptor as the target directory.
-    const FILE_RENAME_TARGET    = 0x0000000000040000;
-    /// The right to invoke [`file_stat_fget()`](fn.file_stat_fget.html).
-    const FILE_STAT_FGET        = 0x0000000000080000;
-    /// The right to invoke [`file_stat_fput()`](fn.file_stat_fput.html) with
-    /// [`SIZE`](struct.fsflags.html#associatedconstant.SIZE).
-    ///
-    /// If [`FILE_OPEN`](struct.rights.html#associatedconstant.FILE_OPEN) is set, includes the right to
-    /// invoke [`file_open()`](fn.file_open.html) with [`TRUNC`](struct.oflags.html#associatedconstant.TRUNC).
-    const FILE_STAT_FPUT_SIZE   = 0x0000000000100000;
-    /// The right to invoke [`file_stat_fput()`](fn.file_stat_fput.html) with
-    /// [`ATIM`](struct.fsflags.html#associatedconstant.ATIM), [`ATIM_NOW`](struct.fsflags.html#associatedconstant.ATIM_NOW), [`MTIM`](struct.fsflags.html#associatedconstant.MTIM),
-    /// and [`MTIM_NOW`](struct.fsflags.html#associatedconstant.MTIM_NOW).
-    const FILE_STAT_FPUT_TIMES  = 0x0000000000200000;
-    /// The right to invoke [`file_stat_get()`](fn.file_stat_get.html).
-    const FILE_STAT_GET         = 0x0000000000400000;
-    /// The right to invoke [`file_stat_put()`](fn.file_stat_put.html) with
-    /// [`ATIM`](struct.fsflags.html#associatedconstant.ATIM), [`ATIM_NOW`](struct.fsflags.html#associatedconstant.ATIM_NOW), [`MTIM`](struct.fsflags.html#associatedconstant.MTIM),
-    /// and [`MTIM_NOW`](struct.fsflags.html#associatedconstant.MTIM_NOW).
-    const FILE_STAT_PUT_TIMES   = 0x0000000000800000;
-    /// The right to invoke [`file_symlink()`](fn.file_symlink.html).
-    const FILE_SYMLINK          = 0x0000000001000000;
-    /// The right to invoke [`file_unlink()`](fn.file_unlink.html).
-    const FILE_UNLINK           = 0x0000000002000000;
-    /// The right to invoke [`mem_map()`](fn.mem_map.html) with [`mprot`] set to
-    /// zero.
-    const MEM_MAP               = 0x0000000004000000;
-    /// If [`MEM_MAP`](struct.rights.html#associatedconstant.MEM_MAP) is set, the right to invoke
-    /// [`mem_map()`](fn.mem_map.html) with [`EXEC`](struct.mprot.html#associatedconstant.EXEC).
-    const MEM_MAP_EXEC          = 0x0000000008000000;
-    /// If [`FD_READ`](struct.rights.html#associatedconstant.FD_READ) is set, includes the right to
-    /// invoke [`poll()`](fn.poll.html) to subscribe to [`FD_READ`](enum.eventtype.html#variant.FD_READ).
-    ///
-    /// If [`FD_WRITE`](struct.rights.html#associatedconstant.FD_WRITE) is set, includes the right to
-    /// invoke [`poll()`](fn.poll.html) to subscribe to [`FD_WRITE`](enum.eventtype.html#variant.FD_WRITE).
-    const POLL_FD_READWRITE     = 0x0000000010000000;
-    /// The right to invoke [`poll()`](fn.poll.html) to subscribe to
-    /// [`PROC_TERMINATE`](enum.eventtype.html#variant.PROC_TERMINATE).
-    const POLL_PROC_TERMINATE   = 0x0000000040000000;
-    /// The right to invoke [`proc_exec()`](fn.proc_exec.html).
-    const PROC_EXEC             = 0x0000000100000000;
-    /// The right to invoke [`sock_shutdown()`](fn.sock_shutdown.html).
-    const SOCK_SHUTDOWN         = 0x0000008000000000;
-  }
-}
-
-bitflags! {
-  /// Flags returned by [`sock_recv()`](fn.sock_recv.html).
-  #[repr(C)]
-  pub struct roflags: u16 {
-    /// Returned by [`sock_recv()`](fn.sock_recv.html): List of file descriptors
-    /// has been truncated.
-    const FDS_TRUNCATED  = 0x0001;
-    /// Returned by [`sock_recv()`](fn.sock_recv.html): Message data has been
-    /// truncated.
-    const DATA_TRUNCATED = 0x0008;
-  }
-}
-
-/// Indicates whether an object is stored in private or shared
-/// memory.
-#[repr(u8)]
-#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
-#[non_exhaustive]
-pub enum scope {
-    /// The object is stored in private memory.
-    PRIVATE = 4,
-    /// The object is stored in shared memory.
-    SHARED = 8,
-}
-
-bitflags! {
-  /// Which channels on a socket need to be shut down.
-  #[repr(C)]
-  pub struct sdflags: u8 {
-    /// Disables further receive operations.
-    const RD = 0x01;
-    /// Disables further send operations.
-    const WR = 0x02;
-  }
-}
-
-bitflags! {
-  /// Flags provided to [`sock_send()`](fn.sock_send.html). As there are currently no flags
-  /// defined, it must be set to zero.
-  #[repr(C)]
-  pub struct siflags: u16 {
-    const DEFAULT = 0;
-  }
-}
-
-/// Signal condition.
-#[repr(u8)]
-#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
-#[non_exhaustive]
-pub enum signal {
-    /// Process abort signal.
-    ///
-    /// Action: Terminates the process.
-    ABRT = 1,
-    /// Alarm clock.
-    ///
-    /// Action: Terminates the process.
-    ALRM = 2,
-    /// Access to an undefined portion of a memory object.
-    ///
-    /// Action: Terminates the process.
-    BUS = 3,
-    /// Child process terminated, stopped, or continued.
-    ///
-    /// Action: Ignored.
-    CHLD = 4,
-    /// Continue executing, if stopped.
-    ///
-    /// Action: Continues executing, if stopped.
-    CONT = 5,
-    /// Erroneous arithmetic operation.
-    ///
-    /// Action: Terminates the process.
-    FPE = 6,
-    /// Hangup.
-    ///
-    /// Action: Terminates the process.
-    HUP = 7,
-    /// Illegal instruction.
-    ///
-    /// Action: Terminates the process.
-    ILL = 8,
-    /// Terminate interrupt signal.
-    ///
-    /// Action: Terminates the process.
-    INT = 9,
-    /// Kill.
-    ///
-    /// Action: Terminates the process.
-    KILL = 10,
-    /// Write on a pipe with no one to read it.
-    ///
-    /// Action: Ignored.
-    PIPE = 11,
-    /// Terminal quit signal.
-    ///
-    /// Action: Terminates the process.
-    QUIT = 12,
-    /// Invalid memory reference.
-    ///
-    /// Action: Terminates the process.
-    SEGV = 13,
-    /// Stop executing.
-    ///
-    /// Action: Stops executing.
-    STOP = 14,
-    /// Bad system call.
-    ///
-    /// Action: Terminates the process.
-    SYS = 15,
-    /// Termination signal.
-    ///
-    /// Action: Terminates the process.
-    TERM = 16,
-    /// Trace/breakpoint trap.
-    ///
-    /// Action: Terminates the process.
-    TRAP = 17,
-    /// Terminal stop signal.
-    ///
-    /// Action: Stops executing.
-    TSTP = 18,
-    /// Background process attempting read.
-    ///
-    /// Action: Stops executing.
-    TTIN = 19,
-    /// Background process attempting write.
-    ///
-    /// Action: Stops executing.
-    TTOU = 20,
-    /// High bandwidth data is available at a socket.
-    ///
-    /// Action: Ignored.
-    URG = 21,
-    /// User-defined signal 1.
-    ///
-    /// Action: Terminates the process.
-    USR1 = 22,
-    /// User-defined signal 2.
-    ///
-    /// Action: Terminates the process.
-    USR2 = 23,
-    /// Virtual timer expired.
-    ///
-    /// Action: Terminates the process.
-    VTALRM = 24,
-    /// CPU time limit exceeded.
-    ///
-    /// Action: Terminates the process.
-    XCPU = 25,
-    /// File size limit exceeded.
-    ///
-    /// Action: Terminates the process.
-    XFSZ = 26,
-}
-
-bitflags! {
-  /// Flags determining how the timestamp provided in
-  /// [`subscription.union.clock.timeout`](struct.subscription_clock.html#structfield.timeout) should be interpreted.
-  #[repr(C)]
-  pub struct subclockflags: u16 {
-    /// If set, treat the timestamp provided in
-    /// [`subscription.union.clock.timeout`](struct.subscription_clock.html#structfield.timeout) as an absolute timestamp
-    /// of clock [`subscription.union.clock.clock_id`](struct.subscription_clock.html#structfield.clock_id).
-    ///
-    /// If clear, treat the timestamp provided in
-    /// [`subscription.union.clock.timeout`](struct.subscription_clock.html#structfield.timeout) relative to the current
-    /// time value of clock [`subscription.union.clock.clock_id`](struct.subscription_clock.html#structfield.clock_id).
-    const ABSTIME = 0x0001;
-  }
-}
-
-bitflags! {
-  /// Flags influencing the method of polling for read or writing on
-  /// a file descriptor.
-  #[repr(C)]
-  pub struct subrwflags: u16 {
-    /// Deprecated. Must be set by callers and ignored by
-    /// implementations.
-    const POLL = 0x0001;
-  }
-}
-
-/// Unique system-local identifier of a thread. This identifier is
-/// only valid during the lifetime of the thread.
-///
-/// Threads must be aware of their thread identifier, as it is
-/// written it into locks when acquiring them for writing. It is
-/// not advised to use these identifiers for any other purpose.
-///
-/// As the thread identifier is also stored in [`lock`] when
-/// [`LOCK_WRLOCKED`](constant.LOCK_WRLOCKED.html) is set, the top two bits of the thread
-/// must always be set to zero.
-#[repr(C)]
-#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
-pub struct tid(pub u32);
-
-/// Timestamp in nanoseconds.
-pub type timestamp = u64;
-
-bitflags! {
-  /// Specifies whether files are unlinked or directories are
-  /// removed.
-  #[repr(C)]
-  pub struct ulflags: u8 {
-    /// If set, removes a directory. Otherwise, unlinks any
-    /// non-directory file.
-    const REMOVEDIR = 0x01;
-  }
-}
-
-/// User-provided value that can be attached to objects that is
-/// retained when extracted from the kernel.
-pub type userdata = u64;
-
-/// Relative to which position the offset of the file descriptor
-/// should be set.
-#[repr(u8)]
-#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
-#[non_exhaustive]
-pub enum whence {
-    /// Seek relative to current position.
-    CUR = 1,
-    /// Seek relative to end-of-file.
-    END = 2,
-    /// Seek relative to start-of-file.
-    SET = 3,
-}
-
-/// Auxiliary vector entry.
-///
-/// The auxiliary vector is a list of key-value pairs that is
-/// provided to the process on startup. Unlike structures, it is
-/// extensible, as it is possible to add new records later on.
-/// The auxiliary vector is always terminated by an entry having
-/// type [`NULL`](enum.auxtype.html#variant.NULL).
-///
-/// The auxiliary vector is part of the x86-64 ABI, but is used by
-/// this environment on all architectures.
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct auxv {
-    /// The type of the auxiliary vector entry.
-    pub a_type: auxtype,
-    pub union: auxv_union,
-}
-/// A union inside `auxv`.
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub union auxv_union {
-    /// Used when `a_type` is [`ARGDATALEN`](enum.auxtype.html#variant.ARGDATALEN), [`CANARYLEN`](enum.auxtype.html#variant.CANARYLEN), [`NCPUS`](enum.auxtype.html#variant.NCPUS), [`PAGESZ`](enum.auxtype.html#variant.PAGESZ), [`PHNUM`](enum.auxtype.html#variant.PHNUM), or [`TID`](enum.auxtype.html#variant.TID).
-    /// A numerical value.
-    pub a_val: usize,
-    /// Used when `a_type` is [`ARGDATA`](enum.auxtype.html#variant.ARGDATA), [`BASE`](enum.auxtype.html#variant.BASE), [`CANARY`](enum.auxtype.html#variant.CANARY), [`PHDR`](enum.auxtype.html#variant.PHDR), [`PID`](enum.auxtype.html#variant.PID), or [`SYSINFO_EHDR`](enum.auxtype.html#variant.SYSINFO_EHDR).
-    /// A pointer value.
-    pub a_ptr: *mut (),
-}
-#[test]
-#[cfg(target_pointer_width = "32")]
-fn auxv_layout_test_32() {
-    assert_eq!(core::mem::size_of::<auxv>(), 8);
-    assert_eq!(core::mem::align_of::<auxv>(), 4);
-    unsafe {
-        let obj: auxv = core::mem::uninitialized();
-        let base = &obj as *const _ as usize;
-        assert_eq!(&obj.a_type as *const _ as usize - base, 0);
-        assert_eq!(&obj.union.a_val as *const _ as usize - base, 4);
-        assert_eq!(&obj.union.a_ptr as *const _ as usize - base, 4);
-    }
-}
-#[test]
-#[cfg(target_pointer_width = "64")]
-fn auxv_layout_test_64() {
-    assert_eq!(core::mem::size_of::<auxv>(), 16);
-    assert_eq!(core::mem::align_of::<auxv>(), 8);
-    unsafe {
-        let obj: auxv = core::mem::uninitialized();
-        let base = &obj as *const _ as usize;
-        assert_eq!(&obj.a_type as *const _ as usize - base, 0);
-        assert_eq!(&obj.union.a_val as *const _ as usize - base, 8);
-        assert_eq!(&obj.union.a_ptr as *const _ as usize - base, 8);
-    }
-}
-
-/// A region of memory for scatter/gather writes.
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct ciovec {
-    /// The address and length of the buffer to be written.
-    pub buf: (*const (), usize),
-}
-#[test]
-#[cfg(target_pointer_width = "32")]
-fn ciovec_layout_test_32() {
-    assert_eq!(core::mem::size_of::<ciovec>(), 8);
-    assert_eq!(core::mem::align_of::<ciovec>(), 4);
-    unsafe {
-        let obj: ciovec = core::mem::uninitialized();
-        let base = &obj as *const _ as usize;
-        assert_eq!(&obj.buf.0 as *const _ as usize - base, 0);
-        assert_eq!(&obj.buf.1 as *const _ as usize - base, 4);
-    }
-}
-#[test]
-#[cfg(target_pointer_width = "64")]
-fn ciovec_layout_test_64() {
-    assert_eq!(core::mem::size_of::<ciovec>(), 16);
-    assert_eq!(core::mem::align_of::<ciovec>(), 8);
-    unsafe {
-        let obj: ciovec = core::mem::uninitialized();
-        let base = &obj as *const _ as usize;
-        assert_eq!(&obj.buf.0 as *const _ as usize - base, 0);
-        assert_eq!(&obj.buf.1 as *const _ as usize - base, 8);
-    }
-}
-
-/// A directory entry.
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct dirent {
-    /// The offset of the next directory entry stored in this
-    /// directory.
-    pub d_next: dircookie,
-    /// The serial number of the file referred to by this
-    /// directory entry.
-    pub d_ino: inode,
-    /// The length of the name of the directory entry.
-    pub d_namlen: u32,
-    /// The type of the file referred to by this directory
-    /// entry.
-    pub d_type: filetype,
-}
-#[test]
-fn dirent_layout_test() {
-    assert_eq!(core::mem::size_of::<dirent>(), 24);
-    assert_eq!(core::mem::align_of::<dirent>(), 8);
-    unsafe {
-        let obj: dirent = core::mem::uninitialized();
-        let base = &obj as *const _ as usize;
-        assert_eq!(&obj.d_next as *const _ as usize - base, 0);
-        assert_eq!(&obj.d_ino as *const _ as usize - base, 8);
-        assert_eq!(&obj.d_namlen as *const _ as usize - base, 16);
-        assert_eq!(&obj.d_type as *const _ as usize - base, 20);
-    }
-}
-
-/// An event that occurred.
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct event {
-    /// User-provided value that got attached to
-    /// [`subscription.userdata`](struct.subscription.html#structfield.userdata).
-    pub userdata: userdata,
-    /// If non-zero, an error that occurred while processing
-    /// the subscription request.
-    pub error: errno,
-    /// The type of the event that occurred.
-    pub type_: eventtype,
-    pub union: event_union,
-}
-/// A union inside `event`.
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub union event_union {
-    /// Used when `type_` is [`FD_READ`](enum.eventtype.html#variant.FD_READ) or [`FD_WRITE`](enum.eventtype.html#variant.FD_WRITE).
-    pub fd_readwrite: event_fd_readwrite,
-    /// Used when `type_` is [`PROC_TERMINATE`](enum.eventtype.html#variant.PROC_TERMINATE).
-    pub proc_terminate: event_proc_terminate,
-}
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct event_fd_readwrite {
-    /// The number of bytes available
-    /// for reading or writing.
-    pub nbytes: filesize,
-    /// Obsolete.
-    pub unused: [u8; 4],
-    /// The state of the file
-    /// descriptor.
-    pub flags: eventrwflags,
-}
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct event_proc_terminate {
-    /// Obsolete.
-    pub unused: [u8; 4],
-    /// If zero, the process has
-    /// exited.
-    /// Otherwise, the signal
-    /// condition causing it to
-    /// terminated.
-    pub signal: signal,
-    /// If exited, the exit code of
-    /// the process.
-    pub exitcode: exitcode,
-}
-#[test]
-fn event_layout_test() {
-    assert_eq!(core::mem::size_of::<event>(), 32);
-    assert_eq!(core::mem::align_of::<event>(), 8);
-    unsafe {
-        let obj: event = core::mem::uninitialized();
-        let base = &obj as *const _ as usize;
-        assert_eq!(&obj.userdata as *const _ as usize - base, 0);
-        assert_eq!(&obj.error as *const _ as usize - base, 8);
-        assert_eq!(&obj.type_ as *const _ as usize - base, 10);
-        assert_eq!(&obj.union.fd_readwrite.nbytes as *const _ as usize - base, 16);
-        assert_eq!(&obj.union.fd_readwrite.unused as *const _ as usize - base, 24);
-        assert_eq!(&obj.union.fd_readwrite.flags as *const _ as usize - base, 28);
-        assert_eq!(&obj.union.proc_terminate.unused as *const _ as usize - base, 16);
-        assert_eq!(&obj.union.proc_terminate.signal as *const _ as usize - base, 20);
-        assert_eq!(&obj.union.proc_terminate.exitcode as *const _ as usize - base, 24);
-    }
-}
-
-/// File descriptor attributes.
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct fdstat {
-    /// File type.
-    pub fs_filetype: filetype,
-    /// File descriptor flags.
-    pub fs_flags: fdflags,
-    /// Rights that apply to this file descriptor.
-    pub fs_rights_base: rights,
-    /// Maximum set of rights that can be installed on new
-    /// file descriptors that are created through this file
-    /// descriptor, e.g., through [`file_open()`](fn.file_open.html).
-    pub fs_rights_inheriting: rights,
-}
-#[test]
-fn fdstat_layout_test() {
-    assert_eq!(core::mem::size_of::<fdstat>(), 24);
-    assert_eq!(core::mem::align_of::<fdstat>(), 8);
-    unsafe {
-        let obj: fdstat = core::mem::uninitialized();
-        let base = &obj as *const _ as usize;
-        assert_eq!(&obj.fs_filetype as *const _ as usize - base, 0);
-        assert_eq!(&obj.fs_flags as *const _ as usize - base, 2);
-        assert_eq!(&obj.fs_rights_base as *const _ as usize - base, 8);
-        assert_eq!(&obj.fs_rights_inheriting as *const _ as usize - base, 16);
-    }
-}
-
-/// File attributes.
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct filestat {
-    /// Device ID of device containing the file.
-    pub st_dev: device,
-    /// File serial number.
-    pub st_ino: inode,
-    /// File type.
-    pub st_filetype: filetype,
-    /// Number of hard links to the file.
-    pub st_nlink: linkcount,
-    /// For regular files, the file size in bytes. For
-    /// symbolic links, the length in bytes of the pathname
-    /// contained in the symbolic link.
-    pub st_size: filesize,
-    /// Last data access timestamp.
-    pub st_atim: timestamp,
-    /// Last data modification timestamp.
-    pub st_mtim: timestamp,
-    /// Last file status change timestamp.
-    pub st_ctim: timestamp,
-}
-#[test]
-fn filestat_layout_test() {
-    assert_eq!(core::mem::size_of::<filestat>(), 56);
-    assert_eq!(core::mem::align_of::<filestat>(), 8);
-    unsafe {
-        let obj: filestat = core::mem::uninitialized();
-        let base = &obj as *const _ as usize;
-        assert_eq!(&obj.st_dev as *const _ as usize - base, 0);
-        assert_eq!(&obj.st_ino as *const _ as usize - base, 8);
-        assert_eq!(&obj.st_filetype as *const _ as usize - base, 16);
-        assert_eq!(&obj.st_nlink as *const _ as usize - base, 20);
-        assert_eq!(&obj.st_size as *const _ as usize - base, 24);
-        assert_eq!(&obj.st_atim as *const _ as usize - base, 32);
-        assert_eq!(&obj.st_mtim as *const _ as usize - base, 40);
-        assert_eq!(&obj.st_ctim as *const _ as usize - base, 48);
-    }
-}
-
-/// A region of memory for scatter/gather reads.
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct iovec {
-    /// The address and length of the buffer to be filled.
-    pub buf: (*mut (), usize),
-}
-#[test]
-#[cfg(target_pointer_width = "32")]
-fn iovec_layout_test_32() {
-    assert_eq!(core::mem::size_of::<iovec>(), 8);
-    assert_eq!(core::mem::align_of::<iovec>(), 4);
-    unsafe {
-        let obj: iovec = core::mem::uninitialized();
-        let base = &obj as *const _ as usize;
-        assert_eq!(&obj.buf.0 as *const _ as usize - base, 0);
-        assert_eq!(&obj.buf.1 as *const _ as usize - base, 4);
-    }
-}
-#[test]
-#[cfg(target_pointer_width = "64")]
-fn iovec_layout_test_64() {
-    assert_eq!(core::mem::size_of::<iovec>(), 16);
-    assert_eq!(core::mem::align_of::<iovec>(), 8);
-    unsafe {
-        let obj: iovec = core::mem::uninitialized();
-        let base = &obj as *const _ as usize;
-        assert_eq!(&obj.buf.0 as *const _ as usize - base, 0);
-        assert_eq!(&obj.buf.1 as *const _ as usize - base, 8);
-    }
-}
-
-/// Path lookup properties.
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct lookup {
-    /// The working directory at which the resolution of the
-    /// path starts.
-    pub fd: fd,
-    /// Flags determining the method of how the path is
-    /// resolved.
-    pub flags: lookupflags,
-}
-#[test]
-fn lookup_layout_test() {
-    assert_eq!(core::mem::size_of::<lookup>(), 8);
-    assert_eq!(core::mem::align_of::<lookup>(), 4);
-    unsafe {
-        let obj: lookup = core::mem::uninitialized();
-        let base = &obj as *const _ as usize;
-        assert_eq!(&obj.fd as *const _ as usize - base, 0);
-        assert_eq!(&obj.flags as *const _ as usize - base, 4);
-    }
-}
-
-/// Entry point for a process (`_start`).
-///
-/// **auxv**:
-/// The auxiliary vector. See [`auxv`].
-pub type processentry = unsafe extern "C" fn(auxv: *const auxv) -> ();
-
-/// Arguments of [`sock_recv()`](fn.sock_recv.html).
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct recv_in {
-    /// List of scatter/gather vectors where message data
-    /// should be stored.
-    pub ri_data: (*const iovec, usize),
-    /// Buffer where numbers of incoming file descriptors
-    /// should be stored.
-    pub ri_fds: (*mut fd, usize),
-    /// Message flags.
-    pub ri_flags: riflags,
-}
-#[test]
-#[cfg(target_pointer_width = "32")]
-fn recv_in_layout_test_32() {
-    assert_eq!(core::mem::size_of::<recv_in>(), 20);
-    assert_eq!(core::mem::align_of::<recv_in>(), 4);
-    unsafe {
-        let obj: recv_in = core::mem::uninitialized();
-        let base = &obj as *const _ as usize;
-        assert_eq!(&obj.ri_data.0 as *const _ as usize - base, 0);
-        assert_eq!(&obj.ri_data.1 as *const _ as usize - base, 4);
-        assert_eq!(&obj.ri_fds.0 as *const _ as usize - base, 8);
-        assert_eq!(&obj.ri_fds.1 as *const _ as usize - base, 12);
-        assert_eq!(&obj.ri_flags as *const _ as usize - base, 16);
-    }
-}
-#[test]
-#[cfg(target_pointer_width = "64")]
-fn recv_in_layout_test_64() {
-    assert_eq!(core::mem::size_of::<recv_in>(), 40);
-    assert_eq!(core::mem::align_of::<recv_in>(), 8);
-    unsafe {
-        let obj: recv_in = core::mem::uninitialized();
-        let base = &obj as *const _ as usize;
-        assert_eq!(&obj.ri_data.0 as *const _ as usize - base, 0);
-        assert_eq!(&obj.ri_data.1 as *const _ as usize - base, 8);
-        assert_eq!(&obj.ri_fds.0 as *const _ as usize - base, 16);
-        assert_eq!(&obj.ri_fds.1 as *const _ as usize - base, 24);
-        assert_eq!(&obj.ri_flags as *const _ as usize - base, 32);
-    }
-}
-
-/// Results of [`sock_recv()`](fn.sock_recv.html).
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct recv_out {
-    /// Number of bytes stored in [`recv_in.ri_data`](struct.recv_in.html#structfield.ri_data).
-    pub ro_datalen: usize,
-    /// Number of file descriptors stored in [`recv_in.ri_fds`](struct.recv_in.html#structfield.ri_fds).
-    pub ro_fdslen: usize,
-    /// Fields that were used by previous implementations.
-    pub ro_unused: [u8; 40],
-    /// Message flags.
-    pub ro_flags: roflags,
-}
-#[test]
-#[cfg(target_pointer_width = "32")]
-fn recv_out_layout_test_32() {
-    assert_eq!(core::mem::size_of::<recv_out>(), 52);
-    assert_eq!(core::mem::align_of::<recv_out>(), 4);
-    unsafe {
-        let obj: recv_out = core::mem::uninitialized();
-        let base = &obj as *const _ as usize;
-        assert_eq!(&obj.ro_datalen as *const _ as usize - base, 0);
-        assert_eq!(&obj.ro_fdslen as *const _ as usize - base, 4);
-        assert_eq!(&obj.ro_unused as *const _ as usize - base, 8);
-        assert_eq!(&obj.ro_flags as *const _ as usize - base, 48);
-    }
-}
-#[test]
-#[cfg(target_pointer_width = "64")]
-fn recv_out_layout_test_64() {
-    assert_eq!(core::mem::size_of::<recv_out>(), 64);
-    assert_eq!(core::mem::align_of::<recv_out>(), 8);
-    unsafe {
-        let obj: recv_out = core::mem::uninitialized();
-        let base = &obj as *const _ as usize;
-        assert_eq!(&obj.ro_datalen as *const _ as usize - base, 0);
-        assert_eq!(&obj.ro_fdslen as *const _ as usize - base, 8);
-        assert_eq!(&obj.ro_unused as *const _ as usize - base, 16);
-        assert_eq!(&obj.ro_flags as *const _ as usize - base, 56);
-    }
-}
-
-/// Arguments of [`sock_send()`](fn.sock_send.html).
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct send_in {
-    /// List of scatter/gather vectors where message data
-    /// should be retrieved.
-    pub si_data: (*const ciovec, usize),
-    /// File descriptors that need to be attached to the
-    /// message.
-    pub si_fds: (*const fd, usize),
-    /// Message flags.
-    pub si_flags: siflags,
-}
-#[test]
-#[cfg(target_pointer_width = "32")]
-fn send_in_layout_test_32() {
-    assert_eq!(core::mem::size_of::<send_in>(), 20);
-    assert_eq!(core::mem::align_of::<send_in>(), 4);
-    unsafe {
-        let obj: send_in = core::mem::uninitialized();
-        let base = &obj as *const _ as usize;
-        assert_eq!(&obj.si_data.0 as *const _ as usize - base, 0);
-        assert_eq!(&obj.si_data.1 as *const _ as usize - base, 4);
-        assert_eq!(&obj.si_fds.0 as *const _ as usize - base, 8);
-        assert_eq!(&obj.si_fds.1 as *const _ as usize - base, 12);
-        assert_eq!(&obj.si_flags as *const _ as usize - base, 16);
-    }
-}
-#[test]
-#[cfg(target_pointer_width = "64")]
-fn send_in_layout_test_64() {
-    assert_eq!(core::mem::size_of::<send_in>(), 40);
-    assert_eq!(core::mem::align_of::<send_in>(), 8);
-    unsafe {
-        let obj: send_in = core::mem::uninitialized();
-        let base = &obj as *const _ as usize;
-        assert_eq!(&obj.si_data.0 as *const _ as usize - base, 0);
-        assert_eq!(&obj.si_data.1 as *const _ as usize - base, 8);
-        assert_eq!(&obj.si_fds.0 as *const _ as usize - base, 16);
-        assert_eq!(&obj.si_fds.1 as *const _ as usize - base, 24);
-        assert_eq!(&obj.si_flags as *const _ as usize - base, 32);
-    }
-}
-
-/// Results of [`sock_send()`](fn.sock_send.html).
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct send_out {
-    /// Number of bytes transmitted.
-    pub so_datalen: usize,
-}
-#[test]
-#[cfg(target_pointer_width = "32")]
-fn send_out_layout_test_32() {
-    assert_eq!(core::mem::size_of::<send_out>(), 4);
-    assert_eq!(core::mem::align_of::<send_out>(), 4);
-    unsafe {
-        let obj: send_out = core::mem::uninitialized();
-        let base = &obj as *const _ as usize;
-        assert_eq!(&obj.so_datalen as *const _ as usize - base, 0);
-    }
-}
-#[test]
-#[cfg(target_pointer_width = "64")]
-fn send_out_layout_test_64() {
-    assert_eq!(core::mem::size_of::<send_out>(), 8);
-    assert_eq!(core::mem::align_of::<send_out>(), 8);
-    unsafe {
-        let obj: send_out = core::mem::uninitialized();
-        let base = &obj as *const _ as usize;
-        assert_eq!(&obj.so_datalen as *const _ as usize - base, 0);
-    }
-}
-
-/// Subscription to an event.
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct subscription {
-    /// User-provided value that is attached to the
-    /// subscription in the kernel and returned through
-    /// [`event.userdata`](struct.event.html#structfield.userdata).
-    pub userdata: userdata,
-    /// Used by previous implementations. Ignored.
-    pub unused: u16,
-    /// The type of the event to which to subscribe.
-    ///
-    /// Currently, [`CONDVAR`](enum.eventtype.html#variant.CONDVAR),
-    /// [`LOCK_RDLOCK`](enum.eventtype.html#variant.LOCK_RDLOCK), and [`LOCK_WRLOCK`](enum.eventtype.html#variant.LOCK_WRLOCK)
-    /// must be provided as the first subscription and may
-    /// only be followed by up to one other subscription,
-    /// having type [`CLOCK`](enum.eventtype.html#variant.CLOCK).
-    pub type_: eventtype,
-    pub union: subscription_union,
-}
-/// A union inside `subscription`.
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub union subscription_union {
-    /// Used when `type_` is [`CLOCK`](enum.eventtype.html#variant.CLOCK).
-    pub clock: subscription_clock,
-    /// Used when `type_` is [`CONDVAR`](enum.eventtype.html#variant.CONDVAR).
-    pub condvar: subscription_condvar,
-    /// Used when `type_` is [`FD_READ`](enum.eventtype.html#variant.FD_READ) or [`FD_WRITE`](enum.eventtype.html#variant.FD_WRITE).
-    pub fd_readwrite: subscription_fd_readwrite,
-    /// Used when `type_` is [`LOCK_RDLOCK`](enum.eventtype.html#variant.LOCK_RDLOCK) or [`LOCK_WRLOCK`](enum.eventtype.html#variant.LOCK_WRLOCK).
-    pub lock: subscription_lock,
-    /// Used when `type_` is [`PROC_TERMINATE`](enum.eventtype.html#variant.PROC_TERMINATE).
-    pub proc_terminate: subscription_proc_terminate,
-}
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct subscription_clock {
-    /// The user-defined unique
-    /// identifier of the clock.
-    pub identifier: userdata,
-    /// The clock against which the
-    /// timestamp should be compared.
-    pub clock_id: clockid,
-    /// The absolute or relative
-    /// timestamp.
-    pub timeout: timestamp,
-    /// The amount of time that the
-    /// kernel may wait additionally
-    /// to coalesce with other events.
-    pub precision: timestamp,
-    /// Flags specifying whether the
-    /// timeout is absolute or
-    /// relative.
-    pub flags: subclockflags,
-}
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct subscription_condvar {
-    /// The condition variable on
-    /// which to wait to be woken up.
-    pub condvar: *mut condvar,
-    /// The lock that will be
-    /// released while waiting.
-    ///
-    /// The lock will be reacquired
-    /// for writing when the condition
-    /// variable triggers.
-    pub lock: *mut lock,
-    /// Whether the condition variable
-    /// is stored in private or shared
-    /// memory.
-    pub condvar_scope: scope,
-    /// Whether the lock is stored in
-    /// private or shared memory.
-    pub lock_scope: scope,
-}
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct subscription_fd_readwrite {
-    /// The file descriptor on which
-    /// to wait for it to become ready
-    /// for reading or writing.
-    pub fd: fd,
-    /// Under which conditions to
-    /// trigger.
-    pub flags: subrwflags,
-}
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct subscription_lock {
-    /// The lock that will be acquired
-    /// for reading or writing.
-    pub lock: *mut lock,
-    /// Whether the lock is stored in
-    /// private or shared memory.
-    pub lock_scope: scope,
-}
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct subscription_proc_terminate {
-    /// The process descriptor on
-    /// which to wait for process
-    /// termination.
-    pub fd: fd,
-}
-#[test]
-#[cfg(target_pointer_width = "32")]
-fn subscription_layout_test_32() {
-    assert_eq!(core::mem::size_of::<subscription>(), 56);
-    assert_eq!(core::mem::align_of::<subscription>(), 8);
-    unsafe {
-        let obj: subscription = core::mem::uninitialized();
-        let base = &obj as *const _ as usize;
-        assert_eq!(&obj.userdata as *const _ as usize - base, 0);
-        assert_eq!(&obj.unused as *const _ as usize - base, 8);
-        assert_eq!(&obj.type_ as *const _ as usize - base, 10);
-        assert_eq!(&obj.union.clock.identifier as *const _ as usize - base, 16);
-        assert_eq!(&obj.union.clock.clock_id as *const _ as usize - base, 24);
-        assert_eq!(&obj.union.clock.timeout as *const _ as usize - base, 32);
-        assert_eq!(&obj.union.clock.precision as *const _ as usize - base, 40);
-        assert_eq!(&obj.union.clock.flags as *const _ as usize - base, 48);
-        assert_eq!(&obj.union.condvar.condvar as *const _ as usize - base, 16);
-        assert_eq!(&obj.union.condvar.lock as *const _ as usize - base, 20);
-        assert_eq!(&obj.union.condvar.condvar_scope as *const _ as usize - base, 24);
-        assert_eq!(&obj.union.condvar.lock_scope as *const _ as usize - base, 25);
-        assert_eq!(&obj.union.fd_readwrite.fd as *const _ as usize - base, 16);
-        assert_eq!(&obj.union.fd_readwrite.flags as *const _ as usize - base, 20);
-        assert_eq!(&obj.union.lock.lock as *const _ as usize - base, 16);
-        assert_eq!(&obj.union.lock.lock_scope as *const _ as usize - base, 20);
-        assert_eq!(&obj.union.proc_terminate.fd as *const _ as usize - base, 16);
-    }
-}
-#[test]
-#[cfg(target_pointer_width = "64")]
-fn subscription_layout_test_64() {
-    assert_eq!(core::mem::size_of::<subscription>(), 56);
-    assert_eq!(core::mem::align_of::<subscription>(), 8);
-    unsafe {
-        let obj: subscription = core::mem::uninitialized();
-        let base = &obj as *const _ as usize;
-        assert_eq!(&obj.userdata as *const _ as usize - base, 0);
-        assert_eq!(&obj.unused as *const _ as usize - base, 8);
-        assert_eq!(&obj.type_ as *const _ as usize - base, 10);
-        assert_eq!(&obj.union.clock.identifier as *const _ as usize - base, 16);
-        assert_eq!(&obj.union.clock.clock_id as *const _ as usize - base, 24);
-        assert_eq!(&obj.union.clock.timeout as *const _ as usize - base, 32);
-        assert_eq!(&obj.union.clock.precision as *const _ as usize - base, 40);
-        assert_eq!(&obj.union.clock.flags as *const _ as usize - base, 48);
-        assert_eq!(&obj.union.condvar.condvar as *const _ as usize - base, 16);
-        assert_eq!(&obj.union.condvar.lock as *const _ as usize - base, 24);
-        assert_eq!(&obj.union.condvar.condvar_scope as *const _ as usize - base, 32);
-        assert_eq!(&obj.union.condvar.lock_scope as *const _ as usize - base, 33);
-        assert_eq!(&obj.union.fd_readwrite.fd as *const _ as usize - base, 16);
-        assert_eq!(&obj.union.fd_readwrite.flags as *const _ as usize - base, 20);
-        assert_eq!(&obj.union.lock.lock as *const _ as usize - base, 16);
-        assert_eq!(&obj.union.lock.lock_scope as *const _ as usize - base, 24);
-        assert_eq!(&obj.union.proc_terminate.fd as *const _ as usize - base, 16);
-    }
-}
-
-/// The Thread Control Block (TCB).
-///
-/// After a thread begins execution (at program startup or when
-/// created through [`thread_create()`](fn.thread_create.html)), the CPU's registers
-/// controlling Thread-Local Storage (TLS) will already be
-/// initialized. They will point to an area only containing the
-/// TCB.
-///
-/// If the thread needs space for storing thread-specific
-/// variables, the thread may allocate a larger area and adjust
-/// the CPU's registers to point to that area instead. However, it
-/// does need to make sure that the TCB is copied over to the new
-/// TLS area.
-///
-/// The purpose of the TCB is that it allows light-weight
-/// emulators to store information related to individual threads.
-/// For example, it may be used to store a copy of the CPU
-/// registers prior emulation, so that TLS for the host system
-/// can be restored if needed.
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct tcb {
-    /// Pointer that may be freely assigned by the system. Its
-    /// value cannot be interpreted by the application.
-    pub parent: *mut (),
-}
-#[test]
-#[cfg(target_pointer_width = "32")]
-fn tcb_layout_test_32() {
-    assert_eq!(core::mem::size_of::<tcb>(), 4);
-    assert_eq!(core::mem::align_of::<tcb>(), 4);
-    unsafe {
-        let obj: tcb = core::mem::uninitialized();
-        let base = &obj as *const _ as usize;
-        assert_eq!(&obj.parent as *const _ as usize - base, 0);
-    }
-}
-#[test]
-#[cfg(target_pointer_width = "64")]
-fn tcb_layout_test_64() {
-    assert_eq!(core::mem::size_of::<tcb>(), 8);
-    assert_eq!(core::mem::align_of::<tcb>(), 8);
-    unsafe {
-        let obj: tcb = core::mem::uninitialized();
-        let base = &obj as *const _ as usize;
-        assert_eq!(&obj.parent as *const _ as usize - base, 0);
-    }
-}
-
-/// Entry point for additionally created threads.
-///
-/// `tid`: thread ID of the current thread.
-///
-/// `aux`: copy of the value stored in
-/// [`threadattr.argument`](struct.threadattr.html#structfield.argument).
-pub type threadentry = unsafe extern "C" fn(tid: tid, aux: *mut ()) -> ();
-
-/// Attributes for thread creation.
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub struct threadattr {
-    /// Initial program counter value.
-    pub entry_point: threadentry,
-    /// Region allocated to serve as stack space.
-    pub stack: (*mut (), usize),
-    /// Argument to be forwarded to the entry point function.
-    pub argument: *mut (),
-}
-#[test]
-#[cfg(target_pointer_width = "32")]
-fn threadattr_layout_test_32() {
-    assert_eq!(core::mem::size_of::<threadattr>(), 16);
-    assert_eq!(core::mem::align_of::<threadattr>(), 4);
-    unsafe {
-        let obj: threadattr = core::mem::uninitialized();
-        let base = &obj as *const _ as usize;
-        assert_eq!(&obj.entry_point as *const _ as usize - base, 0);
-        assert_eq!(&obj.stack.0 as *const _ as usize - base, 4);
-        assert_eq!(&obj.stack.1 as *const _ as usize - base, 8);
-        assert_eq!(&obj.argument as *const _ as usize - base, 12);
-    }
-}
-#[test]
-#[cfg(target_pointer_width = "64")]
-fn threadattr_layout_test_64() {
-    assert_eq!(core::mem::size_of::<threadattr>(), 32);
-    assert_eq!(core::mem::align_of::<threadattr>(), 8);
-    unsafe {
-        let obj: threadattr = core::mem::uninitialized();
-        let base = &obj as *const _ as usize;
-        assert_eq!(&obj.entry_point as *const _ as usize - base, 0);
-        assert_eq!(&obj.stack.0 as *const _ as usize - base, 8);
-        assert_eq!(&obj.stack.1 as *const _ as usize - base, 16);
-        assert_eq!(&obj.argument as *const _ as usize - base, 24);
-    }
-}
-
-/// The table with pointers to all syscall implementations.
-#[allow(improper_ctypes)]
-extern "C" {
-    fn cloudabi_sys_clock_res_get(_: clockid, _: *mut timestamp) -> errno;
-    fn cloudabi_sys_clock_time_get(_: clockid, _: timestamp, _: *mut timestamp) -> errno;
-    fn cloudabi_sys_condvar_signal(_: *mut condvar, _: scope, _: nthreads) -> errno;
-    fn cloudabi_sys_fd_close(_: fd) -> errno;
-    fn cloudabi_sys_fd_create1(_: filetype, _: *mut fd) -> errno;
-    fn cloudabi_sys_fd_create2(_: filetype, _: *mut fd, _: *mut fd) -> errno;
-    fn cloudabi_sys_fd_datasync(_: fd) -> errno;
-    fn cloudabi_sys_fd_dup(_: fd, _: *mut fd) -> errno;
-    fn cloudabi_sys_fd_pread(_: fd, _: *const iovec, _: usize, _: filesize, _: *mut usize)
-    -> errno;
-    fn cloudabi_sys_fd_pwrite(
-        _: fd,
-        _: *const ciovec,
-        _: usize,
-        _: filesize,
-        _: *mut usize,
-    ) -> errno;
-    fn cloudabi_sys_fd_read(_: fd, _: *const iovec, _: usize, _: *mut usize) -> errno;
-    fn cloudabi_sys_fd_replace(_: fd, _: fd) -> errno;
-    fn cloudabi_sys_fd_seek(_: fd, _: filedelta, _: whence, _: *mut filesize) -> errno;
-    fn cloudabi_sys_fd_stat_get(_: fd, _: *mut fdstat) -> errno;
-    fn cloudabi_sys_fd_stat_put(_: fd, _: *const fdstat, _: fdsflags) -> errno;
-    fn cloudabi_sys_fd_sync(_: fd) -> errno;
-    fn cloudabi_sys_fd_write(_: fd, _: *const ciovec, _: usize, _: *mut usize) -> errno;
-    fn cloudabi_sys_file_advise(_: fd, _: filesize, _: filesize, _: advice) -> errno;
-    fn cloudabi_sys_file_allocate(_: fd, _: filesize, _: filesize) -> errno;
-    fn cloudabi_sys_file_create(_: fd, _: *const u8, _: usize, _: filetype) -> errno;
-    fn cloudabi_sys_file_link(
-        _: lookup,
-        _: *const u8,
-        _: usize,
-        _: fd,
-        _: *const u8,
-        _: usize,
-    ) -> errno;
-    fn cloudabi_sys_file_open(
-        _: lookup,
-        _: *const u8,
-        _: usize,
-        _: oflags,
-        _: *const fdstat,
-        _: *mut fd,
-    ) -> errno;
-    fn cloudabi_sys_file_readdir(_: fd, _: *mut (), _: usize, _: dircookie, _: *mut usize)
-    -> errno;
-    fn cloudabi_sys_file_readlink(
-        _: fd,
-        _: *const u8,
-        _: usize,
-        _: *mut u8,
-        _: usize,
-        _: *mut usize,
-    ) -> errno;
-    fn cloudabi_sys_file_rename(
-        _: fd,
-        _: *const u8,
-        _: usize,
-        _: fd,
-        _: *const u8,
-        _: usize,
-    ) -> errno;
-    fn cloudabi_sys_file_stat_fget(_: fd, _: *mut filestat) -> errno;
-    fn cloudabi_sys_file_stat_fput(_: fd, _: *const filestat, _: fsflags) -> errno;
-    fn cloudabi_sys_file_stat_get(_: lookup, _: *const u8, _: usize, _: *mut filestat) -> errno;
-    fn cloudabi_sys_file_stat_put(
-        _: lookup,
-        _: *const u8,
-        _: usize,
-        _: *const filestat,
-        _: fsflags,
-    ) -> errno;
-    fn cloudabi_sys_file_symlink(_: *const u8, _: usize, _: fd, _: *const u8, _: usize) -> errno;
-    fn cloudabi_sys_file_unlink(_: fd, _: *const u8, _: usize, _: ulflags) -> errno;
-    fn cloudabi_sys_lock_unlock(_: *mut lock, _: scope) -> errno;
-    fn cloudabi_sys_mem_advise(_: *mut (), _: usize, _: advice) -> errno;
-    fn cloudabi_sys_mem_map(
-        _: *mut (),
-        _: usize,
-        _: mprot,
-        _: mflags,
-        _: fd,
-        _: filesize,
-        _: *mut *mut (),
-    ) -> errno;
-    fn cloudabi_sys_mem_protect(_: *mut (), _: usize, _: mprot) -> errno;
-    fn cloudabi_sys_mem_sync(_: *mut (), _: usize, _: msflags) -> errno;
-    fn cloudabi_sys_mem_unmap(_: *mut (), _: usize) -> errno;
-    fn cloudabi_sys_poll(_: *const subscription, _: *mut event, _: usize, _: *mut usize) -> errno;
-    fn cloudabi_sys_proc_exec(_: fd, _: *const (), _: usize, _: *const fd, _: usize) -> errno;
-    fn cloudabi_sys_proc_exit(_: exitcode) -> !;
-    fn cloudabi_sys_proc_fork(_: *mut fd, _: *mut tid) -> errno;
-    fn cloudabi_sys_proc_raise(_: signal) -> errno;
-    fn cloudabi_sys_random_get(_: *mut (), _: usize) -> errno;
-    fn cloudabi_sys_sock_recv(_: fd, _: *const recv_in, _: *mut recv_out) -> errno;
-    fn cloudabi_sys_sock_send(_: fd, _: *const send_in, _: *mut send_out) -> errno;
-    fn cloudabi_sys_sock_shutdown(_: fd, _: sdflags) -> errno;
-    fn cloudabi_sys_thread_create(_: *mut threadattr, _: *mut tid) -> errno;
-    fn cloudabi_sys_thread_exit(_: *mut lock, _: scope) -> !;
-    fn cloudabi_sys_thread_yield() -> errno;
-}
-
-/// Obtains the resolution of a clock.
-///
-/// ## Parameters
-///
-/// **clock_id**:
-/// The clock for which the resolution needs to be
-/// returned.
-///
-/// **resolution**:
-/// The resolution of the clock.
-#[inline]
-pub unsafe fn clock_res_get(clock_id_: clockid, resolution_: &mut timestamp) -> errno {
-    unsafe { cloudabi_sys_clock_res_get(clock_id_, resolution_) }
-}
-
-/// Obtains the time value of a clock.
-///
-/// ## Parameters
-///
-/// **clock_id**:
-/// The clock for which the time needs to be
-/// returned.
-///
-/// **precision**:
-/// The maximum lag (exclusive) that the returned
-/// time value may have, compared to its actual
-/// value.
-///
-/// **time**:
-/// The time value of the clock.
-#[inline]
-pub unsafe fn clock_time_get(
-    clock_id_: clockid,
-    precision_: timestamp,
-    time_: *mut timestamp,
-) -> errno {
-    unsafe { cloudabi_sys_clock_time_get(clock_id_, precision_, time_) }
-}
-
-/// Wakes up threads waiting on a userspace condition variable.
-///
-/// If an invocation of this system call causes all waiting
-/// threads to be woken up, the value of the condition variable
-/// is set to [`CONDVAR_HAS_NO_WAITERS`](constant.CONDVAR_HAS_NO_WAITERS.html). As long as the condition
-/// variable is set to this value, it is not needed to invoke this
-/// system call.
-///
-/// ## Parameters
-///
-/// **condvar**:
-/// The userspace condition variable that has
-/// waiting threads.
-///
-/// **scope**:
-/// Whether the condition variable is stored in
-/// private or shared memory.
-///
-/// **nwaiters**:
-/// The number of threads that need to be woken
-/// up. If it exceeds the number of waiting
-/// threads, all threads are woken up.
-#[inline]
-pub unsafe fn condvar_signal(condvar_: *mut condvar, scope_: scope, nwaiters_: nthreads) -> errno {
-    unsafe { cloudabi_sys_condvar_signal(condvar_, scope_, nwaiters_) }
-}
-
-/// Closes a file descriptor.
-///
-/// ## Parameters
-///
-/// **fd**:
-/// The file descriptor that needs to be closed.
-#[inline]
-pub unsafe fn fd_close(fd_: fd) -> errno {
-    unsafe { cloudabi_sys_fd_close(fd_) }
-}
-
-/// Creates a file descriptor.
-///
-/// ## Parameters
-///
-/// **type**:
-/// Possible values:
-///
-///   - [`SHARED_MEMORY`](enum.filetype.html#variant.SHARED_MEMORY):
-///     Creates an anonymous shared memory
-///     object.
-///
-/// **fd**:
-/// The file descriptor that has been created.
-#[inline]
-pub unsafe fn fd_create1(type_: filetype, fd_: &mut fd) -> errno {
-    unsafe { cloudabi_sys_fd_create1(type_, fd_) }
-}
-
-/// Creates a pair of file descriptors.
-///
-/// ## Parameters
-///
-/// **type**:
-/// Possible values:
-///
-///   - [`SOCKET_DGRAM`](enum.filetype.html#variant.SOCKET_DGRAM):
-///     Creates a UNIX datagram socket pair.
-///   - [`SOCKET_STREAM`](enum.filetype.html#variant.SOCKET_STREAM):
-///     Creates a UNIX byte-stream socket
-///     pair.
-///
-/// **fd1**:
-/// The first file descriptor of the pair.
-///
-/// **fd2**:
-/// The second file descriptor of the pair.
-#[inline]
-pub unsafe fn fd_create2(type_: filetype, fd1_: &mut fd, fd2_: &mut fd) -> errno {
-    // SAFETY: the caller must uphold the safety contract for `cloudabi_sys_fd_create2`.
-    unsafe { cloudabi_sys_fd_create2(type_, fd1_, fd2_) }
-}
-
-/// Synchronizes the data of a file to disk.
-///
-/// ## Parameters
-///
-/// **fd**:
-/// The file descriptor of the file whose data
-/// needs to be synchronized to disk.
-#[inline]
-pub unsafe fn fd_datasync(fd_: fd) -> errno {
-    // SAFETY: the caller must guarantee that `fd` is valid
-    // for synchronization.
-    unsafe { cloudabi_sys_fd_datasync(fd_) }
-}
-
-/// Duplicates a file descriptor.
-///
-/// ## Parameters
-///
-/// **from**:
-/// The file descriptor that needs to be
-/// duplicated.
-///
-/// **fd**:
-/// The new file descriptor.
-#[inline]
-pub unsafe fn fd_dup(from_: fd, fd_: &mut fd) -> errno {
-    unsafe { cloudabi_sys_fd_dup(from_, fd_) }
-}
-
-/// Reads from a file descriptor, without using and updating the
-/// file descriptor's offset.
-///
-/// ## Parameters
-///
-/// **fd**:
-/// The file descriptor from which data should be
-/// read.
-///
-/// **iovs**:
-/// List of scatter/gather vectors where data
-/// should be stored.
-///
-/// **offset**:
-/// The offset within the file at which reading
-/// should start.
-///
-/// **nread**:
-/// The number of bytes read.
-#[inline]
-pub unsafe fn fd_pread(fd_: fd, iovs_: &[iovec], offset_: filesize, nread_: &mut usize) -> errno {
-    unsafe { cloudabi_sys_fd_pread(fd_, iovs_.as_ptr(), iovs_.len(), offset_, nread_) }
-}
-
-/// Writes to a file descriptor, without using and updating the
-/// file descriptor's offset.
-///
-/// ## Parameters
-///
-/// **fd**:
-/// The file descriptor to which data should be
-/// written.
-///
-/// **iovs**:
-/// List of scatter/gather vectors where data
-/// should be retrieved.
-///
-/// **offset**:
-/// The offset within the file at which writing
-/// should start.
-///
-/// **nwritten**:
-/// The number of bytes written.
-#[inline]
-pub unsafe fn fd_pwrite(
-    fd_: fd,
-    iovs_: &[ciovec],
-    offset_: filesize,
-    nwritten_: &mut usize,
-) -> errno {
-    unsafe { cloudabi_sys_fd_pwrite(fd_, iovs_.as_ptr(), iovs_.len(), offset_, nwritten_) }
-}
-
-/// Reads from a file descriptor.
-///
-/// ## Parameters
-///
-/// **fd**:
-/// The file descriptor from which data should be
-/// read.
-///
-/// **iovs**:
-/// List of scatter/gather vectors where data
-/// should be stored.
-///
-/// **nread**:
-/// The number of bytes read.
-#[inline]
-pub unsafe fn fd_read(fd_: fd, iovs_: &[iovec], nread_: &mut usize) -> errno {
-    unsafe { cloudabi_sys_fd_read(fd_, iovs_.as_ptr(), iovs_.len(), nread_) }
-}
-
-/// Atomically replaces a file descriptor by a copy of another
-/// file descriptor.
-///
-/// Due to the strong focus on thread safety, this environment
-/// does not provide a mechanism to duplicate a file descriptor to
-/// an arbitrary number, like dup2(). This would be prone to race
-/// conditions, as an actual file descriptor with the same number
-/// could be allocated by a different thread at the same time.
-///
-/// This system call provides a way to atomically replace file
-/// descriptors, which would disappear if dup2() were to be
-/// removed entirely.
-///
-/// ## Parameters
-///
-/// **from**:
-/// The file descriptor that needs to be copied.
-///
-/// **to**:
-/// The file descriptor that needs to be
-/// overwritten.
-#[inline]
-pub unsafe fn fd_replace(from_: fd, to_: fd) -> errno {
-    unsafe { cloudabi_sys_fd_replace(from_, to_) }
-}
-
-/// Moves the offset of the file descriptor.
-///
-/// ## Parameters
-///
-/// **fd**:
-/// The file descriptor whose offset has to be
-/// moved.
-///
-/// **offset**:
-/// The number of bytes to move.
-///
-/// **whence**:
-/// Relative to which position the move should
-/// take place.
-///
-/// **newoffset**:
-/// The new offset of the file descriptor,
-/// relative to the start of the file.
-#[inline]
-pub unsafe fn fd_seek(
-    fd_: fd,
-    offset_: filedelta,
-    whence_: whence,
-    newoffset_: &mut filesize,
-) -> errno {
-    unsafe { cloudabi_sys_fd_seek(fd_, offset_, whence_, newoffset_) }
-}
-
-/// Gets attributes of a file descriptor.
-///
-/// ## Parameters
-///
-/// **fd**:
-/// The file descriptor whose attributes have to
-/// be obtained.
-///
-/// **buf**:
-/// The buffer where the file descriptor's
-/// attributes are stored.
-#[inline]
-pub unsafe fn fd_stat_get(fd_: fd, buf_: *mut fdstat) -> errno {
-    unsafe { cloudabi_sys_fd_stat_get(fd_, buf_) }
-}
-
-/// Adjusts attributes of a file descriptor.
-///
-/// ## Parameters
-///
-/// **fd**:
-/// The file descriptor whose attributes have to
-/// be adjusted.
-///
-/// **buf**:
-/// The desired values of the file descriptor
-/// attributes that are adjusted.
-///
-/// **flags**:
-/// A bitmask indicating which attributes have to
-/// be adjusted.
-#[inline]
-pub unsafe fn fd_stat_put(fd_: fd, buf_: *const fdstat, flags_: fdsflags) -> errno {
-    unsafe { cloudabi_sys_fd_stat_put(fd_, buf_, flags_) }
-}
-
-/// Synchronizes the data and metadata of a file to disk.
-///
-/// ## Parameters
-///
-/// **fd**:
-/// The file descriptor of the file whose data
-/// and metadata needs to be synchronized to disk.
-#[inline]
-pub unsafe fn fd_sync(fd_: fd) -> errno {
-    unsafe { cloudabi_sys_fd_sync(fd_) }
-}
-
-/// Writes to a file descriptor.
-///
-/// ## Parameters
-///
-/// **fd**:
-/// The file descriptor to which data should be
-/// written.
-///
-/// **iovs**:
-/// List of scatter/gather vectors where data
-/// should be retrieved.
-///
-/// **nwritten**:
-/// The number of bytes written.
-#[inline]
-pub unsafe fn fd_write(fd_: fd, iovs_: &[ciovec], nwritten_: &mut usize) -> errno {
-    unsafe { cloudabi_sys_fd_write(fd_, iovs_.as_ptr(), iovs_.len(), nwritten_) }
-}
-
-/// Provides file advisory information on a file descriptor.
-///
-/// ## Parameters
-///
-/// **fd**:
-/// The file descriptor for which to provide file
-/// advisory information.
-///
-/// **offset**:
-/// The offset within the file to which the
-/// advisory applies.
-///
-/// **len**:
-/// The length of the region to which the advisory
-/// applies.
-///
-/// **advice**:
-/// The advice.
-#[inline]
-pub unsafe fn file_advise(fd_: fd, offset_: filesize, len_: filesize, advice_: advice) -> errno {
-    unsafe { cloudabi_sys_file_advise(fd_, offset_, len_, advice_) }
-}
-
-/// Forces the allocation of space in a file.
-///
-/// ## Parameters
-///
-/// **fd**:
-/// The file in which the space should be
-/// allocated.
-///
-/// **offset**:
-/// The offset at which the allocation should
-/// start.
-///
-/// **len**:
-/// The length of the area that is allocated.
-#[inline]
-pub unsafe fn file_allocate(fd_: fd, offset_: filesize, len_: filesize) -> errno {
-    unsafe { cloudabi_sys_file_allocate(fd_, offset_, len_) }
-}
-
-/// Creates a file of a specified type.
-///
-/// ## Parameters
-///
-/// **fd**:
-/// The working directory at which the resolution
-/// of the file to be created starts.
-///
-/// **path**:
-/// The path at which the file should be created.
-///
-/// **type**:
-/// Possible values:
-///
-///   - [`DIRECTORY`](enum.filetype.html#variant.DIRECTORY):
-///     Creates a directory.
-#[inline]
-pub unsafe fn file_create(fd_: fd, path_: &[u8], type_: filetype) -> errno {
-    unsafe { cloudabi_sys_file_create(fd_, path_.as_ptr(), path_.len(), type_)}
-}
-
-/// Creates a hard link.
-///
-/// ## Parameters
-///
-/// **fd1**:
-/// The working directory at which the resolution
-/// of the source path starts.
-///
-/// **path1**:
-/// The source path of the file that should be
-/// hard linked.
-///
-/// **fd2**:
-/// The working directory at which the resolution
-/// of the destination path starts.
-///
-/// **path2**:
-/// The destination path at which the hard link
-/// should be created.
-#[inline]
-pub unsafe fn file_link(fd1_: lookup, path1_: &[u8], fd2_: fd, path2_: &[u8]) -> errno {
-    unsafe { cloudabi_sys_file_link(fd1_, path1_.as_ptr(), path1_.len(), fd2_, path2_.as_ptr(), path2_.len()) }
-}
-
-/// Opens a file.
-///
-/// ## Parameters
-///
-/// **dirfd**:
-/// The working directory at which the resolution
-/// of the file to be opened starts.
-///
-/// **path**:
-/// The path of the file that should be opened.
-///
-/// **oflags**:
-/// The method at which the file should be opened.
-///
-/// **fds**:
-/// [`fdstat.fs_rights_base`](struct.fdstat.html#structfield.fs_rights_base) and
-/// [`fdstat.fs_rights_inheriting`](struct.fdstat.html#structfield.fs_rights_inheriting) specify the
-/// initial rights of the newly created file
-/// descriptor. The operating system is allowed to
-/// return a file descriptor with fewer rights
-/// than specified, if and only if those rights do
-/// not apply to the type of file being opened.
-///
-/// [`fdstat.fs_flags`](struct.fdstat.html#structfield.fs_flags) specifies the initial flags
-/// of the file descriptor.
-///
-/// [`fdstat.fs_filetype`](struct.fdstat.html#structfield.fs_filetype) is ignored.
-///
-/// **fd**:
-/// The file descriptor of the file that has been
-/// opened.
-#[inline]
-pub unsafe fn file_open(
-    dirfd_: lookup,
-    path_: &[u8],
-    oflags_: oflags,
-    fds_: *const fdstat,
-    fd_: &mut fd,
-) -> errno {
-    unsafe { cloudabi_sys_file_open(dirfd_, path_.as_ptr(), path_.len(), oflags_, fds_, fd_) }
-}
-
-/// Reads directory entries from a directory.
-///
-/// When successful, the contents of the output buffer consist of
-/// a sequence of directory entries. Each directory entry consists
-/// of a [`dirent`] object, followed by [`dirent.d_namlen`](struct.dirent.html#structfield.d_namlen) bytes
-/// holding the name of the directory entry.
-///
-/// This system call fills the output buffer as much as possible,
-/// potentially truncating the last directory entry. This allows
-/// the caller to grow its read buffer size in case it's too small
-/// to fit a single large directory entry, or skip the oversized
-/// directory entry.
-///
-/// ## Parameters
-///
-/// **fd**:
-/// The directory from which to read the directory
-/// entries.
-///
-/// **buf**:
-/// The buffer where directory entries are stored.
-///
-/// **cookie**:
-/// The location within the directory to start
-/// reading.
-///
-/// **bufused**:
-/// The number of bytes stored in the read buffer.
-/// If less than the size of the read buffer, the
-/// end of the directory has been reached.
-#[inline]
-pub unsafe fn file_readdir(
-    fd_: fd,
-    buf_: &mut [u8],
-    cookie_: dircookie,
-    bufused_: &mut usize,
-) -> errno {
-    unsafe { cloudabi_sys_file_readdir(fd_, buf_.as_mut_ptr() as *mut (), buf_.len(), cookie_, bufused_) }
-}
-
-/// Reads the contents of a symbolic link.
-///
-/// ## Parameters
-///
-/// **fd**:
-/// The working directory at which the resolution
-/// of the path of the symbolic starts.
-///
-/// **path**:
-/// The path of the symbolic link whose contents
-/// should be read.
-///
-/// **buf**:
-/// The buffer where the contents of the symbolic
-/// link should be stored.
-///
-/// **bufused**:
-/// The number of bytes placed in the buffer.
-#[inline]
-pub unsafe fn file_readlink(fd_: fd, path_: &[u8], buf_: &mut [u8], bufused_: &mut usize) -> errno {
-    unsafe {
-        cloudabi_sys_file_readlink(
-            fd_,
-            path_.as_ptr(),
-            path_.len(),
-            buf_.as_mut_ptr(),
-            buf_.len(),
-            bufused_,
-        )
-    }
-}
-
-/// Renames a file.
-///
-/// ## Parameters
-///
-/// **fd1**:
-/// The working directory at which the resolution
-/// of the source path starts.
-///
-/// **path1**:
-/// The source path of the file that should be
-/// renamed.
-///
-/// **fd2**:
-/// The working directory at which the resolution
-/// of the destination path starts.
-///
-/// **path2**:
-/// The destination path to which the file should
-/// be renamed.
-#[inline]
-pub unsafe fn file_rename(fd1_: fd, path1_: &[u8], fd2_: fd, path2_: &[u8]) -> errno {
-    unsafe {
-        cloudabi_sys_file_rename(
-            fd1_,
-            path1_.as_ptr(),
-            path1_.len(),
-            fd2_,
-            path2_.as_ptr(),
-            path2_.len(),
-        )
-    }
-}
-
-/// Gets attributes of a file by file descriptor.
-///
-/// ## Parameters
-///
-/// **fd**:
-/// The file descriptor whose attributes have to
-/// be obtained.
-///
-/// **buf**:
-/// The buffer where the file's attributes are
-/// stored.
-#[inline]
-pub unsafe fn file_stat_fget(fd_: fd, buf_: *mut filestat) -> errno {
-    unsafe { cloudabi_sys_file_stat_fget(fd_, buf_) }
-}
-
-/// Adjusts attributes of a file by file descriptor.
-///
-/// ## Parameters
-///
-/// **fd**:
-/// The file descriptor whose attributes have to
-/// be adjusted.
-///
-/// **buf**:
-/// The desired values of the file attributes that
-/// are adjusted.
-///
-/// **flags**:
-/// A bitmask indicating which attributes have to
-/// be adjusted.
-#[inline]
-pub unsafe fn file_stat_fput(fd_: fd, buf_: *const filestat, flags_: fsflags) -> errno {
-    unsafe { cloudabi_sys_file_stat_fput(fd_, buf_, flags_) }
-}
-
-/// Gets attributes of a file by path.
-///
-/// ## Parameters
-///
-/// **fd**:
-/// The working directory at which the resolution
-/// of the path whose attributes have to be
-/// obtained starts.
-///
-/// **path**:
-/// The path of the file whose attributes have to
-/// be obtained.
-///
-/// **buf**:
-/// The buffer where the file's attributes are
-/// stored.
-#[inline]
-pub unsafe fn file_stat_get(fd_: lookup, path_: &[u8], buf_: *mut filestat) -> errno {
-    unsafe { cloudabi_sys_file_stat_get(fd_, path_.as_ptr(), path_.len(), buf_) }
-}
-
-/// Adjusts attributes of a file by path.
-///
-/// ## Parameters
-///
-/// **fd**:
-/// The working directory at which the resolution
-/// of the path whose attributes have to be
-/// adjusted starts.
-///
-/// **path**:
-/// The path of the file whose attributes have to
-/// be adjusted.
-///
-/// **buf**:
-/// The desired values of the file attributes that
-/// are adjusted.
-///
-/// **flags**:
-/// A bitmask indicating which attributes have to
-/// be adjusted.
-#[inline]
-pub unsafe fn file_stat_put(
-    fd_: lookup,
-    path_: &[u8],
-    buf_: *const filestat,
-    flags_: fsflags,
-) -> errno {
-    unsafe { cloudabi_sys_file_stat_put(fd_, path_.as_ptr(), path_.len(), buf_, flags_) }
-}
-
-/// Creates a symbolic link.
-///
-/// ## Parameters
-///
-/// **path1**:
-/// The contents of the symbolic link.
-///
-/// **fd**:
-/// The working directory at which the resolution
-/// of the destination path starts.
-///
-/// **path2**:
-/// The destination path at which the symbolic
-/// link should be created.
-#[inline]
-pub unsafe fn file_symlink(path1_: &[u8], fd_: fd, path2_: &[u8]) -> errno {
-    unsafe { cloudabi_sys_file_symlink(path1_.as_ptr(), path1_.len(), fd_, path2_.as_ptr(), path2_.len()) }
-}
-
-/// Unlinks a file, or removes a directory.
-///
-/// ## Parameters
-///
-/// **fd**:
-/// The working directory at which the resolution
-/// of the path starts.
-///
-/// **path**:
-/// The path that needs to be unlinked or removed.
-///
-/// **flags**:
-/// Possible values:
-///
-///   - [`REMOVEDIR`](struct.ulflags.html#associatedconstant.REMOVEDIR):
-///     If set, attempt to remove a directory.
-///     Otherwise, unlink a file.
-#[inline]
-pub unsafe fn file_unlink(fd_: fd, path_: &[u8], flags_: ulflags) -> errno {
-    unsafe { cloudabi_sys_file_unlink(fd_, path_.as_ptr(), path_.len(), flags_) }
-}
-
-/// Unlocks a write-locked userspace lock.
-///
-/// If a userspace lock is unlocked while having its
-/// [`LOCK_KERNEL_MANAGED`](constant.LOCK_KERNEL_MANAGED.html) flag set, the lock cannot be unlocked in
-/// userspace directly. This system call needs to be performed
-/// instead, so that any waiting threads can be woken up.
-///
-/// To prevent spurious invocations of this system call, the lock
-/// must be locked for writing. This prevents other threads from
-/// acquiring additional read locks while the system call is in
-/// progress. If the lock is acquired for reading, it must first
-/// be upgraded to a write lock.
-///
-/// ## Parameters
-///
-/// **lock**:
-/// The userspace lock that is locked for writing
-/// by the calling thread.
-///
-/// **scope**:
-/// Whether the lock is stored in private or
-/// shared memory.
-#[inline]
-pub unsafe fn lock_unlock(lock_: *mut lock, scope_: scope) -> errno {
-    unsafe { cloudabi_sys_lock_unlock(lock_, scope_) }
-}
-
-/// Provides memory advisory information on a region of memory.
-///
-/// ## Parameters
-///
-/// **mapping**:
-/// The pages for which to provide memory advisory
-/// information.
-///
-/// **advice**:
-/// The advice.
-#[inline]
-pub unsafe fn mem_advise(mapping_: &mut [u8], advice_: advice) -> errno {
-    unsafe { cloudabi_sys_mem_advise(mapping_.as_mut_ptr() as *mut (), mapping_.len(), advice_) }
-}
-
-/// Creates a memory mapping, making the contents of a file
-/// accessible through memory.
-///
-/// ## Parameters
-///
-/// **addr**:
-/// If [`FIXED`](struct.mflags.html#associatedconstant.FIXED) is set, specifies to which
-/// address the file region is mapped. Otherwise,
-/// the mapping is performed at an unused
-/// location.
-///
-/// **len**:
-/// The length of the memory mapping to be
-/// created.
-///
-/// **prot**:
-/// Initial memory protection options for the
-/// memory mapping.
-///
-/// **flags**:
-/// Memory mapping flags.
-///
-/// **fd**:
-/// If [`ANON`](struct.mflags.html#associatedconstant.ANON) is set, this argument must be
-/// [`MAP_ANON_FD`](constant.MAP_ANON_FD.html). Otherwise, this argument
-/// specifies the file whose contents need to be
-/// mapped.
-///
-/// **off**:
-/// If [`ANON`](struct.mflags.html#associatedconstant.ANON) is set, this argument must be
-/// zero. Otherwise, this argument specifies the
-/// offset within the file at which the mapping
-/// starts.
-///
-/// **mem**:
-/// The starting address of the memory mapping.
-#[inline]
-pub unsafe fn mem_map(
-    addr_: *mut (),
-    len_: usize,
-    prot_: mprot,
-    flags_: mflags,
-    fd_: fd,
-    off_: filesize,
-    mem_: &mut *mut (),
-) -> errno {
-    unsafe { cloudabi_sys_mem_map(addr_, len_, prot_, flags_, fd_, off_, mem_) }
-}
-
-/// Changes the protection of a memory mapping.
-///
-/// ## Parameters
-///
-/// **mapping**:
-/// The pages that need their protection changed.
-///
-/// **prot**:
-/// New protection options.
-#[inline]
-pub unsafe fn mem_protect(mapping_: &mut [u8], prot_: mprot) -> errno {
-    unsafe { cloudabi_sys_mem_protect(mapping_.as_mut_ptr() as *mut (), mapping_.len(), prot_) }
-}
-
-/// Synchronizes a region of memory with its physical storage.
-///
-/// ## Parameters
-///
-/// **mapping**:
-/// The pages that need to be synchronized.
-///
-/// **flags**:
-/// The method of synchronization.
-#[inline]
-pub unsafe fn mem_sync(mapping_: &mut [u8], flags_: msflags) -> errno {
-    unsafe { cloudabi_sys_mem_sync(mapping_.as_mut_ptr() as *mut (), mapping_.len(), flags_) }
-}
-
-/// Unmaps a region of memory.
-///
-/// ## Parameters
-///
-/// **mapping**:
-/// The pages that needs to be unmapped.
-#[inline]
-pub unsafe fn mem_unmap(mapping_: &mut [u8]) -> errno {
-    unsafe { cloudabi_sys_mem_unmap(mapping_.as_mut_ptr() as *mut (), mapping_.len()) }
-}
-
-/// Concurrently polls for the occurrence of a set of events.
-///
-/// ## Parameters
-///
-/// **in**:
-/// The events to which to subscribe.
-///
-/// **out**:
-/// The events that have occurred.
-///
-/// **nsubscriptions**:
-/// Both the number of subscriptions and events.
-///
-/// **nevents**:
-/// The number of events stored.
-#[inline]
-pub unsafe fn poll(
-    in_: *const subscription,
-    out_: *mut event,
-    nsubscriptions_: usize,
-    nevents_: *mut usize,
-) -> errno {
-    unsafe { cloudabi_sys_poll(in_, out_, nsubscriptions_, nevents_) }
-}
-
-/// Replaces the process by a new executable.
-///
-/// Process execution in CloudABI differs from POSIX in two ways:
-/// handling of arguments and inheritance of file descriptors.
-///
-/// CloudABI does not use string command line arguments. Instead,
-/// a buffer with binary data is copied into the address space of
-/// the new executable. The kernel does not enforce any specific
-/// structure to this data, although CloudABI's C library uses it
-/// to store a tree structure that is semantically identical to
-/// YAML.
-///
-/// Due to the strong focus on thread safety, file descriptors
-/// aren't inherited through close-on-exec flags. An explicit
-/// list of file descriptors that need to be retained needs to be
-/// provided. After execution, file descriptors are placed in the
-/// order in which they are stored in the array. This not only
-/// makes the execution process deterministic. It also prevents
-/// potential information disclosures about the layout of the
-/// original process.
-///
-/// ## Parameters
-///
-/// **fd**:
-/// A file descriptor of the new executable.
-///
-/// **data**:
-/// Binary argument data that is passed on to the
-/// new executable.
-///
-/// **fds**:
-/// The layout of the file descriptor table after
-/// execution.
-#[inline]
-pub unsafe fn proc_exec(fd_: fd, data_: &[u8], fds_: &[fd]) -> errno {
-    unsafe { cloudabi_sys_proc_exec(fd_, data_.as_ptr() as *const (), data_.len(), fds_.as_ptr(), fds_.len()) }
-}
-
-/// Terminates the process normally.
-///
-/// ## Parameters
-///
-/// **rval**:
-/// The exit code returned by the process. The
-/// exit code can be obtained by other processes
-/// through [`event.union.proc_terminate.exitcode`](struct.event_proc_terminate.html#structfield.exitcode).
-#[inline]
-pub unsafe fn proc_exit(rval_: exitcode) -> ! {
-    unsafe { cloudabi_sys_proc_exit(rval_) }
-}
-
-/// Forks the process of the calling thread.
-///
-/// After forking, a new process shall be created, having only a
-/// copy of the calling thread. The parent process will obtain a
-/// process descriptor. When closed, the child process is
-/// automatically signaled with [`KILL`](enum.signal.html#variant.KILL).
-///
-/// ## Parameters
-///
-/// **fd**:
-/// In the parent process: the file descriptor
-/// number of the process descriptor.
-///
-/// In the child process: [`PROCESS_CHILD`](constant.PROCESS_CHILD.html).
-///
-/// **tid**:
-/// In the parent process: undefined.
-///
-/// In the child process: the thread ID of the
-/// initial thread of the child process.
-#[inline]
-pub unsafe fn proc_fork(fd_: &mut fd, tid_: &mut tid) -> errno {
-    unsafe { cloudabi_sys_proc_fork(fd_, tid_) }
-}
-
-/// Sends a signal to the process of the calling thread.
-///
-/// ## Parameters
-///
-/// **sig**:
-/// The signal condition that should be triggered.
-/// If the signal causes the process to terminate,
-/// its condition can be obtained by other
-/// processes through
-/// [`event.union.proc_terminate.signal`](struct.event_proc_terminate.html#structfield.signal).
-#[inline]
-pub unsafe fn proc_raise(sig_: signal) -> errno {
-    unsafe { cloudabi_sys_proc_raise(sig_) }
-}
-
-/// Obtains random data from the kernel random number generator.
-///
-/// As this interface is not guaranteed to be fast, it is advised
-/// that the random data obtained through this system call is used
-/// as the seed for a userspace pseudo-random number generator.
-///
-/// ## Parameters
-///
-/// **buf**:
-/// The buffer that needs to be filled with random
-/// data.
-#[inline]
-pub unsafe fn random_get(buf_: &mut [u8]) -> errno {
-    unsafe { cloudabi_sys_random_get(buf_.as_mut_ptr() as *mut (), buf_.len()) }
-}
-
-/// Receives a message on a socket.
-///
-/// ## Parameters
-///
-/// **sock**:
-/// The socket on which a message should be
-/// received.
-///
-/// **in**:
-/// Input parameters.
-///
-/// **out**:
-/// Output parameters.
-#[inline]
-pub unsafe fn sock_recv(sock_: fd, in_: *const recv_in, out_: *mut recv_out) -> errno {
-    unsafe { cloudabi_sys_sock_recv(sock_, in_, out_) }
-}
-
-/// Sends a message on a socket.
-///
-/// ## Parameters
-///
-/// **sock**:
-/// The socket on which a message should be sent.
-///
-/// **in**:
-/// Input parameters.
-///
-/// **out**:
-/// Output parameters.
-#[inline]
-pub unsafe fn sock_send(sock_: fd, in_: *const send_in, out_: *mut send_out) -> errno {
-    unsafe { cloudabi_sys_sock_send(sock_, in_, out_) }
-}
-
-/// Shuts down socket send and receive channels.
-///
-/// ## Parameters
-///
-/// **sock**:
-/// The socket that needs its channels shut down.
-///
-/// **how**:
-/// Which channels on the socket need to be shut
-/// down.
-#[inline]
-pub unsafe fn sock_shutdown(sock_: fd, how_: sdflags) -> errno {
-    unsafe { cloudabi_sys_sock_shutdown(sock_, how_) }
-}
-
-/// Creates a new thread within the current process.
-///
-/// ## Parameters
-///
-/// **attr**:
-/// The desired attributes of the new thread.
-///
-/// **tid**:
-/// The thread ID of the new thread.
-#[inline]
-pub unsafe fn thread_create(attr_: *mut threadattr, tid_: &mut tid) -> errno {
-    unsafe { cloudabi_sys_thread_create(attr_, tid_) }
-}
-
-/// Terminates the calling thread.
-///
-/// This system call can also unlock a single userspace lock
-/// after termination, which can be used to implement thread
-/// joining.
-///
-/// ## Parameters
-///
-/// **lock**:
-/// Userspace lock that is locked for writing by
-/// the calling thread.
-///
-/// **scope**:
-/// Whether the lock is stored in private or
-/// shared memory.
-#[inline]
-pub unsafe fn thread_exit(lock_: *mut lock, scope_: scope) -> ! {
-    unsafe { cloudabi_sys_thread_exit(lock_, scope_) }
-}
-
-/// Temporarily yields execution of the calling thread.
-#[inline]
-pub unsafe fn thread_yield() -> errno {
-    unsafe { cloudabi_sys_thread_yield() }
-}
diff --git a/library/std/src/sys/cloudabi/abi/mod.rs b/library/std/src/sys/cloudabi/abi/mod.rs
deleted file mode 100644
index 9d01d24ea83..00000000000
--- a/library/std/src/sys/cloudabi/abi/mod.rs
+++ /dev/null
@@ -1,3 +0,0 @@
-#[allow(warnings)]
-mod cloudabi;
-pub use self::cloudabi::*;
diff --git a/library/std/src/sys/cloudabi/args.rs b/library/std/src/sys/cloudabi/args.rs
deleted file mode 100644
index dea562abad3..00000000000
--- a/library/std/src/sys/cloudabi/args.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-pub use crate::sys::cloudabi::shims::args::*;
-
-#[allow(dead_code)]
-pub fn init(_: isize, _: *const *const u8) {}
-
-#[allow(dead_code)]
-pub fn cleanup() {}
diff --git a/library/std/src/sys/cloudabi/condvar.rs b/library/std/src/sys/cloudabi/condvar.rs
deleted file mode 100644
index f09bc01701b..00000000000
--- a/library/std/src/sys/cloudabi/condvar.rs
+++ /dev/null
@@ -1,149 +0,0 @@
-use crate::mem;
-use crate::sync::atomic::{AtomicU32, Ordering};
-use crate::sys::cloudabi::abi;
-use crate::sys::mutex::{self, Mutex};
-use crate::sys::time::checked_dur2intervals;
-use crate::time::Duration;
-
-extern "C" {
-    #[thread_local]
-    static __pthread_thread_id: abi::tid;
-}
-
-pub struct Condvar {
-    condvar: AtomicU32,
-}
-
-pub type MovableCondvar = Condvar;
-
-unsafe impl Send for Condvar {}
-unsafe impl Sync for Condvar {}
-
-impl Condvar {
-    pub const fn new() -> Condvar {
-        Condvar { condvar: AtomicU32::new(abi::CONDVAR_HAS_NO_WAITERS.0) }
-    }
-
-    pub unsafe fn init(&mut self) {}
-
-    pub unsafe fn notify_one(&self) {
-        if self.condvar.load(Ordering::Relaxed) != abi::CONDVAR_HAS_NO_WAITERS.0 {
-            let ret = abi::condvar_signal(
-                &self.condvar as *const AtomicU32 as *mut abi::condvar,
-                abi::scope::PRIVATE,
-                1,
-            );
-            assert_eq!(ret, abi::errno::SUCCESS, "Failed to signal on condition variable");
-        }
-    }
-
-    pub unsafe fn notify_all(&self) {
-        if self.condvar.load(Ordering::Relaxed) != abi::CONDVAR_HAS_NO_WAITERS.0 {
-            let ret = abi::condvar_signal(
-                &self.condvar as *const AtomicU32 as *mut abi::condvar,
-                abi::scope::PRIVATE,
-                abi::nthreads::MAX,
-            );
-            assert_eq!(ret, abi::errno::SUCCESS, "Failed to broadcast on condition variable");
-        }
-    }
-
-    pub unsafe fn wait(&self, mutex: &Mutex) {
-        let mutex = mutex::raw(mutex);
-        assert_eq!(
-            mutex.load(Ordering::Relaxed) & !abi::LOCK_KERNEL_MANAGED.0,
-            __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
-            "This lock is not write-locked by this thread"
-        );
-
-        // Call into the kernel to wait on the condition variable.
-        let subscription = abi::subscription {
-            type_: abi::eventtype::CONDVAR,
-            union: abi::subscription_union {
-                condvar: abi::subscription_condvar {
-                    condvar: &self.condvar as *const AtomicU32 as *mut abi::condvar,
-                    condvar_scope: abi::scope::PRIVATE,
-                    lock: mutex as *const AtomicU32 as *mut abi::lock,
-                    lock_scope: abi::scope::PRIVATE,
-                },
-            },
-            ..mem::zeroed()
-        };
-        let mut event: mem::MaybeUninit<abi::event> = mem::MaybeUninit::uninit();
-        let mut nevents: mem::MaybeUninit<usize> = mem::MaybeUninit::uninit();
-        let ret = abi::poll(&subscription, event.as_mut_ptr(), 1, nevents.as_mut_ptr());
-        assert_eq!(ret, abi::errno::SUCCESS, "Failed to wait on condition variable");
-        assert_eq!(
-            event.assume_init().error,
-            abi::errno::SUCCESS,
-            "Failed to wait on condition variable"
-        );
-    }
-
-    pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
-        let mutex = mutex::raw(mutex);
-        assert_eq!(
-            mutex.load(Ordering::Relaxed) & !abi::LOCK_KERNEL_MANAGED.0,
-            __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
-            "This lock is not write-locked by this thread"
-        );
-
-        // Call into the kernel to wait on the condition variable.
-        let timeout =
-            checked_dur2intervals(&dur).expect("overflow converting duration to nanoseconds");
-        let subscriptions = [
-            abi::subscription {
-                type_: abi::eventtype::CONDVAR,
-                union: abi::subscription_union {
-                    condvar: abi::subscription_condvar {
-                        condvar: &self.condvar as *const AtomicU32 as *mut abi::condvar,
-                        condvar_scope: abi::scope::PRIVATE,
-                        lock: mutex as *const AtomicU32 as *mut abi::lock,
-                        lock_scope: abi::scope::PRIVATE,
-                    },
-                },
-                ..mem::zeroed()
-            },
-            abi::subscription {
-                type_: abi::eventtype::CLOCK,
-                union: abi::subscription_union {
-                    clock: abi::subscription_clock {
-                        clock_id: abi::clockid::MONOTONIC,
-                        timeout,
-                        ..mem::zeroed()
-                    },
-                },
-                ..mem::zeroed()
-            },
-        ];
-        let mut events: [mem::MaybeUninit<abi::event>; 2] = [mem::MaybeUninit::uninit(); 2];
-        let mut nevents: mem::MaybeUninit<usize> = mem::MaybeUninit::uninit();
-        let ret = abi::poll(
-            subscriptions.as_ptr(),
-            mem::MaybeUninit::slice_as_mut_ptr(&mut events),
-            2,
-            nevents.as_mut_ptr(),
-        );
-        assert_eq!(ret, abi::errno::SUCCESS, "Failed to wait on condition variable");
-        let nevents = nevents.assume_init();
-        for i in 0..nevents {
-            assert_eq!(
-                events[i].assume_init().error,
-                abi::errno::SUCCESS,
-                "Failed to wait on condition variable"
-            );
-            if events[i].assume_init().type_ == abi::eventtype::CONDVAR {
-                return true;
-            }
-        }
-        false
-    }
-
-    pub unsafe fn destroy(&self) {
-        assert_eq!(
-            self.condvar.load(Ordering::Relaxed),
-            abi::CONDVAR_HAS_NO_WAITERS.0,
-            "Attempted to destroy a condition variable with blocked threads"
-        );
-    }
-}
diff --git a/library/std/src/sys/cloudabi/io.rs b/library/std/src/sys/cloudabi/io.rs
deleted file mode 100644
index d5f475b4310..00000000000
--- a/library/std/src/sys/cloudabi/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/cloudabi/mod.rs b/library/std/src/sys/cloudabi/mod.rs
deleted file mode 100644
index b4a9246ca4e..00000000000
--- a/library/std/src/sys/cloudabi/mod.rs
+++ /dev/null
@@ -1,73 +0,0 @@
-#![deny(unsafe_op_in_unsafe_fn)]
-
-use crate::io::ErrorKind;
-use crate::mem;
-
-#[path = "../unix/alloc.rs"]
-pub mod alloc;
-pub mod args;
-#[path = "../unix/cmath.rs"]
-pub mod cmath;
-pub mod condvar;
-pub mod io;
-#[path = "../unix/memchr.rs"]
-pub mod memchr;
-pub mod mutex;
-pub mod os;
-pub mod rwlock;
-pub mod stack_overflow;
-pub mod stdio;
-pub mod thread;
-#[path = "../unix/thread_local_key.rs"]
-pub mod thread_local_key;
-pub mod time;
-
-pub use crate::sys_common::os_str_bytes as os_str;
-
-mod abi;
-
-mod shims;
-pub use self::shims::*;
-
-#[allow(dead_code)]
-pub fn init() {}
-
-pub fn decode_error_kind(errno: i32) -> ErrorKind {
-    match errno {
-        x if x == abi::errno::ACCES as i32 => ErrorKind::PermissionDenied,
-        x if x == abi::errno::ADDRINUSE as i32 => ErrorKind::AddrInUse,
-        x if x == abi::errno::ADDRNOTAVAIL as i32 => ErrorKind::AddrNotAvailable,
-        x if x == abi::errno::AGAIN as i32 => ErrorKind::WouldBlock,
-        x if x == abi::errno::CONNABORTED as i32 => ErrorKind::ConnectionAborted,
-        x if x == abi::errno::CONNREFUSED as i32 => ErrorKind::ConnectionRefused,
-        x if x == abi::errno::CONNRESET as i32 => ErrorKind::ConnectionReset,
-        x if x == abi::errno::EXIST as i32 => ErrorKind::AlreadyExists,
-        x if x == abi::errno::INTR as i32 => ErrorKind::Interrupted,
-        x if x == abi::errno::INVAL as i32 => ErrorKind::InvalidInput,
-        x if x == abi::errno::NOENT as i32 => ErrorKind::NotFound,
-        x if x == abi::errno::NOTCONN as i32 => ErrorKind::NotConnected,
-        x if x == abi::errno::PERM as i32 => ErrorKind::PermissionDenied,
-        x if x == abi::errno::PIPE as i32 => ErrorKind::BrokenPipe,
-        x if x == abi::errno::TIMEDOUT as i32 => ErrorKind::TimedOut,
-        _ => ErrorKind::Other,
-    }
-}
-
-pub fn abort_internal() -> ! {
-    core::intrinsics::abort();
-}
-
-pub use libc::strlen;
-
-pub fn hashmap_random_keys() -> (u64, u64) {
-    unsafe {
-        let mut v: mem::MaybeUninit<(u64, u64)> = mem::MaybeUninit::uninit();
-        libc::arc4random_buf(v.as_mut_ptr() as *mut libc::c_void, mem::size_of_val(&v));
-        v.assume_init()
-    }
-}
-
-#[cfg_attr(feature = "backtrace", link(name = "unwind"))]
-#[link(name = "c")]
-#[link(name = "compiler_rt")]
-extern "C" {}
diff --git a/library/std/src/sys/cloudabi/mutex.rs b/library/std/src/sys/cloudabi/mutex.rs
deleted file mode 100644
index 9dafcbc1fba..00000000000
--- a/library/std/src/sys/cloudabi/mutex.rs
+++ /dev/null
@@ -1,153 +0,0 @@
-use crate::cell::Cell;
-use crate::mem;
-use crate::mem::MaybeUninit;
-use crate::sync::atomic::{AtomicU32, Ordering};
-use crate::sys::cloudabi::abi;
-use crate::sys::rwlock::{self, RWLock};
-
-extern "C" {
-    #[thread_local]
-    static __pthread_thread_id: abi::tid;
-}
-
-// Implement Mutex using an RWLock. This doesn't introduce any
-// performance overhead in this environment, as the operations would be
-// implemented identically.
-pub struct Mutex(RWLock);
-
-pub type MovableMutex = Mutex;
-
-pub unsafe fn raw(m: &Mutex) -> &AtomicU32 {
-    rwlock::raw(&m.0)
-}
-
-impl Mutex {
-    pub const fn new() -> Mutex {
-        Mutex(RWLock::new())
-    }
-
-    pub unsafe fn init(&mut self) {
-        // This function should normally reinitialize the mutex after
-        // moving it to a different memory address. This implementation
-        // does not require adjustments after moving.
-    }
-
-    pub unsafe fn try_lock(&self) -> bool {
-        self.0.try_write()
-    }
-
-    pub unsafe fn lock(&self) {
-        self.0.write()
-    }
-
-    pub unsafe fn unlock(&self) {
-        self.0.write_unlock()
-    }
-
-    pub unsafe fn destroy(&self) {
-        self.0.destroy()
-    }
-}
-
-pub struct ReentrantMutex {
-    lock: AtomicU32,
-    recursion: Cell<u32>,
-}
-
-unsafe impl Send for ReentrantMutex {}
-unsafe impl Sync for ReentrantMutex {}
-
-impl ReentrantMutex {
-    pub const unsafe fn uninitialized() -> ReentrantMutex {
-        ReentrantMutex { lock: AtomicU32::new(abi::LOCK_UNLOCKED.0), recursion: Cell::new(0) }
-    }
-
-    pub unsafe fn init(&self) {}
-
-    pub unsafe fn try_lock(&self) -> bool {
-        // Attempt to acquire the lock.
-        if let Err(old) = self.lock.compare_exchange(
-            abi::LOCK_UNLOCKED.0,
-            __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
-            Ordering::Acquire,
-            Ordering::Relaxed,
-        ) {
-            // If we fail to acquire the lock, it may be the case
-            // that we've already acquired it and may need to recurse.
-            if old & !abi::LOCK_KERNEL_MANAGED.0 == __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0 {
-                self.recursion.set(self.recursion.get() + 1);
-                true
-            } else {
-                false
-            }
-        } else {
-            // Success.
-            assert_eq!(self.recursion.get(), 0, "Mutex has invalid recursion count");
-            true
-        }
-    }
-
-    pub unsafe fn lock(&self) {
-        if !self.try_lock() {
-            // Call into the kernel to acquire a write lock.
-            let lock = &self.lock as *const AtomicU32;
-            let subscription = abi::subscription {
-                type_: abi::eventtype::LOCK_WRLOCK,
-                union: abi::subscription_union {
-                    lock: abi::subscription_lock {
-                        lock: lock as *mut abi::lock,
-                        lock_scope: abi::scope::PRIVATE,
-                    },
-                },
-                ..mem::zeroed()
-            };
-            let mut event = MaybeUninit::<abi::event>::uninit();
-            let mut nevents = MaybeUninit::<usize>::uninit();
-            // SAFE: The caller must to ensure that `event` and `nevents` are initialized.
-            let ret =
-                unsafe { abi::poll(&subscription, event.as_mut_ptr(), 1, nevents.as_mut_ptr()) };
-            assert_eq!(ret, abi::errno::SUCCESS, "Failed to acquire mutex");
-            let event = event.assume_init();
-            assert_eq!(event.error, abi::errno::SUCCESS, "Failed to acquire mutex");
-        }
-    }
-
-    pub unsafe fn unlock(&self) {
-        assert_eq!(
-            self.lock.load(Ordering::Relaxed) & !abi::LOCK_KERNEL_MANAGED.0,
-            __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
-            "This mutex is locked by a different thread"
-        );
-
-        let r = self.recursion.get();
-        if r > 0 {
-            self.recursion.set(r - 1);
-        } else if !self
-            .lock
-            .compare_exchange(
-                __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
-                abi::LOCK_UNLOCKED.0,
-                Ordering::Release,
-                Ordering::Relaxed,
-            )
-            .is_ok()
-        {
-            // Lock is managed by kernelspace. Call into the kernel
-            // to unblock waiting threads.
-            let ret = abi::lock_unlock(
-                &self.lock as *const AtomicU32 as *mut abi::lock,
-                abi::scope::PRIVATE,
-            );
-            assert_eq!(ret, abi::errno::SUCCESS, "Failed to unlock a mutex");
-        }
-    }
-
-    pub unsafe fn destroy(&self) {
-        assert_eq!(
-            self.lock.load(Ordering::Relaxed),
-            abi::LOCK_UNLOCKED.0,
-            "Attempted to destroy locked mutex"
-        );
-        assert_eq!(self.recursion.get(), 0, "Recursion counter invalid");
-    }
-}
diff --git a/library/std/src/sys/cloudabi/os.rs b/library/std/src/sys/cloudabi/os.rs
deleted file mode 100644
index 326faaa852a..00000000000
--- a/library/std/src/sys/cloudabi/os.rs
+++ /dev/null
@@ -1,26 +0,0 @@
-use crate::ffi::CStr;
-use crate::str;
-
-use libc::c_int;
-
-pub use crate::sys::cloudabi::shims::os::*;
-
-pub fn errno() -> i32 {
-    extern "C" {
-        #[thread_local]
-        static errno: c_int;
-    }
-
-    unsafe { errno as i32 }
-}
-
-/// Gets a detailed string description for the given error number.
-pub fn error_string(errno: i32) -> String {
-    // cloudlibc's strerror() is guaranteed to be thread-safe. There is
-    // thus no need to use strerror_r().
-    str::from_utf8(unsafe { CStr::from_ptr(libc::strerror(errno)) }.to_bytes()).unwrap().to_owned()
-}
-
-pub fn exit(code: i32) -> ! {
-    unsafe { libc::exit(code as c_int) }
-}
diff --git a/library/std/src/sys/cloudabi/rwlock.rs b/library/std/src/sys/cloudabi/rwlock.rs
deleted file mode 100644
index 508de8ba47c..00000000000
--- a/library/std/src/sys/cloudabi/rwlock.rs
+++ /dev/null
@@ -1,215 +0,0 @@
-use crate::mem;
-use crate::mem::MaybeUninit;
-use crate::sync::atomic::{AtomicU32, Ordering};
-use crate::sys::cloudabi::abi;
-
-extern "C" {
-    #[thread_local]
-    static __pthread_thread_id: abi::tid;
-}
-
-#[thread_local]
-static mut RDLOCKS_ACQUIRED: u32 = 0;
-
-pub struct RWLock {
-    lock: AtomicU32,
-}
-
-pub unsafe fn raw(r: &RWLock) -> &AtomicU32 {
-    &r.lock
-}
-
-unsafe impl Send for RWLock {}
-unsafe impl Sync for RWLock {}
-
-impl RWLock {
-    pub const fn new() -> RWLock {
-        RWLock { lock: AtomicU32::new(abi::LOCK_UNLOCKED.0) }
-    }
-
-    pub unsafe fn try_read(&self) -> bool {
-        let mut old = abi::LOCK_UNLOCKED.0;
-        while let Err(cur) =
-            self.lock.compare_exchange_weak(old, old + 1, Ordering::Acquire, Ordering::Relaxed)
-        {
-            if (cur & abi::LOCK_WRLOCKED.0) != 0 {
-                // Another thread already has a write lock.
-                assert_ne!(
-                    old & !abi::LOCK_KERNEL_MANAGED.0,
-                    __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
-                    "Attempted to acquire a read lock while holding a write lock"
-                );
-                return false;
-            } else if (old & abi::LOCK_KERNEL_MANAGED.0) != 0 && RDLOCKS_ACQUIRED == 0 {
-                // Lock has threads waiting for the lock. Only acquire
-                // the lock if we have already acquired read locks. In
-                // that case, it is justified to acquire this lock to
-                // prevent a deadlock.
-                return false;
-            }
-            old = cur;
-        }
-
-        RDLOCKS_ACQUIRED += 1;
-        true
-    }
-
-    pub unsafe fn read(&self) {
-        if !self.try_read() {
-            // Call into the kernel to acquire a read lock.
-            let subscription = abi::subscription {
-                type_: abi::eventtype::LOCK_RDLOCK,
-                union: abi::subscription_union {
-                    lock: abi::subscription_lock {
-                        lock: &self.lock as *const AtomicU32 as *mut abi::lock,
-                        lock_scope: abi::scope::PRIVATE,
-                    },
-                },
-                ..mem::zeroed()
-            };
-            let mut event = MaybeUninit::<abi::event>::uninit();
-            let mut nevents = MaybeUninit::<usize>::uninit();
-            let ret = abi::poll(&subscription, event.as_mut_ptr(), 1, nevents.as_mut_ptr());
-            assert_eq!(ret, abi::errno::SUCCESS, "Failed to acquire read lock");
-            let event = event.assume_init();
-            assert_eq!(event.error, abi::errno::SUCCESS, "Failed to acquire read lock");
-
-            RDLOCKS_ACQUIRED += 1;
-        }
-    }
-
-    pub unsafe fn read_unlock(&self) {
-        // Perform a read unlock. We can do this in userspace, except when
-        // other threads are blocked and we are performing the last unlock.
-        // In that case, call into the kernel.
-        //
-        // Other threads may attempt to increment the read lock count,
-        // meaning that the call into the kernel could be spurious. To
-        // prevent this from happening, upgrade to a write lock first. This
-        // allows us to call into the kernel, having the guarantee that the
-        // lock value will not change in the meantime.
-        assert!(RDLOCKS_ACQUIRED > 0, "Bad lock count");
-        let mut old = 1;
-        loop {
-            if old == 1 | abi::LOCK_KERNEL_MANAGED.0 {
-                // Last read lock while threads are waiting. Attempt to upgrade
-                // to a write lock before calling into the kernel to unlock.
-                if let Err(cur) = self.lock.compare_exchange_weak(
-                    old,
-                    __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0 | abi::LOCK_KERNEL_MANAGED.0,
-                    Ordering::Acquire,
-                    Ordering::Relaxed,
-                ) {
-                    old = cur;
-                } else {
-                    // Call into the kernel to unlock.
-                    let ret = abi::lock_unlock(
-                        &self.lock as *const AtomicU32 as *mut abi::lock,
-                        abi::scope::PRIVATE,
-                    );
-                    assert_eq!(ret, abi::errno::SUCCESS, "Failed to write unlock a rwlock");
-                    break;
-                }
-            } else {
-                // No threads waiting or not the last read lock. Just decrement
-                // the read lock count.
-                assert_ne!(old & !abi::LOCK_KERNEL_MANAGED.0, 0, "This rwlock is not locked");
-                assert_eq!(
-                    old & abi::LOCK_WRLOCKED.0,
-                    0,
-                    "Attempted to read-unlock a write-locked rwlock"
-                );
-                if let Err(cur) = self.lock.compare_exchange_weak(
-                    old,
-                    old - 1,
-                    Ordering::Acquire,
-                    Ordering::Relaxed,
-                ) {
-                    old = cur;
-                } else {
-                    break;
-                }
-            }
-        }
-
-        RDLOCKS_ACQUIRED -= 1;
-    }
-
-    pub unsafe fn try_write(&self) -> bool {
-        // Attempt to acquire the lock.
-        if let Err(old) = self.lock.compare_exchange(
-            abi::LOCK_UNLOCKED.0,
-            __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
-            Ordering::Acquire,
-            Ordering::Relaxed,
-        ) {
-            // Failure. Crash upon recursive acquisition.
-            assert_ne!(
-                old & !abi::LOCK_KERNEL_MANAGED.0,
-                __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
-                "Attempted to recursive write-lock a rwlock",
-            );
-            false
-        } else {
-            // Success.
-            true
-        }
-    }
-
-    pub unsafe fn write(&self) {
-        if !self.try_write() {
-            // Call into the kernel to acquire a write lock.
-            let subscription = abi::subscription {
-                type_: abi::eventtype::LOCK_WRLOCK,
-                union: abi::subscription_union {
-                    lock: abi::subscription_lock {
-                        lock: &self.lock as *const AtomicU32 as *mut abi::lock,
-                        lock_scope: abi::scope::PRIVATE,
-                    },
-                },
-                ..mem::zeroed()
-            };
-            let mut event = MaybeUninit::<abi::event>::uninit();
-            let mut nevents = MaybeUninit::<usize>::uninit();
-            let ret = abi::poll(&subscription, event.as_mut_ptr(), 1, nevents.as_mut_ptr());
-            assert_eq!(ret, abi::errno::SUCCESS, "Failed to acquire write lock");
-            let event = event.assume_init();
-            assert_eq!(event.error, abi::errno::SUCCESS, "Failed to acquire write lock");
-        }
-    }
-
-    pub unsafe fn write_unlock(&self) {
-        assert_eq!(
-            self.lock.load(Ordering::Relaxed) & !abi::LOCK_KERNEL_MANAGED.0,
-            __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
-            "This rwlock is not write-locked by this thread"
-        );
-
-        if !self
-            .lock
-            .compare_exchange(
-                __pthread_thread_id.0 | abi::LOCK_WRLOCKED.0,
-                abi::LOCK_UNLOCKED.0,
-                Ordering::Release,
-                Ordering::Relaxed,
-            )
-            .is_ok()
-        {
-            // Lock is managed by kernelspace. Call into the kernel
-            // to unblock waiting threads.
-            let ret = abi::lock_unlock(
-                &self.lock as *const AtomicU32 as *mut abi::lock,
-                abi::scope::PRIVATE,
-            );
-            assert_eq!(ret, abi::errno::SUCCESS, "Failed to write unlock a rwlock");
-        }
-    }
-
-    pub unsafe fn destroy(&self) {
-        assert_eq!(
-            self.lock.load(Ordering::Relaxed),
-            abi::LOCK_UNLOCKED.0,
-            "Attempted to destroy locked rwlock"
-        );
-    }
-}
diff --git a/library/std/src/sys/cloudabi/shims/args.rs b/library/std/src/sys/cloudabi/shims/args.rs
deleted file mode 100644
index f5cf71caf6c..00000000000
--- a/library/std/src/sys/cloudabi/shims/args.rs
+++ /dev/null
@@ -1,35 +0,0 @@
-use crate::ffi::OsString;
-
-pub struct Args(());
-
-impl Args {
-    pub fn inner_debug(&self) -> &[OsString] {
-        &[]
-    }
-}
-
-impl Iterator for Args {
-    type Item = OsString;
-    fn next(&mut self) -> Option<OsString> {
-        None
-    }
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        (0, Some(0))
-    }
-}
-
-impl ExactSizeIterator for Args {
-    fn len(&self) -> usize {
-        0
-    }
-}
-
-impl DoubleEndedIterator for Args {
-    fn next_back(&mut self) -> Option<OsString> {
-        None
-    }
-}
-
-pub fn args() -> Args {
-    Args(())
-}
diff --git a/library/std/src/sys/cloudabi/shims/env.rs b/library/std/src/sys/cloudabi/shims/env.rs
deleted file mode 100644
index de165a864b9..00000000000
--- a/library/std/src/sys/cloudabi/shims/env.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-pub mod os {
-    pub const FAMILY: &str = "cloudabi";
-    pub const OS: &str = "cloudabi";
-    pub const DLL_PREFIX: &str = "lib";
-    pub const DLL_SUFFIX: &str = ".so";
-    pub const DLL_EXTENSION: &str = "so";
-    pub const EXE_SUFFIX: &str = "";
-    pub const EXE_EXTENSION: &str = "";
-}
diff --git a/library/std/src/sys/cloudabi/shims/fs.rs b/library/std/src/sys/cloudabi/shims/fs.rs
deleted file mode 100644
index ecb5b51cccd..00000000000
--- a/library/std/src/sys/cloudabi/shims/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/cloudabi/shims/mod.rs b/library/std/src/sys/cloudabi/shims/mod.rs
deleted file mode 100644
index b1b5f142f45..00000000000
--- a/library/std/src/sys/cloudabi/shims/mod.rs
+++ /dev/null
@@ -1,19 +0,0 @@
-use crate::io;
-
-pub mod args;
-pub mod env;
-pub mod fs;
-pub mod net;
-pub mod os;
-#[path = "../../unix/path.rs"]
-pub mod path;
-pub mod pipe;
-pub mod process;
-
-// This enum is used as the storage for a bunch of types which can't actually exist.
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
-pub enum Void {}
-
-pub fn unsupported<T>() -> io::Result<T> {
-    Err(io::Error::new(io::ErrorKind::Other, "This function is not available on CloudABI."))
-}
diff --git a/library/std/src/sys/cloudabi/shims/net.rs b/library/std/src/sys/cloudabi/shims/net.rs
deleted file mode 100644
index 375aaab405d..00000000000
--- a/library/std/src/sys/cloudabi/shims/net.rs
+++ /dev/null
@@ -1,326 +0,0 @@
-use crate::convert::TryFrom;
-use crate::fmt;
-use crate::io::{self, IoSlice, IoSliceMut};
-use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr};
-use crate::sys::{unsupported, Void};
-use crate::time::Duration;
-
-#[allow(unused_extern_crates)]
-pub extern crate libc as netc;
-
-pub struct TcpStream(Void);
-
-impl TcpStream {
-    pub fn connect(_: io::Result<&SocketAddr>) -> io::Result<TcpStream> {
-        unsupported()
-    }
-
-    pub fn connect_timeout(_: &SocketAddr, _: Duration) -> io::Result<TcpStream> {
-        unsupported()
-    }
-
-    pub fn set_read_timeout(&self, _: Option<Duration>) -> io::Result<()> {
-        match self.0 {}
-    }
-
-    pub fn set_write_timeout(&self, _: Option<Duration>) -> io::Result<()> {
-        match self.0 {}
-    }
-
-    pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
-        match self.0 {}
-    }
-
-    pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
-        match self.0 {}
-    }
-
-    pub fn peek(&self, _: &mut [u8]) -> io::Result<usize> {
-        match self.0 {}
-    }
-
-    pub fn read(&self, _: &mut [u8]) -> io::Result<usize> {
-        match self.0 {}
-    }
-
-    pub fn read_vectored(&self, _: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
-        match self.0 {}
-    }
-
-    pub fn is_read_vectored(&self) -> bool {
-        match self.0 {}
-    }
-
-    pub fn write(&self, _: &[u8]) -> io::Result<usize> {
-        match self.0 {}
-    }
-
-    pub fn write_vectored(&self, _: &[IoSlice<'_>]) -> io::Result<usize> {
-        match self.0 {}
-    }
-
-    pub fn is_write_vectored(&self) -> bool {
-        match self.0 {}
-    }
-
-    pub fn peer_addr(&self) -> io::Result<SocketAddr> {
-        match self.0 {}
-    }
-
-    pub fn socket_addr(&self) -> io::Result<SocketAddr> {
-        match self.0 {}
-    }
-
-    pub fn shutdown(&self, _: Shutdown) -> io::Result<()> {
-        match self.0 {}
-    }
-
-    pub fn duplicate(&self) -> io::Result<TcpStream> {
-        match self.0 {}
-    }
-
-    pub fn set_nodelay(&self, _: bool) -> io::Result<()> {
-        match self.0 {}
-    }
-
-    pub fn nodelay(&self) -> io::Result<bool> {
-        match self.0 {}
-    }
-
-    pub fn set_ttl(&self, _: u32) -> io::Result<()> {
-        match self.0 {}
-    }
-
-    pub fn ttl(&self) -> io::Result<u32> {
-        match self.0 {}
-    }
-
-    pub fn take_error(&self) -> io::Result<Option<io::Error>> {
-        match self.0 {}
-    }
-
-    pub fn set_nonblocking(&self, _: bool) -> io::Result<()> {
-        match self.0 {}
-    }
-}
-
-impl fmt::Debug for TcpStream {
-    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self.0 {}
-    }
-}
-
-pub struct TcpListener(Void);
-
-impl TcpListener {
-    pub fn bind(_: io::Result<&SocketAddr>) -> io::Result<TcpListener> {
-        unsupported()
-    }
-
-    pub fn socket_addr(&self) -> io::Result<SocketAddr> {
-        match self.0 {}
-    }
-
-    pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> {
-        match self.0 {}
-    }
-
-    pub fn duplicate(&self) -> io::Result<TcpListener> {
-        match self.0 {}
-    }
-
-    pub fn set_ttl(&self, _: u32) -> io::Result<()> {
-        match self.0 {}
-    }
-
-    pub fn ttl(&self) -> io::Result<u32> {
-        match self.0 {}
-    }
-
-    pub fn set_only_v6(&self, _: bool) -> io::Result<()> {
-        match self.0 {}
-    }
-
-    pub fn only_v6(&self) -> io::Result<bool> {
-        match self.0 {}
-    }
-
-    pub fn take_error(&self) -> io::Result<Option<io::Error>> {
-        match self.0 {}
-    }
-
-    pub fn set_nonblocking(&self, _: bool) -> io::Result<()> {
-        match self.0 {}
-    }
-}
-
-impl fmt::Debug for TcpListener {
-    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self.0 {}
-    }
-}
-
-pub struct UdpSocket(Void);
-
-impl UdpSocket {
-    pub fn bind(_: io::Result<&SocketAddr>) -> io::Result<UdpSocket> {
-        unsupported()
-    }
-
-    pub fn peer_addr(&self) -> io::Result<SocketAddr> {
-        match self.0 {}
-    }
-
-    pub fn socket_addr(&self) -> io::Result<SocketAddr> {
-        match self.0 {}
-    }
-
-    pub fn recv_from(&self, _: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
-        match self.0 {}
-    }
-
-    pub fn peek_from(&self, _: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
-        match self.0 {}
-    }
-
-    pub fn send_to(&self, _: &[u8], _: &SocketAddr) -> io::Result<usize> {
-        match self.0 {}
-    }
-
-    pub fn duplicate(&self) -> io::Result<UdpSocket> {
-        match self.0 {}
-    }
-
-    pub fn set_read_timeout(&self, _: Option<Duration>) -> io::Result<()> {
-        match self.0 {}
-    }
-
-    pub fn set_write_timeout(&self, _: Option<Duration>) -> io::Result<()> {
-        match self.0 {}
-    }
-
-    pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
-        match self.0 {}
-    }
-
-    pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
-        match self.0 {}
-    }
-
-    pub fn set_broadcast(&self, _: bool) -> io::Result<()> {
-        match self.0 {}
-    }
-
-    pub fn broadcast(&self) -> io::Result<bool> {
-        match self.0 {}
-    }
-
-    pub fn set_multicast_loop_v4(&self, _: bool) -> io::Result<()> {
-        match self.0 {}
-    }
-
-    pub fn multicast_loop_v4(&self) -> io::Result<bool> {
-        match self.0 {}
-    }
-
-    pub fn set_multicast_ttl_v4(&self, _: u32) -> io::Result<()> {
-        match self.0 {}
-    }
-
-    pub fn multicast_ttl_v4(&self) -> io::Result<u32> {
-        match self.0 {}
-    }
-
-    pub fn set_multicast_loop_v6(&self, _: bool) -> io::Result<()> {
-        match self.0 {}
-    }
-
-    pub fn multicast_loop_v6(&self) -> io::Result<bool> {
-        match self.0 {}
-    }
-
-    pub fn join_multicast_v4(&self, _: &Ipv4Addr, _: &Ipv4Addr) -> io::Result<()> {
-        match self.0 {}
-    }
-
-    pub fn join_multicast_v6(&self, _: &Ipv6Addr, _: u32) -> io::Result<()> {
-        match self.0 {}
-    }
-
-    pub fn leave_multicast_v4(&self, _: &Ipv4Addr, _: &Ipv4Addr) -> io::Result<()> {
-        match self.0 {}
-    }
-
-    pub fn leave_multicast_v6(&self, _: &Ipv6Addr, _: u32) -> io::Result<()> {
-        match self.0 {}
-    }
-
-    pub fn set_ttl(&self, _: u32) -> io::Result<()> {
-        match self.0 {}
-    }
-
-    pub fn ttl(&self) -> io::Result<u32> {
-        match self.0 {}
-    }
-
-    pub fn take_error(&self) -> io::Result<Option<io::Error>> {
-        match self.0 {}
-    }
-
-    pub fn set_nonblocking(&self, _: bool) -> io::Result<()> {
-        match self.0 {}
-    }
-
-    pub fn recv(&self, _: &mut [u8]) -> io::Result<usize> {
-        match self.0 {}
-    }
-
-    pub fn peek(&self, _: &mut [u8]) -> io::Result<usize> {
-        match self.0 {}
-    }
-
-    pub fn send(&self, _: &[u8]) -> io::Result<usize> {
-        match self.0 {}
-    }
-
-    pub fn connect(&self, _: io::Result<&SocketAddr>) -> io::Result<()> {
-        match self.0 {}
-    }
-}
-
-impl fmt::Debug for UdpSocket {
-    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self.0 {}
-    }
-}
-
-pub struct LookupHost(Void);
-
-impl LookupHost {
-    pub fn port(&self) -> u16 {
-        match self.0 {}
-    }
-}
-
-impl Iterator for LookupHost {
-    type Item = SocketAddr;
-    fn next(&mut self) -> Option<SocketAddr> {
-        match self.0 {}
-    }
-}
-
-impl TryFrom<&str> for LookupHost {
-    type Error = io::Error;
-
-    fn try_from(_v: &str) -> io::Result<LookupHost> {
-        unsupported()
-    }
-}
-
-impl<'a> TryFrom<(&'a str, u16)> for LookupHost {
-    type Error = io::Error;
-
-    fn try_from(_v: (&'a str, u16)) -> io::Result<LookupHost> {
-        unsupported()
-    }
-}
diff --git a/library/std/src/sys/cloudabi/shims/os.rs b/library/std/src/sys/cloudabi/shims/os.rs
deleted file mode 100644
index 779e6d54b7c..00000000000
--- a/library/std/src/sys/cloudabi/shims/os.rs
+++ /dev/null
@@ -1,86 +0,0 @@
-use crate::error::Error as StdError;
-use crate::ffi::{OsStr, OsString};
-use crate::fmt;
-use crate::io;
-use crate::iter;
-use crate::path::{self, PathBuf};
-use crate::sys::{unsupported, Void};
-
-pub fn getcwd() -> io::Result<PathBuf> {
-    unsupported()
-}
-
-pub fn chdir(_: &path::Path) -> io::Result<()> {
-    unsupported()
-}
-
-pub type Env = iter::Empty<(OsString, OsString)>;
-
-pub fn env() -> Env {
-    iter::empty()
-}
-
-pub fn getenv(_: &OsStr) -> io::Result<Option<OsString>> {
-    Ok(None)
-}
-
-pub fn setenv(_: &OsStr, _: &OsStr) -> io::Result<()> {
-    unsupported()
-}
-
-pub fn unsetenv(_: &OsStr) -> io::Result<()> {
-    unsupported()
-}
-
-pub struct SplitPaths<'a>(&'a Void);
-
-pub fn split_paths(_unparsed: &OsStr) -> SplitPaths<'_> {
-    panic!("unsupported")
-}
-
-impl<'a> Iterator for SplitPaths<'a> {
-    type Item = PathBuf;
-    fn next(&mut self) -> Option<PathBuf> {
-        match *self.0 {}
-    }
-}
-
-#[derive(Debug)]
-pub struct JoinPathsError;
-
-pub fn join_paths<I, T>(_paths: I) -> Result<OsString, JoinPathsError>
-where
-    I: Iterator<Item = T>,
-    T: AsRef<OsStr>,
-{
-    Err(JoinPathsError)
-}
-
-impl fmt::Display for JoinPathsError {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        "not supported on CloudABI yet".fmt(f)
-    }
-}
-
-impl StdError for JoinPathsError {
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
-        "not supported on CloudABI yet"
-    }
-}
-
-pub fn home_dir() -> Option<PathBuf> {
-    None
-}
-
-pub fn temp_dir() -> PathBuf {
-    PathBuf::from("/tmp")
-}
-
-pub fn current_exe() -> io::Result<PathBuf> {
-    unsupported()
-}
-
-pub fn getpid() -> u32 {
-    1
-}
diff --git a/library/std/src/sys/cloudabi/shims/pipe.rs b/library/std/src/sys/cloudabi/shims/pipe.rs
deleted file mode 100644
index 10d0925823e..00000000000
--- a/library/std/src/sys/cloudabi/shims/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/cloudabi/shims/process.rs b/library/std/src/sys/cloudabi/shims/process.rs
deleted file mode 100644
index 4702e5c5492..00000000000
--- a/library/std/src/sys/cloudabi/shims/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/cloudabi/stack_overflow.rs b/library/std/src/sys/cloudabi/stack_overflow.rs
deleted file mode 100644
index 9339b143731..00000000000
--- a/library/std/src/sys/cloudabi/stack_overflow.rs
+++ /dev/null
@@ -1,5 +0,0 @@
-#![cfg_attr(test, allow(dead_code))]
-
-pub unsafe fn init() {}
-
-pub unsafe fn cleanup() {}
diff --git a/library/std/src/sys/cloudabi/stdio.rs b/library/std/src/sys/cloudabi/stdio.rs
deleted file mode 100644
index 7fec4731a46..00000000000
--- a/library/std/src/sys/cloudabi/stdio.rs
+++ /dev/null
@@ -1,66 +0,0 @@
-use crate::io;
-use crate::sys::cloudabi::abi;
-
-pub struct Stdin(());
-pub struct Stdout(());
-pub struct Stderr(());
-
-impl Stdin {
-    pub const fn new() -> Stdin {
-        Stdin(())
-    }
-}
-
-impl io::Read for Stdin {
-    fn read(&mut self, _buf: &mut [u8]) -> io::Result<usize> {
-        Ok(0)
-    }
-}
-
-impl Stdout {
-    pub const fn new() -> Stdout {
-        Stdout(())
-    }
-}
-
-impl io::Write for Stdout {
-    fn write(&mut self, _buf: &[u8]) -> io::Result<usize> {
-        Err(io::Error::new(
-            io::ErrorKind::BrokenPipe,
-            "Stdout is not connected to any output in this environment",
-        ))
-    }
-
-    fn flush(&mut self) -> io::Result<()> {
-        Ok(())
-    }
-}
-
-impl Stderr {
-    pub const fn new() -> Stderr {
-        Stderr(())
-    }
-}
-
-impl io::Write for Stderr {
-    fn write(&mut self, _buf: &[u8]) -> io::Result<usize> {
-        Err(io::Error::new(
-            io::ErrorKind::BrokenPipe,
-            "Stderr is not connected to any output in this environment",
-        ))
-    }
-
-    fn flush(&mut self) -> io::Result<()> {
-        Ok(())
-    }
-}
-
-pub fn is_ebadf(err: &io::Error) -> bool {
-    err.raw_os_error() == Some(abi::errno::BADF as i32)
-}
-
-pub const STDIN_BUF_SIZE: usize = crate::sys_common::io::DEFAULT_BUF_SIZE;
-
-pub fn panic_output() -> Option<impl io::Write> {
-    Some(Stderr::new())
-}
diff --git a/library/std/src/sys/cloudabi/thread.rs b/library/std/src/sys/cloudabi/thread.rs
deleted file mode 100644
index a15dc8653e8..00000000000
--- a/library/std/src/sys/cloudabi/thread.rs
+++ /dev/null
@@ -1,118 +0,0 @@
-use crate::cmp;
-use crate::ffi::CStr;
-use crate::io;
-use crate::mem;
-use crate::ptr;
-use crate::sys::cloudabi::abi;
-use crate::sys::time::checked_dur2intervals;
-use crate::time::Duration;
-
-pub const DEFAULT_MIN_STACK_SIZE: usize = 2 * 1024 * 1024;
-
-pub struct Thread {
-    id: libc::pthread_t,
-}
-
-// CloudABI has pthread_t as a pointer in which case we still want
-// a thread to be Send/Sync
-unsafe impl Send for Thread {}
-unsafe impl Sync for Thread {}
-
-impl Thread {
-    // unsafe: see thread::Builder::spawn_unchecked for safety requirements
-    pub unsafe fn new(stack: usize, p: Box<dyn FnOnce()>) -> io::Result<Thread> {
-        let p = Box::into_raw(box p);
-        let mut native: libc::pthread_t = mem::zeroed();
-        let mut attr: libc::pthread_attr_t = mem::zeroed();
-        assert_eq!(libc::pthread_attr_init(&mut attr), 0);
-
-        let stack_size = cmp::max(stack, min_stack_size(&attr));
-        assert_eq!(libc::pthread_attr_setstacksize(&mut attr, stack_size), 0);
-
-        let ret = libc::pthread_create(&mut native, &attr, thread_start, p as *mut _);
-        // Note: if the thread creation fails and this assert fails, then p will
-        // be leaked. However, an alternative design could cause double-free
-        // which is clearly worse.
-        assert_eq!(libc::pthread_attr_destroy(&mut attr), 0);
-
-        return if ret != 0 {
-            // The thread failed to start and as a result p was not consumed. Therefore, it is
-            // safe to reconstruct the box so that it gets deallocated.
-            drop(Box::from_raw(p));
-            Err(io::Error::from_raw_os_error(ret))
-        } else {
-            Ok(Thread { id: native })
-        };
-
-        extern "C" fn thread_start(main: *mut libc::c_void) -> *mut libc::c_void {
-            unsafe {
-                // Let's run some code.
-                Box::from_raw(main as *mut Box<dyn FnOnce()>)();
-            }
-            ptr::null_mut()
-        }
-    }
-
-    pub fn yield_now() {
-        let ret = unsafe { abi::thread_yield() };
-        debug_assert_eq!(ret, abi::errno::SUCCESS);
-    }
-
-    pub fn set_name(_name: &CStr) {
-        // CloudABI has no way to set a thread name.
-    }
-
-    pub fn sleep(dur: Duration) {
-        let timeout =
-            checked_dur2intervals(&dur).expect("overflow converting duration to nanoseconds");
-        unsafe {
-            let subscription = abi::subscription {
-                type_: abi::eventtype::CLOCK,
-                union: abi::subscription_union {
-                    clock: abi::subscription_clock {
-                        clock_id: abi::clockid::MONOTONIC,
-                        timeout,
-                        ..mem::zeroed()
-                    },
-                },
-                ..mem::zeroed()
-            };
-            let mut event = mem::MaybeUninit::<abi::event>::uninit();
-            let mut nevents = mem::MaybeUninit::<usize>::uninit();
-            let ret = abi::poll(&subscription, event.as_mut_ptr(), 1, nevents.as_mut_ptr());
-            assert_eq!(ret, abi::errno::SUCCESS);
-            let event = event.assume_init();
-            assert_eq!(event.error, abi::errno::SUCCESS);
-        }
-    }
-
-    pub fn join(self) {
-        unsafe {
-            let ret = libc::pthread_join(self.id, ptr::null_mut());
-            mem::forget(self);
-            assert!(ret == 0, "failed to join thread: {}", io::Error::from_raw_os_error(ret));
-        }
-    }
-}
-
-impl Drop for Thread {
-    fn drop(&mut self) {
-        let ret = unsafe { libc::pthread_detach(self.id) };
-        debug_assert_eq!(ret, 0);
-    }
-}
-
-#[cfg_attr(test, allow(dead_code))]
-pub mod guard {
-    pub type Guard = !;
-    pub unsafe fn current() -> Option<Guard> {
-        None
-    }
-    pub unsafe fn init() -> Option<Guard> {
-        None
-    }
-}
-
-fn min_stack_size(_: *const libc::pthread_attr_t) -> usize {
-    libc::PTHREAD_STACK_MIN
-}
diff --git a/library/std/src/sys/cloudabi/time.rs b/library/std/src/sys/cloudabi/time.rs
deleted file mode 100644
index c209231cf8c..00000000000
--- a/library/std/src/sys/cloudabi/time.rs
+++ /dev/null
@@ -1,82 +0,0 @@
-use crate::mem;
-use crate::sys::cloudabi::abi;
-use crate::time::Duration;
-
-const NSEC_PER_SEC: abi::timestamp = 1_000_000_000;
-
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
-pub struct Instant {
-    t: abi::timestamp,
-}
-
-pub fn checked_dur2intervals(dur: &Duration) -> Option<abi::timestamp> {
-    dur.as_secs().checked_mul(NSEC_PER_SEC)?.checked_add(dur.subsec_nanos() as abi::timestamp)
-}
-
-impl Instant {
-    pub fn now() -> Instant {
-        unsafe {
-            let mut t: mem::MaybeUninit<abi::timestamp> = mem::MaybeUninit::uninit();
-            let ret = abi::clock_time_get(abi::clockid::MONOTONIC, 0, t.as_mut_ptr());
-            assert_eq!(ret, abi::errno::SUCCESS);
-            Instant { t: t.assume_init() }
-        }
-    }
-
-    pub fn actually_monotonic() -> bool {
-        true
-    }
-
-    pub const fn zero() -> Instant {
-        Instant { t: 0 }
-    }
-
-    pub fn checked_sub_instant(&self, other: &Instant) -> Option<Duration> {
-        let diff = self.t.checked_sub(other.t)?;
-        Some(Duration::new(diff / NSEC_PER_SEC, (diff % NSEC_PER_SEC) as u32))
-    }
-
-    pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> {
-        Some(Instant { t: self.t.checked_add(checked_dur2intervals(other)?)? })
-    }
-
-    pub fn checked_sub_duration(&self, other: &Duration) -> Option<Instant> {
-        Some(Instant { t: self.t.checked_sub(checked_dur2intervals(other)?)? })
-    }
-}
-
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
-pub struct SystemTime {
-    t: abi::timestamp,
-}
-
-impl SystemTime {
-    pub fn now() -> SystemTime {
-        unsafe {
-            let mut t: mem::MaybeUninit<abi::timestamp> = mem::MaybeUninit::uninit();
-            let ret = abi::clock_time_get(abi::clockid::REALTIME, 0, t.as_mut_ptr());
-            assert_eq!(ret, abi::errno::SUCCESS);
-            SystemTime { t: t.assume_init() }
-        }
-    }
-
-    pub fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> {
-        if self.t >= other.t {
-            let diff = self.t - other.t;
-            Ok(Duration::new(diff / NSEC_PER_SEC, (diff % NSEC_PER_SEC) as u32))
-        } else {
-            let diff = other.t - self.t;
-            Err(Duration::new(diff / NSEC_PER_SEC, (diff % NSEC_PER_SEC) as u32))
-        }
-    }
-
-    pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
-        Some(SystemTime { t: self.t.checked_add(checked_dur2intervals(other)?)? })
-    }
-
-    pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
-        Some(SystemTime { t: self.t.checked_sub(checked_dur2intervals(other)?)? })
-    }
-}
-
-pub const UNIX_EPOCH: SystemTime = SystemTime { t: 0 };
diff --git a/library/std/src/sys/hermit/fs.rs b/library/std/src/sys/hermit/fs.rs
index 829d4c943f1..1807655e971 100644
--- a/library/std/src/sys/hermit/fs.rs
+++ b/library/std/src/sys/hermit/fs.rs
@@ -377,11 +377,11 @@ pub fn readlink(_p: &Path) -> io::Result<PathBuf> {
     unsupported()
 }
 
-pub fn symlink(_src: &Path, _dst: &Path) -> io::Result<()> {
+pub fn symlink(_original: &Path, _link: &Path) -> io::Result<()> {
     unsupported()
 }
 
-pub fn link(_src: &Path, _dst: &Path) -> io::Result<()> {
+pub fn link(_original: &Path, _link: &Path) -> io::Result<()> {
     unsupported()
 }
 
diff --git a/library/std/src/sys/mod.rs b/library/std/src/sys/mod.rs
index b4628b64911..d48d9cb0efc 100644
--- a/library/std/src/sys/mod.rs
+++ b/library/std/src/sys/mod.rs
@@ -32,9 +32,6 @@ cfg_if::cfg_if! {
     } else if #[cfg(windows)] {
         mod windows;
         pub use self::windows::*;
-    } else if #[cfg(target_os = "cloudabi")] {
-        mod cloudabi;
-        pub use self::cloudabi::*;
     } else if #[cfg(target_os = "hermit")] {
         mod hermit;
         pub use self::hermit::*;
@@ -63,11 +60,10 @@ cfg_if::cfg_if! {
         // On unix we'll document what's already available
         #[stable(feature = "rust1", since = "1.0.0")]
         pub use self::ext as unix_ext;
-    } else if #[cfg(any(target_os = "cloudabi",
-                        target_os = "hermit",
+    } else if #[cfg(any(target_os = "hermit",
                         target_arch = "wasm32",
                         all(target_vendor = "fortanix", target_env = "sgx")))] {
-        // On CloudABI and wasm right now the module below doesn't compile
+        // On wasm right now the module below doesn't compile
         // (missing things in `libc` which is empty) so just omit everything
         // with an empty module
         #[unstable(issue = "none", feature = "std_internals")]
@@ -88,11 +84,10 @@ cfg_if::cfg_if! {
         #[allow(missing_docs)]
         #[stable(feature = "rust1", since = "1.0.0")]
         pub use self::ext as windows_ext;
-    } else if #[cfg(any(target_os = "cloudabi",
-                        target_os = "hermit",
+    } else if #[cfg(any(target_os = "hermit",
                         target_arch = "wasm32",
                         all(target_vendor = "fortanix", target_env = "sgx")))] {
-        // On CloudABI and wasm right now the shim below doesn't compile, so
+        // On wasm right now the shim below doesn't compile, so
         // just omit it
         #[unstable(issue = "none", feature = "std_internals")]
         #[allow(missing_docs)]
diff --git a/library/std/src/sys/sgx/ext/io.rs b/library/std/src/sys/sgx/ext/io.rs
index f79874a4aec..795a4d190cf 100644
--- a/library/std/src/sys/sgx/ext/io.rs
+++ b/library/std/src/sys/sgx/ext/io.rs
@@ -25,8 +25,11 @@ pub trait AsRawFd {
 /// descriptor.
 #[unstable(feature = "sgx_platform", issue = "56975")]
 pub trait FromRawFd {
+    /// An associated type that contains relevant metadata for `Self`.
+    type Metadata: Default;
+
     /// Constructs a new instance of `Self` from the given raw file
-    /// descriptor.
+    /// descriptor and metadata.
     ///
     /// This function **consumes ownership** of the specified file
     /// descriptor. The returned object will take responsibility for closing
@@ -38,7 +41,7 @@ pub trait FromRawFd {
     /// accidentally allow violating this contract which can cause memory
     /// unsafety in code that relies on it being true.
     #[unstable(feature = "sgx_platform", issue = "56975")]
-    unsafe fn from_raw_fd(fd: RawFd) -> Self;
+    unsafe fn from_raw_fd(fd: RawFd, metadata: Self::Metadata) -> Self;
 }
 
 /// A trait to express the ability to consume an object and acquire ownership of
@@ -71,18 +74,40 @@ impl AsRawFd for net::TcpListener {
     }
 }
 
+/// Metadata for `TcpStream`.
+#[derive(Debug, Clone, Default)]
+#[unstable(feature = "sgx_platform", issue = "56975")]
+pub struct TcpStreamMetadata {
+    /// Local address of the TCP stream
+    pub local_addr: Option<String>,
+    /// Peer address of the TCP stream
+    pub peer_addr: Option<String>,
+}
+
 impl FromRawFd for net::TcpStream {
-    unsafe fn from_raw_fd(fd: RawFd) -> net::TcpStream {
+    type Metadata = TcpStreamMetadata;
+
+    unsafe fn from_raw_fd(fd: RawFd, metadata: Self::Metadata) -> net::TcpStream {
         let fd = sys::fd::FileDesc::from_inner(fd);
-        let socket = sys::net::Socket::from_inner(fd);
-        net::TcpStream::from_inner(sys::net::TcpStream::from_inner((socket, None)))
+        let socket = sys::net::Socket::from_inner((fd, metadata.local_addr));
+        net::TcpStream::from_inner(sys::net::TcpStream::from_inner((socket, metadata.peer_addr)))
     }
 }
 
+/// Metadata for `TcpListener`.
+#[derive(Debug, Clone, Default)]
+#[unstable(feature = "sgx_platform", issue = "56975")]
+pub struct TcpListenerMetadata {
+    /// Local address of the TCP listener
+    pub local_addr: Option<String>,
+}
+
 impl FromRawFd for net::TcpListener {
-    unsafe fn from_raw_fd(fd: RawFd) -> net::TcpListener {
+    type Metadata = TcpListenerMetadata;
+
+    unsafe fn from_raw_fd(fd: RawFd, metadata: Self::Metadata) -> net::TcpListener {
         let fd = sys::fd::FileDesc::from_inner(fd);
-        let socket = sys::net::Socket::from_inner(fd);
+        let socket = sys::net::Socket::from_inner((fd, metadata.local_addr));
         net::TcpListener::from_inner(sys::net::TcpListener::from_inner(socket))
     }
 }
diff --git a/library/std/src/sys/sgx/net.rs b/library/std/src/sys/sgx/net.rs
index 666a157b09c..3dd8267921e 100644
--- a/library/std/src/sys/sgx/net.rs
+++ b/library/std/src/sys/sgx/net.rs
@@ -37,9 +37,9 @@ impl TryIntoInner<FileDesc> for Socket {
     }
 }
 
-impl FromInner<FileDesc> for Socket {
-    fn from_inner(inner: FileDesc) -> Socket {
-        Socket { inner: Arc::new(inner), local_addr: None }
+impl FromInner<(FileDesc, Option<String>)> for Socket {
+    fn from_inner((inner, local_addr): (FileDesc, Option<String>)) -> Socket {
+        Socket { inner: Arc::new(inner), local_addr }
     }
 }
 
diff --git a/library/std/src/sys/unix/ext/fs.rs b/library/std/src/sys/unix/ext/fs.rs
index 66bbc1c5854..ba75b9bac80 100644
--- a/library/std/src/sys/unix/ext/fs.rs
+++ b/library/std/src/sys/unix/ext/fs.rs
@@ -841,7 +841,7 @@ impl DirEntryExt for fs::DirEntry {
 
 /// Creates a new symbolic link on the filesystem.
 ///
-/// The `dst` path will be a symbolic link pointing to the `src` path.
+/// The `link` path will be a symbolic link pointing to the `original` path.
 ///
 /// # Examples
 ///
@@ -854,8 +854,8 @@ impl DirEntryExt for fs::DirEntry {
 /// }
 /// ```
 #[stable(feature = "symlink", since = "1.1.0")]
-pub fn symlink<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> io::Result<()> {
-    sys::fs::symlink(src.as_ref(), dst.as_ref())
+pub fn symlink<P: AsRef<Path>, Q: AsRef<Path>>(original: P, link: Q) -> io::Result<()> {
+    sys::fs::symlink(original.as_ref(), link.as_ref())
 }
 
 /// Unix-specific extensions to [`fs::DirBuilder`].
diff --git a/library/std/src/sys/unix/ext/net.rs b/library/std/src/sys/unix/ext/net.rs
deleted file mode 100644
index 3d2366554b5..00000000000
--- a/library/std/src/sys/unix/ext/net.rs
+++ /dev/null
@@ -1,1768 +0,0 @@
-//! Unix-specific networking functionality.
-
-#![stable(feature = "unix_socket", since = "1.10.0")]
-
-#[cfg(all(test, not(target_os = "emscripten")))]
-mod tests;
-
-// FIXME(#43348): Make libc adapt #[doc(cfg(...))] so we don't need these fake definitions here?
-#[cfg(not(unix))]
-#[allow(non_camel_case_types)]
-mod libc {
-    pub use libc::c_int;
-    pub type socklen_t = u32;
-    pub struct sockaddr;
-    #[derive(Clone)]
-    pub struct sockaddr_un;
-}
-
-use crate::ascii;
-use crate::ffi::OsStr;
-use crate::fmt;
-use crate::io::{self, Initializer, IoSlice, IoSliceMut};
-use crate::mem;
-use crate::net::{self, Shutdown};
-use crate::os::unix::ffi::OsStrExt;
-use crate::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
-use crate::path::Path;
-use crate::sys::net::Socket;
-use crate::sys::{self, cvt};
-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",
-    target_os = "freebsd",
-    target_os = "openbsd",
-    target_os = "netbsd",
-    target_os = "haiku"
-))]
-use libc::MSG_NOSIGNAL;
-#[cfg(not(any(
-    target_os = "linux",
-    target_os = "android",
-    target_os = "dragonfly",
-    target_os = "freebsd",
-    target_os = "openbsd",
-    target_os = "netbsd",
-    target_os = "haiku"
-)))]
-const MSG_NOSIGNAL: libc::c_int = 0x0;
-
-fn sun_path_offset(addr: &libc::sockaddr_un) -> usize {
-    // Work with an actual instance of the type since using a null pointer is UB
-    let base = addr as *const _ as usize;
-    let path = &addr.sun_path as *const _ as usize;
-    path - base
-}
-
-unsafe fn sockaddr_un(path: &Path) -> io::Result<(libc::sockaddr_un, libc::socklen_t)> {
-    let mut addr: libc::sockaddr_un = mem::zeroed();
-    addr.sun_family = libc::AF_UNIX as libc::sa_family_t;
-
-    let bytes = path.as_os_str().as_bytes();
-
-    if bytes.contains(&0) {
-        return Err(io::Error::new(
-            io::ErrorKind::InvalidInput,
-            "paths may not contain interior null bytes",
-        ));
-    }
-
-    if bytes.len() >= addr.sun_path.len() {
-        return Err(io::Error::new(
-            io::ErrorKind::InvalidInput,
-            "path must be shorter than SUN_LEN",
-        ));
-    }
-    for (dst, src) in addr.sun_path.iter_mut().zip(bytes.iter()) {
-        *dst = *src as libc::c_char;
-    }
-    // null byte for pathname addresses is already there because we zeroed the
-    // struct
-
-    let mut len = sun_path_offset(&addr) + bytes.len();
-    match bytes.get(0) {
-        Some(&0) | None => {}
-        Some(_) => len += 1,
-    }
-    Ok((addr, len as libc::socklen_t))
-}
-
-enum AddressKind<'a> {
-    Unnamed,
-    Pathname(&'a Path),
-    Abstract(&'a [u8]),
-}
-
-/// An address associated with a Unix socket.
-///
-/// # Examples
-///
-/// ```
-/// use std::os::unix::net::UnixListener;
-///
-/// let socket = match UnixListener::bind("/tmp/sock") {
-///     Ok(sock) => sock,
-///     Err(e) => {
-///         println!("Couldn't bind: {:?}", e);
-///         return
-///     }
-/// };
-/// let addr = socket.local_addr().expect("Couldn't get local address");
-/// ```
-#[derive(Clone)]
-#[stable(feature = "unix_socket", since = "1.10.0")]
-pub struct SocketAddr {
-    addr: libc::sockaddr_un,
-    len: libc::socklen_t,
-}
-
-impl SocketAddr {
-    fn new<F>(f: F) -> io::Result<SocketAddr>
-    where
-        F: FnOnce(*mut libc::sockaddr, *mut libc::socklen_t) -> libc::c_int,
-    {
-        unsafe {
-            let mut addr: libc::sockaddr_un = mem::zeroed();
-            let mut len = mem::size_of::<libc::sockaddr_un>() as libc::socklen_t;
-            cvt(f(&mut addr as *mut _ as *mut _, &mut len))?;
-            SocketAddr::from_parts(addr, len)
-        }
-    }
-
-    fn from_parts(addr: libc::sockaddr_un, mut len: libc::socklen_t) -> io::Result<SocketAddr> {
-        if len == 0 {
-            // When there is a datagram from unnamed unix socket
-            // linux returns zero bytes of address
-            len = sun_path_offset(&addr) as libc::socklen_t; // i.e., zero-length address
-        } else if addr.sun_family != libc::AF_UNIX as libc::sa_family_t {
-            return Err(io::Error::new(
-                io::ErrorKind::InvalidInput,
-                "file descriptor did not correspond to a Unix socket",
-            ));
-        }
-
-        Ok(SocketAddr { addr, len })
-    }
-
-    /// Returns `true` if the address is unnamed.
-    ///
-    /// # Examples
-    ///
-    /// A named address:
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixListener;
-    ///
-    /// fn main() -> std::io::Result<()> {
-    ///     let socket = UnixListener::bind("/tmp/sock")?;
-    ///     let addr = socket.local_addr().expect("Couldn't get local address");
-    ///     assert_eq!(addr.is_unnamed(), false);
-    ///     Ok(())
-    /// }
-    /// ```
-    ///
-    /// An unnamed address:
-    ///
-    /// ```
-    /// use std::os::unix::net::UnixDatagram;
-    ///
-    /// fn main() -> std::io::Result<()> {
-    ///     let socket = UnixDatagram::unbound()?;
-    ///     let addr = socket.local_addr().expect("Couldn't get local address");
-    ///     assert_eq!(addr.is_unnamed(), true);
-    ///     Ok(())
-    /// }
-    /// ```
-    #[stable(feature = "unix_socket", since = "1.10.0")]
-    pub fn is_unnamed(&self) -> bool {
-        if let AddressKind::Unnamed = self.address() { true } else { false }
-    }
-
-    /// Returns the contents of this address if it is a `pathname` address.
-    ///
-    /// # Examples
-    ///
-    /// With a pathname:
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixListener;
-    /// use std::path::Path;
-    ///
-    /// fn main() -> std::io::Result<()> {
-    ///     let socket = UnixListener::bind("/tmp/sock")?;
-    ///     let addr = socket.local_addr().expect("Couldn't get local address");
-    ///     assert_eq!(addr.as_pathname(), Some(Path::new("/tmp/sock")));
-    ///     Ok(())
-    /// }
-    /// ```
-    ///
-    /// Without a pathname:
-    ///
-    /// ```
-    /// use std::os::unix::net::UnixDatagram;
-    ///
-    /// fn main() -> std::io::Result<()> {
-    ///     let socket = UnixDatagram::unbound()?;
-    ///     let addr = socket.local_addr().expect("Couldn't get local address");
-    ///     assert_eq!(addr.as_pathname(), None);
-    ///     Ok(())
-    /// }
-    /// ```
-    #[stable(feature = "unix_socket", since = "1.10.0")]
-    pub fn as_pathname(&self) -> Option<&Path> {
-        if let AddressKind::Pathname(path) = self.address() { Some(path) } else { None }
-    }
-
-    fn address(&self) -> AddressKind<'_> {
-        let len = self.len as usize - sun_path_offset(&self.addr);
-        let path = unsafe { mem::transmute::<&[libc::c_char], &[u8]>(&self.addr.sun_path) };
-
-        // macOS seems to return a len of 16 and a zeroed sun_path for unnamed addresses
-        if len == 0
-            || (cfg!(not(any(target_os = "linux", target_os = "android")))
-                && self.addr.sun_path[0] == 0)
-        {
-            AddressKind::Unnamed
-        } else if self.addr.sun_path[0] == 0 {
-            AddressKind::Abstract(&path[1..len])
-        } else {
-            AddressKind::Pathname(OsStr::from_bytes(&path[..len - 1]).as_ref())
-        }
-    }
-}
-
-#[stable(feature = "unix_socket", since = "1.10.0")]
-impl fmt::Debug for SocketAddr {
-    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self.address() {
-            AddressKind::Unnamed => write!(fmt, "(unnamed)"),
-            AddressKind::Abstract(name) => write!(fmt, "{} (abstract)", AsciiEscaped(name)),
-            AddressKind::Pathname(path) => write!(fmt, "{:?} (pathname)", path),
-        }
-    }
-}
-
-struct AsciiEscaped<'a>(&'a [u8]);
-
-impl<'a> fmt::Display for AsciiEscaped<'a> {
-    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(fmt, "\"")?;
-        for byte in self.0.iter().cloned().flat_map(ascii::escape_default) {
-            write!(fmt, "{}", byte as char)?;
-        }
-        write!(fmt, "\"")
-    }
-}
-
-/// A Unix stream socket.
-///
-/// # Examples
-///
-/// ```no_run
-/// use std::os::unix::net::UnixStream;
-/// use std::io::prelude::*;
-///
-/// fn main() -> std::io::Result<()> {
-///     let mut stream = UnixStream::connect("/path/to/my/socket")?;
-///     stream.write_all(b"hello world")?;
-///     let mut response = String::new();
-///     stream.read_to_string(&mut response)?;
-///     println!("{}", response);
-///     Ok(())
-/// }
-/// ```
-#[stable(feature = "unix_socket", since = "1.10.0")]
-pub struct UnixStream(Socket);
-
-#[stable(feature = "unix_socket", since = "1.10.0")]
-impl fmt::Debug for UnixStream {
-    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        let mut builder = fmt.debug_struct("UnixStream");
-        builder.field("fd", self.0.as_inner());
-        if let Ok(addr) = self.local_addr() {
-            builder.field("local", &addr);
-        }
-        if let Ok(addr) = self.peer_addr() {
-            builder.field("peer", &addr);
-        }
-        builder.finish()
-    }
-}
-
-impl UnixStream {
-    /// Connects to the socket named by `path`.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixStream;
-    ///
-    /// let socket = match UnixStream::connect("/tmp/sock") {
-    ///     Ok(sock) => sock,
-    ///     Err(e) => {
-    ///         println!("Couldn't connect: {:?}", e);
-    ///         return
-    ///     }
-    /// };
-    /// ```
-    #[stable(feature = "unix_socket", since = "1.10.0")]
-    pub fn connect<P: AsRef<Path>>(path: P) -> io::Result<UnixStream> {
-        fn inner(path: &Path) -> io::Result<UnixStream> {
-            unsafe {
-                let inner = Socket::new_raw(libc::AF_UNIX, libc::SOCK_STREAM)?;
-                let (addr, len) = sockaddr_un(path)?;
-
-                cvt(libc::connect(*inner.as_inner(), &addr as *const _ as *const _, len))?;
-                Ok(UnixStream(inner))
-            }
-        }
-        inner(path.as_ref())
-    }
-
-    /// Creates an unnamed pair of connected sockets.
-    ///
-    /// Returns two `UnixStream`s which are connected to each other.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixStream;
-    ///
-    /// let (sock1, sock2) = match UnixStream::pair() {
-    ///     Ok((sock1, sock2)) => (sock1, sock2),
-    ///     Err(e) => {
-    ///         println!("Couldn't create a pair of sockets: {:?}", e);
-    ///         return
-    ///     }
-    /// };
-    /// ```
-    #[stable(feature = "unix_socket", since = "1.10.0")]
-    pub fn pair() -> io::Result<(UnixStream, UnixStream)> {
-        let (i1, i2) = Socket::new_pair(libc::AF_UNIX, libc::SOCK_STREAM)?;
-        Ok((UnixStream(i1), UnixStream(i2)))
-    }
-
-    /// Creates a new independently owned handle to the underlying socket.
-    ///
-    /// The returned `UnixStream` is a reference to the same stream that this
-    /// object references. Both handles will read and write the same stream of
-    /// data, and options set on one stream will be propagated to the other
-    /// stream.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixStream;
-    ///
-    /// fn main() -> std::io::Result<()> {
-    ///     let socket = UnixStream::connect("/tmp/sock")?;
-    ///     let sock_copy = socket.try_clone().expect("Couldn't clone socket");
-    ///     Ok(())
-    /// }
-    /// ```
-    #[stable(feature = "unix_socket", since = "1.10.0")]
-    pub fn try_clone(&self) -> io::Result<UnixStream> {
-        self.0.duplicate().map(UnixStream)
-    }
-
-    /// Returns the socket address of the local half of this connection.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixStream;
-    ///
-    /// fn main() -> std::io::Result<()> {
-    ///     let socket = UnixStream::connect("/tmp/sock")?;
-    ///     let addr = socket.local_addr().expect("Couldn't get local address");
-    ///     Ok(())
-    /// }
-    /// ```
-    #[stable(feature = "unix_socket", since = "1.10.0")]
-    pub fn local_addr(&self) -> io::Result<SocketAddr> {
-        SocketAddr::new(|addr, len| unsafe { libc::getsockname(*self.0.as_inner(), addr, len) })
-    }
-
-    /// Returns the socket address of the remote half of this connection.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixStream;
-    ///
-    /// fn main() -> std::io::Result<()> {
-    ///     let socket = UnixStream::connect("/tmp/sock")?;
-    ///     let addr = socket.peer_addr().expect("Couldn't get peer address");
-    ///     Ok(())
-    /// }
-    /// ```
-    #[stable(feature = "unix_socket", since = "1.10.0")]
-    pub fn peer_addr(&self) -> io::Result<SocketAddr> {
-        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
-    /// indefinitely. An [`Err`] is returned if the zero [`Duration`] is passed to this
-    /// method.
-    ///
-    /// [`read`]: io::Read::read
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixStream;
-    /// use std::time::Duration;
-    ///
-    /// fn main() -> std::io::Result<()> {
-    ///     let socket = UnixStream::connect("/tmp/sock")?;
-    ///     socket.set_read_timeout(Some(Duration::new(1, 0))).expect("Couldn't set read timeout");
-    ///     Ok(())
-    /// }
-    /// ```
-    ///
-    /// An [`Err`] is returned if the zero [`Duration`] is passed to this
-    /// method:
-    ///
-    /// ```no_run
-    /// use std::io;
-    /// use std::os::unix::net::UnixStream;
-    /// use std::time::Duration;
-    ///
-    /// fn main() -> std::io::Result<()> {
-    ///     let socket = UnixStream::connect("/tmp/sock")?;
-    ///     let result = socket.set_read_timeout(Some(Duration::new(0, 0)));
-    ///     let err = result.unwrap_err();
-    ///     assert_eq!(err.kind(), io::ErrorKind::InvalidInput);
-    ///     Ok(())
-    /// }
-    /// ```
-    #[stable(feature = "unix_socket", since = "1.10.0")]
-    pub fn set_read_timeout(&self, timeout: Option<Duration>) -> io::Result<()> {
-        self.0.set_timeout(timeout, libc::SO_RCVTIMEO)
-    }
-
-    /// Sets the write timeout for the socket.
-    ///
-    /// If the provided value is [`None`], then [`write`] calls will block
-    /// indefinitely. An [`Err`] is returned if the zero [`Duration`] is
-    /// passed to this method.
-    ///
-    /// [`read`]: io::Read::read
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixStream;
-    /// use std::time::Duration;
-    ///
-    /// fn main() -> std::io::Result<()> {
-    ///     let socket = UnixStream::connect("/tmp/sock")?;
-    ///     socket.set_write_timeout(Some(Duration::new(1, 0)))
-    ///         .expect("Couldn't set write timeout");
-    ///     Ok(())
-    /// }
-    /// ```
-    ///
-    /// An [`Err`] is returned if the zero [`Duration`] is passed to this
-    /// method:
-    ///
-    /// ```no_run
-    /// use std::io;
-    /// use std::net::UdpSocket;
-    /// use std::time::Duration;
-    ///
-    /// fn main() -> std::io::Result<()> {
-    ///     let socket = UdpSocket::bind("127.0.0.1:34254")?;
-    ///     let result = socket.set_write_timeout(Some(Duration::new(0, 0)));
-    ///     let err = result.unwrap_err();
-    ///     assert_eq!(err.kind(), io::ErrorKind::InvalidInput);
-    ///     Ok(())
-    /// }
-    /// ```
-    #[stable(feature = "unix_socket", since = "1.10.0")]
-    pub fn set_write_timeout(&self, timeout: Option<Duration>) -> io::Result<()> {
-        self.0.set_timeout(timeout, libc::SO_SNDTIMEO)
-    }
-
-    /// Returns the read timeout of this socket.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixStream;
-    /// use std::time::Duration;
-    ///
-    /// fn main() -> std::io::Result<()> {
-    ///     let socket = UnixStream::connect("/tmp/sock")?;
-    ///     socket.set_read_timeout(Some(Duration::new(1, 0))).expect("Couldn't set read timeout");
-    ///     assert_eq!(socket.read_timeout()?, Some(Duration::new(1, 0)));
-    ///     Ok(())
-    /// }
-    /// ```
-    #[stable(feature = "unix_socket", since = "1.10.0")]
-    pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
-        self.0.timeout(libc::SO_RCVTIMEO)
-    }
-
-    /// Returns the write timeout of this socket.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixStream;
-    /// use std::time::Duration;
-    ///
-    /// fn main() -> std::io::Result<()> {
-    ///     let socket = UnixStream::connect("/tmp/sock")?;
-    ///     socket.set_write_timeout(Some(Duration::new(1, 0)))
-    ///         .expect("Couldn't set write timeout");
-    ///     assert_eq!(socket.write_timeout()?, Some(Duration::new(1, 0)));
-    ///     Ok(())
-    /// }
-    /// ```
-    #[stable(feature = "unix_socket", since = "1.10.0")]
-    pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
-        self.0.timeout(libc::SO_SNDTIMEO)
-    }
-
-    /// Moves the socket into or out of nonblocking mode.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixStream;
-    ///
-    /// fn main() -> std::io::Result<()> {
-    ///     let socket = UnixStream::connect("/tmp/sock")?;
-    ///     socket.set_nonblocking(true).expect("Couldn't set nonblocking");
-    ///     Ok(())
-    /// }
-    /// ```
-    #[stable(feature = "unix_socket", since = "1.10.0")]
-    pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
-        self.0.set_nonblocking(nonblocking)
-    }
-
-    /// Returns the value of the `SO_ERROR` option.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixStream;
-    ///
-    /// fn main() -> std::io::Result<()> {
-    ///     let socket = UnixStream::connect("/tmp/sock")?;
-    ///     if let Ok(Some(err)) = socket.take_error() {
-    ///         println!("Got error: {:?}", err);
-    ///     }
-    ///     Ok(())
-    /// }
-    /// ```
-    ///
-    /// # Platform specific
-    /// On Redox this always returns `None`.
-    #[stable(feature = "unix_socket", since = "1.10.0")]
-    pub fn take_error(&self) -> io::Result<Option<io::Error>> {
-        self.0.take_error()
-    }
-
-    /// Shuts down the read, write, or both halves of this connection.
-    ///
-    /// This function will cause all pending and future I/O calls on the
-    /// specified portions to immediately return with an appropriate value
-    /// (see the documentation of [`Shutdown`]).
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixStream;
-    /// use std::net::Shutdown;
-    ///
-    /// fn main() -> std::io::Result<()> {
-    ///     let socket = UnixStream::connect("/tmp/sock")?;
-    ///     socket.shutdown(Shutdown::Both).expect("shutdown function failed");
-    ///     Ok(())
-    /// }
-    /// ```
-    #[stable(feature = "unix_socket", since = "1.10.0")]
-    pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
-        self.0.shutdown(how)
-    }
-
-    /// Receives data on the socket from the remote address to which it is
-    /// connected, without removing that data from the queue. On success,
-    /// returns the number of bytes peeked.
-    ///
-    /// Successive calls return the same data. This is accomplished by passing
-    /// `MSG_PEEK` as a flag to the underlying `recv` system call.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// #![feature(unix_socket_peek)]
-    ///
-    /// use std::os::unix::net::UnixStream;
-    ///
-    /// fn main() -> std::io::Result<()> {
-    ///     let socket = UnixStream::connect("/tmp/sock")?;
-    ///     let mut buf = [0; 10];
-    ///     let len = socket.peek(&mut buf).expect("peek failed");
-    ///     Ok(())
-    /// }
-    /// ```
-    #[unstable(feature = "unix_socket_peek", issue = "76923")]
-    pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
-        self.0.peek(buf)
-    }
-}
-
-#[stable(feature = "unix_socket", since = "1.10.0")]
-impl io::Read for UnixStream {
-    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
-        io::Read::read(&mut &*self, buf)
-    }
-
-    fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
-        io::Read::read_vectored(&mut &*self, bufs)
-    }
-
-    #[inline]
-    fn is_read_vectored(&self) -> bool {
-        io::Read::is_read_vectored(&&*self)
-    }
-
-    #[inline]
-    unsafe fn initializer(&self) -> Initializer {
-        Initializer::nop()
-    }
-}
-
-#[stable(feature = "unix_socket", since = "1.10.0")]
-impl<'a> io::Read for &'a UnixStream {
-    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
-        self.0.read(buf)
-    }
-
-    fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
-        self.0.read_vectored(bufs)
-    }
-
-    #[inline]
-    fn is_read_vectored(&self) -> bool {
-        self.0.is_read_vectored()
-    }
-
-    #[inline]
-    unsafe fn initializer(&self) -> Initializer {
-        Initializer::nop()
-    }
-}
-
-#[stable(feature = "unix_socket", since = "1.10.0")]
-impl io::Write for UnixStream {
-    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
-        io::Write::write(&mut &*self, buf)
-    }
-
-    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
-        io::Write::write_vectored(&mut &*self, bufs)
-    }
-
-    #[inline]
-    fn is_write_vectored(&self) -> bool {
-        io::Write::is_write_vectored(&&*self)
-    }
-
-    fn flush(&mut self) -> io::Result<()> {
-        io::Write::flush(&mut &*self)
-    }
-}
-
-#[stable(feature = "unix_socket", since = "1.10.0")]
-impl<'a> io::Write for &'a UnixStream {
-    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
-        self.0.write(buf)
-    }
-
-    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
-        self.0.write_vectored(bufs)
-    }
-
-    #[inline]
-    fn is_write_vectored(&self) -> bool {
-        self.0.is_write_vectored()
-    }
-
-    fn flush(&mut self) -> io::Result<()> {
-        Ok(())
-    }
-}
-
-#[stable(feature = "unix_socket", since = "1.10.0")]
-impl AsRawFd for UnixStream {
-    fn as_raw_fd(&self) -> RawFd {
-        *self.0.as_inner()
-    }
-}
-
-#[stable(feature = "unix_socket", since = "1.10.0")]
-impl FromRawFd for UnixStream {
-    unsafe fn from_raw_fd(fd: RawFd) -> UnixStream {
-        UnixStream(Socket::from_inner(fd))
-    }
-}
-
-#[stable(feature = "unix_socket", since = "1.10.0")]
-impl IntoRawFd for UnixStream {
-    fn into_raw_fd(self) -> RawFd {
-        self.0.into_inner()
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl AsRawFd for net::TcpStream {
-    fn as_raw_fd(&self) -> RawFd {
-        *self.as_inner().socket().as_inner()
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl AsRawFd for net::TcpListener {
-    fn as_raw_fd(&self) -> RawFd {
-        *self.as_inner().socket().as_inner()
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl AsRawFd for net::UdpSocket {
-    fn as_raw_fd(&self) -> RawFd {
-        *self.as_inner().socket().as_inner()
-    }
-}
-
-#[stable(feature = "from_raw_os", since = "1.1.0")]
-impl FromRawFd for net::TcpStream {
-    unsafe fn from_raw_fd(fd: RawFd) -> net::TcpStream {
-        let socket = sys::net::Socket::from_inner(fd);
-        net::TcpStream::from_inner(sys_common::net::TcpStream::from_inner(socket))
-    }
-}
-
-#[stable(feature = "from_raw_os", since = "1.1.0")]
-impl FromRawFd for net::TcpListener {
-    unsafe fn from_raw_fd(fd: RawFd) -> net::TcpListener {
-        let socket = sys::net::Socket::from_inner(fd);
-        net::TcpListener::from_inner(sys_common::net::TcpListener::from_inner(socket))
-    }
-}
-
-#[stable(feature = "from_raw_os", since = "1.1.0")]
-impl FromRawFd for net::UdpSocket {
-    unsafe fn from_raw_fd(fd: RawFd) -> net::UdpSocket {
-        let socket = sys::net::Socket::from_inner(fd);
-        net::UdpSocket::from_inner(sys_common::net::UdpSocket::from_inner(socket))
-    }
-}
-
-#[stable(feature = "into_raw_os", since = "1.4.0")]
-impl IntoRawFd for net::TcpStream {
-    fn into_raw_fd(self) -> RawFd {
-        self.into_inner().into_socket().into_inner()
-    }
-}
-#[stable(feature = "into_raw_os", since = "1.4.0")]
-impl IntoRawFd for net::TcpListener {
-    fn into_raw_fd(self) -> RawFd {
-        self.into_inner().into_socket().into_inner()
-    }
-}
-#[stable(feature = "into_raw_os", since = "1.4.0")]
-impl IntoRawFd for net::UdpSocket {
-    fn into_raw_fd(self) -> RawFd {
-        self.into_inner().into_socket().into_inner()
-    }
-}
-
-/// A structure representing a Unix domain socket server.
-///
-/// # Examples
-///
-/// ```no_run
-/// use std::thread;
-/// use std::os::unix::net::{UnixStream, UnixListener};
-///
-/// fn handle_client(stream: UnixStream) {
-///     // ...
-/// }
-///
-/// fn main() -> std::io::Result<()> {
-///     let listener = UnixListener::bind("/path/to/the/socket")?;
-///
-///     // accept connections and process them, spawning a new thread for each one
-///     for stream in listener.incoming() {
-///         match stream {
-///             Ok(stream) => {
-///                 /* connection succeeded */
-///                 thread::spawn(|| handle_client(stream));
-///             }
-///             Err(err) => {
-///                 /* connection failed */
-///                 break;
-///             }
-///         }
-///     }
-///     Ok(())
-/// }
-/// ```
-#[stable(feature = "unix_socket", since = "1.10.0")]
-pub struct UnixListener(Socket);
-
-#[stable(feature = "unix_socket", since = "1.10.0")]
-impl fmt::Debug for UnixListener {
-    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        let mut builder = fmt.debug_struct("UnixListener");
-        builder.field("fd", self.0.as_inner());
-        if let Ok(addr) = self.local_addr() {
-            builder.field("local", &addr);
-        }
-        builder.finish()
-    }
-}
-
-impl UnixListener {
-    /// Creates a new `UnixListener` bound to the specified socket.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixListener;
-    ///
-    /// let listener = match UnixListener::bind("/path/to/the/socket") {
-    ///     Ok(sock) => sock,
-    ///     Err(e) => {
-    ///         println!("Couldn't connect: {:?}", e);
-    ///         return
-    ///     }
-    /// };
-    /// ```
-    #[stable(feature = "unix_socket", since = "1.10.0")]
-    pub fn bind<P: AsRef<Path>>(path: P) -> io::Result<UnixListener> {
-        fn inner(path: &Path) -> io::Result<UnixListener> {
-            unsafe {
-                let inner = Socket::new_raw(libc::AF_UNIX, libc::SOCK_STREAM)?;
-                let (addr, len) = sockaddr_un(path)?;
-
-                cvt(libc::bind(*inner.as_inner(), &addr as *const _ as *const _, len as _))?;
-                cvt(libc::listen(*inner.as_inner(), 128))?;
-
-                Ok(UnixListener(inner))
-            }
-        }
-        inner(path.as_ref())
-    }
-
-    /// Accepts a new incoming connection to this listener.
-    ///
-    /// This function will block the calling thread until a new Unix connection
-    /// is established. When established, the corresponding [`UnixStream`] and
-    /// the remote peer's address will be returned.
-    ///
-    /// [`UnixStream`]: crate::os::unix::net::UnixStream
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixListener;
-    ///
-    /// fn main() -> std::io::Result<()> {
-    ///     let listener = UnixListener::bind("/path/to/the/socket")?;
-    ///
-    ///     match listener.accept() {
-    ///         Ok((socket, addr)) => println!("Got a client: {:?}", addr),
-    ///         Err(e) => println!("accept function failed: {:?}", e),
-    ///     }
-    ///     Ok(())
-    /// }
-    /// ```
-    #[stable(feature = "unix_socket", since = "1.10.0")]
-    pub fn accept(&self) -> io::Result<(UnixStream, SocketAddr)> {
-        let mut storage: libc::sockaddr_un = unsafe { mem::zeroed() };
-        let mut len = mem::size_of_val(&storage) as libc::socklen_t;
-        let sock = self.0.accept(&mut storage as *mut _ as *mut _, &mut len)?;
-        let addr = SocketAddr::from_parts(storage, len)?;
-        Ok((UnixStream(sock), addr))
-    }
-
-    /// Creates a new independently owned handle to the underlying socket.
-    ///
-    /// The returned `UnixListener` is a reference to the same socket that this
-    /// object references. Both handles can be used to accept incoming
-    /// connections and options set on one listener will affect the other.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixListener;
-    ///
-    /// fn main() -> std::io::Result<()> {
-    ///     let listener = UnixListener::bind("/path/to/the/socket")?;
-    ///     let listener_copy = listener.try_clone().expect("try_clone failed");
-    ///     Ok(())
-    /// }
-    /// ```
-    #[stable(feature = "unix_socket", since = "1.10.0")]
-    pub fn try_clone(&self) -> io::Result<UnixListener> {
-        self.0.duplicate().map(UnixListener)
-    }
-
-    /// Returns the local socket address of this listener.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixListener;
-    ///
-    /// fn main() -> std::io::Result<()> {
-    ///     let listener = UnixListener::bind("/path/to/the/socket")?;
-    ///     let addr = listener.local_addr().expect("Couldn't get local address");
-    ///     Ok(())
-    /// }
-    /// ```
-    #[stable(feature = "unix_socket", since = "1.10.0")]
-    pub fn local_addr(&self) -> io::Result<SocketAddr> {
-        SocketAddr::new(|addr, len| unsafe { libc::getsockname(*self.0.as_inner(), addr, len) })
-    }
-
-    /// Moves the socket into or out of nonblocking mode.
-    ///
-    /// This will result in the `accept` operation becoming nonblocking,
-    /// i.e., immediately returning from their calls. If the IO operation is
-    /// successful, `Ok` is returned and no further action is required. If the
-    /// IO operation could not be completed and needs to be retried, an error
-    /// with kind [`io::ErrorKind::WouldBlock`] is returned.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixListener;
-    ///
-    /// fn main() -> std::io::Result<()> {
-    ///     let listener = UnixListener::bind("/path/to/the/socket")?;
-    ///     listener.set_nonblocking(true).expect("Couldn't set non blocking");
-    ///     Ok(())
-    /// }
-    /// ```
-    #[stable(feature = "unix_socket", since = "1.10.0")]
-    pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
-        self.0.set_nonblocking(nonblocking)
-    }
-
-    /// Returns the value of the `SO_ERROR` option.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixListener;
-    ///
-    /// fn main() -> std::io::Result<()> {
-    ///     let listener = UnixListener::bind("/tmp/sock")?;
-    ///
-    ///     if let Ok(Some(err)) = listener.take_error() {
-    ///         println!("Got error: {:?}", err);
-    ///     }
-    ///     Ok(())
-    /// }
-    /// ```
-    ///
-    /// # Platform specific
-    /// On Redox this always returns `None`.
-    #[stable(feature = "unix_socket", since = "1.10.0")]
-    pub fn take_error(&self) -> io::Result<Option<io::Error>> {
-        self.0.take_error()
-    }
-
-    /// Returns an iterator over incoming connections.
-    ///
-    /// The iterator will never return [`None`] and will also not yield the
-    /// peer's [`SocketAddr`] structure.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::thread;
-    /// use std::os::unix::net::{UnixStream, UnixListener};
-    ///
-    /// fn handle_client(stream: UnixStream) {
-    ///     // ...
-    /// }
-    ///
-    /// fn main() -> std::io::Result<()> {
-    ///     let listener = UnixListener::bind("/path/to/the/socket")?;
-    ///
-    ///     for stream in listener.incoming() {
-    ///         match stream {
-    ///             Ok(stream) => {
-    ///                 thread::spawn(|| handle_client(stream));
-    ///             }
-    ///             Err(err) => {
-    ///                 break;
-    ///             }
-    ///         }
-    ///     }
-    ///     Ok(())
-    /// }
-    /// ```
-    #[stable(feature = "unix_socket", since = "1.10.0")]
-    pub fn incoming(&self) -> Incoming<'_> {
-        Incoming { listener: self }
-    }
-}
-
-#[stable(feature = "unix_socket", since = "1.10.0")]
-impl AsRawFd for UnixListener {
-    fn as_raw_fd(&self) -> RawFd {
-        *self.0.as_inner()
-    }
-}
-
-#[stable(feature = "unix_socket", since = "1.10.0")]
-impl FromRawFd for UnixListener {
-    unsafe fn from_raw_fd(fd: RawFd) -> UnixListener {
-        UnixListener(Socket::from_inner(fd))
-    }
-}
-
-#[stable(feature = "unix_socket", since = "1.10.0")]
-impl IntoRawFd for UnixListener {
-    fn into_raw_fd(self) -> RawFd {
-        self.0.into_inner()
-    }
-}
-
-#[stable(feature = "unix_socket", since = "1.10.0")]
-impl<'a> IntoIterator for &'a UnixListener {
-    type Item = io::Result<UnixStream>;
-    type IntoIter = Incoming<'a>;
-
-    fn into_iter(self) -> Incoming<'a> {
-        self.incoming()
-    }
-}
-
-/// An iterator over incoming connections to a [`UnixListener`].
-///
-/// It will never return [`None`].
-///
-/// # Examples
-///
-/// ```no_run
-/// use std::thread;
-/// use std::os::unix::net::{UnixStream, UnixListener};
-///
-/// fn handle_client(stream: UnixStream) {
-///     // ...
-/// }
-///
-/// fn main() -> std::io::Result<()> {
-///     let listener = UnixListener::bind("/path/to/the/socket")?;
-///
-///     for stream in listener.incoming() {
-///         match stream {
-///             Ok(stream) => {
-///                 thread::spawn(|| handle_client(stream));
-///             }
-///             Err(err) => {
-///                 break;
-///             }
-///         }
-///     }
-///     Ok(())
-/// }
-/// ```
-#[derive(Debug)]
-#[stable(feature = "unix_socket", since = "1.10.0")]
-pub struct Incoming<'a> {
-    listener: &'a UnixListener,
-}
-
-#[stable(feature = "unix_socket", since = "1.10.0")]
-impl<'a> Iterator for Incoming<'a> {
-    type Item = io::Result<UnixStream>;
-
-    fn next(&mut self) -> Option<io::Result<UnixStream>> {
-        Some(self.listener.accept().map(|s| s.0))
-    }
-
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        (usize::MAX, None)
-    }
-}
-
-/// A Unix datagram socket.
-///
-/// # Examples
-///
-/// ```no_run
-/// use std::os::unix::net::UnixDatagram;
-///
-/// fn main() -> std::io::Result<()> {
-///     let socket = UnixDatagram::bind("/path/to/my/socket")?;
-///     socket.send_to(b"hello world", "/path/to/other/socket")?;
-///     let mut buf = [0; 100];
-///     let (count, address) = socket.recv_from(&mut buf)?;
-///     println!("socket {:?} sent {:?}", address, &buf[..count]);
-///     Ok(())
-/// }
-/// ```
-#[stable(feature = "unix_socket", since = "1.10.0")]
-pub struct UnixDatagram(Socket);
-
-#[stable(feature = "unix_socket", since = "1.10.0")]
-impl fmt::Debug for UnixDatagram {
-    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        let mut builder = fmt.debug_struct("UnixDatagram");
-        builder.field("fd", self.0.as_inner());
-        if let Ok(addr) = self.local_addr() {
-            builder.field("local", &addr);
-        }
-        if let Ok(addr) = self.peer_addr() {
-            builder.field("peer", &addr);
-        }
-        builder.finish()
-    }
-}
-
-impl UnixDatagram {
-    /// Creates a Unix datagram socket bound to the given path.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixDatagram;
-    ///
-    /// let sock = match UnixDatagram::bind("/path/to/the/socket") {
-    ///     Ok(sock) => sock,
-    ///     Err(e) => {
-    ///         println!("Couldn't bind: {:?}", e);
-    ///         return
-    ///     }
-    /// };
-    /// ```
-    #[stable(feature = "unix_socket", since = "1.10.0")]
-    pub fn bind<P: AsRef<Path>>(path: P) -> io::Result<UnixDatagram> {
-        fn inner(path: &Path) -> io::Result<UnixDatagram> {
-            unsafe {
-                let socket = UnixDatagram::unbound()?;
-                let (addr, len) = sockaddr_un(path)?;
-
-                cvt(libc::bind(*socket.0.as_inner(), &addr as *const _ as *const _, len as _))?;
-
-                Ok(socket)
-            }
-        }
-        inner(path.as_ref())
-    }
-
-    /// Creates a Unix Datagram socket which is not bound to any address.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixDatagram;
-    ///
-    /// let sock = match UnixDatagram::unbound() {
-    ///     Ok(sock) => sock,
-    ///     Err(e) => {
-    ///         println!("Couldn't unbound: {:?}", e);
-    ///         return
-    ///     }
-    /// };
-    /// ```
-    #[stable(feature = "unix_socket", since = "1.10.0")]
-    pub fn unbound() -> io::Result<UnixDatagram> {
-        let inner = Socket::new_raw(libc::AF_UNIX, libc::SOCK_DGRAM)?;
-        Ok(UnixDatagram(inner))
-    }
-
-    /// Creates an unnamed pair of connected sockets.
-    ///
-    /// Returns two `UnixDatagrams`s which are connected to each other.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixDatagram;
-    ///
-    /// let (sock1, sock2) = match UnixDatagram::pair() {
-    ///     Ok((sock1, sock2)) => (sock1, sock2),
-    ///     Err(e) => {
-    ///         println!("Couldn't unbound: {:?}", e);
-    ///         return
-    ///     }
-    /// };
-    /// ```
-    #[stable(feature = "unix_socket", since = "1.10.0")]
-    pub fn pair() -> io::Result<(UnixDatagram, UnixDatagram)> {
-        let (i1, i2) = Socket::new_pair(libc::AF_UNIX, libc::SOCK_DGRAM)?;
-        Ok((UnixDatagram(i1), UnixDatagram(i2)))
-    }
-
-    /// Connects the socket to the specified address.
-    ///
-    /// The [`send`] method may be used to send data to the specified address.
-    /// [`recv`] and [`recv_from`] will only receive data from that address.
-    ///
-    /// [`send`]: UnixDatagram::send
-    /// [`recv`]: UnixDatagram::recv
-    /// [`recv_from`]: UnixDatagram::recv_from
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixDatagram;
-    ///
-    /// fn main() -> std::io::Result<()> {
-    ///     let sock = UnixDatagram::unbound()?;
-    ///     match sock.connect("/path/to/the/socket") {
-    ///         Ok(sock) => sock,
-    ///         Err(e) => {
-    ///             println!("Couldn't connect: {:?}", e);
-    ///             return Err(e)
-    ///         }
-    ///     };
-    ///     Ok(())
-    /// }
-    /// ```
-    #[stable(feature = "unix_socket", since = "1.10.0")]
-    pub fn connect<P: AsRef<Path>>(&self, path: P) -> io::Result<()> {
-        fn inner(d: &UnixDatagram, path: &Path) -> io::Result<()> {
-            unsafe {
-                let (addr, len) = sockaddr_un(path)?;
-
-                cvt(libc::connect(*d.0.as_inner(), &addr as *const _ as *const _, len))?;
-
-                Ok(())
-            }
-        }
-        inner(self, path.as_ref())
-    }
-
-    /// Creates a new independently owned handle to the underlying socket.
-    ///
-    /// The returned `UnixDatagram` is a reference to the same socket that this
-    /// object references. Both handles can be used to accept incoming
-    /// connections and options set on one side will affect the other.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixDatagram;
-    ///
-    /// fn main() -> std::io::Result<()> {
-    ///     let sock = UnixDatagram::bind("/path/to/the/socket")?;
-    ///     let sock_copy = sock.try_clone().expect("try_clone failed");
-    ///     Ok(())
-    /// }
-    /// ```
-    #[stable(feature = "unix_socket", since = "1.10.0")]
-    pub fn try_clone(&self) -> io::Result<UnixDatagram> {
-        self.0.duplicate().map(UnixDatagram)
-    }
-
-    /// Returns the address of this socket.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixDatagram;
-    ///
-    /// fn main() -> std::io::Result<()> {
-    ///     let sock = UnixDatagram::bind("/path/to/the/socket")?;
-    ///     let addr = sock.local_addr().expect("Couldn't get local address");
-    ///     Ok(())
-    /// }
-    /// ```
-    #[stable(feature = "unix_socket", since = "1.10.0")]
-    pub fn local_addr(&self) -> io::Result<SocketAddr> {
-        SocketAddr::new(|addr, len| unsafe { libc::getsockname(*self.0.as_inner(), addr, len) })
-    }
-
-    /// Returns the address of this socket's peer.
-    ///
-    /// The [`connect`] method will connect the socket to a peer.
-    ///
-    /// [`connect`]: UnixDatagram::connect
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixDatagram;
-    ///
-    /// fn main() -> std::io::Result<()> {
-    ///     let sock = UnixDatagram::unbound()?;
-    ///     sock.connect("/path/to/the/socket")?;
-    ///
-    ///     let addr = sock.peer_addr().expect("Couldn't get peer address");
-    ///     Ok(())
-    /// }
-    /// ```
-    #[stable(feature = "unix_socket", since = "1.10.0")]
-    pub fn peer_addr(&self) -> io::Result<SocketAddr> {
-        SocketAddr::new(|addr, len| unsafe { libc::getpeername(*self.0.as_inner(), addr, len) })
-    }
-
-    fn recv_from_flags(
-        &self,
-        buf: &mut [u8],
-        flags: libc::c_int,
-    ) -> io::Result<(usize, SocketAddr)> {
-        let mut count = 0;
-        let addr = SocketAddr::new(|addr, len| unsafe {
-            count = libc::recvfrom(
-                *self.0.as_inner(),
-                buf.as_mut_ptr() as *mut _,
-                buf.len(),
-                flags,
-                addr,
-                len,
-            );
-            if count > 0 {
-                1
-            } else if count == 0 {
-                0
-            } else {
-                -1
-            }
-        })?;
-
-        Ok((count as usize, addr))
-    }
-
-    /// Receives data from the socket.
-    ///
-    /// On success, returns the number of bytes read and the address from
-    /// whence the data came.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixDatagram;
-    ///
-    /// fn main() -> std::io::Result<()> {
-    ///     let sock = UnixDatagram::unbound()?;
-    ///     let mut buf = vec![0; 10];
-    ///     let (size, sender) = sock.recv_from(buf.as_mut_slice())?;
-    ///     println!("received {} bytes from {:?}", size, sender);
-    ///     Ok(())
-    /// }
-    /// ```
-    #[stable(feature = "unix_socket", since = "1.10.0")]
-    pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
-        self.recv_from_flags(buf, 0)
-    }
-
-    /// Receives data from the socket.
-    ///
-    /// On success, returns the number of bytes read.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixDatagram;
-    ///
-    /// fn main() -> std::io::Result<()> {
-    ///     let sock = UnixDatagram::bind("/path/to/the/socket")?;
-    ///     let mut buf = vec![0; 10];
-    ///     sock.recv(buf.as_mut_slice()).expect("recv function failed");
-    ///     Ok(())
-    /// }
-    /// ```
-    #[stable(feature = "unix_socket", since = "1.10.0")]
-    pub fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
-        self.0.read(buf)
-    }
-
-    /// Sends data on the socket to the specified address.
-    ///
-    /// On success, returns the number of bytes written.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixDatagram;
-    ///
-    /// fn main() -> std::io::Result<()> {
-    ///     let sock = UnixDatagram::unbound()?;
-    ///     sock.send_to(b"omelette au fromage", "/some/sock").expect("send_to function failed");
-    ///     Ok(())
-    /// }
-    /// ```
-    #[stable(feature = "unix_socket", since = "1.10.0")]
-    pub fn send_to<P: AsRef<Path>>(&self, buf: &[u8], path: P) -> io::Result<usize> {
-        fn inner(d: &UnixDatagram, buf: &[u8], path: &Path) -> io::Result<usize> {
-            unsafe {
-                let (addr, len) = sockaddr_un(path)?;
-
-                let count = cvt(libc::sendto(
-                    *d.0.as_inner(),
-                    buf.as_ptr() as *const _,
-                    buf.len(),
-                    MSG_NOSIGNAL,
-                    &addr as *const _ as *const _,
-                    len,
-                ))?;
-                Ok(count as usize)
-            }
-        }
-        inner(self, buf, path.as_ref())
-    }
-
-    /// Sends data on the socket to the socket's peer.
-    ///
-    /// The peer address may be set by the `connect` method, and this method
-    /// will return an error if the socket has not already been connected.
-    ///
-    /// On success, returns the number of bytes written.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixDatagram;
-    ///
-    /// fn main() -> std::io::Result<()> {
-    ///     let sock = UnixDatagram::unbound()?;
-    ///     sock.connect("/some/sock").expect("Couldn't connect");
-    ///     sock.send(b"omelette au fromage").expect("send_to function failed");
-    ///     Ok(())
-    /// }
-    /// ```
-    #[stable(feature = "unix_socket", since = "1.10.0")]
-    pub fn send(&self, buf: &[u8]) -> io::Result<usize> {
-        self.0.write(buf)
-    }
-
-    /// Sets the read timeout for the socket.
-    ///
-    /// If the provided value is [`None`], then [`recv`] and [`recv_from`] calls will
-    /// block indefinitely. An [`Err`] is returned if the zero [`Duration`]
-    /// is passed to this method.
-    ///
-    /// [`recv`]: UnixDatagram::recv
-    /// [`recv_from`]: UnixDatagram::recv_from
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::os::unix::net::UnixDatagram;
-    /// use std::time::Duration;
-    ///
-    /// fn main() -> std::io::Result<()> {
-    ///     let sock = UnixDatagram::unbound()?;
-    ///     sock.set_read_timeout(Some(Duration::new(1, 0)))
-    ///         .expect("set_read_timeout function failed");
-    ///     Ok(())
-    /// }
-    /// ```
-    ///
-    /// An [`Err`] is returned if the zero [`Duration`] is passed to this
-    /// method:
-    ///
-    /// ```no_run
-    /// use std::io;
-    /// use std::os::unix::net::UnixDatagram;
-    /// use std::time::Duration;
-    ///
-    /// fn main() -> std::io::Result<()> {
-    ///     let socket = UnixDatagram::unbound()?;
-    ///     let result = socket.set_read_timeout(Some(Duration::new(0, 0)));
-    ///     let err = result.unwrap_err();
-    ///     assert_eq!(err.kind(), io::ErrorKind::InvalidInput);
-    ///     Ok(())
-    /// }
-    /// ```
-    #[stable(feature = "unix_socket", since = "1.10.0")]
-    pub fn set_read_timeout(&self, timeout: Option<Duration>) -> io::Result<()> {
-        self.0.set_timeout(timeout, libc::SO_RCVTIMEO)
-    }
-
-    /// Sets the write timeout for the socket.
-    ///
-    /// If the provided value is [`None`], then [`send`] and [`send_to`] calls will
-    /// block indefinitely. An [`Err`] is returned if the zero [`Duration`] is passed to this
-    /// method.
-    ///
-    /// [`send`]: UnixDatagram::send
-    /// [`send_to`]: UnixDatagram::send_to
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::os::unix::net::UnixDatagram;
-    /// use std::time::Duration;
-    ///
-    /// fn main() -> std::io::Result<()> {
-    ///     let sock = UnixDatagram::unbound()?;
-    ///     sock.set_write_timeout(Some(Duration::new(1, 0)))
-    ///         .expect("set_write_timeout function failed");
-    ///     Ok(())
-    /// }
-    /// ```
-    ///
-    /// An [`Err`] is returned if the zero [`Duration`] is passed to this
-    /// method:
-    ///
-    /// ```no_run
-    /// use std::io;
-    /// use std::os::unix::net::UnixDatagram;
-    /// use std::time::Duration;
-    ///
-    /// fn main() -> std::io::Result<()> {
-    ///     let socket = UnixDatagram::unbound()?;
-    ///     let result = socket.set_write_timeout(Some(Duration::new(0, 0)));
-    ///     let err = result.unwrap_err();
-    ///     assert_eq!(err.kind(), io::ErrorKind::InvalidInput);
-    ///     Ok(())
-    /// }
-    /// ```
-    #[stable(feature = "unix_socket", since = "1.10.0")]
-    pub fn set_write_timeout(&self, timeout: Option<Duration>) -> io::Result<()> {
-        self.0.set_timeout(timeout, libc::SO_SNDTIMEO)
-    }
-
-    /// Returns the read timeout of this socket.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::os::unix::net::UnixDatagram;
-    /// use std::time::Duration;
-    ///
-    /// fn main() -> std::io::Result<()> {
-    ///     let sock = UnixDatagram::unbound()?;
-    ///     sock.set_read_timeout(Some(Duration::new(1, 0)))
-    ///         .expect("set_read_timeout function failed");
-    ///     assert_eq!(sock.read_timeout()?, Some(Duration::new(1, 0)));
-    ///     Ok(())
-    /// }
-    /// ```
-    #[stable(feature = "unix_socket", since = "1.10.0")]
-    pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
-        self.0.timeout(libc::SO_RCVTIMEO)
-    }
-
-    /// Returns the write timeout of this socket.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::os::unix::net::UnixDatagram;
-    /// use std::time::Duration;
-    ///
-    /// fn main() -> std::io::Result<()> {
-    ///     let sock = UnixDatagram::unbound()?;
-    ///     sock.set_write_timeout(Some(Duration::new(1, 0)))
-    ///         .expect("set_write_timeout function failed");
-    ///     assert_eq!(sock.write_timeout()?, Some(Duration::new(1, 0)));
-    ///     Ok(())
-    /// }
-    /// ```
-    #[stable(feature = "unix_socket", since = "1.10.0")]
-    pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
-        self.0.timeout(libc::SO_SNDTIMEO)
-    }
-
-    /// Moves the socket into or out of nonblocking mode.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// use std::os::unix::net::UnixDatagram;
-    ///
-    /// fn main() -> std::io::Result<()> {
-    ///     let sock = UnixDatagram::unbound()?;
-    ///     sock.set_nonblocking(true).expect("set_nonblocking function failed");
-    ///     Ok(())
-    /// }
-    /// ```
-    #[stable(feature = "unix_socket", since = "1.10.0")]
-    pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
-        self.0.set_nonblocking(nonblocking)
-    }
-
-    /// Returns the value of the `SO_ERROR` option.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixDatagram;
-    ///
-    /// fn main() -> std::io::Result<()> {
-    ///     let sock = UnixDatagram::unbound()?;
-    ///     if let Ok(Some(err)) = sock.take_error() {
-    ///         println!("Got error: {:?}", err);
-    ///     }
-    ///     Ok(())
-    /// }
-    /// ```
-    #[stable(feature = "unix_socket", since = "1.10.0")]
-    pub fn take_error(&self) -> io::Result<Option<io::Error>> {
-        self.0.take_error()
-    }
-
-    /// Shut down the read, write, or both halves of this connection.
-    ///
-    /// This function will cause all pending and future I/O calls on the
-    /// specified portions to immediately return with an appropriate value
-    /// (see the documentation of [`Shutdown`]).
-    ///
-    /// ```no_run
-    /// use std::os::unix::net::UnixDatagram;
-    /// use std::net::Shutdown;
-    ///
-    /// fn main() -> std::io::Result<()> {
-    ///     let sock = UnixDatagram::unbound()?;
-    ///     sock.shutdown(Shutdown::Both).expect("shutdown function failed");
-    ///     Ok(())
-    /// }
-    /// ```
-    #[stable(feature = "unix_socket", since = "1.10.0")]
-    pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
-        self.0.shutdown(how)
-    }
-
-    /// Receives data on the socket from the remote address to which it is
-    /// connected, without removing that data from the queue. On success,
-    /// returns the number of bytes peeked.
-    ///
-    /// Successive calls return the same data. This is accomplished by passing
-    /// `MSG_PEEK` as a flag to the underlying `recv` system call.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// #![feature(unix_socket_peek)]
-    ///
-    /// use std::os::unix::net::UnixDatagram;
-    ///
-    /// fn main() -> std::io::Result<()> {
-    ///     let socket = UnixDatagram::bind("/tmp/sock")?;
-    ///     let mut buf = [0; 10];
-    ///     let len = socket.peek(&mut buf).expect("peek failed");
-    ///     Ok(())
-    /// }
-    /// ```
-    #[unstable(feature = "unix_socket_peek", issue = "76923")]
-    pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
-        self.0.peek(buf)
-    }
-
-    /// Receives a single datagram message on the socket, without removing it from the
-    /// queue. On success, returns the number of bytes read and the origin.
-    ///
-    /// The function must be called with valid byte array `buf` of sufficient size to
-    /// hold the message bytes. If a message is too long to fit in the supplied buffer,
-    /// excess bytes may be discarded.
-    ///
-    /// Successive calls return the same data. This is accomplished by passing
-    /// `MSG_PEEK` as a flag to the underlying `recvfrom` system call.
-    ///
-    /// Do not use this function to implement busy waiting, instead use `libc::poll` to
-    /// synchronize IO events on one or more sockets.
-    ///
-    /// # Examples
-    ///
-    /// ```no_run
-    /// #![feature(unix_socket_peek)]
-    ///
-    /// use std::os::unix::net::UnixDatagram;
-    ///
-    /// fn main() -> std::io::Result<()> {
-    ///     let socket = UnixDatagram::bind("/tmp/sock")?;
-    ///     let mut buf = [0; 10];
-    ///     let (len, addr) = socket.peek_from(&mut buf).expect("peek failed");
-    ///     Ok(())
-    /// }
-    /// ```
-    #[unstable(feature = "unix_socket_peek", issue = "76923")]
-    pub fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
-        self.recv_from_flags(buf, libc::MSG_PEEK)
-    }
-}
-
-#[stable(feature = "unix_socket", since = "1.10.0")]
-impl AsRawFd for UnixDatagram {
-    fn as_raw_fd(&self) -> RawFd {
-        *self.0.as_inner()
-    }
-}
-
-#[stable(feature = "unix_socket", since = "1.10.0")]
-impl FromRawFd for UnixDatagram {
-    unsafe fn from_raw_fd(fd: RawFd) -> UnixDatagram {
-        UnixDatagram(Socket::from_inner(fd))
-    }
-}
-
-#[stable(feature = "unix_socket", since = "1.10.0")]
-impl IntoRawFd for UnixDatagram {
-    fn into_raw_fd(self) -> RawFd {
-        self.0.into_inner()
-    }
-}
diff --git a/library/std/src/sys/unix/ext/net/addr.rs b/library/std/src/sys/unix/ext/net/addr.rs
new file mode 100644
index 00000000000..1f9036242eb
--- /dev/null
+++ b/library/std/src/sys/unix/ext/net/addr.rs
@@ -0,0 +1,226 @@
+use crate::ffi::OsStr;
+use crate::os::unix::ffi::OsStrExt;
+use crate::path::Path;
+use crate::sys::cvt;
+use crate::{ascii, fmt, io, mem};
+
+// FIXME(#43348): Make libc adapt #[doc(cfg(...))] so we don't need these fake definitions here?
+#[cfg(not(unix))]
+#[allow(non_camel_case_types)]
+mod libc {
+    pub use libc::c_int;
+    pub type socklen_t = u32;
+    pub struct sockaddr;
+    #[derive(Clone)]
+    pub struct sockaddr_un;
+}
+
+fn sun_path_offset(addr: &libc::sockaddr_un) -> usize {
+    // Work with an actual instance of the type since using a null pointer is UB
+    let base = addr as *const _ as usize;
+    let path = &addr.sun_path as *const _ as usize;
+    path - base
+}
+
+pub(super) unsafe fn sockaddr_un(path: &Path) -> io::Result<(libc::sockaddr_un, libc::socklen_t)> {
+    let mut addr: libc::sockaddr_un = mem::zeroed();
+    addr.sun_family = libc::AF_UNIX as libc::sa_family_t;
+
+    let bytes = path.as_os_str().as_bytes();
+
+    if bytes.contains(&0) {
+        return Err(io::Error::new(
+            io::ErrorKind::InvalidInput,
+            "paths may not contain interior null bytes",
+        ));
+    }
+
+    if bytes.len() >= addr.sun_path.len() {
+        return Err(io::Error::new(
+            io::ErrorKind::InvalidInput,
+            "path must be shorter than SUN_LEN",
+        ));
+    }
+    for (dst, src) in addr.sun_path.iter_mut().zip(bytes.iter()) {
+        *dst = *src as libc::c_char;
+    }
+    // null byte for pathname addresses is already there because we zeroed the
+    // struct
+
+    let mut len = sun_path_offset(&addr) + bytes.len();
+    match bytes.get(0) {
+        Some(&0) | None => {}
+        Some(_) => len += 1,
+    }
+    Ok((addr, len as libc::socklen_t))
+}
+
+enum AddressKind<'a> {
+    Unnamed,
+    Pathname(&'a Path),
+    Abstract(&'a [u8]),
+}
+
+struct AsciiEscaped<'a>(&'a [u8]);
+
+impl<'a> fmt::Display for AsciiEscaped<'a> {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(fmt, "\"")?;
+        for byte in self.0.iter().cloned().flat_map(ascii::escape_default) {
+            write!(fmt, "{}", byte as char)?;
+        }
+        write!(fmt, "\"")
+    }
+}
+
+/// An address associated with a Unix socket.
+///
+/// # Examples
+///
+/// ```
+/// use std::os::unix::net::UnixListener;
+///
+/// let socket = match UnixListener::bind("/tmp/sock") {
+///     Ok(sock) => sock,
+///     Err(e) => {
+///         println!("Couldn't bind: {:?}", e);
+///         return
+///     }
+/// };
+/// let addr = socket.local_addr().expect("Couldn't get local address");
+/// ```
+#[derive(Clone)]
+#[stable(feature = "unix_socket", since = "1.10.0")]
+pub struct SocketAddr {
+    addr: libc::sockaddr_un,
+    len: libc::socklen_t,
+}
+
+impl SocketAddr {
+    pub(super) fn new<F>(f: F) -> io::Result<SocketAddr>
+    where
+        F: FnOnce(*mut libc::sockaddr, *mut libc::socklen_t) -> libc::c_int,
+    {
+        unsafe {
+            let mut addr: libc::sockaddr_un = mem::zeroed();
+            let mut len = mem::size_of::<libc::sockaddr_un>() as libc::socklen_t;
+            cvt(f(&mut addr as *mut _ as *mut _, &mut len))?;
+            SocketAddr::from_parts(addr, len)
+        }
+    }
+
+    pub(super) fn from_parts(
+        addr: libc::sockaddr_un,
+        mut len: libc::socklen_t,
+    ) -> io::Result<SocketAddr> {
+        if len == 0 {
+            // When there is a datagram from unnamed unix socket
+            // linux returns zero bytes of address
+            len = sun_path_offset(&addr) as libc::socklen_t; // i.e., zero-length address
+        } else if addr.sun_family != libc::AF_UNIX as libc::sa_family_t {
+            return Err(io::Error::new(
+                io::ErrorKind::InvalidInput,
+                "file descriptor did not correspond to a Unix socket",
+            ));
+        }
+
+        Ok(SocketAddr { addr, len })
+    }
+
+    /// Returns `true` if the address is unnamed.
+    ///
+    /// # Examples
+    ///
+    /// A named address:
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixListener;
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     let socket = UnixListener::bind("/tmp/sock")?;
+    ///     let addr = socket.local_addr().expect("Couldn't get local address");
+    ///     assert_eq!(addr.is_unnamed(), false);
+    ///     Ok(())
+    /// }
+    /// ```
+    ///
+    /// An unnamed address:
+    ///
+    /// ```
+    /// use std::os::unix::net::UnixDatagram;
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     let socket = UnixDatagram::unbound()?;
+    ///     let addr = socket.local_addr().expect("Couldn't get local address");
+    ///     assert_eq!(addr.is_unnamed(), true);
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "unix_socket", since = "1.10.0")]
+    pub fn is_unnamed(&self) -> bool {
+        if let AddressKind::Unnamed = self.address() { true } else { false }
+    }
+
+    /// Returns the contents of this address if it is a `pathname` address.
+    ///
+    /// # Examples
+    ///
+    /// With a pathname:
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixListener;
+    /// use std::path::Path;
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     let socket = UnixListener::bind("/tmp/sock")?;
+    ///     let addr = socket.local_addr().expect("Couldn't get local address");
+    ///     assert_eq!(addr.as_pathname(), Some(Path::new("/tmp/sock")));
+    ///     Ok(())
+    /// }
+    /// ```
+    ///
+    /// Without a pathname:
+    ///
+    /// ```
+    /// use std::os::unix::net::UnixDatagram;
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     let socket = UnixDatagram::unbound()?;
+    ///     let addr = socket.local_addr().expect("Couldn't get local address");
+    ///     assert_eq!(addr.as_pathname(), None);
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "unix_socket", since = "1.10.0")]
+    pub fn as_pathname(&self) -> Option<&Path> {
+        if let AddressKind::Pathname(path) = self.address() { Some(path) } else { None }
+    }
+
+    fn address(&self) -> AddressKind<'_> {
+        let len = self.len as usize - sun_path_offset(&self.addr);
+        let path = unsafe { mem::transmute::<&[libc::c_char], &[u8]>(&self.addr.sun_path) };
+
+        // macOS seems to return a len of 16 and a zeroed sun_path for unnamed addresses
+        if len == 0
+            || (cfg!(not(any(target_os = "linux", target_os = "android")))
+                && self.addr.sun_path[0] == 0)
+        {
+            AddressKind::Unnamed
+        } else if self.addr.sun_path[0] == 0 {
+            AddressKind::Abstract(&path[1..len])
+        } else {
+            AddressKind::Pathname(OsStr::from_bytes(&path[..len - 1]).as_ref())
+        }
+    }
+}
+
+#[stable(feature = "unix_socket", since = "1.10.0")]
+impl fmt::Debug for SocketAddr {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self.address() {
+            AddressKind::Unnamed => write!(fmt, "(unnamed)"),
+            AddressKind::Abstract(name) => write!(fmt, "{} (abstract)", AsciiEscaped(name)),
+            AddressKind::Pathname(path) => write!(fmt, "{:?} (pathname)", path),
+        }
+    }
+}
diff --git a/library/std/src/sys/unix/ext/net/ancillary.rs b/library/std/src/sys/unix/ext/net/ancillary.rs
new file mode 100644
index 00000000000..2c91ba70dd0
--- /dev/null
+++ b/library/std/src/sys/unix/ext/net/ancillary.rs
@@ -0,0 +1,660 @@
+use super::{sockaddr_un, SocketAddr};
+use crate::convert::TryFrom;
+use crate::io::{self, IoSliceMut};
+use crate::marker::PhantomData;
+use crate::mem::{size_of, zeroed};
+use crate::os::unix::io::RawFd;
+use crate::path::Path;
+#[cfg(target_os = "android")]
+use crate::ptr::eq;
+use crate::ptr::read_unaligned;
+use crate::slice::from_raw_parts;
+use crate::sys::net::Socket;
+
+// FIXME(#43348): Make libc adapt #[doc(cfg(...))] so we don't need these fake definitions here?
+#[cfg(all(doc, not(target_os = "linux"), not(target_os = "android")))]
+#[allow(non_camel_case_types)]
+mod libc {
+    pub use libc::c_int;
+    pub struct ucred;
+    pub struct cmsghdr;
+    pub type pid_t = i32;
+    pub type gid_t = u32;
+    pub type uid_t = u32;
+}
+
+pub(super) fn recv_vectored_with_ancillary_from(
+    socket: &Socket,
+    bufs: &mut [IoSliceMut<'_>],
+    ancillary: &mut SocketAncillary<'_>,
+) -> io::Result<(usize, bool, io::Result<SocketAddr>)> {
+    unsafe {
+        let mut msg_name: libc::sockaddr_un = zeroed();
+
+        let mut msg: libc::msghdr = zeroed();
+        msg.msg_name = &mut msg_name as *mut _ as *mut _;
+        msg.msg_namelen = size_of::<libc::sockaddr_un>() as libc::socklen_t;
+        msg.msg_iov = bufs.as_mut_ptr().cast();
+        msg.msg_control = ancillary.buffer.as_mut_ptr().cast();
+        cfg_if::cfg_if! {
+            if #[cfg(any(target_os = "android", all(target_os = "linux", target_env = "gnu")))] {
+                msg.msg_iovlen = bufs.len() as libc::size_t;
+                msg.msg_controllen = ancillary.buffer.len() as libc::size_t;
+            } else if #[cfg(any(
+                          target_os = "dragonfly",
+                          target_os = "emscripten",
+                          target_os = "freebsd",
+                          all(target_os = "linux", target_env = "musl",),
+                          target_os = "netbsd",
+                          target_os = "openbsd",
+                      ))] {
+                msg.msg_iovlen = bufs.len() as libc::c_int;
+                msg.msg_controllen = ancillary.buffer.len() as libc::socklen_t;
+            }
+        }
+
+        let count = socket.recv_msg(&mut msg)?;
+
+        ancillary.length = msg.msg_controllen as usize;
+        ancillary.truncated = msg.msg_flags & libc::MSG_CTRUNC == libc::MSG_CTRUNC;
+
+        let truncated = msg.msg_flags & libc::MSG_TRUNC == libc::MSG_TRUNC;
+        let addr = SocketAddr::from_parts(msg_name, msg.msg_namelen);
+
+        Ok((count, truncated, addr))
+    }
+}
+
+pub(super) fn send_vectored_with_ancillary_to(
+    socket: &Socket,
+    path: Option<&Path>,
+    bufs: &mut [IoSliceMut<'_>],
+    ancillary: &mut SocketAncillary<'_>,
+) -> io::Result<usize> {
+    unsafe {
+        let (mut msg_name, msg_namelen) =
+            if let Some(path) = path { sockaddr_un(path)? } else { (zeroed(), 0) };
+
+        let mut msg: libc::msghdr = zeroed();
+        msg.msg_name = &mut msg_name as *mut _ as *mut _;
+        msg.msg_namelen = msg_namelen;
+        msg.msg_iov = bufs.as_mut_ptr().cast();
+        msg.msg_control = ancillary.buffer.as_mut_ptr().cast();
+        cfg_if::cfg_if! {
+            if #[cfg(any(target_os = "android", all(target_os = "linux", target_env = "gnu")))] {
+                msg.msg_iovlen = bufs.len() as libc::size_t;
+                msg.msg_controllen = ancillary.length as libc::size_t;
+            } else if #[cfg(any(
+                          target_os = "dragonfly",
+                          target_os = "emscripten",
+                          target_os = "freebsd",
+                          all(target_os = "linux", target_env = "musl",),
+                          target_os = "netbsd",
+                          target_os = "openbsd",
+                      ))] {
+                msg.msg_iovlen = bufs.len() as libc::c_int;
+                msg.msg_controllen = ancillary.length as libc::socklen_t;
+            }
+        }
+
+        ancillary.truncated = false;
+
+        socket.send_msg(&mut msg)
+    }
+}
+
+fn add_to_ancillary_data<T>(
+    buffer: &mut [u8],
+    length: &mut usize,
+    source: &[T],
+    cmsg_level: libc::c_int,
+    cmsg_type: libc::c_int,
+) -> bool {
+    let source_len = if let Some(source_len) = source.len().checked_mul(size_of::<T>()) {
+        if let Ok(source_len) = u32::try_from(source_len) {
+            source_len
+        } else {
+            return false;
+        }
+    } else {
+        return false;
+    };
+
+    unsafe {
+        let additional_space = libc::CMSG_SPACE(source_len) as usize;
+
+        let new_length = if let Some(new_length) = additional_space.checked_add(*length) {
+            new_length
+        } else {
+            return false;
+        };
+
+        if new_length > buffer.len() {
+            return false;
+        }
+
+        buffer[*length..new_length].fill(0);
+
+        *length = new_length;
+
+        let mut msg: libc::msghdr = zeroed();
+        msg.msg_control = buffer.as_mut_ptr().cast();
+        cfg_if::cfg_if! {
+            if #[cfg(any(target_os = "android", all(target_os = "linux", target_env = "gnu")))] {
+                msg.msg_controllen = *length as libc::size_t;
+            } else if #[cfg(any(
+                          target_os = "dragonfly",
+                          target_os = "emscripten",
+                          target_os = "freebsd",
+                          all(target_os = "linux", target_env = "musl",),
+                          target_os = "netbsd",
+                          target_os = "openbsd",
+                      ))] {
+                msg.msg_controllen = *length as libc::socklen_t;
+            }
+        }
+
+        let mut cmsg = libc::CMSG_FIRSTHDR(&msg);
+        let mut previous_cmsg = cmsg;
+        while !cmsg.is_null() {
+            previous_cmsg = cmsg;
+            cmsg = libc::CMSG_NXTHDR(&msg, cmsg);
+            cfg_if::cfg_if! {
+                // Android return the same pointer if it is the last cmsg.
+                // Therefore, check it if the previous pointer is the same as the current one.
+                if #[cfg(target_os = "android")] {
+                    if cmsg == previous_cmsg {
+                        break;
+                    }
+                }
+            }
+        }
+
+        if previous_cmsg.is_null() {
+            return false;
+        }
+
+        (*previous_cmsg).cmsg_level = cmsg_level;
+        (*previous_cmsg).cmsg_type = cmsg_type;
+        cfg_if::cfg_if! {
+            if #[cfg(any(target_os = "android", all(target_os = "linux", target_env = "gnu")))] {
+                (*previous_cmsg).cmsg_len = libc::CMSG_LEN(source_len) as libc::size_t;
+            } else if #[cfg(any(
+                          target_os = "dragonfly",
+                          target_os = "emscripten",
+                          target_os = "freebsd",
+                          all(target_os = "linux", target_env = "musl",),
+                          target_os = "netbsd",
+                          target_os = "openbsd",
+                      ))] {
+                (*previous_cmsg).cmsg_len = libc::CMSG_LEN(source_len) as libc::socklen_t;
+            }
+        }
+
+        let data = libc::CMSG_DATA(previous_cmsg).cast();
+
+        libc::memcpy(data, source.as_ptr().cast(), source_len as usize);
+    }
+    true
+}
+
+struct AncillaryDataIter<'a, T> {
+    data: &'a [u8],
+    phantom: PhantomData<T>,
+}
+
+impl<'a, T> AncillaryDataIter<'a, T> {
+    /// Create `AncillaryDataIter` struct to iterate through the data unit in the control message.
+    ///
+    /// # Safety
+    ///
+    /// `data` must contain a valid control message.
+    unsafe fn new(data: &'a [u8]) -> AncillaryDataIter<'a, T> {
+        AncillaryDataIter { data, phantom: PhantomData }
+    }
+}
+
+impl<'a, T> Iterator for AncillaryDataIter<'a, T> {
+    type Item = T;
+
+    fn next(&mut self) -> Option<T> {
+        if size_of::<T>() <= self.data.len() {
+            unsafe {
+                let unit = read_unaligned(self.data.as_ptr().cast());
+                self.data = &self.data[size_of::<T>()..];
+                Some(unit)
+            }
+        } else {
+            None
+        }
+    }
+}
+
+/// Unix credential.
+#[cfg(any(doc, target_os = "android", target_os = "linux",))]
+#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
+#[derive(Clone)]
+pub struct SocketCred(libc::ucred);
+
+#[cfg(any(doc, target_os = "android", target_os = "linux",))]
+impl SocketCred {
+    /// Create a Unix credential struct.
+    ///
+    /// PID, UID and GID is set to 0.
+    #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
+    pub fn new() -> SocketCred {
+        SocketCred(libc::ucred { pid: 0, uid: 0, gid: 0 })
+    }
+
+    /// Set the PID.
+    #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
+    pub fn set_pid(&mut self, pid: libc::pid_t) {
+        self.0.pid = pid;
+    }
+
+    /// Get the current PID.
+    #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
+    pub fn get_pid(&self) -> libc::pid_t {
+        self.0.pid
+    }
+
+    /// Set the UID.
+    #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
+    pub fn set_uid(&mut self, uid: libc::uid_t) {
+        self.0.uid = uid;
+    }
+
+    /// Get the current UID.
+    #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
+    pub fn get_uid(&self) -> libc::uid_t {
+        self.0.uid
+    }
+
+    /// Set the GID.
+    #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
+    pub fn set_gid(&mut self, gid: libc::gid_t) {
+        self.0.gid = gid;
+    }
+
+    /// Get the current GID.
+    #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
+    pub fn get_gid(&self) -> libc::gid_t {
+        self.0.gid
+    }
+}
+
+/// This control message contains file descriptors.
+///
+/// The level is equal to `SOL_SOCKET` and the type is equal to `SCM_RIGHTS`.
+#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
+pub struct ScmRights<'a>(AncillaryDataIter<'a, RawFd>);
+
+#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
+impl<'a> Iterator for ScmRights<'a> {
+    type Item = RawFd;
+
+    fn next(&mut self) -> Option<RawFd> {
+        self.0.next()
+    }
+}
+
+/// This control message contains unix credentials.
+///
+/// The level is equal to `SOL_SOCKET` and the type is equal to `SCM_CREDENTIALS` or `SCM_CREDS`.
+#[cfg(any(doc, target_os = "android", target_os = "linux",))]
+#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
+pub struct ScmCredentials<'a>(AncillaryDataIter<'a, libc::ucred>);
+
+#[cfg(any(doc, target_os = "android", target_os = "linux",))]
+#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
+impl<'a> Iterator for ScmCredentials<'a> {
+    type Item = SocketCred;
+
+    fn next(&mut self) -> Option<SocketCred> {
+        Some(SocketCred(self.0.next()?))
+    }
+}
+
+/// The error type which is returned from parsing the type a control message.
+#[non_exhaustive]
+#[derive(Debug)]
+#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
+pub enum AncillaryError {
+    Unknown { cmsg_level: i32, cmsg_type: i32 },
+}
+
+/// This enum represent one control message of variable type.
+#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
+pub enum AncillaryData<'a> {
+    ScmRights(ScmRights<'a>),
+    #[cfg(any(doc, target_os = "android", target_os = "linux",))]
+    ScmCredentials(ScmCredentials<'a>),
+}
+
+impl<'a> AncillaryData<'a> {
+    /// Create a `AncillaryData::ScmRights` variant.
+    ///
+    /// # Safety
+    ///
+    /// `data` must contain a valid control message and the control message must be type of
+    /// `SOL_SOCKET` and level of `SCM_RIGHTS`.
+    unsafe fn as_rights(data: &'a [u8]) -> Self {
+        let ancillary_data_iter = AncillaryDataIter::new(data);
+        let scm_rights = ScmRights(ancillary_data_iter);
+        AncillaryData::ScmRights(scm_rights)
+    }
+
+    /// Create a `AncillaryData::ScmCredentials` variant.
+    ///
+    /// # Safety
+    ///
+    /// `data` must contain a valid control message and the control message must be type of
+    /// `SOL_SOCKET` and level of `SCM_CREDENTIALS` or `SCM_CREDENTIALS`.
+    #[cfg(any(doc, target_os = "android", target_os = "linux",))]
+    unsafe fn as_credentials(data: &'a [u8]) -> Self {
+        let ancillary_data_iter = AncillaryDataIter::new(data);
+        let scm_credentials = ScmCredentials(ancillary_data_iter);
+        AncillaryData::ScmCredentials(scm_credentials)
+    }
+
+    fn try_from_cmsghdr(cmsg: &'a libc::cmsghdr) -> Result<Self, AncillaryError> {
+        unsafe {
+            cfg_if::cfg_if! {
+                if #[cfg(any(target_os = "android", all(target_os = "linux", target_env = "gnu")))] {
+                    let cmsg_len_zero = libc::CMSG_LEN(0) as libc::size_t;
+                } else if #[cfg(any(
+                              target_os = "dragonfly",
+                              target_os = "emscripten",
+                              target_os = "freebsd",
+                              all(target_os = "linux", target_env = "musl",),
+                              target_os = "netbsd",
+                              target_os = "openbsd",
+                          ))] {
+                    let cmsg_len_zero = libc::CMSG_LEN(0) as libc::socklen_t;
+                }
+            }
+            let data_len = (*cmsg).cmsg_len - cmsg_len_zero;
+            let data = libc::CMSG_DATA(cmsg).cast();
+            let data = from_raw_parts(data, data_len as usize);
+
+            match (*cmsg).cmsg_level {
+                libc::SOL_SOCKET => match (*cmsg).cmsg_type {
+                    libc::SCM_RIGHTS => Ok(AncillaryData::as_rights(data)),
+                    #[cfg(any(target_os = "android", target_os = "linux",))]
+                    libc::SCM_CREDENTIALS => Ok(AncillaryData::as_credentials(data)),
+                    cmsg_type => {
+                        Err(AncillaryError::Unknown { cmsg_level: libc::SOL_SOCKET, cmsg_type })
+                    }
+                },
+                cmsg_level => {
+                    Err(AncillaryError::Unknown { cmsg_level, cmsg_type: (*cmsg).cmsg_type })
+                }
+            }
+        }
+    }
+}
+
+/// This struct is used to iterate through the control messages.
+#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
+pub struct Messages<'a> {
+    buffer: &'a [u8],
+    current: Option<&'a libc::cmsghdr>,
+}
+
+#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
+impl<'a> Iterator for Messages<'a> {
+    type Item = Result<AncillaryData<'a>, AncillaryError>;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        unsafe {
+            let mut msg: libc::msghdr = zeroed();
+            msg.msg_control = self.buffer.as_ptr() as *mut _;
+            cfg_if::cfg_if! {
+                if #[cfg(any(target_os = "android", all(target_os = "linux", target_env = "gnu")))] {
+                    msg.msg_controllen = self.buffer.len() as libc::size_t;
+                } else if #[cfg(any(
+                              target_os = "dragonfly",
+                              target_os = "emscripten",
+                              target_os = "freebsd",
+                              all(target_os = "linux", target_env = "musl",),
+                              target_os = "netbsd",
+                              target_os = "openbsd",
+                          ))] {
+                    msg.msg_controllen = self.buffer.len() as libc::socklen_t;
+                }
+            }
+
+            let cmsg = if let Some(current) = self.current {
+                libc::CMSG_NXTHDR(&msg, current)
+            } else {
+                libc::CMSG_FIRSTHDR(&msg)
+            };
+
+            let cmsg = cmsg.as_ref()?;
+            cfg_if::cfg_if! {
+                // Android return the same pointer if it is the last cmsg.
+                // Therefore, check it if the previous pointer is the same as the current one.
+                if #[cfg(target_os = "android")] {
+                    if let Some(current) = self.current {
+                        if eq(current, cmsg) {
+                            return None;
+                        }
+                    }
+                }
+            }
+
+            self.current = Some(cmsg);
+            let ancillary_result = AncillaryData::try_from_cmsghdr(cmsg);
+            Some(ancillary_result)
+        }
+    }
+}
+
+/// A Unix socket Ancillary data struct.
+///
+/// # Example
+/// ```no_run
+/// #![feature(unix_socket_ancillary_data)]
+/// use std::os::unix::net::{UnixStream, SocketAncillary, AncillaryData};
+/// use std::io::IoSliceMut;
+///
+/// fn main() -> std::io::Result<()> {
+///     let sock = UnixStream::connect("/tmp/sock")?;
+///
+///     let mut fds = [0; 8];
+///     let mut ancillary_buffer = [0; 128];
+///     let mut ancillary = SocketAncillary::new(&mut ancillary_buffer[..]);
+///
+///     let mut buf = [1; 8];
+///     let mut bufs = &mut [IoSliceMut::new(&mut buf[..])][..];
+///     sock.recv_vectored_with_ancillary(bufs, &mut ancillary)?;
+///
+///     for ancillary_result in ancillary.messages() {
+///         if let AncillaryData::ScmRights(scm_rights) = ancillary_result.unwrap() {
+///             for fd in scm_rights {
+///                 println!("receive file descriptor: {}", fd);
+///             }
+///         }
+///     }
+///     Ok(())
+/// }
+/// ```
+#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
+#[derive(Debug)]
+pub struct SocketAncillary<'a> {
+    buffer: &'a mut [u8],
+    length: usize,
+    truncated: bool,
+}
+
+impl<'a> SocketAncillary<'a> {
+    /// Create an ancillary data with the given buffer.
+    ///
+    /// # Example
+    ///
+    /// ```no_run
+    /// # #![allow(unused_mut)]
+    /// #![feature(unix_socket_ancillary_data)]
+    /// use std::os::unix::net::SocketAncillary;
+    /// let mut ancillary_buffer = [0; 128];
+    /// let mut ancillary = SocketAncillary::new(&mut ancillary_buffer[..]);
+    /// ```
+    #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
+    pub fn new(buffer: &'a mut [u8]) -> Self {
+        SocketAncillary { buffer, length: 0, truncated: false }
+    }
+
+    /// Returns the capacity of the buffer.
+    #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
+    pub fn capacity(&self) -> usize {
+        self.buffer.len()
+    }
+
+    /// Returns the number of used bytes.
+    #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
+    pub fn len(&self) -> usize {
+        self.length
+    }
+
+    /// Returns the iterator of the control messages.
+    #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
+    pub fn messages(&self) -> Messages<'_> {
+        Messages { buffer: &self.buffer[..self.length], current: None }
+    }
+
+    /// Is `true` if during a recv operation the ancillary was truncated.
+    ///
+    /// # Example
+    ///
+    /// ```no_run
+    /// #![feature(unix_socket_ancillary_data)]
+    /// use std::os::unix::net::{UnixStream, SocketAncillary};
+    /// use std::io::IoSliceMut;
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     let sock = UnixStream::connect("/tmp/sock")?;
+    ///
+    ///     let mut ancillary_buffer = [0; 128];
+    ///     let mut ancillary = SocketAncillary::new(&mut ancillary_buffer[..]);
+    ///
+    ///     let mut buf = [1; 8];
+    ///     let mut bufs = &mut [IoSliceMut::new(&mut buf[..])][..];
+    ///     sock.recv_vectored_with_ancillary(bufs, &mut ancillary)?;
+    ///
+    ///     println!("Is truncated: {}", ancillary.truncated());
+    ///     Ok(())
+    /// }
+    /// ```
+    #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
+    pub fn truncated(&self) -> bool {
+        self.truncated
+    }
+
+    /// Add file descriptors to the ancillary data.
+    ///
+    /// The function returns `true` if there was enough space in the buffer.
+    /// If there was not enough space then no file descriptors was appended.
+    /// Technically, that means this operation adds a control message with the level `SOL_SOCKET`
+    /// and type `SCM_RIGHTS`.
+    ///
+    /// # Example
+    ///
+    /// ```no_run
+    /// #![feature(unix_socket_ancillary_data)]
+    /// use std::os::unix::net::{UnixStream, SocketAncillary};
+    /// use std::os::unix::io::AsRawFd;
+    /// use std::io::IoSliceMut;
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     let sock = UnixStream::connect("/tmp/sock")?;
+    ///
+    ///     let mut ancillary_buffer = [0; 128];
+    ///     let mut ancillary = SocketAncillary::new(&mut ancillary_buffer[..]);
+    ///     ancillary.add_fds(&[sock.as_raw_fd()][..]);
+    ///
+    ///     let mut buf = [1; 8];
+    ///     let mut bufs = &mut [IoSliceMut::new(&mut buf[..])][..];
+    ///     sock.send_vectored_with_ancillary(bufs, &mut ancillary)?;
+    ///     Ok(())
+    /// }
+    /// ```
+    #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
+    pub fn add_fds(&mut self, fds: &[RawFd]) -> bool {
+        self.truncated = false;
+        add_to_ancillary_data(
+            &mut self.buffer,
+            &mut self.length,
+            fds,
+            libc::SOL_SOCKET,
+            libc::SCM_RIGHTS,
+        )
+    }
+
+    /// Add credentials to the ancillary data.
+    ///
+    /// The function returns `true` if there was enough space in the buffer.
+    /// If there was not enough space then no credentials was appended.
+    /// Technically, that means this operation adds a control message with the level `SOL_SOCKET`
+    /// and type `SCM_CREDENTIALS` or `SCM_CREDS`.
+    ///
+    #[cfg(any(doc, target_os = "android", target_os = "linux",))]
+    #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
+    pub fn add_creds(&mut self, creds: &[SocketCred]) -> bool {
+        self.truncated = false;
+        add_to_ancillary_data(
+            &mut self.buffer,
+            &mut self.length,
+            creds,
+            libc::SOL_SOCKET,
+            libc::SCM_CREDENTIALS,
+        )
+    }
+
+    /// Clears the ancillary data, removing all values.
+    ///
+    /// # Example
+    ///
+    /// ```no_run
+    /// #![feature(unix_socket_ancillary_data)]
+    /// use std::os::unix::net::{UnixStream, SocketAncillary, AncillaryData};
+    /// use std::io::IoSliceMut;
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     let sock = UnixStream::connect("/tmp/sock")?;
+    ///
+    ///     let mut fds1 = [0; 8];
+    ///     let mut fds2 = [0; 8];
+    ///     let mut ancillary_buffer = [0; 128];
+    ///     let mut ancillary = SocketAncillary::new(&mut ancillary_buffer[..]);
+    ///
+    ///     let mut buf = [1; 8];
+    ///     let mut bufs = &mut [IoSliceMut::new(&mut buf[..])][..];
+    ///
+    ///     sock.recv_vectored_with_ancillary(bufs, &mut ancillary)?;
+    ///     for ancillary_result in ancillary.messages() {
+    ///         if let AncillaryData::ScmRights(scm_rights) = ancillary_result.unwrap() {
+    ///             for fd in scm_rights {
+    ///                 println!("receive file descriptor: {}", fd);
+    ///             }
+    ///         }
+    ///     }
+    ///
+    ///     ancillary.clear();
+    ///
+    ///     sock.recv_vectored_with_ancillary(bufs, &mut ancillary)?;
+    ///     for ancillary_result in ancillary.messages() {
+    ///         if let AncillaryData::ScmRights(scm_rights) = ancillary_result.unwrap() {
+    ///             for fd in scm_rights {
+    ///                 println!("receive file descriptor: {}", fd);
+    ///             }
+    ///         }
+    ///     }
+    ///     Ok(())
+    /// }
+    /// ```
+    #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
+    pub fn clear(&mut self) {
+        self.length = 0;
+        self.truncated = false;
+    }
+}
diff --git a/library/std/src/sys/unix/ext/net/datagram.rs b/library/std/src/sys/unix/ext/net/datagram.rs
new file mode 100644
index 00000000000..0f532c47c8f
--- /dev/null
+++ b/library/std/src/sys/unix/ext/net/datagram.rs
@@ -0,0 +1,897 @@
+#[cfg(any(
+    doc,
+    target_os = "android",
+    target_os = "dragonfly",
+    target_os = "emscripten",
+    target_os = "freebsd",
+    target_os = "linux",
+    target_os = "netbsd",
+    target_os = "openbsd",
+))]
+use super::{recv_vectored_with_ancillary_from, send_vectored_with_ancillary_to, SocketAncillary};
+use super::{sockaddr_un, SocketAddr};
+#[cfg(any(
+    target_os = "android",
+    target_os = "dragonfly",
+    target_os = "emscripten",
+    target_os = "freebsd",
+    target_os = "linux",
+    target_os = "netbsd",
+    target_os = "openbsd",
+))]
+use crate::io::IoSliceMut;
+use crate::net::Shutdown;
+use crate::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
+use crate::path::Path;
+use crate::sys::cvt;
+use crate::sys::net::Socket;
+use crate::sys_common::{AsInner, FromInner, IntoInner};
+use crate::time::Duration;
+use crate::{fmt, io};
+
+#[cfg(any(
+    target_os = "linux",
+    target_os = "android",
+    target_os = "dragonfly",
+    target_os = "freebsd",
+    target_os = "openbsd",
+    target_os = "netbsd",
+    target_os = "haiku"
+))]
+use libc::MSG_NOSIGNAL;
+#[cfg(not(any(
+    target_os = "linux",
+    target_os = "android",
+    target_os = "dragonfly",
+    target_os = "freebsd",
+    target_os = "openbsd",
+    target_os = "netbsd",
+    target_os = "haiku"
+)))]
+const MSG_NOSIGNAL: libc::c_int = 0x0;
+
+/// A Unix datagram socket.
+///
+/// # Examples
+///
+/// ```no_run
+/// use std::os::unix::net::UnixDatagram;
+///
+/// fn main() -> std::io::Result<()> {
+///     let socket = UnixDatagram::bind("/path/to/my/socket")?;
+///     socket.send_to(b"hello world", "/path/to/other/socket")?;
+///     let mut buf = [0; 100];
+///     let (count, address) = socket.recv_from(&mut buf)?;
+///     println!("socket {:?} sent {:?}", address, &buf[..count]);
+///     Ok(())
+/// }
+/// ```
+#[stable(feature = "unix_socket", since = "1.10.0")]
+pub struct UnixDatagram(Socket);
+
+#[stable(feature = "unix_socket", since = "1.10.0")]
+impl fmt::Debug for UnixDatagram {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        let mut builder = fmt.debug_struct("UnixDatagram");
+        builder.field("fd", self.0.as_inner());
+        if let Ok(addr) = self.local_addr() {
+            builder.field("local", &addr);
+        }
+        if let Ok(addr) = self.peer_addr() {
+            builder.field("peer", &addr);
+        }
+        builder.finish()
+    }
+}
+
+impl UnixDatagram {
+    /// Creates a Unix datagram socket bound to the given path.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixDatagram;
+    ///
+    /// let sock = match UnixDatagram::bind("/path/to/the/socket") {
+    ///     Ok(sock) => sock,
+    ///     Err(e) => {
+    ///         println!("Couldn't bind: {:?}", e);
+    ///         return
+    ///     }
+    /// };
+    /// ```
+    #[stable(feature = "unix_socket", since = "1.10.0")]
+    pub fn bind<P: AsRef<Path>>(path: P) -> io::Result<UnixDatagram> {
+        unsafe {
+            let socket = UnixDatagram::unbound()?;
+            let (addr, len) = sockaddr_un(path.as_ref())?;
+
+            cvt(libc::bind(*socket.0.as_inner(), &addr as *const _ as *const _, len as _))?;
+
+            Ok(socket)
+        }
+    }
+
+    /// Creates a Unix Datagram socket which is not bound to any address.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixDatagram;
+    ///
+    /// let sock = match UnixDatagram::unbound() {
+    ///     Ok(sock) => sock,
+    ///     Err(e) => {
+    ///         println!("Couldn't unbound: {:?}", e);
+    ///         return
+    ///     }
+    /// };
+    /// ```
+    #[stable(feature = "unix_socket", since = "1.10.0")]
+    pub fn unbound() -> io::Result<UnixDatagram> {
+        let inner = Socket::new_raw(libc::AF_UNIX, libc::SOCK_DGRAM)?;
+        Ok(UnixDatagram(inner))
+    }
+
+    /// Creates an unnamed pair of connected sockets.
+    ///
+    /// Returns two `UnixDatagrams`s which are connected to each other.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixDatagram;
+    ///
+    /// let (sock1, sock2) = match UnixDatagram::pair() {
+    ///     Ok((sock1, sock2)) => (sock1, sock2),
+    ///     Err(e) => {
+    ///         println!("Couldn't unbound: {:?}", e);
+    ///         return
+    ///     }
+    /// };
+    /// ```
+    #[stable(feature = "unix_socket", since = "1.10.0")]
+    pub fn pair() -> io::Result<(UnixDatagram, UnixDatagram)> {
+        let (i1, i2) = Socket::new_pair(libc::AF_UNIX, libc::SOCK_DGRAM)?;
+        Ok((UnixDatagram(i1), UnixDatagram(i2)))
+    }
+
+    /// Connects the socket to the specified address.
+    ///
+    /// The [`send`] method may be used to send data to the specified address.
+    /// [`recv`] and [`recv_from`] will only receive data from that address.
+    ///
+    /// [`send`]: UnixDatagram::send
+    /// [`recv`]: UnixDatagram::recv
+    /// [`recv_from`]: UnixDatagram::recv_from
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixDatagram;
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     let sock = UnixDatagram::unbound()?;
+    ///     match sock.connect("/path/to/the/socket") {
+    ///         Ok(sock) => sock,
+    ///         Err(e) => {
+    ///             println!("Couldn't connect: {:?}", e);
+    ///             return Err(e)
+    ///         }
+    ///     };
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "unix_socket", since = "1.10.0")]
+    pub fn connect<P: AsRef<Path>>(&self, path: P) -> io::Result<()> {
+        unsafe {
+            let (addr, len) = sockaddr_un(path.as_ref())?;
+
+            cvt(libc::connect(*self.0.as_inner(), &addr as *const _ as *const _, len))?;
+        }
+        Ok(())
+    }
+
+    /// Creates a new independently owned handle to the underlying socket.
+    ///
+    /// The returned `UnixDatagram` is a reference to the same socket that this
+    /// object references. Both handles can be used to accept incoming
+    /// connections and options set on one side will affect the other.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixDatagram;
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     let sock = UnixDatagram::bind("/path/to/the/socket")?;
+    ///     let sock_copy = sock.try_clone().expect("try_clone failed");
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "unix_socket", since = "1.10.0")]
+    pub fn try_clone(&self) -> io::Result<UnixDatagram> {
+        self.0.duplicate().map(UnixDatagram)
+    }
+
+    /// Returns the address of this socket.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixDatagram;
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     let sock = UnixDatagram::bind("/path/to/the/socket")?;
+    ///     let addr = sock.local_addr().expect("Couldn't get local address");
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "unix_socket", since = "1.10.0")]
+    pub fn local_addr(&self) -> io::Result<SocketAddr> {
+        SocketAddr::new(|addr, len| unsafe { libc::getsockname(*self.0.as_inner(), addr, len) })
+    }
+
+    /// Returns the address of this socket's peer.
+    ///
+    /// The [`connect`] method will connect the socket to a peer.
+    ///
+    /// [`connect`]: UnixDatagram::connect
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixDatagram;
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     let sock = UnixDatagram::unbound()?;
+    ///     sock.connect("/path/to/the/socket")?;
+    ///
+    ///     let addr = sock.peer_addr().expect("Couldn't get peer address");
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "unix_socket", since = "1.10.0")]
+    pub fn peer_addr(&self) -> io::Result<SocketAddr> {
+        SocketAddr::new(|addr, len| unsafe { libc::getpeername(*self.0.as_inner(), addr, len) })
+    }
+
+    fn recv_from_flags(
+        &self,
+        buf: &mut [u8],
+        flags: libc::c_int,
+    ) -> io::Result<(usize, SocketAddr)> {
+        let mut count = 0;
+        let addr = SocketAddr::new(|addr, len| unsafe {
+            count = libc::recvfrom(
+                *self.0.as_inner(),
+                buf.as_mut_ptr() as *mut _,
+                buf.len(),
+                flags,
+                addr,
+                len,
+            );
+            if count > 0 {
+                1
+            } else if count == 0 {
+                0
+            } else {
+                -1
+            }
+        })?;
+
+        Ok((count as usize, addr))
+    }
+
+    /// Receives data from the socket.
+    ///
+    /// On success, returns the number of bytes read and the address from
+    /// whence the data came.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixDatagram;
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     let sock = UnixDatagram::unbound()?;
+    ///     let mut buf = vec![0; 10];
+    ///     let (size, sender) = sock.recv_from(buf.as_mut_slice())?;
+    ///     println!("received {} bytes from {:?}", size, sender);
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "unix_socket", since = "1.10.0")]
+    pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
+        self.recv_from_flags(buf, 0)
+    }
+
+    /// Receives data from the socket.
+    ///
+    /// On success, returns the number of bytes read.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixDatagram;
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     let sock = UnixDatagram::bind("/path/to/the/socket")?;
+    ///     let mut buf = vec![0; 10];
+    ///     sock.recv(buf.as_mut_slice()).expect("recv function failed");
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "unix_socket", since = "1.10.0")]
+    pub fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
+        self.0.read(buf)
+    }
+
+    /// Receives data and ancillary data from socket.
+    ///
+    /// On success, returns the number of bytes read, if the data was truncated and the address from whence the msg came.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// #![feature(unix_socket_ancillary_data)]
+    /// use std::os::unix::net::{UnixDatagram, SocketAncillary, AncillaryData};
+    /// use std::io::IoSliceMut;
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     let sock = UnixDatagram::unbound()?;
+    ///     let mut buf1 = [1; 8];
+    ///     let mut buf2 = [2; 16];
+    ///     let mut buf3 = [3; 8];
+    ///     let mut bufs = &mut [
+    ///         IoSliceMut::new(&mut buf1),
+    ///         IoSliceMut::new(&mut buf2),
+    ///         IoSliceMut::new(&mut buf3),
+    ///     ][..];
+    ///     let mut fds = [0; 8];
+    ///     let mut ancillary_buffer = [0; 128];
+    ///     let mut ancillary = SocketAncillary::new(&mut ancillary_buffer[..]);
+    ///     let (size, _truncated, sender) = sock.recv_vectored_with_ancillary_from(bufs, &mut ancillary)?;
+    ///     println!("received {}", size);
+    ///     for ancillary_result in ancillary.messages() {
+    ///         if let AncillaryData::ScmRights(scm_rights) = ancillary_result.unwrap() {
+    ///             for fd in scm_rights {
+    ///                 println!("receive file descriptor: {}", fd);
+    ///             }
+    ///         }
+    ///     }
+    ///     Ok(())
+    /// }
+    /// ```
+    #[cfg(any(
+        target_os = "android",
+        target_os = "dragonfly",
+        target_os = "emscripten",
+        target_os = "freebsd",
+        target_os = "linux",
+        target_os = "netbsd",
+        target_os = "openbsd",
+    ))]
+    #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
+    pub fn recv_vectored_with_ancillary_from(
+        &self,
+        bufs: &mut [IoSliceMut<'_>],
+        ancillary: &mut SocketAncillary<'_>,
+    ) -> io::Result<(usize, bool, SocketAddr)> {
+        let (count, truncated, addr) = recv_vectored_with_ancillary_from(&self.0, bufs, ancillary)?;
+        let addr = addr?;
+
+        Ok((count, truncated, addr))
+    }
+
+    /// Receives data and ancillary data from socket.
+    ///
+    /// On success, returns the number of bytes read and if the data was truncated.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// #![feature(unix_socket_ancillary_data)]
+    /// use std::os::unix::net::{UnixDatagram, SocketAncillary, AncillaryData};
+    /// use std::io::IoSliceMut;
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     let sock = UnixDatagram::unbound()?;
+    ///     let mut buf1 = [1; 8];
+    ///     let mut buf2 = [2; 16];
+    ///     let mut buf3 = [3; 8];
+    ///     let mut bufs = &mut [
+    ///         IoSliceMut::new(&mut buf1),
+    ///         IoSliceMut::new(&mut buf2),
+    ///         IoSliceMut::new(&mut buf3),
+    ///     ][..];
+    ///     let mut fds = [0; 8];
+    ///     let mut ancillary_buffer = [0; 128];
+    ///     let mut ancillary = SocketAncillary::new(&mut ancillary_buffer[..]);
+    ///     let (size, _truncated) = sock.recv_vectored_with_ancillary(bufs, &mut ancillary)?;
+    ///     println!("received {}", size);
+    ///     for ancillary_result in ancillary.messages() {
+    ///         if let AncillaryData::ScmRights(scm_rights) = ancillary_result.unwrap() {
+    ///             for fd in scm_rights {
+    ///                 println!("receive file descriptor: {}", fd);
+    ///             }
+    ///         }
+    ///     }
+    ///     Ok(())
+    /// }
+    /// ```
+    #[cfg(any(
+        target_os = "android",
+        target_os = "dragonfly",
+        target_os = "emscripten",
+        target_os = "freebsd",
+        target_os = "linux",
+        target_os = "netbsd",
+        target_os = "openbsd",
+    ))]
+    #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
+    pub fn recv_vectored_with_ancillary(
+        &self,
+        bufs: &mut [IoSliceMut<'_>],
+        ancillary: &mut SocketAncillary<'_>,
+    ) -> io::Result<(usize, bool)> {
+        let (count, truncated, addr) = recv_vectored_with_ancillary_from(&self.0, bufs, ancillary)?;
+        addr?;
+
+        Ok((count, truncated))
+    }
+
+    /// Sends data on the socket to the specified address.
+    ///
+    /// On success, returns the number of bytes written.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixDatagram;
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     let sock = UnixDatagram::unbound()?;
+    ///     sock.send_to(b"omelette au fromage", "/some/sock").expect("send_to function failed");
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "unix_socket", since = "1.10.0")]
+    pub fn send_to<P: AsRef<Path>>(&self, buf: &[u8], path: P) -> io::Result<usize> {
+        unsafe {
+            let (addr, len) = sockaddr_un(path.as_ref())?;
+
+            let count = cvt(libc::sendto(
+                *self.0.as_inner(),
+                buf.as_ptr() as *const _,
+                buf.len(),
+                MSG_NOSIGNAL,
+                &addr as *const _ as *const _,
+                len,
+            ))?;
+            Ok(count as usize)
+        }
+    }
+
+    /// Sends data on the socket to the socket's peer.
+    ///
+    /// The peer address may be set by the `connect` method, and this method
+    /// will return an error if the socket has not already been connected.
+    ///
+    /// On success, returns the number of bytes written.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixDatagram;
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     let sock = UnixDatagram::unbound()?;
+    ///     sock.connect("/some/sock").expect("Couldn't connect");
+    ///     sock.send(b"omelette au fromage").expect("send_to function failed");
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "unix_socket", since = "1.10.0")]
+    pub fn send(&self, buf: &[u8]) -> io::Result<usize> {
+        self.0.write(buf)
+    }
+
+    /// Sends data and ancillary data on the socket to the specified address.
+    ///
+    /// On success, returns the number of bytes written.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// #![feature(unix_socket_ancillary_data)]
+    /// use std::os::unix::net::{UnixDatagram, SocketAncillary};
+    /// use std::io::IoSliceMut;
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     let sock = UnixDatagram::unbound()?;
+    ///     let mut buf1 = [1; 8];
+    ///     let mut buf2 = [2; 16];
+    ///     let mut buf3 = [3; 8];
+    ///     let mut bufs = &mut [
+    ///         IoSliceMut::new(&mut buf1),
+    ///         IoSliceMut::new(&mut buf2),
+    ///         IoSliceMut::new(&mut buf3),
+    ///     ][..];
+    ///     let fds = [0, 1, 2];
+    ///     let mut ancillary_buffer = [0; 128];
+    ///     let mut ancillary = SocketAncillary::new(&mut ancillary_buffer[..]);
+    ///     ancillary.add_fds(&fds[..]);
+    ///     sock.send_vectored_with_ancillary_to(bufs, &mut ancillary, "/some/sock").expect("send_vectored_with_ancillary_to function failed");
+    ///     Ok(())
+    /// }
+    /// ```
+    #[cfg(any(
+        target_os = "android",
+        target_os = "dragonfly",
+        target_os = "emscripten",
+        target_os = "freebsd",
+        target_os = "linux",
+        target_os = "netbsd",
+        target_os = "openbsd",
+    ))]
+    #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
+    pub fn send_vectored_with_ancillary_to<P: AsRef<Path>>(
+        &self,
+        bufs: &mut [IoSliceMut<'_>],
+        ancillary: &mut SocketAncillary<'_>,
+        path: P,
+    ) -> io::Result<usize> {
+        send_vectored_with_ancillary_to(&self.0, Some(path.as_ref()), bufs, ancillary)
+    }
+
+    /// Sends data and ancillary data on the socket.
+    ///
+    /// On success, returns the number of bytes written.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// #![feature(unix_socket_ancillary_data)]
+    /// use std::os::unix::net::{UnixDatagram, SocketAncillary};
+    /// use std::io::IoSliceMut;
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     let sock = UnixDatagram::unbound()?;
+    ///     let mut buf1 = [1; 8];
+    ///     let mut buf2 = [2; 16];
+    ///     let mut buf3 = [3; 8];
+    ///     let mut bufs = &mut [
+    ///         IoSliceMut::new(&mut buf1),
+    ///         IoSliceMut::new(&mut buf2),
+    ///         IoSliceMut::new(&mut buf3),
+    ///     ][..];
+    ///     let fds = [0, 1, 2];
+    ///     let mut ancillary_buffer = [0; 128];
+    ///     let mut ancillary = SocketAncillary::new(&mut ancillary_buffer[..]);
+    ///     ancillary.add_fds(&fds[..]);
+    ///     sock.send_vectored_with_ancillary(bufs, &mut ancillary).expect("send_vectored_with_ancillary function failed");
+    ///     Ok(())
+    /// }
+    /// ```
+    #[cfg(any(
+        target_os = "android",
+        target_os = "dragonfly",
+        target_os = "emscripten",
+        target_os = "freebsd",
+        target_os = "linux",
+        target_os = "netbsd",
+        target_os = "openbsd",
+    ))]
+    #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
+    pub fn send_vectored_with_ancillary(
+        &self,
+        bufs: &mut [IoSliceMut<'_>],
+        ancillary: &mut SocketAncillary<'_>,
+    ) -> io::Result<usize> {
+        send_vectored_with_ancillary_to(&self.0, None, bufs, ancillary)
+    }
+
+    /// Sets the read timeout for the socket.
+    ///
+    /// If the provided value is [`None`], then [`recv`] and [`recv_from`] calls will
+    /// block indefinitely. An [`Err`] is returned if the zero [`Duration`]
+    /// is passed to this method.
+    ///
+    /// [`recv`]: UnixDatagram::recv
+    /// [`recv_from`]: UnixDatagram::recv_from
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::os::unix::net::UnixDatagram;
+    /// use std::time::Duration;
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     let sock = UnixDatagram::unbound()?;
+    ///     sock.set_read_timeout(Some(Duration::new(1, 0)))
+    ///         .expect("set_read_timeout function failed");
+    ///     Ok(())
+    /// }
+    /// ```
+    ///
+    /// An [`Err`] is returned if the zero [`Duration`] is passed to this
+    /// method:
+    ///
+    /// ```no_run
+    /// use std::io;
+    /// use std::os::unix::net::UnixDatagram;
+    /// use std::time::Duration;
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     let socket = UnixDatagram::unbound()?;
+    ///     let result = socket.set_read_timeout(Some(Duration::new(0, 0)));
+    ///     let err = result.unwrap_err();
+    ///     assert_eq!(err.kind(), io::ErrorKind::InvalidInput);
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "unix_socket", since = "1.10.0")]
+    pub fn set_read_timeout(&self, timeout: Option<Duration>) -> io::Result<()> {
+        self.0.set_timeout(timeout, libc::SO_RCVTIMEO)
+    }
+
+    /// Sets the write timeout for the socket.
+    ///
+    /// If the provided value is [`None`], then [`send`] and [`send_to`] calls will
+    /// block indefinitely. An [`Err`] is returned if the zero [`Duration`] is passed to this
+    /// method.
+    ///
+    /// [`send`]: UnixDatagram::send
+    /// [`send_to`]: UnixDatagram::send_to
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::os::unix::net::UnixDatagram;
+    /// use std::time::Duration;
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     let sock = UnixDatagram::unbound()?;
+    ///     sock.set_write_timeout(Some(Duration::new(1, 0)))
+    ///         .expect("set_write_timeout function failed");
+    ///     Ok(())
+    /// }
+    /// ```
+    ///
+    /// An [`Err`] is returned if the zero [`Duration`] is passed to this
+    /// method:
+    ///
+    /// ```no_run
+    /// use std::io;
+    /// use std::os::unix::net::UnixDatagram;
+    /// use std::time::Duration;
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     let socket = UnixDatagram::unbound()?;
+    ///     let result = socket.set_write_timeout(Some(Duration::new(0, 0)));
+    ///     let err = result.unwrap_err();
+    ///     assert_eq!(err.kind(), io::ErrorKind::InvalidInput);
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "unix_socket", since = "1.10.0")]
+    pub fn set_write_timeout(&self, timeout: Option<Duration>) -> io::Result<()> {
+        self.0.set_timeout(timeout, libc::SO_SNDTIMEO)
+    }
+
+    /// Returns the read timeout of this socket.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::os::unix::net::UnixDatagram;
+    /// use std::time::Duration;
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     let sock = UnixDatagram::unbound()?;
+    ///     sock.set_read_timeout(Some(Duration::new(1, 0)))
+    ///         .expect("set_read_timeout function failed");
+    ///     assert_eq!(sock.read_timeout()?, Some(Duration::new(1, 0)));
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "unix_socket", since = "1.10.0")]
+    pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
+        self.0.timeout(libc::SO_RCVTIMEO)
+    }
+
+    /// Returns the write timeout of this socket.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::os::unix::net::UnixDatagram;
+    /// use std::time::Duration;
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     let sock = UnixDatagram::unbound()?;
+    ///     sock.set_write_timeout(Some(Duration::new(1, 0)))
+    ///         .expect("set_write_timeout function failed");
+    ///     assert_eq!(sock.write_timeout()?, Some(Duration::new(1, 0)));
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "unix_socket", since = "1.10.0")]
+    pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
+        self.0.timeout(libc::SO_SNDTIMEO)
+    }
+
+    /// Moves the socket into or out of nonblocking mode.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::os::unix::net::UnixDatagram;
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     let sock = UnixDatagram::unbound()?;
+    ///     sock.set_nonblocking(true).expect("set_nonblocking function failed");
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "unix_socket", since = "1.10.0")]
+    pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
+        self.0.set_nonblocking(nonblocking)
+    }
+
+    /// Moves the socket to pass unix credentials as control message in [`SocketAncillary`].
+    ///
+    /// Set the socket option `SO_PASSCRED`.
+    ///
+    /// # Examples
+    ///
+    #[cfg_attr(any(target_os = "android", target_os = "linux"), doc = "```no_run")]
+    #[cfg_attr(not(any(target_os = "android", target_os = "linux")), doc = "```ignore")]
+    /// #![feature(unix_socket_ancillary_data)]
+    /// use std::os::unix::net::UnixDatagram;
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     let sock = UnixDatagram::unbound()?;
+    ///     sock.set_passcred(true).expect("set_passcred function failed");
+    ///     Ok(())
+    /// }
+    /// ```
+    #[cfg(any(doc, target_os = "android", target_os = "linux",))]
+    #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
+    pub fn set_passcred(&self, passcred: bool) -> io::Result<()> {
+        self.0.set_passcred(passcred)
+    }
+
+    /// Get the current value of the socket for passing unix credentials in [`SocketAncillary`].
+    /// This value can be change by [`set_passcred`].
+    ///
+    /// Get the socket option `SO_PASSCRED`.
+    ///
+    /// [`set_passcred`]: UnixDatagram::set_passcred
+    #[cfg(any(doc, target_os = "android", target_os = "linux",))]
+    #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
+    pub fn passcred(&self) -> io::Result<bool> {
+        self.0.passcred()
+    }
+
+    /// Returns the value of the `SO_ERROR` option.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixDatagram;
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     let sock = UnixDatagram::unbound()?;
+    ///     if let Ok(Some(err)) = sock.take_error() {
+    ///         println!("Got error: {:?}", err);
+    ///     }
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "unix_socket", since = "1.10.0")]
+    pub fn take_error(&self) -> io::Result<Option<io::Error>> {
+        self.0.take_error()
+    }
+
+    /// Shut down the read, write, or both halves of this connection.
+    ///
+    /// This function will cause all pending and future I/O calls on the
+    /// specified portions to immediately return with an appropriate value
+    /// (see the documentation of [`Shutdown`]).
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixDatagram;
+    /// use std::net::Shutdown;
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     let sock = UnixDatagram::unbound()?;
+    ///     sock.shutdown(Shutdown::Both).expect("shutdown function failed");
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "unix_socket", since = "1.10.0")]
+    pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
+        self.0.shutdown(how)
+    }
+
+    /// Receives data on the socket from the remote address to which it is
+    /// connected, without removing that data from the queue. On success,
+    /// returns the number of bytes peeked.
+    ///
+    /// Successive calls return the same data. This is accomplished by passing
+    /// `MSG_PEEK` as a flag to the underlying `recv` system call.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// #![feature(unix_socket_peek)]
+    ///
+    /// use std::os::unix::net::UnixDatagram;
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     let socket = UnixDatagram::bind("/tmp/sock")?;
+    ///     let mut buf = [0; 10];
+    ///     let len = socket.peek(&mut buf).expect("peek failed");
+    ///     Ok(())
+    /// }
+    /// ```
+    #[unstable(feature = "unix_socket_peek", issue = "76923")]
+    pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
+        self.0.peek(buf)
+    }
+
+    /// Receives a single datagram message on the socket, without removing it from the
+    /// queue. On success, returns the number of bytes read and the origin.
+    ///
+    /// The function must be called with valid byte array `buf` of sufficient size to
+    /// hold the message bytes. If a message is too long to fit in the supplied buffer,
+    /// excess bytes may be discarded.
+    ///
+    /// Successive calls return the same data. This is accomplished by passing
+    /// `MSG_PEEK` as a flag to the underlying `recvfrom` system call.
+    ///
+    /// Do not use this function to implement busy waiting, instead use `libc::poll` to
+    /// synchronize IO events on one or more sockets.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// #![feature(unix_socket_peek)]
+    ///
+    /// use std::os::unix::net::UnixDatagram;
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     let socket = UnixDatagram::bind("/tmp/sock")?;
+    ///     let mut buf = [0; 10];
+    ///     let (len, addr) = socket.peek_from(&mut buf).expect("peek failed");
+    ///     Ok(())
+    /// }
+    /// ```
+    #[unstable(feature = "unix_socket_peek", issue = "76923")]
+    pub fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
+        self.recv_from_flags(buf, libc::MSG_PEEK)
+    }
+}
+
+#[stable(feature = "unix_socket", since = "1.10.0")]
+impl AsRawFd for UnixDatagram {
+    fn as_raw_fd(&self) -> RawFd {
+        *self.0.as_inner()
+    }
+}
+
+#[stable(feature = "unix_socket", since = "1.10.0")]
+impl FromRawFd for UnixDatagram {
+    unsafe fn from_raw_fd(fd: RawFd) -> UnixDatagram {
+        UnixDatagram(Socket::from_inner(fd))
+    }
+}
+
+#[stable(feature = "unix_socket", since = "1.10.0")]
+impl IntoRawFd for UnixDatagram {
+    fn into_raw_fd(self) -> RawFd {
+        self.0.into_inner()
+    }
+}
diff --git a/library/std/src/sys/unix/ext/net/listener.rs b/library/std/src/sys/unix/ext/net/listener.rs
new file mode 100644
index 00000000000..9803c6e2746
--- /dev/null
+++ b/library/std/src/sys/unix/ext/net/listener.rs
@@ -0,0 +1,319 @@
+use super::{sockaddr_un, SocketAddr, UnixStream};
+use crate::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
+use crate::path::Path;
+use crate::sys::cvt;
+use crate::sys::net::Socket;
+use crate::sys_common::{AsInner, FromInner, IntoInner};
+use crate::{fmt, io, mem};
+
+/// A structure representing a Unix domain socket server.
+///
+/// # Examples
+///
+/// ```no_run
+/// use std::thread;
+/// use std::os::unix::net::{UnixStream, UnixListener};
+///
+/// fn handle_client(stream: UnixStream) {
+///     // ...
+/// }
+///
+/// fn main() -> std::io::Result<()> {
+///     let listener = UnixListener::bind("/path/to/the/socket")?;
+///
+///     // accept connections and process them, spawning a new thread for each one
+///     for stream in listener.incoming() {
+///         match stream {
+///             Ok(stream) => {
+///                 /* connection succeeded */
+///                 thread::spawn(|| handle_client(stream));
+///             }
+///             Err(err) => {
+///                 /* connection failed */
+///                 break;
+///             }
+///         }
+///     }
+///     Ok(())
+/// }
+/// ```
+#[stable(feature = "unix_socket", since = "1.10.0")]
+pub struct UnixListener(Socket);
+
+#[stable(feature = "unix_socket", since = "1.10.0")]
+impl fmt::Debug for UnixListener {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        let mut builder = fmt.debug_struct("UnixListener");
+        builder.field("fd", self.0.as_inner());
+        if let Ok(addr) = self.local_addr() {
+            builder.field("local", &addr);
+        }
+        builder.finish()
+    }
+}
+
+impl UnixListener {
+    /// Creates a new `UnixListener` bound to the specified socket.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixListener;
+    ///
+    /// let listener = match UnixListener::bind("/path/to/the/socket") {
+    ///     Ok(sock) => sock,
+    ///     Err(e) => {
+    ///         println!("Couldn't connect: {:?}", e);
+    ///         return
+    ///     }
+    /// };
+    /// ```
+    #[stable(feature = "unix_socket", since = "1.10.0")]
+    pub fn bind<P: AsRef<Path>>(path: P) -> io::Result<UnixListener> {
+        unsafe {
+            let inner = Socket::new_raw(libc::AF_UNIX, libc::SOCK_STREAM)?;
+            let (addr, len) = sockaddr_un(path.as_ref())?;
+
+            cvt(libc::bind(*inner.as_inner(), &addr as *const _ as *const _, len as _))?;
+            cvt(libc::listen(*inner.as_inner(), 128))?;
+
+            Ok(UnixListener(inner))
+        }
+    }
+
+    /// Accepts a new incoming connection to this listener.
+    ///
+    /// This function will block the calling thread until a new Unix connection
+    /// is established. When established, the corresponding [`UnixStream`] and
+    /// the remote peer's address will be returned.
+    ///
+    /// [`UnixStream`]: crate::os::unix::net::UnixStream
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixListener;
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     let listener = UnixListener::bind("/path/to/the/socket")?;
+    ///
+    ///     match listener.accept() {
+    ///         Ok((socket, addr)) => println!("Got a client: {:?}", addr),
+    ///         Err(e) => println!("accept function failed: {:?}", e),
+    ///     }
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "unix_socket", since = "1.10.0")]
+    pub fn accept(&self) -> io::Result<(UnixStream, SocketAddr)> {
+        let mut storage: libc::sockaddr_un = unsafe { mem::zeroed() };
+        let mut len = mem::size_of_val(&storage) as libc::socklen_t;
+        let sock = self.0.accept(&mut storage as *mut _ as *mut _, &mut len)?;
+        let addr = SocketAddr::from_parts(storage, len)?;
+        Ok((UnixStream(sock), addr))
+    }
+
+    /// Creates a new independently owned handle to the underlying socket.
+    ///
+    /// The returned `UnixListener` is a reference to the same socket that this
+    /// object references. Both handles can be used to accept incoming
+    /// connections and options set on one listener will affect the other.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixListener;
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     let listener = UnixListener::bind("/path/to/the/socket")?;
+    ///     let listener_copy = listener.try_clone().expect("try_clone failed");
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "unix_socket", since = "1.10.0")]
+    pub fn try_clone(&self) -> io::Result<UnixListener> {
+        self.0.duplicate().map(UnixListener)
+    }
+
+    /// Returns the local socket address of this listener.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixListener;
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     let listener = UnixListener::bind("/path/to/the/socket")?;
+    ///     let addr = listener.local_addr().expect("Couldn't get local address");
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "unix_socket", since = "1.10.0")]
+    pub fn local_addr(&self) -> io::Result<SocketAddr> {
+        SocketAddr::new(|addr, len| unsafe { libc::getsockname(*self.0.as_inner(), addr, len) })
+    }
+
+    /// Moves the socket into or out of nonblocking mode.
+    ///
+    /// This will result in the `accept` operation becoming nonblocking,
+    /// i.e., immediately returning from their calls. If the IO operation is
+    /// successful, `Ok` is returned and no further action is required. If the
+    /// IO operation could not be completed and needs to be retried, an error
+    /// with kind [`io::ErrorKind::WouldBlock`] is returned.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixListener;
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     let listener = UnixListener::bind("/path/to/the/socket")?;
+    ///     listener.set_nonblocking(true).expect("Couldn't set non blocking");
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "unix_socket", since = "1.10.0")]
+    pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
+        self.0.set_nonblocking(nonblocking)
+    }
+
+    /// Returns the value of the `SO_ERROR` option.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixListener;
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     let listener = UnixListener::bind("/tmp/sock")?;
+    ///
+    ///     if let Ok(Some(err)) = listener.take_error() {
+    ///         println!("Got error: {:?}", err);
+    ///     }
+    ///     Ok(())
+    /// }
+    /// ```
+    ///
+    /// # Platform specific
+    /// On Redox this always returns `None`.
+    #[stable(feature = "unix_socket", since = "1.10.0")]
+    pub fn take_error(&self) -> io::Result<Option<io::Error>> {
+        self.0.take_error()
+    }
+
+    /// Returns an iterator over incoming connections.
+    ///
+    /// The iterator will never return [`None`] and will also not yield the
+    /// peer's [`SocketAddr`] structure.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::thread;
+    /// use std::os::unix::net::{UnixStream, UnixListener};
+    ///
+    /// fn handle_client(stream: UnixStream) {
+    ///     // ...
+    /// }
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     let listener = UnixListener::bind("/path/to/the/socket")?;
+    ///
+    ///     for stream in listener.incoming() {
+    ///         match stream {
+    ///             Ok(stream) => {
+    ///                 thread::spawn(|| handle_client(stream));
+    ///             }
+    ///             Err(err) => {
+    ///                 break;
+    ///             }
+    ///         }
+    ///     }
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "unix_socket", since = "1.10.0")]
+    pub fn incoming(&self) -> Incoming<'_> {
+        Incoming { listener: self }
+    }
+}
+
+#[stable(feature = "unix_socket", since = "1.10.0")]
+impl AsRawFd for UnixListener {
+    fn as_raw_fd(&self) -> RawFd {
+        *self.0.as_inner()
+    }
+}
+
+#[stable(feature = "unix_socket", since = "1.10.0")]
+impl FromRawFd for UnixListener {
+    unsafe fn from_raw_fd(fd: RawFd) -> UnixListener {
+        UnixListener(Socket::from_inner(fd))
+    }
+}
+
+#[stable(feature = "unix_socket", since = "1.10.0")]
+impl IntoRawFd for UnixListener {
+    fn into_raw_fd(self) -> RawFd {
+        self.0.into_inner()
+    }
+}
+
+#[stable(feature = "unix_socket", since = "1.10.0")]
+impl<'a> IntoIterator for &'a UnixListener {
+    type Item = io::Result<UnixStream>;
+    type IntoIter = Incoming<'a>;
+
+    fn into_iter(self) -> Incoming<'a> {
+        self.incoming()
+    }
+}
+
+/// An iterator over incoming connections to a [`UnixListener`].
+///
+/// It will never return [`None`].
+///
+/// # Examples
+///
+/// ```no_run
+/// use std::thread;
+/// use std::os::unix::net::{UnixStream, UnixListener};
+///
+/// fn handle_client(stream: UnixStream) {
+///     // ...
+/// }
+///
+/// fn main() -> std::io::Result<()> {
+///     let listener = UnixListener::bind("/path/to/the/socket")?;
+///
+///     for stream in listener.incoming() {
+///         match stream {
+///             Ok(stream) => {
+///                 thread::spawn(|| handle_client(stream));
+///             }
+///             Err(err) => {
+///                 break;
+///             }
+///         }
+///     }
+///     Ok(())
+/// }
+/// ```
+#[derive(Debug)]
+#[stable(feature = "unix_socket", since = "1.10.0")]
+pub struct Incoming<'a> {
+    listener: &'a UnixListener,
+}
+
+#[stable(feature = "unix_socket", since = "1.10.0")]
+impl<'a> Iterator for Incoming<'a> {
+    type Item = io::Result<UnixStream>;
+
+    fn next(&mut self) -> Option<io::Result<UnixStream>> {
+        Some(self.listener.accept().map(|s| s.0))
+    }
+
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        (usize::MAX, None)
+    }
+}
diff --git a/library/std/src/sys/unix/ext/net/mod.rs b/library/std/src/sys/unix/ext/net/mod.rs
new file mode 100644
index 00000000000..3088ffb5e5c
--- /dev/null
+++ b/library/std/src/sys/unix/ext/net/mod.rs
@@ -0,0 +1,54 @@
+//! Unix-specific networking functionality
+
+#![stable(feature = "unix_socket", since = "1.10.0")]
+
+mod addr;
+#[doc(cfg(any(
+    target_os = "android",
+    target_os = "dragonfly",
+    target_os = "emscripten",
+    target_os = "freebsd",
+    target_os = "linux",
+    target_os = "netbsd",
+    target_os = "openbsd",
+)))]
+#[cfg(any(
+    doc,
+    target_os = "android",
+    target_os = "dragonfly",
+    target_os = "emscripten",
+    target_os = "freebsd",
+    target_os = "linux",
+    target_os = "netbsd",
+    target_os = "openbsd",
+))]
+mod ancillary;
+mod datagram;
+mod listener;
+mod raw_fd;
+mod stream;
+#[cfg(all(test, not(target_os = "emscripten")))]
+mod tests;
+
+#[stable(feature = "unix_socket", since = "1.10.0")]
+pub use self::addr::*;
+#[cfg(any(
+    doc,
+    target_os = "android",
+    target_os = "dragonfly",
+    target_os = "emscripten",
+    target_os = "freebsd",
+    target_os = "linux",
+    target_os = "netbsd",
+    target_os = "openbsd",
+))]
+#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
+pub use self::ancillary::*;
+#[stable(feature = "unix_socket", since = "1.10.0")]
+pub use self::datagram::*;
+#[stable(feature = "unix_socket", since = "1.10.0")]
+pub use self::listener::*;
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use self::raw_fd::*;
+#[stable(feature = "unix_socket", since = "1.10.0")]
+pub use self::stream::*;
diff --git a/library/std/src/sys/unix/ext/net/raw_fd.rs b/library/std/src/sys/unix/ext/net/raw_fd.rs
new file mode 100644
index 00000000000..c42fee4c73b
--- /dev/null
+++ b/library/std/src/sys/unix/ext/net/raw_fd.rs
@@ -0,0 +1,40 @@
+use crate::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
+use crate::sys_common::{self, AsInner, FromInner, IntoInner};
+use crate::{net, sys};
+
+macro_rules! impl_as_raw_fd {
+    ($($t:ident)*) => {$(
+        #[stable(feature = "rust1", since = "1.0.0")]
+        impl AsRawFd for net::$t {
+            fn as_raw_fd(&self) -> RawFd {
+                *self.as_inner().socket().as_inner()
+            }
+        }
+    )*};
+}
+impl_as_raw_fd! { TcpStream TcpListener UdpSocket }
+
+macro_rules! impl_from_raw_fd {
+    ($($t:ident)*) => {$(
+        #[stable(feature = "from_raw_os", since = "1.1.0")]
+        impl FromRawFd for net::$t {
+            unsafe fn from_raw_fd(fd: RawFd) -> net::$t {
+                let socket = sys::net::Socket::from_inner(fd);
+                net::$t::from_inner(sys_common::net::$t::from_inner(socket))
+            }
+        }
+    )*};
+}
+impl_from_raw_fd! { TcpStream TcpListener UdpSocket }
+
+macro_rules! impl_into_raw_fd {
+    ($($t:ident)*) => {$(
+        #[stable(feature = "into_raw_os", since = "1.4.0")]
+        impl IntoRawFd for net::$t {
+            fn into_raw_fd(self) -> RawFd {
+                self.into_inner().into_socket().into_inner()
+            }
+        }
+    )*};
+}
+impl_into_raw_fd! { TcpStream TcpListener UdpSocket }
diff --git a/library/std/src/sys/unix/ext/net/stream.rs b/library/std/src/sys/unix/ext/net/stream.rs
new file mode 100644
index 00000000000..9fe6b85837e
--- /dev/null
+++ b/library/std/src/sys/unix/ext/net/stream.rs
@@ -0,0 +1,673 @@
+#[cfg(any(
+    doc,
+    target_os = "android",
+    target_os = "dragonfly",
+    target_os = "emscripten",
+    target_os = "freebsd",
+    target_os = "linux",
+    target_os = "netbsd",
+    target_os = "openbsd",
+))]
+use super::{recv_vectored_with_ancillary_from, send_vectored_with_ancillary_to, SocketAncillary};
+use super::{sockaddr_un, SocketAddr};
+use crate::fmt;
+use crate::io::{self, Initializer, IoSlice, IoSliceMut};
+use crate::net::Shutdown;
+use crate::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
+#[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;
+use crate::path::Path;
+use crate::sys::cvt;
+use crate::sys::net::Socket;
+use crate::sys_common::{AsInner, FromInner, IntoInner};
+use crate::time::Duration;
+
+#[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;
+
+/// A Unix stream socket.
+///
+/// # Examples
+///
+/// ```no_run
+/// use std::os::unix::net::UnixStream;
+/// use std::io::prelude::*;
+///
+/// fn main() -> std::io::Result<()> {
+///     let mut stream = UnixStream::connect("/path/to/my/socket")?;
+///     stream.write_all(b"hello world")?;
+///     let mut response = String::new();
+///     stream.read_to_string(&mut response)?;
+///     println!("{}", response);
+///     Ok(())
+/// }
+/// ```
+#[stable(feature = "unix_socket", since = "1.10.0")]
+pub struct UnixStream(pub(super) Socket);
+
+#[stable(feature = "unix_socket", since = "1.10.0")]
+impl fmt::Debug for UnixStream {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        let mut builder = fmt.debug_struct("UnixStream");
+        builder.field("fd", self.0.as_inner());
+        if let Ok(addr) = self.local_addr() {
+            builder.field("local", &addr);
+        }
+        if let Ok(addr) = self.peer_addr() {
+            builder.field("peer", &addr);
+        }
+        builder.finish()
+    }
+}
+
+impl UnixStream {
+    /// Connects to the socket named by `path`.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixStream;
+    ///
+    /// let socket = match UnixStream::connect("/tmp/sock") {
+    ///     Ok(sock) => sock,
+    ///     Err(e) => {
+    ///         println!("Couldn't connect: {:?}", e);
+    ///         return
+    ///     }
+    /// };
+    /// ```
+    #[stable(feature = "unix_socket", since = "1.10.0")]
+    pub fn connect<P: AsRef<Path>>(path: P) -> io::Result<UnixStream> {
+        unsafe {
+            let inner = Socket::new_raw(libc::AF_UNIX, libc::SOCK_STREAM)?;
+            let (addr, len) = sockaddr_un(path.as_ref())?;
+
+            cvt(libc::connect(*inner.as_inner(), &addr as *const _ as *const _, len))?;
+            Ok(UnixStream(inner))
+        }
+    }
+
+    /// Creates an unnamed pair of connected sockets.
+    ///
+    /// Returns two `UnixStream`s which are connected to each other.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixStream;
+    ///
+    /// let (sock1, sock2) = match UnixStream::pair() {
+    ///     Ok((sock1, sock2)) => (sock1, sock2),
+    ///     Err(e) => {
+    ///         println!("Couldn't create a pair of sockets: {:?}", e);
+    ///         return
+    ///     }
+    /// };
+    /// ```
+    #[stable(feature = "unix_socket", since = "1.10.0")]
+    pub fn pair() -> io::Result<(UnixStream, UnixStream)> {
+        let (i1, i2) = Socket::new_pair(libc::AF_UNIX, libc::SOCK_STREAM)?;
+        Ok((UnixStream(i1), UnixStream(i2)))
+    }
+
+    /// Creates a new independently owned handle to the underlying socket.
+    ///
+    /// The returned `UnixStream` is a reference to the same stream that this
+    /// object references. Both handles will read and write the same stream of
+    /// data, and options set on one stream will be propagated to the other
+    /// stream.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixStream;
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     let socket = UnixStream::connect("/tmp/sock")?;
+    ///     let sock_copy = socket.try_clone().expect("Couldn't clone socket");
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "unix_socket", since = "1.10.0")]
+    pub fn try_clone(&self) -> io::Result<UnixStream> {
+        self.0.duplicate().map(UnixStream)
+    }
+
+    /// Returns the socket address of the local half of this connection.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixStream;
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     let socket = UnixStream::connect("/tmp/sock")?;
+    ///     let addr = socket.local_addr().expect("Couldn't get local address");
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "unix_socket", since = "1.10.0")]
+    pub fn local_addr(&self) -> io::Result<SocketAddr> {
+        SocketAddr::new(|addr, len| unsafe { libc::getsockname(*self.0.as_inner(), addr, len) })
+    }
+
+    /// Returns the socket address of the remote half of this connection.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixStream;
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     let socket = UnixStream::connect("/tmp/sock")?;
+    ///     let addr = socket.peer_addr().expect("Couldn't get peer address");
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "unix_socket", since = "1.10.0")]
+    pub fn peer_addr(&self) -> io::Result<SocketAddr> {
+        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
+    /// indefinitely. An [`Err`] is returned if the zero [`Duration`] is passed to this
+    /// method.
+    ///
+    /// [`read`]: io::Read::read
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixStream;
+    /// use std::time::Duration;
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     let socket = UnixStream::connect("/tmp/sock")?;
+    ///     socket.set_read_timeout(Some(Duration::new(1, 0))).expect("Couldn't set read timeout");
+    ///     Ok(())
+    /// }
+    /// ```
+    ///
+    /// An [`Err`] is returned if the zero [`Duration`] is passed to this
+    /// method:
+    ///
+    /// ```no_run
+    /// use std::io;
+    /// use std::os::unix::net::UnixStream;
+    /// use std::time::Duration;
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     let socket = UnixStream::connect("/tmp/sock")?;
+    ///     let result = socket.set_read_timeout(Some(Duration::new(0, 0)));
+    ///     let err = result.unwrap_err();
+    ///     assert_eq!(err.kind(), io::ErrorKind::InvalidInput);
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "unix_socket", since = "1.10.0")]
+    pub fn set_read_timeout(&self, timeout: Option<Duration>) -> io::Result<()> {
+        self.0.set_timeout(timeout, libc::SO_RCVTIMEO)
+    }
+
+    /// Sets the write timeout for the socket.
+    ///
+    /// If the provided value is [`None`], then [`write`] calls will block
+    /// indefinitely. An [`Err`] is returned if the zero [`Duration`] is
+    /// passed to this method.
+    ///
+    /// [`read`]: io::Read::read
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixStream;
+    /// use std::time::Duration;
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     let socket = UnixStream::connect("/tmp/sock")?;
+    ///     socket.set_write_timeout(Some(Duration::new(1, 0)))
+    ///         .expect("Couldn't set write timeout");
+    ///     Ok(())
+    /// }
+    /// ```
+    ///
+    /// An [`Err`] is returned if the zero [`Duration`] is passed to this
+    /// method:
+    ///
+    /// ```no_run
+    /// use std::io;
+    /// use std::net::UdpSocket;
+    /// use std::time::Duration;
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     let socket = UdpSocket::bind("127.0.0.1:34254")?;
+    ///     let result = socket.set_write_timeout(Some(Duration::new(0, 0)));
+    ///     let err = result.unwrap_err();
+    ///     assert_eq!(err.kind(), io::ErrorKind::InvalidInput);
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "unix_socket", since = "1.10.0")]
+    pub fn set_write_timeout(&self, timeout: Option<Duration>) -> io::Result<()> {
+        self.0.set_timeout(timeout, libc::SO_SNDTIMEO)
+    }
+
+    /// Returns the read timeout of this socket.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixStream;
+    /// use std::time::Duration;
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     let socket = UnixStream::connect("/tmp/sock")?;
+    ///     socket.set_read_timeout(Some(Duration::new(1, 0))).expect("Couldn't set read timeout");
+    ///     assert_eq!(socket.read_timeout()?, Some(Duration::new(1, 0)));
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "unix_socket", since = "1.10.0")]
+    pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
+        self.0.timeout(libc::SO_RCVTIMEO)
+    }
+
+    /// Returns the write timeout of this socket.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixStream;
+    /// use std::time::Duration;
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     let socket = UnixStream::connect("/tmp/sock")?;
+    ///     socket.set_write_timeout(Some(Duration::new(1, 0)))
+    ///         .expect("Couldn't set write timeout");
+    ///     assert_eq!(socket.write_timeout()?, Some(Duration::new(1, 0)));
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "unix_socket", since = "1.10.0")]
+    pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
+        self.0.timeout(libc::SO_SNDTIMEO)
+    }
+
+    /// Moves the socket into or out of nonblocking mode.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixStream;
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     let socket = UnixStream::connect("/tmp/sock")?;
+    ///     socket.set_nonblocking(true).expect("Couldn't set nonblocking");
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "unix_socket", since = "1.10.0")]
+    pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
+        self.0.set_nonblocking(nonblocking)
+    }
+
+    /// Moves the socket to pass unix credentials as control message in [`SocketAncillary`].
+    ///
+    /// Set the socket option `SO_PASSCRED`.
+    ///
+    /// # Examples
+    ///
+    #[cfg_attr(any(target_os = "android", target_os = "linux"), doc = "```no_run")]
+    #[cfg_attr(not(any(target_os = "android", target_os = "linux")), doc = "```ignore")]
+    /// #![feature(unix_socket_ancillary_data)]
+    /// use std::os::unix::net::UnixStream;
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     let socket = UnixStream::connect("/tmp/sock")?;
+    ///     socket.set_passcred(true).expect("Couldn't set passcred");
+    ///     Ok(())
+    /// }
+    /// ```
+    #[cfg(any(doc, target_os = "android", target_os = "linux",))]
+    #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
+    pub fn set_passcred(&self, passcred: bool) -> io::Result<()> {
+        self.0.set_passcred(passcred)
+    }
+
+    /// Get the current value of the socket for passing unix credentials in [`SocketAncillary`].
+    /// This value can be change by [`set_passcred`].
+    ///
+    /// Get the socket option `SO_PASSCRED`.
+    ///
+    /// [`set_passcred`]: UnixStream::set_passcred
+    #[cfg(any(doc, target_os = "android", target_os = "linux",))]
+    #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
+    pub fn passcred(&self) -> io::Result<bool> {
+        self.0.passcred()
+    }
+
+    /// Returns the value of the `SO_ERROR` option.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixStream;
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     let socket = UnixStream::connect("/tmp/sock")?;
+    ///     if let Ok(Some(err)) = socket.take_error() {
+    ///         println!("Got error: {:?}", err);
+    ///     }
+    ///     Ok(())
+    /// }
+    /// ```
+    ///
+    /// # Platform specific
+    /// On Redox this always returns `None`.
+    #[stable(feature = "unix_socket", since = "1.10.0")]
+    pub fn take_error(&self) -> io::Result<Option<io::Error>> {
+        self.0.take_error()
+    }
+
+    /// Shuts down the read, write, or both halves of this connection.
+    ///
+    /// This function will cause all pending and future I/O calls on the
+    /// specified portions to immediately return with an appropriate value
+    /// (see the documentation of [`Shutdown`]).
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixStream;
+    /// use std::net::Shutdown;
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     let socket = UnixStream::connect("/tmp/sock")?;
+    ///     socket.shutdown(Shutdown::Both).expect("shutdown function failed");
+    ///     Ok(())
+    /// }
+    /// ```
+    #[stable(feature = "unix_socket", since = "1.10.0")]
+    pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
+        self.0.shutdown(how)
+    }
+
+    /// Receives data on the socket from the remote address to which it is
+    /// connected, without removing that data from the queue. On success,
+    /// returns the number of bytes peeked.
+    ///
+    /// Successive calls return the same data. This is accomplished by passing
+    /// `MSG_PEEK` as a flag to the underlying `recv` system call.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// #![feature(unix_socket_peek)]
+    ///
+    /// use std::os::unix::net::UnixStream;
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     let socket = UnixStream::connect("/tmp/sock")?;
+    ///     let mut buf = [0; 10];
+    ///     let len = socket.peek(&mut buf).expect("peek failed");
+    ///     Ok(())
+    /// }
+    /// ```
+    #[unstable(feature = "unix_socket_peek", issue = "76923")]
+    pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
+        self.0.peek(buf)
+    }
+
+    /// Receives data and ancillary data from socket.
+    ///
+    /// On success, returns the number of bytes read.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// #![feature(unix_socket_ancillary_data)]
+    /// use std::os::unix::net::{UnixStream, SocketAncillary, AncillaryData};
+    /// use std::io::IoSliceMut;
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     let socket = UnixStream::connect("/tmp/sock")?;
+    ///     let mut buf1 = [1; 8];
+    ///     let mut buf2 = [2; 16];
+    ///     let mut buf3 = [3; 8];
+    ///     let mut bufs = &mut [
+    ///         IoSliceMut::new(&mut buf1),
+    ///         IoSliceMut::new(&mut buf2),
+    ///         IoSliceMut::new(&mut buf3),
+    ///     ][..];
+    ///     let mut fds = [0; 8];
+    ///     let mut ancillary_buffer = [0; 128];
+    ///     let mut ancillary = SocketAncillary::new(&mut ancillary_buffer[..]);
+    ///     let size = socket.recv_vectored_with_ancillary(bufs, &mut ancillary)?;
+    ///     println!("received {}", size);
+    ///     for ancillary_result in ancillary.messages() {
+    ///         if let AncillaryData::ScmRights(scm_rights) = ancillary_result.unwrap() {
+    ///             for fd in scm_rights {
+    ///                 println!("receive file descriptor: {}", fd);
+    ///             }
+    ///         }
+    ///     }
+    ///     Ok(())
+    /// }
+    /// ```
+    #[cfg(any(
+        target_os = "android",
+        target_os = "dragonfly",
+        target_os = "emscripten",
+        target_os = "freebsd",
+        target_os = "linux",
+        target_os = "netbsd",
+        target_os = "openbsd",
+    ))]
+    #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
+    pub fn recv_vectored_with_ancillary(
+        &self,
+        bufs: &mut [IoSliceMut<'_>],
+        ancillary: &mut SocketAncillary<'_>,
+    ) -> io::Result<usize> {
+        let (count, _, _) = recv_vectored_with_ancillary_from(&self.0, bufs, ancillary)?;
+
+        Ok(count)
+    }
+
+    /// Sends data and ancillary data on the socket.
+    ///
+    /// On success, returns the number of bytes written.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// #![feature(unix_socket_ancillary_data)]
+    /// use std::os::unix::net::{UnixStream, SocketAncillary};
+    /// use std::io::IoSliceMut;
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     let socket = UnixStream::connect("/tmp/sock")?;
+    ///     let mut buf1 = [1; 8];
+    ///     let mut buf2 = [2; 16];
+    ///     let mut buf3 = [3; 8];
+    ///     let mut bufs = &mut [
+    ///         IoSliceMut::new(&mut buf1),
+    ///         IoSliceMut::new(&mut buf2),
+    ///         IoSliceMut::new(&mut buf3),
+    ///     ][..];
+    ///     let fds = [0, 1, 2];
+    ///     let mut ancillary_buffer = [0; 128];
+    ///     let mut ancillary = SocketAncillary::new(&mut ancillary_buffer[..]);
+    ///     ancillary.add_fds(&fds[..]);
+    ///     socket.send_vectored_with_ancillary(bufs, &mut ancillary).expect("send_vectored_with_ancillary function failed");
+    ///     Ok(())
+    /// }
+    /// ```
+    #[cfg(any(
+        target_os = "android",
+        target_os = "dragonfly",
+        target_os = "emscripten",
+        target_os = "freebsd",
+        target_os = "linux",
+        target_os = "netbsd",
+        target_os = "openbsd",
+    ))]
+    #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
+    pub fn send_vectored_with_ancillary(
+        &self,
+        bufs: &mut [IoSliceMut<'_>],
+        ancillary: &mut SocketAncillary<'_>,
+    ) -> io::Result<usize> {
+        send_vectored_with_ancillary_to(&self.0, None, bufs, ancillary)
+    }
+}
+
+#[stable(feature = "unix_socket", since = "1.10.0")]
+impl io::Read for UnixStream {
+    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
+        io::Read::read(&mut &*self, buf)
+    }
+
+    fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
+        io::Read::read_vectored(&mut &*self, bufs)
+    }
+
+    #[inline]
+    fn is_read_vectored(&self) -> bool {
+        io::Read::is_read_vectored(&&*self)
+    }
+
+    #[inline]
+    unsafe fn initializer(&self) -> Initializer {
+        Initializer::nop()
+    }
+}
+
+#[stable(feature = "unix_socket", since = "1.10.0")]
+impl<'a> io::Read for &'a UnixStream {
+    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
+        self.0.read(buf)
+    }
+
+    fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
+        self.0.read_vectored(bufs)
+    }
+
+    #[inline]
+    fn is_read_vectored(&self) -> bool {
+        self.0.is_read_vectored()
+    }
+
+    #[inline]
+    unsafe fn initializer(&self) -> Initializer {
+        Initializer::nop()
+    }
+}
+
+#[stable(feature = "unix_socket", since = "1.10.0")]
+impl io::Write for UnixStream {
+    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
+        io::Write::write(&mut &*self, buf)
+    }
+
+    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
+        io::Write::write_vectored(&mut &*self, bufs)
+    }
+
+    #[inline]
+    fn is_write_vectored(&self) -> bool {
+        io::Write::is_write_vectored(&&*self)
+    }
+
+    fn flush(&mut self) -> io::Result<()> {
+        io::Write::flush(&mut &*self)
+    }
+}
+
+#[stable(feature = "unix_socket", since = "1.10.0")]
+impl<'a> io::Write for &'a UnixStream {
+    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
+        self.0.write(buf)
+    }
+
+    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
+        self.0.write_vectored(bufs)
+    }
+
+    #[inline]
+    fn is_write_vectored(&self) -> bool {
+        self.0.is_write_vectored()
+    }
+
+    fn flush(&mut self) -> io::Result<()> {
+        Ok(())
+    }
+}
+
+#[stable(feature = "unix_socket", since = "1.10.0")]
+impl AsRawFd for UnixStream {
+    fn as_raw_fd(&self) -> RawFd {
+        *self.0.as_inner()
+    }
+}
+
+#[stable(feature = "unix_socket", since = "1.10.0")]
+impl FromRawFd for UnixStream {
+    unsafe fn from_raw_fd(fd: RawFd) -> UnixStream {
+        UnixStream(Socket::from_inner(fd))
+    }
+}
+
+#[stable(feature = "unix_socket", since = "1.10.0")]
+impl IntoRawFd for UnixStream {
+    fn into_raw_fd(self) -> RawFd {
+        self.0.into_inner()
+    }
+}
diff --git a/library/std/src/sys/unix/ext/net/tests.rs b/library/std/src/sys/unix/ext/net/tests.rs
index ee73a6ed538..97a016904b4 100644
--- a/library/std/src/sys/unix/ext/net/tests.rs
+++ b/library/std/src/sys/unix/ext/net/tests.rs
@@ -1,11 +1,30 @@
+use super::*;
 use crate::io::prelude::*;
-use crate::io::{self, ErrorKind};
+use crate::io::{self, ErrorKind, IoSlice, IoSliceMut};
+#[cfg(any(
+    target_os = "android",
+    target_os = "dragonfly",
+    target_os = "emscripten",
+    target_os = "freebsd",
+    target_os = "linux",
+    target_os = "netbsd",
+    target_os = "openbsd",
+))]
+use crate::iter::FromIterator;
+#[cfg(any(
+    target_os = "android",
+    target_os = "dragonfly",
+    target_os = "emscripten",
+    target_os = "freebsd",
+    target_os = "linux",
+    target_os = "netbsd",
+    target_os = "openbsd",
+))]
+use crate::os::unix::io::AsRawFd;
 use crate::sys_common::io::test::tmpdir;
 use crate::thread;
 use crate::time::Duration;
 
-use super::*;
-
 macro_rules! or_panic {
     ($e:expr) => {
         match $e {
@@ -452,3 +471,170 @@ fn test_unix_datagram_peek_from() {
     assert_eq!(size, 11);
     assert_eq!(msg, &buf[..]);
 }
+
+#[cfg(any(
+    target_os = "android",
+    target_os = "dragonfly",
+    target_os = "emscripten",
+    target_os = "freebsd",
+    target_os = "linux",
+    target_os = "netbsd",
+    target_os = "openbsd",
+))]
+#[test]
+fn test_send_vectored_fds_unix_stream() {
+    let (s1, s2) = or_panic!(UnixStream::pair());
+
+    let mut buf1 = [1; 8];
+    let mut bufs_send = &mut [IoSliceMut::new(&mut buf1[..])][..];
+
+    let mut ancillary1_buffer = [0; 128];
+    let mut ancillary1 = SocketAncillary::new(&mut ancillary1_buffer[..]);
+    assert!(ancillary1.add_fds(&[s1.as_raw_fd()][..]));
+
+    let usize = or_panic!(s1.send_vectored_with_ancillary(&mut bufs_send, &mut ancillary1));
+    assert_eq!(usize, 8);
+
+    let mut buf2 = [0; 8];
+    let mut bufs_recv = &mut [IoSliceMut::new(&mut buf2[..])][..];
+
+    let mut ancillary2_buffer = [0; 128];
+    let mut ancillary2 = SocketAncillary::new(&mut ancillary2_buffer[..]);
+
+    let usize = or_panic!(s2.recv_vectored_with_ancillary(&mut bufs_recv, &mut ancillary2));
+    assert_eq!(usize, 8);
+    assert_eq!(buf1, buf2);
+
+    let mut ancillary_data_vec = Vec::from_iter(ancillary2.messages());
+    assert_eq!(ancillary_data_vec.len(), 1);
+    if let AncillaryData::ScmRights(scm_rights) = ancillary_data_vec.pop().unwrap().unwrap() {
+        let fd_vec = Vec::from_iter(scm_rights);
+        assert_eq!(fd_vec.len(), 1);
+        unsafe {
+            libc::close(fd_vec[0]);
+        }
+    } else {
+        unreachable!("must be ScmRights");
+    }
+}
+
+#[cfg(any(target_os = "android", target_os = "emscripten", target_os = "linux",))]
+#[test]
+fn test_send_vectored_with_ancillary_to_unix_datagram() {
+    fn getpid() -> libc::pid_t {
+        unsafe { libc::getpid() }
+    }
+
+    fn getuid() -> libc::uid_t {
+        unsafe { libc::getuid() }
+    }
+
+    fn getgid() -> libc::gid_t {
+        unsafe { libc::getgid() }
+    }
+
+    let dir = tmpdir();
+    let path1 = dir.path().join("sock1");
+    let path2 = dir.path().join("sock2");
+
+    let bsock1 = or_panic!(UnixDatagram::bind(&path1));
+    let bsock2 = or_panic!(UnixDatagram::bind(&path2));
+
+    or_panic!(bsock2.set_passcred(true));
+
+    let mut buf1 = [1; 8];
+    let mut bufs_send = &mut [IoSliceMut::new(&mut buf1[..])][..];
+
+    let mut ancillary1_buffer = [0; 128];
+    let mut ancillary1 = SocketAncillary::new(&mut ancillary1_buffer[..]);
+    let mut cred1 = SocketCred::new();
+    cred1.set_pid(getpid());
+    cred1.set_uid(getuid());
+    cred1.set_gid(getgid());
+    assert!(ancillary1.add_creds(&[cred1.clone()][..]));
+
+    let usize =
+        or_panic!(bsock1.send_vectored_with_ancillary_to(&mut bufs_send, &mut ancillary1, &path2));
+    assert_eq!(usize, 8);
+
+    let mut buf2 = [0; 8];
+    let mut bufs_recv = &mut [IoSliceMut::new(&mut buf2[..])][..];
+
+    let mut ancillary2_buffer = [0; 128];
+    let mut ancillary2 = SocketAncillary::new(&mut ancillary2_buffer[..]);
+
+    let (usize, truncated, _addr) =
+        or_panic!(bsock2.recv_vectored_with_ancillary_from(&mut bufs_recv, &mut ancillary2));
+    assert_eq!(ancillary2.truncated(), false);
+    assert_eq!(usize, 8);
+    assert_eq!(truncated, false);
+    assert_eq!(buf1, buf2);
+
+    let mut ancillary_data_vec = Vec::from_iter(ancillary2.messages());
+    assert_eq!(ancillary_data_vec.len(), 1);
+    if let AncillaryData::ScmCredentials(scm_credentials) =
+        ancillary_data_vec.pop().unwrap().unwrap()
+    {
+        let cred_vec = Vec::from_iter(scm_credentials);
+        assert_eq!(cred_vec.len(), 1);
+        assert_eq!(cred1.get_pid(), cred_vec[0].get_pid());
+        assert_eq!(cred1.get_uid(), cred_vec[0].get_uid());
+        assert_eq!(cred1.get_gid(), cred_vec[0].get_gid());
+    } else {
+        unreachable!("must be ScmCredentials");
+    }
+}
+
+#[cfg(any(
+    target_os = "android",
+    target_os = "dragonfly",
+    target_os = "emscripten",
+    target_os = "freebsd",
+    target_os = "linux",
+    target_os = "netbsd",
+    target_os = "openbsd",
+))]
+#[test]
+fn test_send_vectored_with_ancillary_unix_datagram() {
+    let dir = tmpdir();
+    let path1 = dir.path().join("sock1");
+    let path2 = dir.path().join("sock2");
+
+    let bsock1 = or_panic!(UnixDatagram::bind(&path1));
+    let bsock2 = or_panic!(UnixDatagram::bind(&path2));
+
+    let mut buf1 = [1; 8];
+    let mut bufs_send = &mut [IoSliceMut::new(&mut buf1[..])][..];
+
+    let mut ancillary1_buffer = [0; 128];
+    let mut ancillary1 = SocketAncillary::new(&mut ancillary1_buffer[..]);
+    assert!(ancillary1.add_fds(&[bsock1.as_raw_fd()][..]));
+
+    or_panic!(bsock1.connect(&path2));
+    let usize = or_panic!(bsock1.send_vectored_with_ancillary(&mut bufs_send, &mut ancillary1));
+    assert_eq!(usize, 8);
+
+    let mut buf2 = [0; 8];
+    let mut bufs_recv = &mut [IoSliceMut::new(&mut buf2[..])][..];
+
+    let mut ancillary2_buffer = [0; 128];
+    let mut ancillary2 = SocketAncillary::new(&mut ancillary2_buffer[..]);
+
+    let (usize, truncated) =
+        or_panic!(bsock2.recv_vectored_with_ancillary(&mut bufs_recv, &mut ancillary2));
+    assert_eq!(usize, 8);
+    assert_eq!(truncated, false);
+    assert_eq!(buf1, buf2);
+
+    let mut ancillary_data_vec = Vec::from_iter(ancillary2.messages());
+    assert_eq!(ancillary_data_vec.len(), 1);
+    if let AncillaryData::ScmRights(scm_rights) = ancillary_data_vec.pop().unwrap().unwrap() {
+        let fd_vec = Vec::from_iter(scm_rights);
+        assert_eq!(fd_vec.len(), 1);
+        unsafe {
+            libc::close(fd_vec[0]);
+        }
+    } else {
+        unreachable!("must be ScmRights");
+    }
+}
diff --git a/library/std/src/sys/unix/ext/ucred.rs b/library/std/src/sys/unix/ext/ucred.rs
index ed7516c7f28..1b4c18d3d84 100644
--- a/library/std/src/sys/unix/ext/ucred.rs
+++ b/library/std/src/sys/unix/ext/ucred.rs
@@ -28,15 +28,12 @@ pub struct UCred {
 #[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"
-))]
+#[cfg(any(target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd"))]
 pub use self::impl_bsd::peer_cred;
 
+#[cfg(any(target_os = "macos", target_os = "ios",))]
+pub use self::impl_mac::peer_cred;
+
 #[cfg(any(target_os = "linux", target_os = "android"))]
 pub mod impl_linux {
     use super::UCred;
@@ -73,13 +70,7 @@ pub mod impl_linux {
     }
 }
 
-#[cfg(any(
-    target_os = "dragonfly",
-    target_os = "macos",
-    target_os = "ios",
-    target_os = "freebsd",
-    target_os = "openbsd"
-))]
+#[cfg(any(target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd"))]
 pub mod impl_bsd {
     use super::UCred;
     use crate::io;
@@ -95,3 +86,41 @@ pub mod impl_bsd {
         }
     }
 }
+
+#[cfg(any(target_os = "macos", target_os = "ios",))]
+pub mod impl_mac {
+    use super::UCred;
+    use crate::os::unix::io::AsRawFd;
+    use crate::os::unix::net::UnixStream;
+    use crate::{io, mem};
+    use libc::{c_void, getpeereid, getsockopt, pid_t, socklen_t, LOCAL_PEERPID, SOL_LOCAL};
+
+    pub fn peer_cred(socket: &UnixStream) -> io::Result<UCred> {
+        let mut cred = UCred { uid: 1, gid: 1, pid: None };
+        unsafe {
+            let ret = getpeereid(socket.as_raw_fd(), &mut cred.uid, &mut cred.gid);
+
+            if ret != 0 {
+                return Err(io::Error::last_os_error());
+            }
+
+            let mut pid: pid_t = 1;
+            let mut pid_size = mem::size_of::<pid_t>() as socklen_t;
+
+            let ret = getsockopt(
+                socket.as_raw_fd(),
+                SOL_LOCAL,
+                LOCAL_PEERPID,
+                &mut pid as *mut pid_t as *mut c_void,
+                &mut pid_size,
+            );
+
+            if ret == 0 && pid_size as usize == mem::size_of::<pid_t>() {
+                cred.pid = Some(pid);
+                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
index 451b534b266..42d79418cf7 100644
--- a/library/std/src/sys/unix/ext/ucred/tests.rs
+++ b/library/std/src/sys/unix/ext/ucred/tests.rs
@@ -1,5 +1,5 @@
 use crate::os::unix::net::UnixStream;
-use libc::{getegid, geteuid};
+use libc::{getegid, geteuid, getpid};
 
 #[test]
 #[cfg(any(
@@ -23,3 +23,16 @@ fn test_socket_pair() {
     assert_eq!(cred_a.uid, uid);
     assert_eq!(cred_a.gid, gid);
 }
+
+#[test]
+#[cfg(any(target_os = "linux", target_os = "ios", target_os = "macos",))]
+fn test_socket_pair_pids(arg: Type) -> RetType {
+    // Create two connected sockets and get their peer credentials.
+    let (sock_a, sock_b) = UnixStream::pair().unwrap();
+    let (cred_a, cred_b) = (sock_a.peer_cred().unwrap(), sock_b.peer_cred().unwrap());
+
+    // On supported platforms (see the cfg above), the credentials should always include the PID.
+    let pid = unsafe { getpid() };
+    assert_eq!(cred_a.pid, Some(pid));
+    assert_eq!(cred_b.pid, Some(pid));
+}
diff --git a/library/std/src/sys/unix/fs.rs b/library/std/src/sys/unix/fs.rs
index 13cf930379c..d1b0ad9e5f8 100644
--- a/library/std/src/sys/unix/fs.rs
+++ b/library/std/src/sys/unix/fs.rs
@@ -1071,28 +1071,28 @@ pub fn readlink(p: &Path) -> io::Result<PathBuf> {
     }
 }
 
-pub fn symlink(src: &Path, dst: &Path) -> io::Result<()> {
-    let src = cstr(src)?;
-    let dst = cstr(dst)?;
-    cvt(unsafe { libc::symlink(src.as_ptr(), dst.as_ptr()) })?;
+pub fn symlink(original: &Path, link: &Path) -> io::Result<()> {
+    let original = cstr(original)?;
+    let link = cstr(link)?;
+    cvt(unsafe { libc::symlink(original.as_ptr(), link.as_ptr()) })?;
     Ok(())
 }
 
-pub fn link(src: &Path, dst: &Path) -> io::Result<()> {
-    let src = cstr(src)?;
-    let dst = cstr(dst)?;
+pub fn link(original: &Path, link: &Path) -> io::Result<()> {
+    let original = cstr(original)?;
+    let link = cstr(link)?;
     cfg_if::cfg_if! {
         if #[cfg(any(target_os = "vxworks", target_os = "redox", target_os = "android"))] {
             // VxWorks, Redox, and old versions of Android lack `linkat`, so use
             // `link` instead. POSIX leaves it implementation-defined whether
             // `link` follows symlinks, so rely on the `symlink_hard_link` test
             // in library/std/src/fs/tests.rs to check the behavior.
-            cvt(unsafe { libc::link(src.as_ptr(), dst.as_ptr()) })?;
+            cvt(unsafe { libc::link(original.as_ptr(), link.as_ptr()) })?;
         } else {
             // Use `linkat` with `AT_FDCWD` instead of `link` as `linkat` gives
             // us a flag to specify how symlinks should be handled. Pass 0 as
             // the flags argument, meaning don't follow symlinks.
-            cvt(unsafe { libc::linkat(libc::AT_FDCWD, src.as_ptr(), libc::AT_FDCWD, dst.as_ptr(), 0) })?;
+            cvt(unsafe { libc::linkat(libc::AT_FDCWD, original.as_ptr(), libc::AT_FDCWD, link.as_ptr(), 0) })?;
         }
     }
     Ok(())
@@ -1211,7 +1211,8 @@ pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
     use super::kernel_copy::{copy_regular_files, CopyResult};
 
     match copy_regular_files(reader.as_raw_fd(), writer.as_raw_fd(), max_len) {
-        CopyResult::Ended(result) => result,
+        CopyResult::Ended(bytes) => Ok(bytes),
+        CopyResult::Error(e, _) => Err(e),
         CopyResult::Fallback(written) => match io::copy::generic_copy(&mut reader, &mut writer) {
             Ok(bytes) => Ok(bytes + written),
             Err(e) => Err(e),
diff --git a/library/std/src/sys/unix/kernel_copy.rs b/library/std/src/sys/unix/kernel_copy.rs
index ac2fcfcb53f..200dbf06ff8 100644
--- a/library/std/src/sys/unix/kernel_copy.rs
+++ b/library/std/src/sys/unix/kernel_copy.rs
@@ -56,9 +56,10 @@ use crate::mem::ManuallyDrop;
 use crate::net::TcpStream;
 use crate::os::unix::fs::FileTypeExt;
 use crate::os::unix::io::{AsRawFd, FromRawFd, RawFd};
+use crate::os::unix::net::UnixStream;
 use crate::process::{ChildStderr, ChildStdin, ChildStdout};
 use crate::ptr;
-use crate::sync::atomic::{AtomicBool, Ordering};
+use crate::sync::atomic::{AtomicBool, AtomicU8, Ordering};
 use crate::sys::cvt;
 
 #[cfg(test)]
@@ -166,10 +167,11 @@ impl<R: CopyRead, W: CopyWrite> SpecCopy for Copier<'_, '_, R, W> {
 
             if input_meta.copy_file_range_candidate() && output_meta.copy_file_range_candidate() {
                 let result = copy_regular_files(readfd, writefd, max_write);
+                result.update_take(reader);
 
                 match result {
-                    CopyResult::Ended(Ok(bytes_copied)) => return Ok(bytes_copied + written),
-                    CopyResult::Ended(err) => return err,
+                    CopyResult::Ended(bytes_copied) => return Ok(bytes_copied + written),
+                    CopyResult::Error(e, _) => return Err(e),
                     CopyResult::Fallback(bytes) => written += bytes,
                 }
             }
@@ -181,20 +183,22 @@ impl<R: CopyRead, W: CopyWrite> SpecCopy for Copier<'_, '_, R, W> {
             // fall back to the generic copy loop.
             if input_meta.potential_sendfile_source() {
                 let result = sendfile_splice(SpliceMode::Sendfile, readfd, writefd, max_write);
+                result.update_take(reader);
 
                 match result {
-                    CopyResult::Ended(Ok(bytes_copied)) => return Ok(bytes_copied + written),
-                    CopyResult::Ended(err) => return err,
+                    CopyResult::Ended(bytes_copied) => return Ok(bytes_copied + written),
+                    CopyResult::Error(e, _) => return Err(e),
                     CopyResult::Fallback(bytes) => written += bytes,
                 }
             }
 
             if input_meta.maybe_fifo() || output_meta.maybe_fifo() {
                 let result = sendfile_splice(SpliceMode::Splice, readfd, writefd, max_write);
+                result.update_take(reader);
 
                 match result {
-                    CopyResult::Ended(Ok(bytes_copied)) => return Ok(bytes_copied + written),
-                    CopyResult::Ended(err) => return err,
+                    CopyResult::Ended(bytes_copied) => return Ok(bytes_copied + written),
+                    CopyResult::Error(e, _) => return Err(e),
                     CopyResult::Fallback(0) => { /* use the fallback below */ }
                     CopyResult::Fallback(_) => {
                         unreachable!("splice should not return > 0 bytes on the fallback path")
@@ -224,6 +228,9 @@ trait CopyRead: Read {
         Ok(0)
     }
 
+    /// Updates `Take` wrappers to remove the number of bytes copied.
+    fn taken(&mut self, _bytes: u64) {}
+
     /// The minimum of the limit of all `Take<_>` wrappers, `u64::MAX` otherwise.
     /// This method does not account for data `BufReader` buffers and would underreport
     /// the limit of a `Take<BufReader<Take<_>>>` type. Thus its result is only valid
@@ -250,6 +257,10 @@ where
         (**self).drain_to(writer, limit)
     }
 
+    fn taken(&mut self, bytes: u64) {
+        (**self).taken(bytes);
+    }
+
     fn min_limit(&self) -> u64 {
         (**self).min_limit()
     }
@@ -320,6 +331,34 @@ impl CopyWrite for &TcpStream {
     }
 }
 
+impl CopyRead for UnixStream {
+    fn properties(&self) -> CopyParams {
+        // avoid the stat syscall since we can be fairly sure it's a socket
+        CopyParams(FdMeta::Socket, Some(self.as_raw_fd()))
+    }
+}
+
+impl CopyRead for &UnixStream {
+    fn properties(&self) -> CopyParams {
+        // avoid the stat syscall since we can be fairly sure it's a socket
+        CopyParams(FdMeta::Socket, Some(self.as_raw_fd()))
+    }
+}
+
+impl CopyWrite for UnixStream {
+    fn properties(&self) -> CopyParams {
+        // avoid the stat syscall since we can be fairly sure it's a socket
+        CopyParams(FdMeta::Socket, Some(self.as_raw_fd()))
+    }
+}
+
+impl CopyWrite for &UnixStream {
+    fn properties(&self) -> CopyParams {
+        // avoid the stat syscall since we can be fairly sure it's a socket
+        CopyParams(FdMeta::Socket, Some(self.as_raw_fd()))
+    }
+}
+
 impl CopyWrite for ChildStdin {
     fn properties(&self) -> CopyParams {
         CopyParams(FdMeta::Pipe, Some(self.as_raw_fd()))
@@ -378,6 +417,11 @@ impl<T: CopyRead> CopyRead for Take<T> {
         Ok(bytes_drained)
     }
 
+    fn taken(&mut self, bytes: u64) {
+        self.set_limit(self.limit() - bytes);
+        self.get_mut().taken(bytes);
+    }
+
     fn min_limit(&self) -> u64 {
         min(Take::limit(self), self.get_ref().min_limit())
     }
@@ -403,6 +447,10 @@ impl<T: CopyRead> CopyRead for BufReader<T> {
         Ok(bytes as u64 + inner_bytes)
     }
 
+    fn taken(&mut self, bytes: u64) {
+        self.get_mut().taken(bytes);
+    }
+
     fn min_limit(&self) -> u64 {
         self.get_ref().min_limit()
     }
@@ -428,12 +476,30 @@ fn fd_to_meta<T: AsRawFd>(fd: &T) -> FdMeta {
 }
 
 pub(super) enum CopyResult {
-    Ended(Result<u64>),
+    Ended(u64),
+    Error(Error, u64),
     Fallback(u64),
 }
 
-/// linux-specific implementation that will attempt to use copy_file_range for copy offloading
-/// as the name says, it only works on regular files
+impl CopyResult {
+    fn update_take(&self, reader: &mut impl CopyRead) {
+        match *self {
+            CopyResult::Fallback(bytes)
+            | CopyResult::Ended(bytes)
+            | CopyResult::Error(_, bytes) => reader.taken(bytes),
+        }
+    }
+}
+
+/// Invalid file descriptor.
+///
+/// Valid file descriptors are guaranteed to be positive numbers (see `open()` manpage)
+/// while negative values are used to indicate errors.
+/// Thus -1 will never be overlap with a valid open file.
+const INVALID_FD: RawFd = -1;
+
+/// Linux-specific implementation that will attempt to use copy_file_range for copy offloading.
+/// As the name says, it only works on regular files.
 ///
 /// Callers must handle fallback to a generic copy loop.
 /// `Fallback` may indicate non-zero number of bytes already written
@@ -441,54 +507,58 @@ pub(super) enum CopyResult {
 pub(super) fn copy_regular_files(reader: RawFd, writer: RawFd, max_len: u64) -> CopyResult {
     use crate::cmp;
 
+    const NOT_PROBED: u8 = 0;
+    const UNAVAILABLE: u8 = 1;
+    const AVAILABLE: u8 = 2;
+
     // Kernel prior to 4.5 don't have copy_file_range
     // We store the availability in a global to avoid unnecessary syscalls
-    static HAS_COPY_FILE_RANGE: AtomicBool = AtomicBool::new(true);
+    static HAS_COPY_FILE_RANGE: AtomicU8 = AtomicU8::new(NOT_PROBED);
 
-    unsafe fn copy_file_range(
-        fd_in: libc::c_int,
-        off_in: *mut libc::loff_t,
-        fd_out: libc::c_int,
-        off_out: *mut libc::loff_t,
-        len: libc::size_t,
-        flags: libc::c_uint,
-    ) -> libc::c_long {
-        libc::syscall(libc::SYS_copy_file_range, fd_in, off_in, fd_out, off_out, len, flags)
+    syscall! {
+        fn copy_file_range(
+            fd_in: libc::c_int,
+            off_in: *mut libc::loff_t,
+            fd_out: libc::c_int,
+            off_out: *mut libc::loff_t,
+            len: libc::size_t,
+            flags: libc::c_uint
+        ) -> libc::ssize_t
     }
 
-    let has_copy_file_range = HAS_COPY_FILE_RANGE.load(Ordering::Relaxed);
-    let mut written = 0u64;
-    while written < max_len {
-        let copy_result = if has_copy_file_range {
-            let bytes_to_copy = cmp::min(max_len - written, usize::MAX as u64);
-            // cap to 1GB chunks in case u64::MAX is passed as max_len and the file has a non-zero seek position
-            // this allows us to copy large chunks without hitting EOVERFLOW,
-            // unless someone sets a file offset close to u64::MAX - 1GB, in which case a fallback would be required
-            let bytes_to_copy = cmp::min(bytes_to_copy as usize, 0x4000_0000usize);
-            let copy_result = unsafe {
-                // We actually don't have to adjust the offsets,
-                // because copy_file_range adjusts the file offset automatically
-                cvt(copy_file_range(
-                    reader,
-                    ptr::null_mut(),
-                    writer,
-                    ptr::null_mut(),
-                    bytes_to_copy,
-                    0,
-                ))
+    match HAS_COPY_FILE_RANGE.load(Ordering::Relaxed) {
+        NOT_PROBED => {
+            // EPERM can indicate seccomp filters or an immutable file.
+            // To distinguish these cases we probe with invalid file descriptors which should result in EBADF if the syscall is supported
+            // and some other error (ENOSYS or EPERM) if it's not available
+            let result = unsafe {
+                cvt(copy_file_range(INVALID_FD, ptr::null_mut(), INVALID_FD, ptr::null_mut(), 1, 0))
             };
-            if let Err(ref copy_err) = copy_result {
-                match copy_err.raw_os_error() {
-                    Some(libc::ENOSYS | libc::EPERM | libc::EOPNOTSUPP) => {
-                        HAS_COPY_FILE_RANGE.store(false, Ordering::Relaxed);
-                    }
-                    _ => {}
-                }
+
+            if matches!(result.map_err(|e| e.raw_os_error()), Err(Some(libc::EBADF))) {
+                HAS_COPY_FILE_RANGE.store(AVAILABLE, Ordering::Relaxed);
+            } else {
+                HAS_COPY_FILE_RANGE.store(UNAVAILABLE, Ordering::Relaxed);
+                return CopyResult::Fallback(0);
             }
-            copy_result
-        } else {
-            Err(Error::from_raw_os_error(libc::ENOSYS))
+        }
+        UNAVAILABLE => return CopyResult::Fallback(0),
+        _ => {}
+    };
+
+    let mut written = 0u64;
+    while written < max_len {
+        let bytes_to_copy = cmp::min(max_len - written, usize::MAX as u64);
+        // cap to 1GB chunks in case u64::MAX is passed as max_len and the file has a non-zero seek position
+        // this allows us to copy large chunks without hitting EOVERFLOW,
+        // unless someone sets a file offset close to u64::MAX - 1GB, in which case a fallback would be required
+        let bytes_to_copy = cmp::min(bytes_to_copy as usize, 0x4000_0000usize);
+        let copy_result = unsafe {
+            // We actually don't have to adjust the offsets,
+            // because copy_file_range adjusts the file offset automatically
+            cvt(copy_file_range(reader, ptr::null_mut(), writer, ptr::null_mut(), bytes_to_copy, 0))
         };
+
         match copy_result {
             Ok(0) if written == 0 => {
                 // fallback to work around several kernel bugs where copy_file_range will fail to
@@ -498,7 +568,7 @@ pub(super) fn copy_regular_files(reader: RawFd, writer: RawFd, max_len: u64) ->
                 // - copying from an overlay filesystem in docker. reported to occur on fedora 32.
                 return CopyResult::Fallback(0);
             }
-            Ok(0) => return CopyResult::Ended(Ok(written)), // reached EOF
+            Ok(0) => return CopyResult::Ended(written), // reached EOF
             Ok(ret) => written += ret as u64,
             Err(err) => {
                 return match err.raw_os_error() {
@@ -508,20 +578,23 @@ pub(super) fn copy_regular_files(reader: RawFd, writer: RawFd, max_len: u64) ->
                         libc::ENOSYS | libc::EXDEV | libc::EINVAL | libc::EPERM | libc::EOPNOTSUPP,
                     ) => {
                         // Try fallback io::copy if either:
-                        // - Kernel version is < 4.5 (ENOSYS)
+                        // - Kernel version is < 4.5 (ENOSYS¹)
                         // - Files are mounted on different fs (EXDEV)
                         // - copy_file_range is broken in various ways on RHEL/CentOS 7 (EOPNOTSUPP)
-                        // - copy_file_range is disallowed, for example by seccomp (EPERM)
+                        // - copy_file_range file is immutable or syscall is blocked by seccomp¹ (EPERM)
                         // - copy_file_range cannot be used with pipes or device nodes (EINVAL)
+                        //
+                        // ¹ these cases should be detected by the initial probe but we handle them here
+                        //   anyway in case syscall interception changes during runtime
                         assert_eq!(written, 0);
                         CopyResult::Fallback(0)
                     }
-                    _ => CopyResult::Ended(Err(err)),
+                    _ => CopyResult::Error(err, written),
                 };
             }
         }
     }
-    CopyResult::Ended(Ok(written))
+    CopyResult::Ended(written)
 }
 
 #[derive(PartialEq)]
@@ -594,10 +667,10 @@ fn sendfile_splice(mode: SpliceMode, reader: RawFd, writer: RawFd, len: u64) ->
                     Some(os_err) if mode == SpliceMode::Sendfile && os_err == libc::EOVERFLOW => {
                         CopyResult::Fallback(written)
                     }
-                    _ => CopyResult::Ended(Err(err)),
+                    _ => CopyResult::Error(err, written),
                 };
             }
         }
     }
-    CopyResult::Ended(Ok(written))
+    CopyResult::Ended(written)
 }
diff --git a/library/std/src/sys/unix/kernel_copy/tests.rs b/library/std/src/sys/unix/kernel_copy/tests.rs
index 21b121c26ff..77369cdd35f 100644
--- a/library/std/src/sys/unix/kernel_copy/tests.rs
+++ b/library/std/src/sys/unix/kernel_copy/tests.rs
@@ -1,18 +1,18 @@
-use crate::env::temp_dir;
 use crate::fs::OpenOptions;
 use crate::io;
 use crate::io::Result;
 use crate::io::SeekFrom;
 use crate::io::{BufRead, Read, Seek, Write};
 use crate::os::unix::io::AsRawFd;
+use crate::sys_common::io::test::tmpdir;
 
 #[test]
 fn copy_specialization() -> Result<()> {
     use crate::io::{BufReader, BufWriter};
 
-    let path = crate::env::temp_dir();
-    let source_path = path.join("copy-spec.source");
-    let sink_path = path.join("copy-spec.sink");
+    let tmp_path = tmpdir();
+    let source_path = tmp_path.join("copy-spec.source");
+    let sink_path = tmp_path.join("copy-spec.sink");
 
     let result: Result<()> = try {
         let mut source = crate::fs::OpenOptions::new()
@@ -42,8 +42,15 @@ fn copy_specialization() -> Result<()> {
         assert_eq!(sink.buffer(), b"wxyz");
 
         let copied = crate::io::copy(&mut source, &mut sink)?;
-        assert_eq!(copied, 10);
-        assert_eq!(sink.buffer().len(), 0);
+        assert_eq!(copied, 10, "copy obeyed limit imposed by Take");
+        assert_eq!(sink.buffer().len(), 0, "sink buffer was flushed");
+        assert_eq!(source.limit(), 0, "outer Take was exhausted");
+        assert_eq!(source.get_ref().buffer().len(), 0, "source buffer should be drained");
+        assert_eq!(
+            source.get_ref().get_ref().limit(),
+            1,
+            "inner Take allowed reading beyond end of file, some bytes should be left"
+        );
 
         let mut sink = sink.into_inner()?;
         sink.seek(SeekFrom::Start(0))?;
@@ -61,7 +68,8 @@ fn copy_specialization() -> Result<()> {
 #[bench]
 fn bench_file_to_file_copy(b: &mut test::Bencher) {
     const BYTES: usize = 128 * 1024;
-    let src_path = temp_dir().join("file-copy-bench-src");
+    let temp_path = tmpdir();
+    let src_path = temp_path.join("file-copy-bench-src");
     let mut src = crate::fs::OpenOptions::new()
         .create(true)
         .truncate(true)
@@ -71,7 +79,7 @@ fn bench_file_to_file_copy(b: &mut test::Bencher) {
         .unwrap();
     src.write(&vec![0u8; BYTES]).unwrap();
 
-    let sink_path = temp_dir().join("file-copy-bench-sink");
+    let sink_path = temp_path.join("file-copy-bench-sink");
     let mut sink = crate::fs::OpenOptions::new()
         .create(true)
         .truncate(true)
@@ -90,7 +98,8 @@ fn bench_file_to_file_copy(b: &mut test::Bencher) {
 #[bench]
 fn bench_file_to_socket_copy(b: &mut test::Bencher) {
     const BYTES: usize = 128 * 1024;
-    let src_path = temp_dir().join("pipe-copy-bench-src");
+    let temp_path = tmpdir();
+    let src_path = temp_path.join("pipe-copy-bench-src");
     let mut src = OpenOptions::new()
         .create(true)
         .truncate(true)
@@ -118,6 +127,36 @@ fn bench_file_to_socket_copy(b: &mut test::Bencher) {
     });
 }
 
+#[bench]
+fn bench_file_to_uds_copy(b: &mut test::Bencher) {
+    const BYTES: usize = 128 * 1024;
+    let temp_path = tmpdir();
+    let src_path = temp_path.join("uds-copy-bench-src");
+    let mut src = OpenOptions::new()
+        .create(true)
+        .truncate(true)
+        .read(true)
+        .write(true)
+        .open(src_path)
+        .unwrap();
+    src.write(&vec![0u8; BYTES]).unwrap();
+
+    let (mut sink, mut sink_drainer) = crate::os::unix::net::UnixStream::pair().unwrap();
+
+    crate::thread::spawn(move || {
+        let mut sink_buf = vec![0u8; 1024 * 1024];
+        loop {
+            sink_drainer.read(&mut sink_buf[..]).unwrap();
+        }
+    });
+
+    b.bytes = BYTES as u64;
+    b.iter(|| {
+        src.seek(SeekFrom::Start(0)).unwrap();
+        assert_eq!(BYTES as u64, io::copy(&mut src, &mut sink).unwrap());
+    });
+}
+
 #[cfg(any(target_os = "linux", target_os = "android"))]
 #[bench]
 fn bench_socket_pipe_socket_copy(b: &mut test::Bencher) {
@@ -181,7 +220,7 @@ fn bench_socket_pipe_socket_copy(b: &mut test::Bencher) {
     );
 
     match probe {
-        CopyResult::Ended(Ok(1)) => {
+        CopyResult::Ended(1) => {
             // splice works
         }
         _ => {
diff --git a/library/std/src/sys/unix/net.rs b/library/std/src/sys/unix/net.rs
index 378d690f8bf..7198a2f08d6 100644
--- a/library/std/src/sys/unix/net.rs
+++ b/library/std/src/sys/unix/net.rs
@@ -275,6 +275,20 @@ impl Socket {
         self.recv_from_with_flags(buf, 0)
     }
 
+    #[cfg(any(
+        target_os = "android",
+        target_os = "dragonfly",
+        target_os = "emscripten",
+        target_os = "freebsd",
+        target_os = "linux",
+        target_os = "netbsd",
+        target_os = "openbsd",
+    ))]
+    pub fn recv_msg(&self, msg: &mut libc::msghdr) -> io::Result<usize> {
+        let n = cvt(unsafe { libc::recvmsg(self.0.raw(), msg, libc::MSG_CMSG_CLOEXEC) })?;
+        Ok(n as usize)
+    }
+
     pub fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
         self.recv_from_with_flags(buf, MSG_PEEK)
     }
@@ -292,6 +306,20 @@ impl Socket {
         self.0.is_write_vectored()
     }
 
+    #[cfg(any(
+        target_os = "android",
+        target_os = "dragonfly",
+        target_os = "emscripten",
+        target_os = "freebsd",
+        target_os = "linux",
+        target_os = "netbsd",
+        target_os = "openbsd",
+    ))]
+    pub fn send_msg(&self, msg: &mut libc::msghdr) -> io::Result<usize> {
+        let n = cvt(unsafe { libc::sendmsg(self.0.raw(), msg, 0) })?;
+        Ok(n as usize)
+    }
+
     pub fn set_timeout(&self, dur: Option<Duration>, kind: libc::c_int) -> io::Result<()> {
         let timeout = match dur {
             Some(dur) => {
@@ -351,6 +379,17 @@ impl Socket {
         Ok(raw != 0)
     }
 
+    #[cfg(any(target_os = "android", target_os = "linux",))]
+    pub fn set_passcred(&self, passcred: bool) -> io::Result<()> {
+        setsockopt(self, libc::SOL_SOCKET, libc::SO_PASSCRED, passcred as libc::c_int)
+    }
+
+    #[cfg(any(target_os = "android", target_os = "linux",))]
+    pub fn passcred(&self) -> io::Result<bool> {
+        let passcred: libc::c_int = getsockopt(self, libc::SOL_SOCKET, libc::SO_PASSCRED)?;
+        Ok(passcred != 0)
+    }
+
     #[cfg(not(any(target_os = "solaris", target_os = "illumos")))]
     pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
         let mut nonblocking = nonblocking as libc::c_int;
diff --git a/library/std/src/sys/unix/rand.rs b/library/std/src/sys/unix/rand.rs
index eed6fbf13b7..38ddb41700c 100644
--- a/library/std/src/sys/unix/rand.rs
+++ b/library/std/src/sys/unix/rand.rs
@@ -25,10 +25,19 @@ mod imp {
     use crate::io::Read;
 
     #[cfg(any(target_os = "linux", target_os = "android"))]
-    fn getrandom(buf: &mut [u8]) -> libc::c_long {
-        unsafe {
-            libc::syscall(libc::SYS_getrandom, buf.as_mut_ptr(), buf.len(), libc::GRND_NONBLOCK)
+    fn getrandom(buf: &mut [u8]) -> libc::ssize_t {
+        // A weak symbol allows interposition, e.g. for perf measurements that want to
+        // disable randomness for consistency. Otherwise, we'll try a raw syscall.
+        // (`getrandom` was added in glibc 2.25, musl 1.1.20, android API level 28)
+        syscall! {
+            fn getrandom(
+                buffer: *mut libc::c_void,
+                length: libc::size_t,
+                flags: libc::c_uint
+            ) -> libc::ssize_t
         }
+
+        unsafe { getrandom(buf.as_mut_ptr().cast(), buf.len(), libc::GRND_NONBLOCK) }
     }
 
     #[cfg(not(any(target_os = "linux", target_os = "android")))]
diff --git a/library/std/src/sys/unix/weak.rs b/library/std/src/sys/unix/weak.rs
index f4b33a00f7c..e93a4972caa 100644
--- a/library/std/src/sys/unix/weak.rs
+++ b/library/std/src/sys/unix/weak.rs
@@ -24,7 +24,7 @@
 use crate::ffi::CStr;
 use crate::marker;
 use crate::mem;
-use crate::sync::atomic::{AtomicUsize, Ordering};
+use crate::sync::atomic::{self, AtomicUsize, Ordering};
 
 macro_rules! weak {
     (fn $name:ident($($t:ty),*) -> $ret:ty) => (
@@ -47,15 +47,49 @@ impl<F> Weak<F> {
     pub fn get(&self) -> Option<F> {
         assert_eq!(mem::size_of::<F>(), mem::size_of::<usize>());
         unsafe {
-            if self.addr.load(Ordering::SeqCst) == 1 {
-                self.addr.store(fetch(self.name), Ordering::SeqCst);
-            }
-            match self.addr.load(Ordering::SeqCst) {
+            // Relaxed is fine here because we fence before reading through the
+            // pointer (see the comment below).
+            match self.addr.load(Ordering::Relaxed) {
+                1 => self.initialize(),
                 0 => None,
-                addr => Some(mem::transmute_copy::<usize, F>(&addr)),
+                addr => {
+                    let func = mem::transmute_copy::<usize, F>(&addr);
+                    // The caller is presumably going to read through this value
+                    // (by calling the function we've dlsymed). This means we'd
+                    // need to have loaded it with at least C11's consume
+                    // ordering in order to be guaranteed that the data we read
+                    // from the pointer isn't from before the pointer was
+                    // stored. Rust has no equivalent to memory_order_consume,
+                    // so we use an acquire fence (sorry, ARM).
+                    //
+                    // Now, in practice this likely isn't needed even on CPUs
+                    // where relaxed and consume mean different things. The
+                    // symbols we're loading are probably present (or not) at
+                    // init, and even if they aren't the runtime dynamic loader
+                    // is extremely likely have sufficient barriers internally
+                    // (possibly implicitly, for example the ones provided by
+                    // invoking `mprotect`).
+                    //
+                    // That said, none of that's *guaranteed*, and so we fence.
+                    atomic::fence(Ordering::Acquire);
+                    Some(func)
+                }
             }
         }
     }
+
+    // Cold because it should only happen during first-time initalization.
+    #[cold]
+    unsafe fn initialize(&self) -> Option<F> {
+        let val = fetch(self.name);
+        // This synchronizes with the acquire fence in `get`.
+        self.addr.store(val, Ordering::Release);
+
+        match val {
+            0 => None,
+            addr => Some(mem::transmute_copy::<usize, F>(&addr)),
+        }
+    }
 }
 
 unsafe fn fetch(name: &str) -> usize {
@@ -66,7 +100,7 @@ unsafe fn fetch(name: &str) -> usize {
     libc::dlsym(libc::RTLD_DEFAULT, name.as_ptr()) as usize
 }
 
-#[cfg(not(target_os = "linux"))]
+#[cfg(not(any(target_os = "linux", target_os = "android")))]
 macro_rules! syscall {
     (fn $name:ident($($arg_name:ident: $t:ty),*) -> $ret:ty) => (
         unsafe fn $name($($arg_name: $t),*) -> $ret {
@@ -84,7 +118,7 @@ macro_rules! syscall {
     )
 }
 
-#[cfg(target_os = "linux")]
+#[cfg(any(target_os = "linux", target_os = "android"))]
 macro_rules! syscall {
     (fn $name:ident($($arg_name:ident: $t:ty),*) -> $ret:ty) => (
         unsafe fn $name($($arg_name:$t),*) -> $ret {
@@ -92,10 +126,18 @@ macro_rules! syscall {
             // (not paths).
             use libc::*;
 
-            syscall(
-                concat_idents!(SYS_, $name),
-                $($arg_name as c_long),*
-            ) as $ret
+            weak! { fn $name($($t),*) -> $ret }
+
+            // Use a weak symbol from libc when possible, allowing `LD_PRELOAD`
+            // interposition, but if it's not found just use a raw syscall.
+            if let Some(fun) = $name.get() {
+                fun($($arg_name),*)
+            } else {
+                syscall(
+                    concat_idents!(SYS_, $name),
+                    $($arg_name),*
+                ) as $ret
+            }
         }
     )
 }
diff --git a/library/std/src/sys/unsupported/fs.rs b/library/std/src/sys/unsupported/fs.rs
index faa53b6a744..4271d9b3345 100644
--- a/library/std/src/sys/unsupported/fs.rs
+++ b/library/std/src/sys/unsupported/fs.rs
@@ -279,7 +279,7 @@ pub fn readlink(_p: &Path) -> io::Result<PathBuf> {
     unsupported()
 }
 
-pub fn symlink(_src: &Path, _dst: &Path) -> io::Result<()> {
+pub fn symlink(_original: &Path, _link: &Path) -> io::Result<()> {
     unsupported()
 }
 
diff --git a/library/std/src/sys/wasi/fs.rs b/library/std/src/sys/wasi/fs.rs
index 93a92b49cfc..120b9f59f1e 100644
--- a/library/std/src/sys/wasi/fs.rs
+++ b/library/std/src/sys/wasi/fs.rs
@@ -549,19 +549,19 @@ fn read_link(fd: &WasiFd, file: &Path) -> io::Result<PathBuf> {
     }
 }
 
-pub fn symlink(src: &Path, dst: &Path) -> io::Result<()> {
-    let (dst, dst_file) = open_parent(dst)?;
-    dst.symlink(osstr2str(src.as_ref())?, osstr2str(dst_file.as_ref())?)
+pub fn symlink(original: &Path, link: &Path) -> io::Result<()> {
+    let (link, link_file) = open_parent(link)?;
+    link.symlink(osstr2str(original.as_ref())?, osstr2str(link_file.as_ref())?)
 }
 
-pub fn link(src: &Path, dst: &Path) -> io::Result<()> {
-    let (src, src_file) = open_parent(src)?;
-    let (dst, dst_file) = open_parent(dst)?;
-    src.link(
+pub fn link(original: &Path, link: &Path) -> io::Result<()> {
+    let (original, original_file) = open_parent(original)?;
+    let (link, link_file) = open_parent(link)?;
+    original.link(
         wasi::LOOKUPFLAGS_SYMLINK_FOLLOW,
-        osstr2str(src_file.as_ref())?,
-        &dst,
-        osstr2str(dst_file.as_ref())?,
+        osstr2str(original_file.as_ref())?,
+        &link,
+        osstr2str(link_file.as_ref())?,
     )
 }
 
diff --git a/library/std/src/sys/windows/c.rs b/library/std/src/sys/windows/c.rs
index 657421e3fa4..2b1bc92dc84 100644
--- a/library/std/src/sys/windows/c.rs
+++ b/library/std/src/sys/windows/c.rs
@@ -31,6 +31,8 @@ pub type WORD = u16;
 pub type CHAR = c_char;
 pub type ULONG_PTR = usize;
 pub type ULONG = c_ulong;
+pub type NTSTATUS = LONG;
+pub type ACCESS_MASK = DWORD;
 
 pub type LPBOOL = *mut BOOL;
 pub type LPBYTE = *mut BYTE;
@@ -285,6 +287,8 @@ pub const STACK_SIZE_PARAM_IS_A_RESERVATION: DWORD = 0x00010000;
 
 pub const HEAP_ZERO_MEMORY: DWORD = 0x00000008;
 
+pub const STATUS_SUCCESS: NTSTATUS = 0x00000000;
+
 #[repr(C)]
 #[cfg(not(target_pointer_width = "64"))]
 pub struct WSADATA {
@@ -1085,3 +1089,46 @@ compat_fn! {
         panic!("rwlocks not available")
     }
 }
+compat_fn! {
+    "api-ms-win-core-synch-l1-2-0":
+    pub fn WaitOnAddress(
+        Address: LPVOID,
+        CompareAddress: LPVOID,
+        AddressSize: SIZE_T,
+        dwMilliseconds: DWORD
+    ) -> BOOL {
+        panic!("WaitOnAddress not available")
+    }
+    pub fn WakeByAddressSingle(Address: LPVOID) -> () {
+        // If this api is unavailable, there cannot be anything waiting, because
+        // WaitOnAddress would've panicked. So it's fine to do nothing here.
+    }
+}
+
+compat_fn! {
+    "ntdll":
+    pub fn NtCreateKeyedEvent(
+        KeyedEventHandle: LPHANDLE,
+        DesiredAccess: ACCESS_MASK,
+        ObjectAttributes: LPVOID,
+        Flags: ULONG
+    ) -> NTSTATUS {
+        panic!("keyed events not available")
+    }
+    pub fn NtReleaseKeyedEvent(
+        EventHandle: HANDLE,
+        Key: LPVOID,
+        Alertable: BOOLEAN,
+        Timeout: PLARGE_INTEGER
+    ) -> NTSTATUS {
+        panic!("keyed events not available")
+    }
+    pub fn NtWaitForKeyedEvent(
+        EventHandle: HANDLE,
+        Key: LPVOID,
+        Alertable: BOOLEAN,
+        Timeout: PLARGE_INTEGER
+    ) -> NTSTATUS {
+        panic!("keyed events not available")
+    }
+}
diff --git a/library/std/src/sys/windows/compat.rs b/library/std/src/sys/windows/compat.rs
index 3f25f05e1b9..e9588e29758 100644
--- a/library/std/src/sys/windows/compat.rs
+++ b/library/std/src/sys/windows/compat.rs
@@ -34,6 +34,7 @@ macro_rules! compat_fn {
     )*) => ($(
         $(#[$meta])*
         pub mod $symbol {
+            #[allow(unused_imports)]
             use super::*;
             use crate::sync::atomic::{AtomicUsize, Ordering};
             use crate::mem;
@@ -90,6 +91,7 @@ macro_rules! compat_fn {
             }
         }
 
+        $(#[$meta])*
         pub use $symbol::call as $symbol;
     )*)
 }
diff --git a/library/std/src/sys/windows/ext/fs.rs b/library/std/src/sys/windows/ext/fs.rs
index e0615f2d334..b20eafb4d53 100644
--- a/library/std/src/sys/windows/ext/fs.rs
+++ b/library/std/src/sys/windows/ext/fs.rs
@@ -519,7 +519,7 @@ impl FileTypeExt for fs::FileType {
 
 /// Creates a new file symbolic link on the filesystem.
 ///
-/// The `dst` path will be a file symbolic link pointing to the `src`
+/// The `link` path will be a file symbolic link pointing to the `original`
 /// path.
 ///
 /// # Examples
@@ -533,13 +533,13 @@ impl FileTypeExt for fs::FileType {
 /// }
 /// ```
 #[stable(feature = "symlink", since = "1.1.0")]
-pub fn symlink_file<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> io::Result<()> {
-    sys::fs::symlink_inner(src.as_ref(), dst.as_ref(), false)
+pub fn symlink_file<P: AsRef<Path>, Q: AsRef<Path>>(original: P, link: Q) -> io::Result<()> {
+    sys::fs::symlink_inner(original.as_ref(), link.as_ref(), false)
 }
 
 /// Creates a new directory symlink on the filesystem.
 ///
-/// The `dst` path will be a directory symbolic link pointing to the `src`
+/// The `link` path will be a directory symbolic link pointing to the `original`
 /// path.
 ///
 /// # Examples
@@ -553,6 +553,6 @@ pub fn symlink_file<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> io::Resul
 /// }
 /// ```
 #[stable(feature = "symlink", since = "1.1.0")]
-pub fn symlink_dir<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> io::Result<()> {
-    sys::fs::symlink_inner(src.as_ref(), dst.as_ref(), true)
+pub fn symlink_dir<P: AsRef<Path>, Q: AsRef<Path>>(original: P, link: Q) -> io::Result<()> {
+    sys::fs::symlink_inner(original.as_ref(), link.as_ref(), true)
 }
diff --git a/library/std/src/sys/windows/fs.rs b/library/std/src/sys/windows/fs.rs
index cdbfac267b9..307a47678c6 100644
--- a/library/std/src/sys/windows/fs.rs
+++ b/library/std/src/sys/windows/fs.rs
@@ -759,13 +759,13 @@ pub fn readlink(path: &Path) -> io::Result<PathBuf> {
     file.readlink()
 }
 
-pub fn symlink(src: &Path, dst: &Path) -> io::Result<()> {
-    symlink_inner(src, dst, false)
+pub fn symlink(original: &Path, link: &Path) -> io::Result<()> {
+    symlink_inner(original, link, false)
 }
 
-pub fn symlink_inner(src: &Path, dst: &Path, dir: bool) -> io::Result<()> {
-    let src = to_u16s(src)?;
-    let dst = to_u16s(dst)?;
+pub fn symlink_inner(original: &Path, link: &Path, dir: bool) -> io::Result<()> {
+    let original = to_u16s(original)?;
+    let link = to_u16s(link)?;
     let flags = if dir { c::SYMBOLIC_LINK_FLAG_DIRECTORY } else { 0 };
     // Formerly, symlink creation required the SeCreateSymbolicLink privilege. For the Windows 10
     // Creators Update, Microsoft loosened this to allow unprivileged symlink creation if the
@@ -773,8 +773,8 @@ pub fn symlink_inner(src: &Path, dst: &Path, dir: bool) -> io::Result<()> {
     // added to dwFlags to opt into this behaviour.
     let result = cvt(unsafe {
         c::CreateSymbolicLinkW(
-            dst.as_ptr(),
-            src.as_ptr(),
+            link.as_ptr(),
+            original.as_ptr(),
             flags | c::SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE,
         ) as c::BOOL
     });
@@ -782,7 +782,9 @@ pub fn symlink_inner(src: &Path, dst: &Path, dir: bool) -> io::Result<()> {
         if err.raw_os_error() == Some(c::ERROR_INVALID_PARAMETER as i32) {
             // Older Windows objects to SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE,
             // so if we encounter ERROR_INVALID_PARAMETER, retry without that flag.
-            cvt(unsafe { c::CreateSymbolicLinkW(dst.as_ptr(), src.as_ptr(), flags) as c::BOOL })?;
+            cvt(unsafe {
+                c::CreateSymbolicLinkW(link.as_ptr(), original.as_ptr(), flags) as c::BOOL
+            })?;
         } else {
             return Err(err);
         }
@@ -791,15 +793,15 @@ pub fn symlink_inner(src: &Path, dst: &Path, dir: bool) -> io::Result<()> {
 }
 
 #[cfg(not(target_vendor = "uwp"))]
-pub fn link(src: &Path, dst: &Path) -> io::Result<()> {
-    let src = to_u16s(src)?;
-    let dst = to_u16s(dst)?;
-    cvt(unsafe { c::CreateHardLinkW(dst.as_ptr(), src.as_ptr(), ptr::null_mut()) })?;
+pub fn link(original: &Path, link: &Path) -> io::Result<()> {
+    let original = to_u16s(original)?;
+    let link = to_u16s(link)?;
+    cvt(unsafe { c::CreateHardLinkW(link.as_ptr(), original.as_ptr(), ptr::null_mut()) })?;
     Ok(())
 }
 
 #[cfg(target_vendor = "uwp")]
-pub fn link(_src: &Path, _dst: &Path) -> io::Result<()> {
+pub fn link(_original: &Path, _link: &Path) -> io::Result<()> {
     return Err(io::Error::new(io::ErrorKind::Other, "hard link are not supported on UWP"));
 }
 
@@ -883,8 +885,11 @@ pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
 }
 
 #[allow(dead_code)]
-pub fn symlink_junction<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> io::Result<()> {
-    symlink_junction_inner(src.as_ref(), dst.as_ref())
+pub fn symlink_junction<P: AsRef<Path>, Q: AsRef<Path>>(
+    original: P,
+    junction: Q,
+) -> io::Result<()> {
+    symlink_junction_inner(original.as_ref(), junction.as_ref())
 }
 
 // Creating a directory junction on windows involves dealing with reparse
@@ -893,7 +898,7 @@ pub fn symlink_junction<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> io::R
 //
 // http://www.flexhex.com/docs/articles/hard-links.phtml
 #[allow(dead_code)]
-fn symlink_junction_inner(target: &Path, junction: &Path) -> io::Result<()> {
+fn symlink_junction_inner(original: &Path, junction: &Path) -> io::Result<()> {
     let d = DirBuilder::new();
     d.mkdir(&junction)?;
 
@@ -911,7 +916,7 @@ fn symlink_junction_inner(target: &Path, junction: &Path) -> io::Result<()> {
         // FIXME: this conversion is very hacky
         let v = br"\??\";
         let v = v.iter().map(|x| *x as u16);
-        for c in v.chain(target.as_os_str().encode_wide()) {
+        for c in v.chain(original.as_os_str().encode_wide()) {
             *buf.offset(i) = c;
             i += 1;
         }
diff --git a/library/std/src/sys/windows/mod.rs b/library/std/src/sys/windows/mod.rs
index c36c6196d79..fcbff59dec0 100644
--- a/library/std/src/sys/windows/mod.rs
+++ b/library/std/src/sys/windows/mod.rs
@@ -35,6 +35,7 @@ pub mod rwlock;
 pub mod thread;
 pub mod thread_local_dtor;
 pub mod thread_local_key;
+pub mod thread_parker;
 pub mod time;
 cfg_if::cfg_if! {
     if #[cfg(not(target_vendor = "uwp"))] {
diff --git a/library/std/src/sys/windows/thread_local_key.rs b/library/std/src/sys/windows/thread_local_key.rs
index 82901871e78..065365e5572 100644
--- a/library/std/src/sys/windows/thread_local_key.rs
+++ b/library/std/src/sys/windows/thread_local_key.rs
@@ -1,4 +1,4 @@
-use crate::mem;
+use crate::mem::ManuallyDrop;
 use crate::ptr;
 use crate::sync::atomic::AtomicPtr;
 use crate::sync::atomic::Ordering::SeqCst;
@@ -110,30 +110,14 @@ struct Node {
     next: *mut Node,
 }
 
-#[cfg(miri)]
-extern "Rust" {
-    /// Miri-provided extern function to mark the block `ptr` points to as a "root"
-    /// for some static memory. This memory and everything reachable by it is not
-    /// considered leaking even if it still exists when the program terminates.
-    ///
-    /// `ptr` has to point to the beginning of an allocated block.
-    fn miri_static_root(ptr: *const u8);
-}
-
 unsafe fn register_dtor(key: Key, dtor: Dtor) {
-    let mut node = Box::new(Node { key, dtor, next: ptr::null_mut() });
+    let mut node = ManuallyDrop::new(Box::new(Node { key, dtor, next: ptr::null_mut() }));
 
     let mut head = DTORS.load(SeqCst);
     loop {
         node.next = head;
-        match DTORS.compare_exchange(head, &mut *node, SeqCst, SeqCst) {
-            Ok(_) => {
-                #[cfg(miri)]
-                miri_static_root(&*node as *const _ as *const u8);
-
-                mem::forget(node);
-                return;
-            }
+        match DTORS.compare_exchange(head, &mut **node, SeqCst, SeqCst) {
+            Ok(_) => return, // nothing to drop, we successfully added the node to the list
             Err(cur) => head = cur,
         }
     }
diff --git a/library/std/src/sys/windows/thread_parker.rs b/library/std/src/sys/windows/thread_parker.rs
new file mode 100644
index 00000000000..701c6e2e9be
--- /dev/null
+++ b/library/std/src/sys/windows/thread_parker.rs
@@ -0,0 +1,250 @@
+// Thread parker implementation for Windows.
+//
+// This uses WaitOnAddress and WakeByAddressSingle if available (Windows 8+).
+// This modern API is exactly the same as the futex syscalls the Linux thread
+// parker uses. When These APIs are available, the implementation of this
+// thread parker matches the Linux thread parker exactly.
+//
+// However, when the modern API is not available, this implementation falls
+// back to NT Keyed Events, which are similar, but have some important
+// differences. These are available since Windows XP.
+//
+// WaitOnAddress first checks the state of the thread parker to make sure it no
+// WakeByAddressSingle calls can be missed between updating the parker state
+// and calling the function.
+//
+// NtWaitForKeyedEvent does not have this option, and unconditionally blocks
+// without checking the parker state first. Instead, NtReleaseKeyedEvent
+// (unlike WakeByAddressSingle) *blocks* until it woke up a thread waiting for
+// it by NtWaitForKeyedEvent. This way, we can be sure no events are missed,
+// but we need to be careful not to block unpark() if park_timeout() was woken
+// up by a timeout instead of unpark().
+//
+// Unlike WaitOnAddress, NtWaitForKeyedEvent/NtReleaseKeyedEvent operate on a
+// HANDLE (created with NtCreateKeyedEvent). This means that we can be sure
+// a succesfully awoken park() was awoken by unpark() and not a
+// NtReleaseKeyedEvent call from some other code, as these events are not only
+// matched by the key (address of the parker (state)), but also by this HANDLE.
+// We lazily allocate this handle the first time it is needed.
+//
+// The fast path (calling park() after unpark() was already called) and the
+// possible states are the same for both implementations. This is used here to
+// make sure the fast path does not even check which API to use, but can return
+// right away, independent of the used API. Only the slow paths (which will
+// actually block/wake a thread) check which API is available and have
+// different implementations.
+//
+// Unfortunately, NT Keyed Events are an undocumented Windows API. However:
+// - This API is relatively simple with obvious behaviour, and there are
+//   several (unofficial) articles documenting the details. [1]
+// - `parking_lot` has been using this API for years (on Windows versions
+//   before Windows 8). [2] Many big projects extensively use parking_lot,
+//   such as servo and the Rust compiler itself.
+// - It is the underlying API used by Windows SRW locks and Windows critical
+//   sections. [3] [4]
+// - The source code of the implementations of Wine, ReactOs, and Windows XP
+//   are available and match the expected behaviour.
+// - The main risk with an undocumented API is that it might change in the
+//   future. But since we only use it for older versions of Windows, that's not
+//   a problem.
+// - Even if these functions do not block or wake as we expect (which is
+//   unlikely, see all previous points), this implementation would still be
+//   memory safe. The NT Keyed Events API is only used to sleep/block in the
+//   right place.
+//
+// [1]: http://www.locklessinc.com/articles/keyed_events/
+// [2]: https://github.com/Amanieu/parking_lot/commit/43abbc964e
+// [3]: https://docs.microsoft.com/en-us/archive/msdn-magazine/2012/november/windows-with-c-the-evolution-of-synchronization-in-windows-and-c
+// [4]: Windows Internals, Part 1, ISBN 9780735671300
+
+use crate::convert::TryFrom;
+use crate::ptr;
+use crate::sync::atomic::{
+    AtomicI8, AtomicUsize,
+    Ordering::{Acquire, Relaxed, Release},
+};
+use crate::sys::{c, dur2timeout};
+use crate::time::Duration;
+
+pub struct Parker {
+    state: AtomicI8,
+}
+
+const PARKED: i8 = -1;
+const EMPTY: i8 = 0;
+const NOTIFIED: i8 = 1;
+
+// Notes about memory ordering:
+//
+// Memory ordering is only relevant for the relative ordering of operations
+// between different variables. Even Ordering::Relaxed guarantees a
+// monotonic/consistent order when looking at just a single atomic variable.
+//
+// So, since this parker is just a single atomic variable, we only need to look
+// at the ordering guarantees we need to provide to the 'outside world'.
+//
+// The only memory ordering guarantee that parking and unparking provide, is
+// that things which happened before unpark() are visible on the thread
+// returning from park() afterwards. Otherwise, it was effectively unparked
+// before unpark() was called while still consuming the 'token'.
+//
+// In other words, unpark() needs to synchronize with the part of park() that
+// consumes the token and returns.
+//
+// This is done with a release-acquire synchronization, by using
+// Ordering::Release when writing NOTIFIED (the 'token') in unpark(), and using
+// Ordering::Acquire when reading this state in park() after waking up.
+impl Parker {
+    pub fn new() -> Self {
+        Self { state: AtomicI8::new(EMPTY) }
+    }
+
+    // Assumes this is only called by the thread that owns the Parker,
+    // which means that `self.state != PARKED`.
+    pub unsafe fn park(&self) {
+        // Change NOTIFIED=>EMPTY or EMPTY=>PARKED, and directly return in the
+        // first case.
+        if self.state.fetch_sub(1, Acquire) == NOTIFIED {
+            return;
+        }
+
+        if c::WaitOnAddress::is_available() {
+            loop {
+                // Wait for something to happen, assuming it's still set to PARKED.
+                c::WaitOnAddress(self.ptr(), &PARKED as *const _ as c::LPVOID, 1, c::INFINITE);
+                // Change NOTIFIED=>EMPTY but leave PARKED alone.
+                if self.state.compare_and_swap(NOTIFIED, EMPTY, Acquire) == NOTIFIED {
+                    // Actually woken up by unpark().
+                    return;
+                } else {
+                    // Spurious wake up. We loop to try again.
+                }
+            }
+        } else {
+            // Wait for unpark() to produce this event.
+            c::NtWaitForKeyedEvent(keyed_event_handle(), self.ptr(), 0, ptr::null_mut());
+            // Set the state back to EMPTY (from either PARKED or NOTIFIED).
+            // Note that we don't just write EMPTY, but use swap() to also
+            // include an acquire-ordered read to synchronize with unpark()'s
+            // release-ordered write.
+            self.state.swap(EMPTY, Acquire);
+        }
+    }
+
+    // Assumes this is only called by the thread that owns the Parker,
+    // which means that `self.state != PARKED`.
+    pub unsafe fn park_timeout(&self, timeout: Duration) {
+        // Change NOTIFIED=>EMPTY or EMPTY=>PARKED, and directly return in the
+        // first case.
+        if self.state.fetch_sub(1, Acquire) == NOTIFIED {
+            return;
+        }
+
+        if c::WaitOnAddress::is_available() {
+            // Wait for something to happen, assuming it's still set to PARKED.
+            c::WaitOnAddress(self.ptr(), &PARKED as *const _ as c::LPVOID, 1, dur2timeout(timeout));
+            // Set the state back to EMPTY (from either PARKED or NOTIFIED).
+            // Note that we don't just write EMPTY, but use swap() to also
+            // include an acquire-ordered read to synchronize with unpark()'s
+            // release-ordered write.
+            if self.state.swap(EMPTY, Acquire) == NOTIFIED {
+                // Actually woken up by unpark().
+            } else {
+                // Timeout or spurious wake up.
+                // We return either way, because we can't easily tell if it was the
+                // timeout or not.
+            }
+        } else {
+            // Need to wait for unpark() using NtWaitForKeyedEvent.
+            let handle = keyed_event_handle();
+
+            // NtWaitForKeyedEvent uses a unit of 100ns, and uses negative
+            // values to indicate a relative time on the monotonic clock.
+            // This is documented here for the underlying KeWaitForSingleObject function:
+            // https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/nf-wdm-kewaitforsingleobject
+            let mut timeout = match i64::try_from((timeout.as_nanos() + 99) / 100) {
+                Ok(t) => -t,
+                Err(_) => i64::MIN,
+            };
+
+            // Wait for unpark() to produce this event.
+            let unparked =
+                c::NtWaitForKeyedEvent(handle, self.ptr(), 0, &mut timeout) == c::STATUS_SUCCESS;
+
+            // Set the state back to EMPTY (from either PARKED or NOTIFIED).
+            let prev_state = self.state.swap(EMPTY, Acquire);
+
+            if !unparked && prev_state == NOTIFIED {
+                // We were awoken by a timeout, not by unpark(), but the state
+                // was set to NOTIFIED, which means we *just* missed an
+                // unpark(), which is now blocked on us to wait for it.
+                // Wait for it to consume the event and unblock that thread.
+                c::NtWaitForKeyedEvent(handle, self.ptr(), 0, ptr::null_mut());
+            }
+        }
+    }
+
+    pub fn unpark(&self) {
+        // Change PARKED=>NOTIFIED, EMPTY=>NOTIFIED, or NOTIFIED=>NOTIFIED, and
+        // wake the thread in the first case.
+        //
+        // Note that even NOTIFIED=>NOTIFIED results in a write. This is on
+        // purpose, to make sure every unpark() has a release-acquire ordering
+        // with park().
+        if self.state.swap(NOTIFIED, Release) == PARKED {
+            if c::WakeByAddressSingle::is_available() {
+                unsafe {
+                    c::WakeByAddressSingle(self.ptr());
+                }
+            } else {
+                // If we run NtReleaseKeyedEvent before the waiting thread runs
+                // NtWaitForKeyedEvent, this (shortly) blocks until we can wake it up.
+                // If the waiting thread wakes up before we run NtReleaseKeyedEvent
+                // (e.g. due to a timeout), this blocks until we do wake up a thread.
+                // To prevent this thread from blocking indefinitely in that case,
+                // park_impl() will, after seeing the state set to NOTIFIED after
+                // waking up, call NtWaitForKeyedEvent again to unblock us.
+                unsafe {
+                    c::NtReleaseKeyedEvent(keyed_event_handle(), self.ptr(), 0, ptr::null_mut());
+                }
+            }
+        }
+    }
+
+    fn ptr(&self) -> c::LPVOID {
+        &self.state as *const _ as c::LPVOID
+    }
+}
+
+fn keyed_event_handle() -> c::HANDLE {
+    const INVALID: usize = !0;
+    static HANDLE: AtomicUsize = AtomicUsize::new(INVALID);
+    match HANDLE.load(Relaxed) {
+        INVALID => {
+            let mut handle = c::INVALID_HANDLE_VALUE;
+            unsafe {
+                match c::NtCreateKeyedEvent(
+                    &mut handle,
+                    c::GENERIC_READ | c::GENERIC_WRITE,
+                    ptr::null_mut(),
+                    0,
+                ) {
+                    c::STATUS_SUCCESS => {}
+                    r => panic!("Unable to create keyed event handle: error {}", r),
+                }
+            }
+            match HANDLE.compare_exchange(INVALID, handle as usize, Relaxed, Relaxed) {
+                Ok(_) => handle,
+                Err(h) => {
+                    // Lost the race to another thread initializing HANDLE before we did.
+                    // Closing our handle and using theirs instead.
+                    unsafe {
+                        c::CloseHandle(handle);
+                    }
+                    h as c::HANDLE
+                }
+            }
+        }
+        handle => handle as c::HANDLE,
+    }
+}
diff --git a/library/std/src/sys_common/mod.rs b/library/std/src/sys_common/mod.rs
index 234b257aa92..660f0e0df97 100644
--- a/library/std/src/sys_common/mod.rs
+++ b/library/std/src/sys_common/mod.rs
@@ -71,8 +71,7 @@ pub mod util;
 pub mod wtf8;
 
 cfg_if::cfg_if! {
-    if #[cfg(any(target_os = "cloudabi",
-                 target_os = "l4re",
+    if #[cfg(any(target_os = "l4re",
                  target_os = "hermit",
                  feature = "restricted-std",
                  all(target_arch = "wasm32", not(target_os = "emscripten")),
diff --git a/library/std/src/sys_common/net.rs b/library/std/src/sys_common/net.rs
index 48ba4ddfc0b..38ba0d2fbdb 100644
--- a/library/std/src/sys_common/net.rs
+++ b/library/std/src/sys_common/net.rs
@@ -177,11 +177,8 @@ impl TryFrom<&str> for LookupHost {
         }
 
         // split the string by ':' and convert the second part to u16
-        let mut parts_iter = s.rsplitn(2, ':');
-        let port_str = try_opt!(parts_iter.next(), "invalid socket address");
-        let host = try_opt!(parts_iter.next(), "invalid socket address");
+        let (host, port_str) = try_opt!(s.rsplit_once(':'), "invalid socket address");
         let port: u16 = try_opt!(port_str.parse().ok(), "invalid port value");
-
         (host, port).try_into()
     }
 }
diff --git a/library/std/src/sys_common/remutex.rs b/library/std/src/sys_common/remutex.rs
index 162eab2388d..475bfca9b6d 100644
--- a/library/std/src/sys_common/remutex.rs
+++ b/library/std/src/sys_common/remutex.rs
@@ -1,10 +1,10 @@
 #[cfg(all(test, not(target_os = "emscripten")))]
 mod tests;
 
-use crate::fmt;
-use crate::marker;
+use crate::marker::PhantomPinned;
 use crate::ops::Deref;
 use crate::panic::{RefUnwindSafe, UnwindSafe};
+use crate::pin::Pin;
 use crate::sys::mutex as sys;
 
 /// A re-entrant mutual exclusion
@@ -15,6 +15,7 @@ use crate::sys::mutex as sys;
 pub struct ReentrantMutex<T> {
     inner: sys::ReentrantMutex,
     data: T,
+    _pinned: PhantomPinned,
 }
 
 unsafe impl<T: Send> Send for ReentrantMutex<T> {}
@@ -37,10 +38,10 @@ impl<T> RefUnwindSafe for ReentrantMutex<T> {}
 /// guarded data.
 #[must_use = "if unused the ReentrantMutex will immediately unlock"]
 pub struct ReentrantMutexGuard<'a, T: 'a> {
-    lock: &'a ReentrantMutex<T>,
+    lock: Pin<&'a ReentrantMutex<T>>,
 }
 
-impl<T> !marker::Send for ReentrantMutexGuard<'_, T> {}
+impl<T> !Send for ReentrantMutexGuard<'_, T> {}
 
 impl<T> ReentrantMutex<T> {
     /// Creates a new reentrant mutex in an unlocked state.
@@ -51,7 +52,11 @@ impl<T> ReentrantMutex<T> {
     /// once this mutex is in its final resting place, and only then are the
     /// lock/unlock methods safe.
     pub const unsafe fn new(t: T) -> ReentrantMutex<T> {
-        ReentrantMutex { inner: sys::ReentrantMutex::uninitialized(), data: t }
+        ReentrantMutex {
+            inner: sys::ReentrantMutex::uninitialized(),
+            data: t,
+            _pinned: PhantomPinned,
+        }
     }
 
     /// Initializes this mutex so it's ready for use.
@@ -60,8 +65,8 @@ impl<T> ReentrantMutex<T> {
     ///
     /// Unsafe to call more than once, and must be called after this will no
     /// longer move in memory.
-    pub unsafe fn init(&self) {
-        self.inner.init();
+    pub unsafe fn init(self: Pin<&mut Self>) {
+        self.get_unchecked_mut().inner.init()
     }
 
     /// Acquires a mutex, blocking the current thread until it is able to do so.
@@ -76,9 +81,9 @@ impl<T> ReentrantMutex<T> {
     /// If another user of this mutex panicked while holding the mutex, then
     /// this call will return failure if the mutex would otherwise be
     /// acquired.
-    pub fn lock(&self) -> ReentrantMutexGuard<'_, T> {
+    pub fn lock(self: Pin<&Self>) -> ReentrantMutexGuard<'_, T> {
         unsafe { self.inner.lock() }
-        ReentrantMutexGuard::new(&self)
+        ReentrantMutexGuard { lock: self }
     }
 
     /// Attempts to acquire this lock.
@@ -93,8 +98,12 @@ impl<T> ReentrantMutex<T> {
     /// If another user of this mutex panicked while holding the mutex, then
     /// this call will return failure if the mutex would otherwise be
     /// acquired.
-    pub fn try_lock(&self) -> Option<ReentrantMutexGuard<'_, T>> {
-        if unsafe { self.inner.try_lock() } { Some(ReentrantMutexGuard::new(&self)) } else { None }
+    pub fn try_lock(self: Pin<&Self>) -> Option<ReentrantMutexGuard<'_, T>> {
+        if unsafe { self.inner.try_lock() } {
+            Some(ReentrantMutexGuard { lock: self })
+        } else {
+            None
+        }
     }
 }
 
@@ -107,30 +116,6 @@ impl<T> Drop for ReentrantMutex<T> {
     }
 }
 
-impl<T: fmt::Debug + 'static> fmt::Debug for ReentrantMutex<T> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self.try_lock() {
-            Some(guard) => f.debug_struct("ReentrantMutex").field("data", &*guard).finish(),
-            None => {
-                struct LockedPlaceholder;
-                impl fmt::Debug for LockedPlaceholder {
-                    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-                        f.write_str("<locked>")
-                    }
-                }
-
-                f.debug_struct("ReentrantMutex").field("data", &LockedPlaceholder).finish()
-            }
-        }
-    }
-}
-
-impl<'mutex, T> ReentrantMutexGuard<'mutex, T> {
-    fn new(lock: &'mutex ReentrantMutex<T>) -> ReentrantMutexGuard<'mutex, T> {
-        ReentrantMutexGuard { lock }
-    }
-}
-
 impl<T> Deref for ReentrantMutexGuard<'_, T> {
     type Target = T;
 
diff --git a/library/std/src/sys_common/remutex/tests.rs b/library/std/src/sys_common/remutex/tests.rs
index 9c686e579d7..88453ded2f9 100644
--- a/library/std/src/sys_common/remutex/tests.rs
+++ b/library/std/src/sys_common/remutex/tests.rs
@@ -1,4 +1,6 @@
+use crate::boxed::Box;
 use crate::cell::RefCell;
+use crate::pin::Pin;
 use crate::sync::Arc;
 use crate::sys_common::remutex::{ReentrantMutex, ReentrantMutexGuard};
 use crate::thread;
@@ -6,10 +8,11 @@ use crate::thread;
 #[test]
 fn smoke() {
     let m = unsafe {
-        let m = ReentrantMutex::new(());
-        m.init();
+        let mut m = Box::pin(ReentrantMutex::new(()));
+        m.as_mut().init();
         m
     };
+    let m = m.as_ref();
     {
         let a = m.lock();
         {
@@ -27,18 +30,19 @@ fn smoke() {
 #[test]
 fn is_mutex() {
     let m = unsafe {
-        let m = Arc::new(ReentrantMutex::new(RefCell::new(0)));
-        m.init();
-        m
+        // FIXME: Simplify this if Arc gets a Arc::get_pin_mut.
+        let mut m = Arc::new(ReentrantMutex::new(RefCell::new(0)));
+        Pin::new_unchecked(Arc::get_mut_unchecked(&mut m)).init();
+        Pin::new_unchecked(m)
     };
     let m2 = m.clone();
-    let lock = m.lock();
+    let lock = m.as_ref().lock();
     let child = thread::spawn(move || {
-        let lock = m2.lock();
+        let lock = m2.as_ref().lock();
         assert_eq!(*lock.borrow(), 4950);
     });
     for i in 0..100 {
-        let lock = m.lock();
+        let lock = m.as_ref().lock();
         *lock.borrow_mut() += i;
     }
     drop(lock);
@@ -48,20 +52,21 @@ fn is_mutex() {
 #[test]
 fn trylock_works() {
     let m = unsafe {
-        let m = Arc::new(ReentrantMutex::new(()));
-        m.init();
-        m
+        // FIXME: Simplify this if Arc gets a Arc::get_pin_mut.
+        let mut m = Arc::new(ReentrantMutex::new(()));
+        Pin::new_unchecked(Arc::get_mut_unchecked(&mut m)).init();
+        Pin::new_unchecked(m)
     };
     let m2 = m.clone();
-    let _lock = m.try_lock();
-    let _lock2 = m.try_lock();
+    let _lock = m.as_ref().try_lock();
+    let _lock2 = m.as_ref().try_lock();
     thread::spawn(move || {
-        let lock = m2.try_lock();
+        let lock = m2.as_ref().try_lock();
         assert!(lock.is_none());
     })
     .join()
     .unwrap();
-    let _lock3 = m.try_lock();
+    let _lock3 = m.as_ref().try_lock();
 }
 
 pub struct Answer<'a>(pub ReentrantMutexGuard<'a, RefCell<u32>>);
diff --git a/library/std/src/sys_common/thread_parker/mod.rs b/library/std/src/sys_common/thread_parker/mod.rs
index 5e75ac65de4..ba896bd676b 100644
--- a/library/std/src/sys_common/thread_parker/mod.rs
+++ b/library/std/src/sys_common/thread_parker/mod.rs
@@ -6,6 +6,8 @@ cfg_if::cfg_if! {
     ))] {
         mod futex;
         pub use futex::Parker;
+    } else if #[cfg(windows)] {
+        pub use crate::sys::thread_parker::Parker;
     } else {
         mod generic;
         pub use generic::Parker;
diff --git a/library/std/src/thread/available_concurrency.rs b/library/std/src/thread/available_concurrency.rs
index 4e805e4f599..64a5f89890a 100644
--- a/library/std/src/thread/available_concurrency.rs
+++ b/library/std/src/thread/available_concurrency.rs
@@ -70,7 +70,6 @@ cfg_if::cfg_if! {
         }
     } else if #[cfg(any(
         target_os = "android",
-        target_os = "cloudabi",
         target_os = "emscripten",
         target_os = "fuchsia",
         target_os = "ios",
diff --git a/library/std/src/time.rs b/library/std/src/time.rs
index e433f69a8b0..89addae0789 100644
--- a/library/std/src/time.rs
+++ b/library/std/src/time.rs
@@ -83,7 +83,6 @@ pub use core::time::Duration;
 ///
 /// |  Platform |               System call                                            |
 /// |:---------:|:--------------------------------------------------------------------:|
-/// | CloudABI  | [clock_time_get (Monotonic Clock)]                                   |
 /// | SGX       | [`insecure_time` usercall]. More information on [timekeeping in SGX] |
 /// | UNIX      | [clock_gettime (Monotonic Clock)]                                    |
 /// | Darwin    | [mach_absolute_time]                                                 |
@@ -97,7 +96,6 @@ pub use core::time::Duration;
 /// [__wasi_clock_time_get (Monotonic Clock)]: https://github.com/WebAssembly/WASI/blob/master/phases/snapshot/docs.md#clock_time_get
 /// [clock_gettime (Monotonic Clock)]: https://linux.die.net/man/3/clock_gettime
 /// [mach_absolute_time]: https://developer.apple.com/library/archive/documentation/Darwin/Conceptual/KernelProgramming/services/services.html
-/// [clock_time_get (Monotonic Clock)]: https://nuxi.nl/cloudabi/#clock_time_get
 ///
 /// **Disclaimer:** These system calls might change over time.
 ///
@@ -161,7 +159,6 @@ pub struct Instant(time::Instant);
 ///
 /// |  Platform |               System call                                            |
 /// |:---------:|:--------------------------------------------------------------------:|
-/// | CloudABI  | [clock_time_get (Realtime Clock)]                                    |
 /// | SGX       | [`insecure_time` usercall]. More information on [timekeeping in SGX] |
 /// | UNIX      | [clock_gettime (Realtime Clock)]                                     |
 /// | Darwin    | [gettimeofday]                                                       |
@@ -169,7 +166,6 @@ pub struct Instant(time::Instant);
 /// | WASI      | [__wasi_clock_time_get (Realtime Clock)]                             |
 /// | Windows   | [GetSystemTimePreciseAsFileTime] / [GetSystemTimeAsFileTime]         |
 ///
-/// [clock_time_get (Realtime Clock)]: https://nuxi.nl/cloudabi/#clock_time_get
 /// [`insecure_time` usercall]: https://edp.fortanix.com/docs/api/fortanix_sgx_abi/struct.Usercalls.html#method.insecure_time
 /// [timekeeping in SGX]: https://edp.fortanix.com/docs/concepts/rust-std/#codestdtimecode
 /// [gettimeofday]: http://man7.org/linux/man-pages/man2/gettimeofday.2.html