about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/libstd/env.rs11
-rw-r--r--src/libstd/fs.rs2
-rw-r--r--src/libstd/net/tcp.rs2
-rw-r--r--src/libstd/net/udp.rs2
-rw-r--r--src/libstd/process.rs2
-rw-r--r--src/libstd/sys/cloudabi/abi/bitflags.rs51
-rw-r--r--src/libstd/sys/cloudabi/abi/cloudabi.rs2847
-rw-r--r--src/libstd/sys/cloudabi/abi/mod.rs13
-rw-r--r--src/libstd/sys/cloudabi/args.rs17
-rw-r--r--src/libstd/sys/cloudabi/backtrace.rs121
-rw-r--r--src/libstd/sys/cloudabi/condvar.rs169
-rw-r--r--src/libstd/sys/cloudabi/mod.rs76
-rw-r--r--src/libstd/sys/cloudabi/mutex.rs158
-rw-r--r--src/libstd/sys/cloudabi/os.rs37
-rw-r--r--src/libstd/sys/cloudabi/rwlock.rs237
-rw-r--r--src/libstd/sys/cloudabi/shims/args.rs45
-rw-r--r--src/libstd/sys/cloudabi/shims/env.rs19
-rw-r--r--src/libstd/sys/cloudabi/shims/fs.rs302
-rw-r--r--src/libstd/sys/cloudabi/shims/mod.rs32
-rw-r--r--src/libstd/sys/cloudabi/shims/net.rs296
-rw-r--r--src/libstd/sys/cloudabi/shims/os.rs95
-rw-r--r--src/libstd/sys/cloudabi/shims/pipe.rs32
-rw-r--r--src/libstd/sys/cloudabi/shims/process.rs147
-rw-r--r--src/libstd/sys/cloudabi/stack_overflow.rs23
-rw-r--r--src/libstd/sys/cloudabi/stdio.rs79
-rw-r--r--src/libstd/sys/cloudabi/thread.rs124
-rw-r--r--src/libstd/sys/cloudabi/time.rs111
-rw-r--r--src/libstd/sys/mod.rs15
-rw-r--r--src/libstd/sys_common/mod.rs2
-rw-r--r--src/tools/tidy/src/pal.rs4
30 files changed, 5057 insertions, 14 deletions
diff --git a/src/libstd/env.rs b/src/libstd/env.rs
index ed34c1204b3..27bf326631f 100644
--- a/src/libstd/env.rs
+++ b/src/libstd/env.rs
@@ -956,8 +956,7 @@ mod arch {
 mod tests {
     use super::*;
 
-    use ffi::OsStr;
-    use path::{Path, PathBuf};
+    use path::Path;
 
     #[test]
     #[cfg_attr(target_os = "emscripten", ignore)]
@@ -980,6 +979,8 @@ mod tests {
     #[test]
     #[cfg(windows)]
     fn split_paths_windows() {
+        use path::PathBuf;
+
         fn check_parse(unparsed: &str, parsed: &[&str]) -> bool {
             split_paths(unparsed).collect::<Vec<_>>() ==
                 parsed.iter().map(|s| PathBuf::from(*s)).collect::<Vec<_>>()
@@ -1000,6 +1001,8 @@ mod tests {
     #[test]
     #[cfg(unix)]
     fn split_paths_unix() {
+        use path::PathBuf;
+
         fn check_parse(unparsed: &str, parsed: &[&str]) -> bool {
             split_paths(unparsed).collect::<Vec<_>>() ==
                 parsed.iter().map(|s| PathBuf::from(*s)).collect::<Vec<_>>()
@@ -1015,6 +1018,8 @@ mod tests {
     #[test]
     #[cfg(unix)]
     fn join_paths_unix() {
+        use ffi::OsStr;
+
         fn test_eq(input: &[&str], output: &str) -> bool {
             &*join_paths(input.iter().cloned()).unwrap() ==
                 OsStr::new(output)
@@ -1031,6 +1036,8 @@ mod tests {
     #[test]
     #[cfg(windows)]
     fn join_paths_windows() {
+        use ffi::OsStr;
+
         fn test_eq(input: &[&str], output: &str) -> bool {
             &*join_paths(input.iter().cloned()).unwrap() ==
                 OsStr::new(output)
diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs
index 51cb9609120..4e0ff450cab 100644
--- a/src/libstd/fs.rs
+++ b/src/libstd/fs.rs
@@ -1989,7 +1989,7 @@ impl AsInnerMut<fs_imp::DirBuilder> for DirBuilder {
     }
 }
 
-#[cfg(all(test, not(target_os = "emscripten")))]
+#[cfg(all(test, not(any(target_os = "cloudabi", target_os = "emscripten"))))]
 mod tests {
     use io::prelude::*;
 
diff --git a/src/libstd/net/tcp.rs b/src/libstd/net/tcp.rs
index 539ff1df187..78235ea1b4b 100644
--- a/src/libstd/net/tcp.rs
+++ b/src/libstd/net/tcp.rs
@@ -885,7 +885,7 @@ impl fmt::Debug for TcpListener {
     }
 }
 
-#[cfg(all(test, not(target_os = "emscripten")))]
+#[cfg(all(test, not(any(target_os = "cloudabi", target_os = "emscripten"))))]
 mod tests {
     use io::ErrorKind;
     use io::prelude::*;
diff --git a/src/libstd/net/udp.rs b/src/libstd/net/udp.rs
index 84ceaa65951..fc7f9205d06 100644
--- a/src/libstd/net/udp.rs
+++ b/src/libstd/net/udp.rs
@@ -786,7 +786,7 @@ impl fmt::Debug for UdpSocket {
     }
 }
 
-#[cfg(all(test, not(target_os = "emscripten")))]
+#[cfg(all(test, not(any(target_os = "cloudabi", target_os = "emscripten"))))]
 mod tests {
     use io::ErrorKind;
     use net::*;
diff --git a/src/libstd/process.rs b/src/libstd/process.rs
index 33e8a87a0b6..5c66ac6ddde 100644
--- a/src/libstd/process.rs
+++ b/src/libstd/process.rs
@@ -1392,7 +1392,7 @@ pub fn id() -> u32 {
     ::sys::os::getpid()
 }
 
-#[cfg(all(test, not(target_os = "emscripten")))]
+#[cfg(all(test, not(any(target_os = "cloudabi", target_os = "emscripten"))))]
 mod tests {
     use io::prelude::*;
 
diff --git a/src/libstd/sys/cloudabi/abi/bitflags.rs b/src/libstd/sys/cloudabi/abi/bitflags.rs
new file mode 100644
index 00000000000..f764cc1df5a
--- /dev/null
+++ b/src/libstd/sys/cloudabi/abi/bitflags.rs
@@ -0,0 +1,51 @@
+// 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.
+
+// Appease Rust's tidy.
+// ignore-license
+
+#[cfg(feature = "bitflags")]
+#[macro_use]
+extern crate 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/src/libstd/sys/cloudabi/abi/cloudabi.rs b/src/libstd/sys/cloudabi/abi/cloudabi.rs
new file mode 100644
index 00000000000..2909db5098e
--- /dev/null
+++ b/src/libstd/sys/cloudabi/abi/cloudabi.rs
@@ -0,0 +1,2847 @@
+// 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-license
+// 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 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)]
+
+include!("bitflags.rs");
+
+/// File or memory access pattern advisory information.
+#[repr(u8)]
+#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+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,
+  #[doc(hidden)] _NonExhaustive = -1 as isize as u8,
+}
+
+/// Enumeration describing the kind of value stored in [`auxv`](struct.auxv.html).
+#[repr(u32)]
+#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+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,
+  #[doc(hidden)] _NonExhaustive = -1 as isize as u32,
+}
+
+/// Identifiers for clocks.
+#[repr(u32)]
+#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+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,
+  #[doc(hidden)] _NonExhaustive = -1 as isize as u32,
+}
+
+/// 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`](struct.inode.html) 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)]
+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,
+  #[doc(hidden)] _NonExhaustive = -1 as isize as u16,
+}
+
+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)]
+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,
+  #[doc(hidden)] _NonExhaustive = -1 as isize as u8,
+}
+
+/// 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)]
+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,
+  #[doc(hidden)] _NonExhaustive = -1 as isize as u8,
+}
+
+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 {
+    /// Perform asynchronous writes.
+    const ASYNC      = 0x01;
+    /// Invalidate cached data.
+    const INVALIDATE = 0x02;
+    /// Perform 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`](struct.mprot.html) 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)]
+pub enum scope {
+  /// The object is stored in private memory.
+  PRIVATE = 4,
+  /// The object is stored in shared memory.
+  SHARED  = 8,
+  #[doc(hidden)] _NonExhaustive = -1 as isize as u8,
+}
+
+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)]
+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,
+  #[doc(hidden)] _NonExhaustive = -1 as isize as u8,
+}
+
+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`](struct.lock.html) 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)]
+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,
+  #[doc(hidden)] _NonExhaustive = -1 as isize as u8,
+}
+
+/// 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`](struct.auxv.html).
+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 {
+  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 {
+  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 {
+  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 {
+  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 {
+  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 {
+  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 {
+  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 {
+  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 {
+  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 {
+  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 {
+  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 {
+  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 {
+  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 {
+  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 {
+  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 {
+  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 {
+  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 {
+  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 {
+  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 {
+  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 {
+  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 {
+  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`](struct.dirent.html) 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 {
+  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 {
+  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 {
+  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 {
+  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 {
+  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 {
+  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 {
+  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 {
+  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 {
+  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 {
+  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 {
+  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 {
+  cloudabi_sys_mem_map(addr_, len_, prot_, flags_, fd_, off_, mem_)
+}
+
+/// Change 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 {
+  cloudabi_sys_mem_protect(mapping_.as_mut_ptr() as *mut (), mapping_.len(), prot_)
+}
+
+/// Synchronize 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 {
+  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 {
+  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 {
+  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 {
+  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) -> ! {
+  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 {
+  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 {
+  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 {
+  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 {
+  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 {
+  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 {
+  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 {
+  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) -> ! {
+  cloudabi_sys_thread_exit(lock_, scope_)
+}
+
+/// Temporarily yields execution of the calling thread.
+#[inline]
+pub unsafe fn thread_yield() -> errno {
+  cloudabi_sys_thread_yield()
+}
diff --git a/src/libstd/sys/cloudabi/abi/mod.rs b/src/libstd/sys/cloudabi/abi/mod.rs
new file mode 100644
index 00000000000..81a4d293423
--- /dev/null
+++ b/src/libstd/sys/cloudabi/abi/mod.rs
@@ -0,0 +1,13 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[allow(warnings)]
+mod cloudabi;
+pub use self::cloudabi::*;
diff --git a/src/libstd/sys/cloudabi/args.rs b/src/libstd/sys/cloudabi/args.rs
new file mode 100644
index 00000000000..7b62cc6adc9
--- /dev/null
+++ b/src/libstd/sys/cloudabi/args.rs
@@ -0,0 +1,17 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+pub use sys::cloudabi::shims::args::*;
+
+#[allow(dead_code)]
+pub fn init(_: isize, _: *const *const u8) {}
+
+#[allow(dead_code)]
+pub fn cleanup() {}
diff --git a/src/libstd/sys/cloudabi/backtrace.rs b/src/libstd/sys/cloudabi/backtrace.rs
new file mode 100644
index 00000000000..33d93179237
--- /dev/null
+++ b/src/libstd/sys/cloudabi/backtrace.rs
@@ -0,0 +1,121 @@
+// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use error::Error;
+use ffi::CStr;
+use intrinsics;
+use io;
+use libc;
+use sys_common::backtrace::Frame;
+use unwind as uw;
+
+pub struct BacktraceContext;
+
+struct Context<'a> {
+    idx: usize,
+    frames: &'a mut [Frame],
+}
+
+#[derive(Debug)]
+struct UnwindError(uw::_Unwind_Reason_Code);
+
+impl Error for UnwindError {
+    fn description(&self) -> &'static str {
+        "unexpected return value while unwinding"
+    }
+}
+
+impl ::fmt::Display for UnwindError {
+    fn fmt(&self, f: &mut ::fmt::Formatter) -> ::fmt::Result {
+        write!(f, "{}: {:?}", self.description(), self.0)
+    }
+}
+
+#[inline(never)] // if we know this is a function call, we can skip it when
+                 // tracing
+pub fn unwind_backtrace(frames: &mut [Frame]) -> io::Result<(usize, BacktraceContext)> {
+    let mut cx = Context { idx: 0, frames };
+    let result_unwind =
+        unsafe { uw::_Unwind_Backtrace(trace_fn, &mut cx as *mut Context as *mut libc::c_void) };
+    // See libunwind:src/unwind/Backtrace.c for the return values.
+    // No, there is no doc.
+    match result_unwind {
+        // These return codes seem to be benign and need to be ignored for backtraces
+        // to show up properly on all tested platforms.
+        uw::_URC_END_OF_STACK | uw::_URC_FATAL_PHASE1_ERROR | uw::_URC_FAILURE => {
+            Ok((cx.idx, BacktraceContext))
+        }
+        _ => Err(io::Error::new(
+            io::ErrorKind::Other,
+            UnwindError(result_unwind),
+        )),
+    }
+}
+
+extern "C" fn trace_fn(
+    ctx: *mut uw::_Unwind_Context,
+    arg: *mut libc::c_void,
+) -> uw::_Unwind_Reason_Code {
+    let cx = unsafe { &mut *(arg as *mut Context) };
+    let mut ip_before_insn = 0;
+    let mut ip = unsafe { uw::_Unwind_GetIPInfo(ctx, &mut ip_before_insn) as *mut libc::c_void };
+    if !ip.is_null() && ip_before_insn == 0 {
+        // this is a non-signaling frame, so `ip` refers to the address
+        // after the calling instruction. account for that.
+        ip = (ip as usize - 1) as *mut _;
+    }
+
+    let symaddr = unsafe { uw::_Unwind_FindEnclosingFunction(ip) };
+    if cx.idx < cx.frames.len() {
+        cx.frames[cx.idx] = Frame {
+            symbol_addr: symaddr as *mut u8,
+            exact_position: ip as *mut u8,
+        };
+        cx.idx += 1;
+    }
+
+    uw::_URC_NO_REASON
+}
+
+pub fn foreach_symbol_fileline<F>(_: Frame, _: F, _: &BacktraceContext) -> io::Result<bool>
+where
+    F: FnMut(&[u8], u32) -> io::Result<()>,
+{
+    // No way to obtain this information on CloudABI.
+    Ok(false)
+}
+
+pub fn resolve_symname<F>(frame: Frame, callback: F, _: &BacktraceContext) -> io::Result<()>
+where
+    F: FnOnce(Option<&str>) -> io::Result<()>,
+{
+    unsafe {
+        let mut info: Dl_info = intrinsics::init();
+        let symname =
+            if dladdr(frame.exact_position as *mut _, &mut info) == 0 || info.dli_sname.is_null() {
+                None
+            } else {
+                CStr::from_ptr(info.dli_sname).to_str().ok()
+            };
+        callback(symname)
+    }
+}
+
+#[repr(C)]
+struct Dl_info {
+    dli_fname: *const libc::c_char,
+    dli_fbase: *mut libc::c_void,
+    dli_sname: *const libc::c_char,
+    dli_saddr: *mut libc::c_void,
+}
+
+extern "C" {
+    fn dladdr(addr: *const libc::c_void, info: *mut Dl_info) -> libc::c_int;
+}
diff --git a/src/libstd/sys/cloudabi/condvar.rs b/src/libstd/sys/cloudabi/condvar.rs
new file mode 100644
index 00000000000..c05c837ade2
--- /dev/null
+++ b/src/libstd/sys/cloudabi/condvar.rs
@@ -0,0 +1,169 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use cell::UnsafeCell;
+use mem;
+use sync::atomic::{AtomicU32, Ordering};
+use sys::cloudabi::abi;
+use sys::mutex::{self, Mutex};
+use sys::time::dur2intervals;
+use time::Duration;
+
+extern "C" {
+    #[thread_local]
+    static __pthread_thread_id: abi::tid;
+}
+
+pub struct Condvar {
+    condvar: UnsafeCell<AtomicU32>,
+}
+
+unsafe impl Send for Condvar {}
+unsafe impl Sync for Condvar {}
+
+impl Condvar {
+    pub const fn new() -> Condvar {
+        Condvar {
+            condvar: UnsafeCell::new(AtomicU32::new(abi::CONDVAR_HAS_NO_WAITERS.0)),
+        }
+    }
+
+    pub unsafe fn init(&mut self) {}
+
+    pub unsafe fn notify_one(&self) {
+        let condvar = self.condvar.get();
+        if (*condvar).load(Ordering::Relaxed) != abi::CONDVAR_HAS_NO_WAITERS.0 {
+            let ret = abi::condvar_signal(condvar 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) {
+        let condvar = self.condvar.get();
+        if (*condvar).load(Ordering::Relaxed) != abi::CONDVAR_HAS_NO_WAITERS.0 {
+            let ret = abi::condvar_signal(
+                condvar as *mut abi::condvar,
+                abi::scope::PRIVATE,
+                abi::nthreads::max_value(),
+            );
+            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 condvar = self.condvar.get();
+        let subscription = abi::subscription {
+            type_: abi::eventtype::CONDVAR,
+            union: abi::subscription_union {
+                condvar: abi::subscription_condvar {
+                    condvar: condvar as *mut abi::condvar,
+                    condvar_scope: abi::scope::PRIVATE,
+                    lock: mutex as *mut abi::lock,
+                    lock_scope: abi::scope::PRIVATE,
+                },
+            },
+            ..mem::zeroed()
+        };
+        let mut event: abi::event = mem::uninitialized();
+        let mut nevents: usize = mem::uninitialized();
+        let ret = abi::poll(&subscription, &mut event, 1, &mut nevents);
+        assert_eq!(
+            ret,
+            abi::errno::SUCCESS,
+            "Failed to wait on condition variable"
+        );
+        assert_eq!(
+            event.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 condvar = self.condvar.get();
+        let subscriptions = [
+            abi::subscription {
+                type_: abi::eventtype::CONDVAR,
+                union: abi::subscription_union {
+                    condvar: abi::subscription_condvar {
+                        condvar: condvar as *mut abi::condvar,
+                        condvar_scope: abi::scope::PRIVATE,
+                        lock: mutex 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: dur2intervals(&dur),
+                        ..mem::zeroed()
+                    },
+                },
+                ..mem::zeroed()
+            },
+        ];
+        let mut events: [abi::event; 2] = mem::uninitialized();
+        let mut nevents: usize = mem::uninitialized();
+        let ret = abi::poll(subscriptions.as_ptr(), events.as_mut_ptr(), 2, &mut nevents);
+        assert_eq!(
+            ret,
+            abi::errno::SUCCESS,
+            "Failed to wait on condition variable"
+        );
+        for i in 0..nevents {
+            assert_eq!(
+                events[i].error,
+                abi::errno::SUCCESS,
+                "Failed to wait on condition variable"
+            );
+            if events[i].type_ == abi::eventtype::CONDVAR {
+                return true;
+            }
+        }
+        false
+    }
+
+    pub unsafe fn destroy(&self) {
+        let condvar = self.condvar.get();
+        assert_eq!(
+            (*condvar).load(Ordering::Relaxed),
+            abi::CONDVAR_HAS_NO_WAITERS.0,
+            "Attempted to destroy a condition variable with blocked threads"
+        );
+    }
+}
diff --git a/src/libstd/sys/cloudabi/mod.rs b/src/libstd/sys/cloudabi/mod.rs
new file mode 100644
index 00000000000..9e943c17fc8
--- /dev/null
+++ b/src/libstd/sys/cloudabi/mod.rs
@@ -0,0 +1,76 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use io;
+use libc;
+use mem;
+
+pub mod args;
+#[cfg(feature = "backtrace")]
+pub mod backtrace;
+#[path = "../unix/cmath.rs"]
+pub mod cmath;
+pub mod condvar;
+#[path = "../unix/memchr.rs"]
+pub mod memchr;
+pub mod mutex;
+pub mod os;
+#[path = "../unix/os_str.rs"]
+pub mod os_str;
+pub mod rwlock;
+pub mod stack_overflow;
+pub mod stdio;
+pub mod thread;
+#[path = "../unix/thread_local.rs"]
+pub mod thread_local;
+pub mod time;
+
+mod abi;
+
+mod shims;
+pub use self::shims::*;
+
+#[allow(dead_code)]
+pub fn init() {}
+
+pub fn decode_error_kind(errno: i32) -> io::ErrorKind {
+    match errno {
+        x if x == abi::errno::ACCES as i32 => io::ErrorKind::PermissionDenied,
+        x if x == abi::errno::ADDRINUSE as i32 => io::ErrorKind::AddrInUse,
+        x if x == abi::errno::ADDRNOTAVAIL as i32 => io::ErrorKind::AddrNotAvailable,
+        x if x == abi::errno::AGAIN as i32 => io::ErrorKind::WouldBlock,
+        x if x == abi::errno::CONNABORTED as i32 => io::ErrorKind::ConnectionAborted,
+        x if x == abi::errno::CONNREFUSED as i32 => io::ErrorKind::ConnectionRefused,
+        x if x == abi::errno::CONNRESET as i32 => io::ErrorKind::ConnectionReset,
+        x if x == abi::errno::EXIST as i32 => io::ErrorKind::AlreadyExists,
+        x if x == abi::errno::INTR as i32 => io::ErrorKind::Interrupted,
+        x if x == abi::errno::INVAL as i32 => io::ErrorKind::InvalidInput,
+        x if x == abi::errno::NOENT as i32 => io::ErrorKind::NotFound,
+        x if x == abi::errno::NOTCONN as i32 => io::ErrorKind::NotConnected,
+        x if x == abi::errno::PERM as i32 => io::ErrorKind::PermissionDenied,
+        x if x == abi::errno::PIPE as i32 => io::ErrorKind::BrokenPipe,
+        x if x == abi::errno::TIMEDOUT as i32 => io::ErrorKind::TimedOut,
+        _ => io::ErrorKind::Other,
+    }
+}
+
+pub unsafe fn abort_internal() -> ! {
+    ::core::intrinsics::abort();
+}
+
+pub use libc::strlen;
+
+pub fn hashmap_random_keys() -> (u64, u64) {
+    unsafe {
+        let mut v = mem::uninitialized();
+        libc::arc4random_buf(&mut v as *mut _ as *mut libc::c_void, mem::size_of_val(&v));
+        v
+    }
+}
diff --git a/src/libstd/sys/cloudabi/mutex.rs b/src/libstd/sys/cloudabi/mutex.rs
new file mode 100644
index 00000000000..d4ba6bcfc80
--- /dev/null
+++ b/src/libstd/sys/cloudabi/mutex.rs
@@ -0,0 +1,158 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use cell::UnsafeCell;
+use mem;
+use sync::atomic::{AtomicU32, Ordering};
+use sys::cloudabi::abi;
+use 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 unsafe fn raw(m: &Mutex) -> *mut 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: UnsafeCell<AtomicU32>,
+    recursion: UnsafeCell<u32>,
+}
+
+impl ReentrantMutex {
+    pub unsafe fn uninitialized() -> ReentrantMutex {
+        mem::uninitialized()
+    }
+
+    pub unsafe fn init(&mut self) {
+        self.lock = UnsafeCell::new(AtomicU32::new(abi::LOCK_UNLOCKED.0));
+        self.recursion = UnsafeCell::new(0);
+    }
+
+    pub unsafe fn try_lock(&self) -> bool {
+        // Attempt to acquire the lock.
+        let lock = self.lock.get();
+        let recursion = self.recursion.get();
+        if let Err(old) = (*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 {
+                *recursion += 1;
+                true
+            } else {
+                false
+            }
+        } else {
+            // Success.
+            assert_eq!(*recursion, 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.get();
+            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: abi::event = mem::uninitialized();
+            let mut nevents: usize = mem::uninitialized();
+            let ret = abi::poll(&subscription, &mut event, 1, &mut nevents);
+            assert_eq!(ret, abi::errno::SUCCESS, "Failed to acquire mutex");
+            assert_eq!(event.error, abi::errno::SUCCESS, "Failed to acquire mutex");
+        }
+    }
+
+    pub unsafe fn unlock(&self) {
+        let lock = self.lock.get();
+        let recursion = self.recursion.get();
+        assert_eq!(
+            (*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"
+        );
+
+        if *recursion > 0 {
+            *recursion -= 1;
+        } else if !(*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(lock as *mut abi::lock, abi::scope::PRIVATE);
+            assert_eq!(ret, abi::errno::SUCCESS, "Failed to unlock a mutex");
+        }
+    }
+
+    pub unsafe fn destroy(&self) {
+        let lock = self.lock.get();
+        let recursion = self.recursion.get();
+        assert_eq!(
+            (*lock).load(Ordering::Relaxed),
+            abi::LOCK_UNLOCKED.0,
+            "Attempted to destroy locked mutex"
+        );
+        assert_eq!(*recursion, 0, "Recursion counter invalid");
+    }
+}
diff --git a/src/libstd/sys/cloudabi/os.rs b/src/libstd/sys/cloudabi/os.rs
new file mode 100644
index 00000000000..7e506b84df1
--- /dev/null
+++ b/src/libstd/sys/cloudabi/os.rs
@@ -0,0 +1,37 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use ffi::CStr;
+use libc::{self, c_int};
+use str;
+
+pub use 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/src/libstd/sys/cloudabi/rwlock.rs b/src/libstd/sys/cloudabi/rwlock.rs
new file mode 100644
index 00000000000..8539aec5e2c
--- /dev/null
+++ b/src/libstd/sys/cloudabi/rwlock.rs
@@ -0,0 +1,237 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use cell::UnsafeCell;
+use mem;
+use sync::atomic::{AtomicU32, Ordering};
+use 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: UnsafeCell<AtomicU32>,
+}
+
+pub unsafe fn raw(r: &RWLock) -> *mut AtomicU32 {
+    r.lock.get()
+}
+
+unsafe impl Send for RWLock {}
+unsafe impl Sync for RWLock {}
+
+impl RWLock {
+    pub const fn new() -> RWLock {
+        RWLock {
+            lock: UnsafeCell::new(AtomicU32::new(abi::LOCK_UNLOCKED.0)),
+        }
+    }
+
+    pub unsafe fn try_read(&self) -> bool {
+        let lock = self.lock.get();
+        let mut old = abi::LOCK_UNLOCKED.0;
+        while let Err(cur) =
+            (*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 lock = self.lock.get();
+            let subscription = abi::subscription {
+                type_: abi::eventtype::LOCK_RDLOCK,
+                union: abi::subscription_union {
+                    lock: abi::subscription_lock {
+                        lock: lock as *mut abi::lock,
+                        lock_scope: abi::scope::PRIVATE,
+                    },
+                },
+                ..mem::zeroed()
+            };
+            let mut event: abi::event = mem::uninitialized();
+            let mut nevents: usize = mem::uninitialized();
+            let ret = abi::poll(&subscription, &mut event, 1, &mut nevents);
+            assert_eq!(ret, abi::errno::SUCCESS, "Failed to acquire read lock");
+            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 {
+            let lock = self.lock.get();
+            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) = (*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(lock 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) = (*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.
+        let lock = self.lock.get();
+        if let Err(old) = (*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 lock = self.lock.get();
+            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: abi::event = mem::uninitialized();
+            let mut nevents: usize = mem::uninitialized();
+            let ret = abi::poll(&subscription, &mut event, 1, &mut nevents);
+            assert_eq!(ret, abi::errno::SUCCESS, "Failed to acquire write lock");
+            assert_eq!(
+                event.error,
+                abi::errno::SUCCESS,
+                "Failed to acquire write lock"
+            );
+        }
+    }
+
+    pub unsafe fn write_unlock(&self) {
+        let lock = self.lock.get();
+        assert_eq!(
+            (*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 !(*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(lock as *mut abi::lock, abi::scope::PRIVATE);
+            assert_eq!(ret, abi::errno::SUCCESS, "Failed to write unlock a rwlock");
+        }
+    }
+
+    pub unsafe fn destroy(&self) {
+        let lock = self.lock.get();
+        assert_eq!(
+            (*lock).load(Ordering::Relaxed),
+            abi::LOCK_UNLOCKED.0,
+            "Attempted to destroy locked rwlock"
+        );
+    }
+}
diff --git a/src/libstd/sys/cloudabi/shims/args.rs b/src/libstd/sys/cloudabi/shims/args.rs
new file mode 100644
index 00000000000..1b5785adc8a
--- /dev/null
+++ b/src/libstd/sys/cloudabi/shims/args.rs
@@ -0,0 +1,45 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use 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/src/libstd/sys/cloudabi/shims/env.rs b/src/libstd/sys/cloudabi/shims/env.rs
new file mode 100644
index 00000000000..31777aa94bc
--- /dev/null
+++ b/src/libstd/sys/cloudabi/shims/env.rs
@@ -0,0 +1,19 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+pub mod os {
+    pub const FAMILY: &'static str = "cloudabi";
+    pub const OS: &'static str = "cloudabi";
+    pub const DLL_PREFIX: &'static str = "lib";
+    pub const DLL_SUFFIX: &'static str = ".so";
+    pub const DLL_EXTENSION: &'static str = "so";
+    pub const EXE_SUFFIX: &'static str = "";
+    pub const EXE_EXTENSION: &'static str = "";
+}
diff --git a/src/libstd/sys/cloudabi/shims/fs.rs b/src/libstd/sys/cloudabi/shims/fs.rs
new file mode 100644
index 00000000000..d3da0fbc371
--- /dev/null
+++ b/src/libstd/sys/cloudabi/shims/fs.rs
@@ -0,0 +1,302 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use ffi::OsString;
+use fmt;
+use hash::{Hash, Hasher};
+use io::{self, SeekFrom};
+use path::{Path, PathBuf};
+use sys::time::SystemTime;
+use 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 write(&self, _buf: &[u8]) -> io::Result<usize> {
+        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/src/libstd/sys/cloudabi/shims/mod.rs b/src/libstd/sys/cloudabi/shims/mod.rs
new file mode 100644
index 00000000000..407c2b90511
--- /dev/null
+++ b/src/libstd/sys/cloudabi/shims/mod.rs
@@ -0,0 +1,32 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use io;
+
+pub mod args;
+pub mod env;
+pub mod fs;
+pub mod net;
+#[path = "../../unix/path.rs"]
+pub mod path;
+pub mod pipe;
+pub mod process;
+pub mod os;
+
+// 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/src/libstd/sys/cloudabi/shims/net.rs b/src/libstd/sys/cloudabi/shims/net.rs
new file mode 100644
index 00000000000..93eaf6a9e7d
--- /dev/null
+++ b/src/libstd/sys/cloudabi/shims/net.rs
@@ -0,0 +1,296 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use fmt;
+use io;
+use net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr};
+use time::Duration;
+use sys::{unsupported, Void};
+
+pub extern crate libc as netc;
+
+pub struct TcpStream(Void);
+
+impl TcpStream {
+    pub fn connect(_: &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 write(&self, _: &[u8]) -> io::Result<usize> {
+        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(_: &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(_: &SocketAddr) -> io::Result<UdpSocket> {
+        unsupported()
+    }
+
+    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, _: &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 Iterator for LookupHost {
+    type Item = SocketAddr;
+    fn next(&mut self) -> Option<SocketAddr> {
+        match self.0 {}
+    }
+}
+
+pub fn lookup_host(_: &str) -> io::Result<LookupHost> {
+    unsupported()
+}
diff --git a/src/libstd/sys/cloudabi/shims/os.rs b/src/libstd/sys/cloudabi/shims/os.rs
new file mode 100644
index 00000000000..1e355d9ad04
--- /dev/null
+++ b/src/libstd/sys/cloudabi/shims/os.rs
@@ -0,0 +1,95 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use error::Error as StdError;
+use ffi::{OsStr, OsString};
+use fmt;
+use io;
+use iter;
+use path::{self, PathBuf};
+use 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 {
+    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/src/libstd/sys/cloudabi/shims/pipe.rs b/src/libstd/sys/cloudabi/shims/pipe.rs
new file mode 100644
index 00000000000..77a9cd62590
--- /dev/null
+++ b/src/libstd/sys/cloudabi/shims/pipe.rs
@@ -0,0 +1,32 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use io;
+use sys::Void;
+
+pub struct AnonPipe(Void);
+
+impl AnonPipe {
+    pub fn read(&self, _buf: &mut [u8]) -> io::Result<usize> {
+        match self.0 {}
+    }
+
+    pub fn write(&self, _buf: &[u8]) -> io::Result<usize> {
+        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/src/libstd/sys/cloudabi/shims/process.rs b/src/libstd/sys/cloudabi/shims/process.rs
new file mode 100644
index 00000000000..52e8c82e2b2
--- /dev/null
+++ b/src/libstd/sys/cloudabi/shims/process.rs
@@ -0,0 +1,147 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use ffi::OsStr;
+use fmt;
+use io;
+use sys::fs::File;
+use sys::pipe::AnonPipe;
+use sys::{unsupported, Void};
+use sys_common::process::{CommandEnv, DefaultEnvKey};
+
+////////////////////////////////////////////////////////////////////////////////
+// Command
+////////////////////////////////////////////////////////////////////////////////
+
+pub struct Command {
+    env: CommandEnv<DefaultEnvKey>,
+}
+
+// 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<DefaultEnvKey> {
+        &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 {}
+    }
+}
+
+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/src/libstd/sys/cloudabi/stack_overflow.rs b/src/libstd/sys/cloudabi/stack_overflow.rs
new file mode 100644
index 00000000000..5c0b1e5671e
--- /dev/null
+++ b/src/libstd/sys/cloudabi/stack_overflow.rs
@@ -0,0 +1,23 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![cfg_attr(test, allow(dead_code))]
+
+pub struct Handler;
+
+impl Handler {
+    pub unsafe fn new() -> Handler {
+        Handler
+    }
+}
+
+pub unsafe fn init() {}
+
+pub unsafe fn cleanup() {}
diff --git a/src/libstd/sys/cloudabi/stdio.rs b/src/libstd/sys/cloudabi/stdio.rs
new file mode 100644
index 00000000000..9519a926471
--- /dev/null
+++ b/src/libstd/sys/cloudabi/stdio.rs
@@ -0,0 +1,79 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use io;
+use sys::cloudabi::abi;
+
+pub struct Stdin(());
+pub struct Stdout(());
+pub struct Stderr(());
+
+impl Stdin {
+    pub fn new() -> io::Result<Stdin> {
+        Ok(Stdin(()))
+    }
+
+    pub fn read(&self, _: &mut [u8]) -> io::Result<usize> {
+        Ok(0)
+    }
+}
+
+impl Stdout {
+    pub fn new() -> io::Result<Stdout> {
+        Ok(Stdout(()))
+    }
+
+    pub fn write(&self, _: &[u8]) -> io::Result<usize> {
+        Err(io::Error::new(
+            io::ErrorKind::BrokenPipe,
+            "Stdout is not connected to any output in this environment",
+        ))
+    }
+
+    pub fn flush(&self) -> io::Result<()> {
+        Ok(())
+    }
+}
+
+impl Stderr {
+    pub fn new() -> io::Result<Stderr> {
+        Ok(Stderr(()))
+    }
+
+    pub fn write(&self, _: &[u8]) -> io::Result<usize> {
+        Err(io::Error::new(
+            io::ErrorKind::BrokenPipe,
+            "Stderr is not connected to any output in this environment",
+        ))
+    }
+
+    pub fn flush(&self) -> io::Result<()> {
+        Ok(())
+    }
+}
+
+// FIXME: right now this raw stderr handle is used in a few places because
+//        std::io::stderr_raw isn't exposed, but once that's exposed this impl
+//        should go away
+impl io::Write for Stderr {
+    fn write(&mut self, data: &[u8]) -> io::Result<usize> {
+        Stderr::write(self, data)
+    }
+
+    fn flush(&mut self) -> io::Result<()> {
+        Stderr::flush(self)
+    }
+}
+
+pub fn is_ebadf(err: &io::Error) -> bool {
+    err.raw_os_error() == Some(abi::errno::BADF as i32)
+}
+
+pub const STDIN_BUF_SIZE: usize = ::sys_common::io::DEFAULT_BUF_SIZE;
diff --git a/src/libstd/sys/cloudabi/thread.rs b/src/libstd/sys/cloudabi/thread.rs
new file mode 100644
index 00000000000..c980ae75261
--- /dev/null
+++ b/src/libstd/sys/cloudabi/thread.rs
@@ -0,0 +1,124 @@
+// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use alloc::boxed::FnBox;
+use cmp;
+use ffi::CStr;
+use io;
+use libc;
+use mem;
+use ptr;
+use sys::cloudabi::abi;
+use sys::time::dur2intervals;
+use sys_common::thread::*;
+use 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 {
+    pub unsafe fn new<'a>(stack: usize, p: Box<FnBox() + 'a>) -> io::Result<Thread> {
+        let p = 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 *const _ as *mut _);
+        assert_eq!(libc::pthread_attr_destroy(&mut attr), 0);
+
+        return if ret != 0 {
+            Err(io::Error::from_raw_os_error(ret))
+        } else {
+            mem::forget(p); // ownership passed to pthread_create
+            Ok(Thread { id: native })
+        };
+
+        extern "C" fn thread_start(main: *mut libc::c_void) -> *mut libc::c_void {
+            unsafe {
+                start_thread(main as *mut u8);
+            }
+            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) {
+        unsafe {
+            let subscription = abi::subscription {
+                type_: abi::eventtype::CLOCK,
+                union: abi::subscription_union {
+                    clock: abi::subscription_clock {
+                        clock_id: abi::clockid::MONOTONIC,
+                        timeout: dur2intervals(&dur),
+                        ..mem::zeroed()
+                    },
+                },
+                ..mem::zeroed()
+            };
+            let mut event: abi::event = mem::uninitialized();
+            let mut nevents: usize = mem::uninitialized();
+            let ret = abi::poll(&subscription, &mut event, 1, &mut nevents);
+            assert_eq!(ret, abi::errno::SUCCESS);
+            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 unsafe fn current() -> Option<usize> {
+        None
+    }
+    pub unsafe fn init() -> Option<usize> {
+        None
+    }
+}
+
+fn min_stack_size(_: *const libc::pthread_attr_t) -> usize {
+    libc::PTHREAD_STACK_MIN
+}
diff --git a/src/libstd/sys/cloudabi/time.rs b/src/libstd/sys/cloudabi/time.rs
new file mode 100644
index 00000000000..ee12731619a
--- /dev/null
+++ b/src/libstd/sys/cloudabi/time.rs
@@ -0,0 +1,111 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use mem;
+use sys::cloudabi::abi;
+use 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 dur2intervals(dur: &Duration) -> abi::timestamp {
+    dur.as_secs()
+        .checked_mul(NSEC_PER_SEC)
+        .and_then(|nanos| nanos.checked_add(dur.subsec_nanos() as abi::timestamp))
+        .expect("overflow converting duration to nanoseconds")
+}
+
+impl Instant {
+    pub fn now() -> Instant {
+        unsafe {
+            let mut t = mem::uninitialized();
+            let ret = abi::clock_time_get(abi::clockid::MONOTONIC, 0, &mut t);
+            assert_eq!(ret, abi::errno::SUCCESS);
+            Instant { t: t }
+        }
+    }
+
+    pub fn sub_instant(&self, other: &Instant) -> Duration {
+        let diff = self.t
+            .checked_sub(other.t)
+            .expect("second instant is later than self");
+        Duration::new(diff / NSEC_PER_SEC, (diff % NSEC_PER_SEC) as u32)
+    }
+
+    pub fn add_duration(&self, other: &Duration) -> Instant {
+        Instant {
+            t: self.t
+                .checked_add(dur2intervals(other))
+                .expect("overflow when adding duration to instant"),
+        }
+    }
+
+    pub fn sub_duration(&self, other: &Duration) -> Instant {
+        Instant {
+            t: self.t
+                .checked_sub(dur2intervals(other))
+                .expect("overflow when subtracting duration from instant"),
+        }
+    }
+}
+
+#[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::uninitialized();
+            let ret = abi::clock_time_get(abi::clockid::REALTIME, 0, &mut t);
+            assert_eq!(ret, abi::errno::SUCCESS);
+            SystemTime { t: t }
+        }
+    }
+
+    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 add_duration(&self, other: &Duration) -> SystemTime {
+        SystemTime {
+            t: self.t
+                .checked_add(dur2intervals(other))
+                .expect("overflow when adding duration to instant"),
+        }
+    }
+
+    pub fn sub_duration(&self, other: &Duration) -> SystemTime {
+        SystemTime {
+            t: self.t
+                .checked_sub(dur2intervals(other))
+                .expect("overflow when subtracting duration from instant"),
+        }
+    }
+}
+
+pub const UNIX_EPOCH: SystemTime = SystemTime { t: 0 };
diff --git a/src/libstd/sys/mod.rs b/src/libstd/sys/mod.rs
index be8cb88416b..1231898ed7e 100644
--- a/src/libstd/sys/mod.rs
+++ b/src/libstd/sys/mod.rs
@@ -39,6 +39,9 @@ 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 = "redox")] {
         mod redox;
         pub use self::redox::*;
@@ -59,9 +62,10 @@ cfg_if! {
     if #[cfg(any(unix, target_os = "redox"))] {
         // On unix we'll document what's already available
         pub use self::ext as unix_ext;
-    } else if #[cfg(target_arch = "wasm32")] {
-        // 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
+    } else if #[cfg(any(target_os = "cloudabi", target_arch = "wasm32"))] {
+        // On CloudABI and 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 = "0", feature = "std_internals")]
         pub mod unix_ext {}
     } else {
@@ -77,8 +81,9 @@ cfg_if! {
     if #[cfg(windows)] {
         // On windows we'll just be documenting what's already available
         pub use self::ext as windows_ext;
-    } else if #[cfg(target_arch = "wasm32")] {
-        // On wasm right now the shim below doesn't compile, so just omit it
+    } else if #[cfg(any(target_os = "cloudabi", target_arch = "wasm32"))] {
+        // On CloudABI and wasm right now the shim below doesn't compile, so
+        // just omit it
         #[unstable(issue = "0", feature = "std_internals")]
         pub mod windows_ext {}
     } else {
diff --git a/src/libstd/sys_common/mod.rs b/src/libstd/sys_common/mod.rs
index 938e8656808..27504d374dd 100644
--- a/src/libstd/sys_common/mod.rs
+++ b/src/libstd/sys_common/mod.rs
@@ -46,7 +46,7 @@ pub mod bytestring;
 pub mod process;
 
 cfg_if! {
-    if #[cfg(any(target_os = "redox", target_os = "l4re"))] {
+    if #[cfg(any(target_os = "cloudabi", target_os = "l4re", target_os = "redox"))] {
         pub use sys::net;
     } else if #[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))] {
         pub use sys::net;
diff --git a/src/tools/tidy/src/pal.rs b/src/tools/tidy/src/pal.rs
index fdbcfd10bde..8071f07d811 100644
--- a/src/tools/tidy/src/pal.rs
+++ b/src/tools/tidy/src/pal.rs
@@ -168,8 +168,8 @@ fn find_test_mod(contents: &str) -> usize {
         let prev_newline_idx = contents[..prev_newline_idx].rfind('\n');
         if let Some(nl) = prev_newline_idx {
             let prev_line = &contents[nl + 1 .. mod_tests_idx];
-            let emcc_cfg = "cfg(all(test, not(target_os";
-            if prev_line.contains(emcc_cfg) {
+            if prev_line.contains("cfg(all(test, not(target_os")
+                || prev_line.contains("cfg(all(test, not(any(target_os") {
                 nl
             } else {
                 mod_tests_idx