about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorEsteban Küber <esteban@kuber.com.ar>2016-12-27 17:02:52 -0800
committerEsteban Küber <esteban@kuber.com.ar>2016-12-27 17:02:52 -0800
commite766c465d2e4c4e3c106bfa8343cbe6f9192d445 (patch)
tree821a7cf1e0b04ac9c0cddede6eb760bbf2d0ce62 /src/libstd
parent96c52d4fd86aed6320732a511c04bcbfff7d117f (diff)
parent314c28b729ae359b99586cc62c486c28e0d44424 (diff)
downloadrust-e766c465d2e4c4e3c106bfa8343cbe6f9192d445.tar.gz
rust-e766c465d2e4c4e3c106bfa8343cbe6f9192d445.zip
Merge branch 'master' into escape-reason-docs
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/ascii.rs8
-rw-r--r--src/libstd/build.rs4
-rw-r--r--src/libstd/collections/hash/map.rs83
-rw-r--r--src/libstd/collections/hash/set.rs77
-rw-r--r--src/libstd/collections/hash/table.rs29
-rw-r--r--src/libstd/env.rs36
-rw-r--r--src/libstd/fs.rs107
-rw-r--r--src/libstd/io/buffered.rs99
-rw-r--r--src/libstd/io/mod.rs25
-rw-r--r--src/libstd/io/stdio.rs52
-rw-r--r--src/libstd/io/util.rs22
-rw-r--r--src/libstd/lib.rs2
-rw-r--r--src/libstd/net/ip.rs28
-rw-r--r--src/libstd/net/mod.rs8
-rw-r--r--src/libstd/net/tcp.rs1
-rw-r--r--src/libstd/net/udp.rs59
-rw-r--r--src/libstd/os/linux/raw.rs1
-rw-r--r--src/libstd/os/mod.rs4
-rw-r--r--src/libstd/os/raw.rs9
-rw-r--r--src/libstd/panic.rs10
-rw-r--r--src/libstd/panicking.rs2
-rw-r--r--src/libstd/process.rs56
-rw-r--r--src/libstd/rand/mod.rs7
-rw-r--r--src/libstd/sync/barrier.rs17
-rw-r--r--src/libstd/sync/condvar.rs8
-rw-r--r--src/libstd/sync/mpsc/mod.rs230
-rw-r--r--src/libstd/sync/mpsc/oneshot.rs293
-rw-r--r--src/libstd/sync/mpsc/shared.rs106
-rw-r--r--src/libstd/sync/mpsc/stream.rs65
-rw-r--r--src/libstd/sync/mutex.rs9
-rw-r--r--src/libstd/sync/once.rs9
-rw-r--r--src/libstd/sync/rwlock.rs18
-rw-r--r--src/libstd/sys/mod.rs6
-rw-r--r--src/libstd/sys/redox/args.rs109
-rw-r--r--src/libstd/sys/redox/backtrace.rs18
-rw-r--r--src/libstd/sys/redox/condvar.rs106
-rw-r--r--src/libstd/sys/redox/env.rs19
-rw-r--r--src/libstd/sys/redox/ext/ffi.rs61
-rw-r--r--src/libstd/sys/redox/ext/fs.rs298
-rw-r--r--src/libstd/sys/redox/ext/io.rs151
-rw-r--r--src/libstd/sys/redox/ext/mod.rs50
-rw-r--r--src/libstd/sys/redox/ext/process.rs183
-rw-r--r--src/libstd/sys/redox/fast_thread_local.rs116
-rw-r--r--src/libstd/sys/redox/fd.rs100
-rw-r--r--src/libstd/sys/redox/fs.rs470
-rw-r--r--src/libstd/sys/redox/memchr.rs14
-rw-r--r--src/libstd/sys/redox/mod.rs95
-rw-r--r--src/libstd/sys/redox/mutex.rs179
-rw-r--r--src/libstd/sys/redox/net/dns/answer.rs22
-rw-r--r--src/libstd/sys/redox/net/dns/mod.rs217
-rw-r--r--src/libstd/sys/redox/net/dns/query.rs18
-rw-r--r--src/libstd/sys/redox/net/mod.rs113
-rw-r--r--src/libstd/sys/redox/net/netc.rs57
-rw-r--r--src/libstd/sys/redox/net/tcp.rs199
-rw-r--r--src/libstd/sys/redox/net/udp.rs188
-rw-r--r--src/libstd/sys/redox/os.rs204
-rw-r--r--src/libstd/sys/redox/os_str.rs119
-rw-r--r--src/libstd/sys/redox/path.rs39
-rw-r--r--src/libstd/sys/redox/pipe.rs107
-rw-r--r--src/libstd/sys/redox/process.rs504
-rw-r--r--src/libstd/sys/redox/rand.rs57
-rw-r--r--src/libstd/sys/redox/rwlock.rs61
-rw-r--r--src/libstd/sys/redox/stack_overflow.rs27
-rw-r--r--src/libstd/sys/redox/stdio.rs81
-rw-r--r--src/libstd/sys/redox/syscall/arch/arm.rs83
-rw-r--r--src/libstd/sys/redox/syscall/arch/x86.rs83
-rw-r--r--src/libstd/sys/redox/syscall/arch/x86_64.rs84
-rw-r--r--src/libstd/sys/redox/syscall/call.rs300
-rw-r--r--src/libstd/sys/redox/syscall/data.rs86
-rw-r--r--src/libstd/sys/redox/syscall/error.rs325
-rw-r--r--src/libstd/sys/redox/syscall/flag.rs94
-rw-r--r--src/libstd/sys/redox/syscall/mod.rs43
-rw-r--r--src/libstd/sys/redox/syscall/number.rs73
-rw-r--r--src/libstd/sys/redox/thread.rs91
-rw-r--r--src/libstd/sys/redox/thread_local.rs66
-rw-r--r--src/libstd/sys/redox/time.rs198
-rw-r--r--src/libstd/sys/unix/ext/fs.rs8
-rw-r--r--src/libstd/sys/unix/ext/mod.rs2
-rw-r--r--src/libstd/sys/unix/ext/net.rs591
-rw-r--r--src/libstd/sys/unix/ext/process.rs2
-rw-r--r--src/libstd/sys/unix/fast_thread_local.rs7
-rw-r--r--src/libstd/sys/unix/fd.rs1
-rw-r--r--src/libstd/sys/unix/fs.rs3
-rw-r--r--src/libstd/sys/unix/process/magenta.rs1
-rw-r--r--src/libstd/sys/unix/stdio.rs13
-rw-r--r--src/libstd/sys/windows/c.rs18
-rw-r--r--src/libstd/sys/windows/ext/fs.rs8
-rw-r--r--src/libstd/sys/windows/ext/mod.rs2
-rw-r--r--src/libstd/sys/windows/fs.rs3
-rw-r--r--src/libstd/sys/windows/stdio.rs37
-rw-r--r--src/libstd/sys_common/mod.rs8
-rw-r--r--src/libstd/thread/local.rs18
-rw-r--r--src/libstd/thread/mod.rs174
-rw-r--r--src/libstd/time/duration.rs79
94 files changed, 7475 insertions, 498 deletions
diff --git a/src/libstd/ascii.rs b/src/libstd/ascii.rs
index a063b856468..f5e9ec6d89d 100644
--- a/src/libstd/ascii.rs
+++ b/src/libstd/ascii.rs
@@ -12,6 +12,7 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
+use fmt;
 use mem;
 use ops::Range;
 use iter::FusedIterator;
@@ -370,6 +371,13 @@ impl ExactSizeIterator for EscapeDefault {}
 #[unstable(feature = "fused", issue = "35602")]
 impl FusedIterator for EscapeDefault {}
 
+#[stable(feature = "std_debug", since = "1.15.0")]
+impl fmt::Debug for EscapeDefault {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.pad("EscapeDefault { .. }")
+    }
+}
+
 
 static ASCII_LOWERCASE_MAP: [u8; 256] = [
     0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
diff --git a/src/libstd/build.rs b/src/libstd/build.rs
index 1087d1f2447..5e1c3a28515 100644
--- a/src/libstd/build.rs
+++ b/src/libstd/build.rs
@@ -26,7 +26,7 @@ fn main() {
     let target = env::var("TARGET").expect("TARGET was not set");
     let host = env::var("HOST").expect("HOST was not set");
     if cfg!(feature = "backtrace") && !target.contains("apple") && !target.contains("msvc") &&
-        !target.contains("emscripten") && !target.contains("fuchsia") {
+        !target.contains("emscripten") && !target.contains("fuchsia") && !target.contains("redox") {
         build_libbacktrace(&host, &target);
     }
 
@@ -104,7 +104,7 @@ fn build_libbacktrace(host: &str, target: &str) {
                 .env("AR", &ar)
                 .env("RANLIB", format!("{} s", ar.display()))
                 .env("CFLAGS", cflags));
-    run(Command::new("make")
+    run(Command::new(build_helper::make(host))
                 .current_dir(&build_dir)
                 .arg(format!("INCDIR={}", src_dir.display()))
                 .arg("-j").arg(env::var("NUM_JOBS").expect("NUM_JOBS was not set")));
diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs
index 0b310eb2585..2fa3a9c4844 100644
--- a/src/libstd/collections/hash/map.rs
+++ b/src/libstd/collections/hash/map.rs
@@ -1276,6 +1276,15 @@ impl<'a, K, V> Clone for Iter<'a, K, V> {
     }
 }
 
+#[stable(feature = "std_debug", since = "1.15.0")]
+impl<'a, K: Debug, V: Debug> fmt::Debug for Iter<'a, K, V> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.debug_list()
+            .entries(self.clone())
+            .finish()
+    }
+}
+
 /// HashMap mutable values iterator.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct IterMut<'a, K: 'a, V: 'a> {
@@ -1285,7 +1294,7 @@ pub struct IterMut<'a, K: 'a, V: 'a> {
 /// HashMap move iterator.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct IntoIter<K, V> {
-    inner: table::IntoIter<K, V>,
+    pub(super) inner: table::IntoIter<K, V>,
 }
 
 /// HashMap keys iterator.
@@ -1302,6 +1311,15 @@ impl<'a, K, V> Clone for Keys<'a, K, V> {
     }
 }
 
+#[stable(feature = "std_debug", since = "1.15.0")]
+impl<'a, K: Debug, V: Debug> fmt::Debug for Keys<'a, K, V> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.debug_list()
+            .entries(self.clone())
+            .finish()
+    }
+}
+
 /// HashMap values iterator.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Values<'a, K: 'a, V: 'a> {
@@ -1316,10 +1334,19 @@ impl<'a, K, V> Clone for Values<'a, K, V> {
     }
 }
 
+#[stable(feature = "std_debug", since = "1.15.0")]
+impl<'a, K: Debug, V: Debug> fmt::Debug for Values<'a, K, V> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.debug_list()
+            .entries(self.clone())
+            .finish()
+    }
+}
+
 /// HashMap drain iterator.
 #[stable(feature = "drain", since = "1.6.0")]
 pub struct Drain<'a, K: 'a, V: 'a> {
-    inner: table::Drain<'a, K, V>,
+    pub(super) inner: table::Drain<'a, K, V>,
 }
 
 /// Mutable HashMap values iterator.
@@ -1557,6 +1584,18 @@ impl<'a, K, V> ExactSizeIterator for IterMut<'a, K, V> {
 #[unstable(feature = "fused", issue = "35602")]
 impl<'a, K, V> FusedIterator for IterMut<'a, K, V> {}
 
+#[stable(feature = "std_debug", since = "1.15.0")]
+impl<'a, K, V> fmt::Debug for IterMut<'a, K, V>
+    where K: fmt::Debug,
+          V: fmt::Debug,
+{
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.debug_list()
+            .entries(self.inner.iter())
+            .finish()
+    }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<K, V> Iterator for IntoIter<K, V> {
     type Item = (K, V);
@@ -1580,6 +1619,15 @@ impl<K, V> ExactSizeIterator for IntoIter<K, V> {
 #[unstable(feature = "fused", issue = "35602")]
 impl<K, V> FusedIterator for IntoIter<K, V> {}
 
+#[stable(feature = "std_debug", since = "1.15.0")]
+impl<K: Debug, V: Debug> fmt::Debug for IntoIter<K, V> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.debug_list()
+            .entries(self.inner.iter())
+            .finish()
+    }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, K, V> Iterator for Keys<'a, K, V> {
     type Item = &'a K;
@@ -1649,6 +1697,18 @@ impl<'a, K, V> ExactSizeIterator for ValuesMut<'a, K, V> {
 #[unstable(feature = "fused", issue = "35602")]
 impl<'a, K, V> FusedIterator for ValuesMut<'a, K, V> {}
 
+#[stable(feature = "std_debug", since = "1.15.0")]
+impl<'a, K, V> fmt::Debug for ValuesMut<'a, K, V>
+    where K: fmt::Debug,
+          V: fmt::Debug,
+{
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.debug_list()
+            .entries(self.inner.inner.iter())
+            .finish()
+    }
+}
+
 #[stable(feature = "drain", since = "1.6.0")]
 impl<'a, K, V> Iterator for Drain<'a, K, V> {
     type Item = (K, V);
@@ -1672,6 +1732,18 @@ impl<'a, K, V> ExactSizeIterator for Drain<'a, K, V> {
 #[unstable(feature = "fused", issue = "35602")]
 impl<'a, K, V> FusedIterator for Drain<'a, K, V> {}
 
+#[stable(feature = "std_debug", since = "1.15.0")]
+impl<'a, K, V> fmt::Debug for Drain<'a, K, V>
+    where K: fmt::Debug,
+          V: fmt::Debug,
+{
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.debug_list()
+            .entries(self.inner.iter())
+            .finish()
+    }
+}
+
 impl<'a, K, V> Entry<'a, K, V> {
     #[stable(feature = "rust1", since = "1.0.0")]
     /// Ensures a value is in the entry by inserting the default if empty, and returns
@@ -2148,6 +2220,13 @@ impl Default for RandomState {
     }
 }
 
+#[stable(feature = "std_debug", since = "1.15.0")]
+impl fmt::Debug for RandomState {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.pad("RandomState { .. }")
+    }
+}
+
 impl<K, S, Q: ?Sized> super::Recover<Q> for HashMap<K, (), S>
     where K: Eq + Hash + Borrow<Q>,
           S: BuildHasher,
diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs
index 72af612f569..341b050862f 100644
--- a/src/libstd/collections/hash/set.rs
+++ b/src/libstd/collections/hash/set.rs
@@ -948,6 +948,15 @@ impl<'a, K> ExactSizeIterator for Iter<'a, K> {
 #[unstable(feature = "fused", issue = "35602")]
 impl<'a, K> FusedIterator for Iter<'a, K> {}
 
+#[stable(feature = "std_debug", since = "1.15.0")]
+impl<'a, K: fmt::Debug> fmt::Debug for Iter<'a, K> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.debug_list()
+            .entries(self.clone())
+            .finish()
+    }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<K> Iterator for IntoIter<K> {
     type Item = K;
@@ -968,6 +977,16 @@ impl<K> ExactSizeIterator for IntoIter<K> {
 #[unstable(feature = "fused", issue = "35602")]
 impl<K> FusedIterator for IntoIter<K> {}
 
+#[stable(feature = "std_debug", since = "1.15.0")]
+impl<K: fmt::Debug> fmt::Debug for IntoIter<K> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        let entries_iter = self.iter.inner.iter().map(|(k, _)| k);
+        f.debug_list()
+            .entries(entries_iter)
+            .finish()
+    }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, K> Iterator for Drain<'a, K> {
     type Item = K;
@@ -988,6 +1007,16 @@ impl<'a, K> ExactSizeIterator for Drain<'a, K> {
 #[unstable(feature = "fused", issue = "35602")]
 impl<'a, K> FusedIterator for Drain<'a, K> {}
 
+#[stable(feature = "std_debug", since = "1.15.0")]
+impl<'a, K: fmt::Debug> fmt::Debug for Drain<'a, K> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        let entries_iter = self.iter.inner.iter().map(|(k, _)| k);
+        f.debug_list()
+            .entries(entries_iter)
+            .finish()
+    }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T, S> Clone for Intersection<'a, T, S> {
     fn clone(&self) -> Intersection<'a, T, S> {
@@ -1021,6 +1050,18 @@ impl<'a, T, S> Iterator for Intersection<'a, T, S>
     }
 }
 
+#[stable(feature = "std_debug", since = "1.15.0")]
+impl<'a, T, S> fmt::Debug for Intersection<'a, T, S>
+    where T: fmt::Debug + Eq + Hash,
+          S: BuildHasher,
+{
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.debug_list()
+            .entries(self.clone())
+            .finish()
+    }
+}
+
 #[unstable(feature = "fused", issue = "35602")]
 impl<'a, T, S> FusedIterator for Intersection<'a, T, S>
     where T: Eq + Hash,
@@ -1068,6 +1109,18 @@ impl<'a, T, S> FusedIterator for Difference<'a, T, S>
 {
 }
 
+#[stable(feature = "std_debug", since = "1.15.0")]
+impl<'a, T, S> fmt::Debug for Difference<'a, T, S>
+    where T: fmt::Debug + Eq + Hash,
+          S: BuildHasher,
+{
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.debug_list()
+            .entries(self.clone())
+            .finish()
+    }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T, S> Clone for SymmetricDifference<'a, T, S> {
     fn clone(&self) -> SymmetricDifference<'a, T, S> {
@@ -1097,6 +1150,18 @@ impl<'a, T, S> FusedIterator for SymmetricDifference<'a, T, S>
 {
 }
 
+#[stable(feature = "std_debug", since = "1.15.0")]
+impl<'a, T, S> fmt::Debug for SymmetricDifference<'a, T, S>
+    where T: fmt::Debug + Eq + Hash,
+          S: BuildHasher,
+{
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.debug_list()
+            .entries(self.clone())
+            .finish()
+    }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T, S> Clone for Union<'a, T, S> {
     fn clone(&self) -> Union<'a, T, S> {
@@ -1111,6 +1176,18 @@ impl<'a, T, S> FusedIterator for Union<'a, T, S>
 {
 }
 
+#[stable(feature = "std_debug", since = "1.15.0")]
+impl<'a, T, S> fmt::Debug for Union<'a, T, S>
+    where T: fmt::Debug + Eq + Hash,
+          S: BuildHasher,
+{
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.debug_list()
+            .entries(self.clone())
+            .finish()
+    }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T, S> Iterator for Union<'a, T, S>
     where T: Eq + Hash,
diff --git a/src/libstd/collections/hash/table.rs b/src/libstd/collections/hash/table.rs
index a784d8e50f9..2cd9362a657 100644
--- a/src/libstd/collections/hash/table.rs
+++ b/src/libstd/collections/hash/table.rs
@@ -882,6 +882,15 @@ unsafe impl<'a, K: Sync, V: Sync> Sync for IterMut<'a, K, V> {}
 // but Send is the more useful bound
 unsafe impl<'a, K: Send, V: Send> Send for IterMut<'a, K, V> {}
 
+impl<'a, K: 'a, V: 'a> IterMut<'a, K, V> {
+    pub fn iter(&self) -> Iter<K, V> {
+        Iter {
+            iter: self.iter.clone(),
+            elems_left: self.elems_left,
+        }
+    }
+}
+
 /// Iterator over the entries in a table, consuming the table.
 pub struct IntoIter<K, V> {
     table: RawTable<K, V>,
@@ -891,6 +900,15 @@ pub struct IntoIter<K, V> {
 unsafe impl<K: Sync, V: Sync> Sync for IntoIter<K, V> {}
 unsafe impl<K: Send, V: Send> Send for IntoIter<K, V> {}
 
+impl<K, V> IntoIter<K, V> {
+    pub fn iter(&self) -> Iter<K, V> {
+        Iter {
+            iter: self.iter.clone(),
+            elems_left: self.table.size,
+        }
+    }
+}
+
 /// Iterator over the entries in a table, clearing the table.
 pub struct Drain<'a, K: 'a, V: 'a> {
     table: Shared<RawTable<K, V>>,
@@ -901,6 +919,17 @@ pub struct Drain<'a, K: 'a, V: 'a> {
 unsafe impl<'a, K: Sync, V: Sync> Sync for Drain<'a, K, V> {}
 unsafe impl<'a, K: Send, V: Send> Send for Drain<'a, K, V> {}
 
+impl<'a, K, V> Drain<'a, K, V> {
+    pub fn iter(&self) -> Iter<K, V> {
+        unsafe {
+            Iter {
+                iter: self.iter.clone(),
+                elems_left: (**self.table).size,
+            }
+        }
+    }
+}
+
 impl<'a, K, V> Iterator for Iter<'a, K, V> {
     type Item = (&'a K, &'a V);
 
diff --git a/src/libstd/env.rs b/src/libstd/env.rs
index ee6a907f616..0521f301321 100644
--- a/src/libstd/env.rs
+++ b/src/libstd/env.rs
@@ -143,6 +143,13 @@ impl Iterator for Vars {
     fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
 }
 
+#[stable(feature = "std_debug", since = "1.15.0")]
+impl fmt::Debug for Vars {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.pad("Vars { .. }")
+    }
+}
+
 #[stable(feature = "env", since = "1.0.0")]
 impl Iterator for VarsOs {
     type Item = (OsString, OsString);
@@ -150,6 +157,13 @@ impl Iterator for VarsOs {
     fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
 }
 
+#[stable(feature = "std_debug", since = "1.15.0")]
+impl fmt::Debug for VarsOs {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.pad("VarsOs { .. }")
+    }
+}
+
 /// Fetches the environment variable `key` from the current process.
 ///
 /// The returned result is `Ok(s)` if the environment variable is present and is
@@ -364,6 +378,13 @@ impl<'a> Iterator for SplitPaths<'a> {
     fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
 }
 
+#[stable(feature = "std_debug", since = "1.15.0")]
+impl<'a> fmt::Debug for SplitPaths<'a> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.pad("SplitPaths { .. }")
+    }
+}
+
 /// Error type returned from `std::env::join_paths` when paths fail to be
 /// joined.
 #[derive(Debug)]
@@ -640,6 +661,13 @@ impl DoubleEndedIterator for Args {
     }
 }
 
+#[stable(feature = "std_debug", since = "1.15.0")]
+impl fmt::Debug for Args {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.pad("Args { .. }")
+    }
+}
+
 #[stable(feature = "env", since = "1.0.0")]
 impl Iterator for ArgsOs {
     type Item = OsString;
@@ -657,6 +685,14 @@ impl ExactSizeIterator for ArgsOs {
 impl DoubleEndedIterator for ArgsOs {
     fn next_back(&mut self) -> Option<OsString> { self.inner.next_back() }
 }
+
+#[stable(feature = "std_debug", since = "1.15.0")]
+impl fmt::Debug for ArgsOs {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.pad("ArgsOs { .. }")
+    }
+}
+
 /// Constants associated with the current target
 #[stable(feature = "env", since = "1.0.0")]
 pub mod consts {
diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs
index e91e808c548..41934dc057e 100644
--- a/src/libstd/fs.rs
+++ b/src/libstd/fs.rs
@@ -35,21 +35,53 @@ use time::SystemTime;
 ///
 /// # Examples
 ///
+/// Create a new file and write bytes to it:
+///
 /// ```no_run
+/// use std::fs::File;
 /// use std::io::prelude::*;
+///
+/// # fn foo() -> std::io::Result<()> {
+/// let mut file = try!(File::create("foo.txt"));
+/// try!(file.write_all(b"Hello, world!"));
+/// # Ok(())
+/// # }
+/// ```
+///
+/// Read the contents of a file into a `String`:
+///
+/// ```no_run
 /// use std::fs::File;
+/// use std::io::prelude::*;
 ///
 /// # fn foo() -> std::io::Result<()> {
-/// let mut f = try!(File::create("foo.txt"));
-/// try!(f.write_all(b"Hello, world!"));
+/// let mut file = try!(File::open("foo.txt"));
+/// let mut contents = String::new();
+/// try!(file.read_to_string(&mut contents));
+/// assert_eq!(contents, "Hello, world!");
+/// # Ok(())
+/// # }
+/// ```
 ///
-/// let mut f = try!(File::open("foo.txt"));
-/// let mut s = String::new();
-/// try!(f.read_to_string(&mut s));
-/// assert_eq!(s, "Hello, world!");
+/// It can be more efficient to read the contents of a file with a buffered
+/// [`Read`]er. This can be accomplished with [`BufReader<R>`]:
+///
+/// ```no_run
+/// use std::fs::File;
+/// use std::io::BufReader;
+/// use std::io::prelude::*;
+///
+/// # fn foo() -> std::io::Result<()> {
+/// let file = try!(File::open("foo.txt"));
+/// let mut buf_reader = BufReader::new(file);
+/// let mut contents = String::new();
+/// try!(buf_reader.read_to_string(&mut contents));
+/// assert_eq!(contents, "Hello, world!");
 /// # Ok(())
 /// # }
 /// ```
+///
+/// [`BufReader`]: ../io/struct.BufReader.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct File {
     inner: fs_imp::File,
@@ -140,7 +172,7 @@ pub struct DirEntry(fs_imp::DirEntry);
 ///             .create(true)
 ///             .open("foo.txt");
 /// ```
-#[derive(Clone)]
+#[derive(Clone, Debug)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct OpenOptions(fs_imp::OpenOptions);
 
@@ -168,6 +200,7 @@ pub struct FileType(fs_imp::FileType);
 ///
 /// This builder also supports platform-specific options.
 #[stable(feature = "dir_builder", since = "1.6.0")]
+#[derive(Debug)]
 pub struct DirBuilder {
     inner: fs_imp::DirBuilder,
     recursive: bool,
@@ -834,6 +867,21 @@ impl Metadata {
     }
 }
 
+#[stable(feature = "std_debug", since = "1.15.0")]
+impl fmt::Debug for Metadata {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.debug_struct("Metadata")
+            .field("file_type", &self.file_type())
+            .field("is_dir", &self.is_dir())
+            .field("is_file", &self.is_file())
+            .field("permissions", &self.permissions())
+            .field("modified", &self.modified())
+            .field("accessed", &self.accessed())
+            .field("created", &self.created())
+            .finish()
+    }
+}
+
 impl AsInner<fs_imp::FileAttr> for Metadata {
     fn as_inner(&self) -> &fs_imp::FileAttr { &self.0 }
 }
@@ -1751,6 +1799,16 @@ mod tests {
         }
     ) }
 
+    #[cfg(windows)]
+    macro_rules! error { ($e:expr, $s:expr) => (
+        match $e {
+            Ok(_) => panic!("Unexpected success. Should've been: {:?}", $s),
+            Err(ref err) => assert!(err.raw_os_error() == Some($s),
+                                    format!("`{}` did not have a code of `{}`", err, $s))
+        }
+    ) }
+
+    #[cfg(unix)]
     macro_rules! error { ($e:expr, $s:expr) => (
         match $e {
             Ok(_) => panic!("Unexpected success. Should've been: {:?}", $s),
@@ -1771,12 +1829,9 @@ mod tests {
 
         match symlink_file(r"nonexisting_target", link) {
             Ok(_) => true,
-            Err(ref err) =>
-                if err.to_string().contains("A required privilege is not held by the client.") {
-                    false
-                } else {
-                    true
-                }
+            // ERROR_PRIVILEGE_NOT_HELD = 1314
+            Err(ref err) if err.raw_os_error() == Some(1314) => false,
+            Err(_) => true,
         }
     }
 
@@ -1807,12 +1862,10 @@ mod tests {
         let filename = &tmpdir.join("file_that_does_not_exist.txt");
         let result = File::open(filename);
 
-        if cfg!(unix) {
-            error!(result, "No such file or directory");
-        }
-        if cfg!(windows) {
-            error!(result, "The system cannot find the file specified");
-        }
+        #[cfg(unix)]
+        error!(result, "No such file or directory");
+        #[cfg(windows)]
+        error!(result, 2); // ERROR_FILE_NOT_FOUND
     }
 
     #[test]
@@ -1822,12 +1875,10 @@ mod tests {
 
         let result = fs::remove_file(filename);
 
-        if cfg!(unix) {
-            error!(result, "No such file or directory");
-        }
-        if cfg!(windows) {
-            error!(result, "The system cannot find the file specified");
-        }
+        #[cfg(unix)]
+        error!(result, "No such file or directory");
+        #[cfg(windows)]
+        error!(result, 2); // ERROR_FILE_NOT_FOUND
     }
 
     #[test]
@@ -2582,8 +2633,10 @@ mod tests {
         let mut a = OO::new(); a.append(true);
         let mut ra = OO::new(); ra.read(true).append(true);
 
-        let invalid_options = if cfg!(windows) { "The parameter is incorrect" }
-                              else { "Invalid argument" };
+        #[cfg(windows)]
+        let invalid_options = 87; // ERROR_INVALID_PARAMETER
+        #[cfg(unix)]
+        let invalid_options = "Invalid argument";
 
         // Test various combinations of creation modes and access modes.
         //
diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs
index cd7a50d07e2..c15a1c8328c 100644
--- a/src/libstd/io/buffered.rs
+++ b/src/libstd/io/buffered.rs
@@ -652,6 +652,7 @@ impl<W> fmt::Display for IntoInnerError<W> {
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct LineWriter<W: Write> {
     inner: BufWriter<W>,
+    need_flush: bool,
 }
 
 impl<W: Write> LineWriter<W> {
@@ -692,7 +693,10 @@ impl<W: Write> LineWriter<W> {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn with_capacity(cap: usize, inner: W) -> LineWriter<W> {
-        LineWriter { inner: BufWriter::with_capacity(cap, inner) }
+        LineWriter {
+            inner: BufWriter::with_capacity(cap, inner),
+            need_flush: false,
+        }
     }
 
     /// Gets a reference to the underlying writer.
@@ -759,7 +763,10 @@ impl<W: Write> LineWriter<W> {
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn into_inner(self) -> Result<W, IntoInnerError<LineWriter<W>>> {
         self.inner.into_inner().map_err(|IntoInnerError(buf, e)| {
-            IntoInnerError(LineWriter { inner: buf }, e)
+            IntoInnerError(LineWriter {
+                inner: buf,
+                need_flush: false,
+            }, e)
         })
     }
 }
@@ -767,20 +774,46 @@ impl<W: Write> LineWriter<W> {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<W: Write> Write for LineWriter<W> {
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
-        match memchr::memrchr(b'\n', buf) {
-            Some(i) => {
-                let n = self.inner.write(&buf[..i + 1])?;
-                if n != i + 1 || self.inner.flush().is_err() {
-                    // Do not return errors on partial writes.
-                    return Ok(n);
-                }
-                self.inner.write(&buf[i + 1..]).map(|i| n + i)
-            }
-            None => self.inner.write(buf),
+        if self.need_flush {
+            self.flush()?;
+        }
+
+        // Find the last newline character in the buffer provided. If found then
+        // we're going to write all the data up to that point and then flush,
+        // otherewise we just write the whole block to the underlying writer.
+        let i = match memchr::memrchr(b'\n', buf) {
+            Some(i) => i,
+            None => return self.inner.write(buf),
+        };
+
+
+        // Ok, we're going to write a partial amount of the data given first
+        // followed by flushing the newline. After we've successfully written
+        // some data then we *must* report that we wrote that data, so future
+        // errors are ignored. We set our internal `need_flush` flag, though, in
+        // case flushing fails and we need to try it first next time.
+        let n = self.inner.write(&buf[..i + 1])?;
+        self.need_flush = true;
+        if self.flush().is_err() || n != i + 1 {
+            return Ok(n)
+        }
+
+        // At this point we successfully wrote `i + 1` bytes and flushed it out,
+        // meaning that the entire line is now flushed out on the screen. While
+        // we can attempt to finish writing the rest of the data provided.
+        // Remember though that we ignore errors here as we've successfully
+        // written data, so we need to report that.
+        match self.inner.write(&buf[i + 1..]) {
+            Ok(i) => Ok(n + i),
+            Err(_) => Ok(n),
         }
     }
 
-    fn flush(&mut self) -> io::Result<()> { self.inner.flush() }
+    fn flush(&mut self) -> io::Result<()> {
+        self.inner.flush()?;
+        self.need_flush = false;
+        Ok(())
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -1153,4 +1186,44 @@ mod tests {
             BufWriter::new(io::sink())
         });
     }
+
+    struct AcceptOneThenFail {
+        written: bool,
+        flushed: bool,
+    }
+
+    impl Write for AcceptOneThenFail {
+        fn write(&mut self, data: &[u8]) -> io::Result<usize> {
+            if !self.written {
+                assert_eq!(data, b"a\nb\n");
+                self.written = true;
+                Ok(data.len())
+            } else {
+                Err(io::Error::new(io::ErrorKind::NotFound, "test"))
+            }
+        }
+
+        fn flush(&mut self) -> io::Result<()> {
+            assert!(self.written);
+            assert!(!self.flushed);
+            self.flushed = true;
+            Err(io::Error::new(io::ErrorKind::Other, "test"))
+        }
+    }
+
+    #[test]
+    fn erroneous_flush_retried() {
+        let a = AcceptOneThenFail {
+            written: false,
+            flushed: false,
+        };
+
+        let mut l = LineWriter::new(a);
+        assert_eq!(l.write(b"a\nb\na").unwrap(), 4);
+        assert!(l.get_ref().written);
+        assert!(l.get_ref().flushed);
+        l.get_mut().flushed = false;
+
+        assert_eq!(l.write(b"a").unwrap_err().kind(), io::ErrorKind::Other)
+    }
 }
diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs
index b3b89213df1..5450a10c9bd 100644
--- a/src/libstd/io/mod.rs
+++ b/src/libstd/io/mod.rs
@@ -1425,6 +1425,12 @@ pub trait BufRead: Read {
     ///     println!("{}", line.unwrap());
     /// }
     /// ```
+    ///
+    /// # Errors
+    ///
+    /// Each line of the iterator has the same error semantics as [`BufRead::read_line()`].
+    ///
+    /// [`BufRead::read_line()`]: trait.BufRead.html#method.read_line
     #[stable(feature = "rust1", since = "1.0.0")]
     fn lines(self) -> Lines<Self> where Self: Sized {
         Lines { buf: self }
@@ -1444,6 +1450,16 @@ pub struct Chain<T, U> {
     done_first: bool,
 }
 
+#[stable(feature = "std_debug", since = "1.15.0")]
+impl<T: fmt::Debug, U: fmt::Debug> fmt::Debug for Chain<T, U> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.debug_struct("Chain")
+            .field("t", &self.first)
+            .field("u", &self.second)
+            .finish()
+    }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: Read, U: Read> Read for Chain<T, U> {
     fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
@@ -1485,6 +1501,7 @@ impl<T: BufRead, U: BufRead> BufRead for Chain<T, U> {
 ///
 /// [`take()`]: trait.Read.html#method.take
 #[stable(feature = "rust1", since = "1.0.0")]
+#[derive(Debug)]
 pub struct Take<T> {
     inner: T,
     limit: u64,
@@ -1526,8 +1543,6 @@ impl<T> Take<T> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(io_take_into_inner)]
-    ///
     /// use std::io;
     /// use std::io::prelude::*;
     /// use std::fs::File;
@@ -1543,7 +1558,7 @@ impl<T> Take<T> {
     /// # Ok(())
     /// # }
     /// ```
-    #[unstable(feature = "io_take_into_inner", issue = "23755")]
+    #[stable(feature = "io_take_into_inner", since = "1.15.0")]
     pub fn into_inner(self) -> T {
         self.inner
     }
@@ -1604,6 +1619,7 @@ fn read_one_byte(reader: &mut Read) -> Option<Result<u8>> {
 ///
 /// [`bytes()`]: trait.Read.html#method.bytes
 #[stable(feature = "rust1", since = "1.0.0")]
+#[derive(Debug)]
 pub struct Bytes<R> {
     inner: R,
 }
@@ -1625,6 +1641,7 @@ impl<R: Read> Iterator for Bytes<R> {
 /// [chars]: trait.Read.html#method.chars
 #[unstable(feature = "io", reason = "awaiting stability of Read::chars",
            issue = "27802")]
+#[derive(Debug)]
 pub struct Chars<R> {
     inner: R,
 }
@@ -1714,6 +1731,7 @@ impl fmt::Display for CharsError {
 ///
 /// [split]: trait.BufRead.html#method.split
 #[stable(feature = "rust1", since = "1.0.0")]
+#[derive(Debug)]
 pub struct Split<B> {
     buf: B,
     delim: u8,
@@ -1745,6 +1763,7 @@ impl<B: BufRead> Iterator for Split<B> {
 ///
 /// [lines]: trait.BufRead.html#method.lines
 #[stable(feature = "rust1", since = "1.0.0")]
+#[derive(Debug)]
 pub struct Lines<B> {
     buf: B,
 }
diff --git a/src/libstd/io/stdio.rs b/src/libstd/io/stdio.rs
index e8b812daed8..9d1c8942f8c 100644
--- a/src/libstd/io/stdio.rs
+++ b/src/libstd/io/stdio.rs
@@ -10,7 +10,7 @@
 
 use io::prelude::*;
 
-use cell::{RefCell, BorrowState};
+use cell::RefCell;
 use fmt;
 use io::lazy::Lazy;
 use io::{self, BufReader, LineWriter};
@@ -81,11 +81,11 @@ impl Read for StdinRaw {
 }
 impl Write for StdoutRaw {
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> { self.0.write(buf) }
-    fn flush(&mut self) -> io::Result<()> { Ok(()) }
+    fn flush(&mut self) -> io::Result<()> { self.0.flush() }
 }
 impl Write for StderrRaw {
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> { self.0.write(buf) }
-    fn flush(&mut self) -> io::Result<()> { Ok(()) }
+    fn flush(&mut self) -> io::Result<()> { self.0.flush() }
 }
 
 enum Maybe<T> {
@@ -282,6 +282,13 @@ impl Stdin {
     }
 }
 
+#[stable(feature = "std_debug", since = "1.15.0")]
+impl fmt::Debug for Stdin {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.pad("Stdin { .. }")
+    }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl Read for Stdin {
     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
@@ -314,6 +321,13 @@ impl<'a> BufRead for StdinLock<'a> {
     fn consume(&mut self, n: usize) { self.inner.consume(n) }
 }
 
+#[stable(feature = "std_debug", since = "1.15.0")]
+impl<'a> fmt::Debug for StdinLock<'a> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.pad("StdinLock { .. }")
+    }
+}
+
 /// A handle to the global standard output stream of the current process.
 ///
 /// Each handle shares a global buffer of data to be written to the standard
@@ -424,6 +438,13 @@ impl Stdout {
     }
 }
 
+#[stable(feature = "std_debug", since = "1.15.0")]
+impl fmt::Debug for Stdout {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.pad("Stdout { .. }")
+    }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl Write for Stdout {
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
@@ -449,6 +470,13 @@ impl<'a> Write for StdoutLock<'a> {
     }
 }
 
+#[stable(feature = "std_debug", since = "1.15.0")]
+impl<'a> fmt::Debug for StdoutLock<'a> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.pad("StdoutLock { .. }")
+    }
+}
+
 /// A handle to the standard error stream of a process.
 ///
 /// For more information, see the [`io::stderr`] method.
@@ -545,6 +573,13 @@ impl Stderr {
     }
 }
 
+#[stable(feature = "std_debug", since = "1.15.0")]
+impl fmt::Debug for Stderr {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.pad("Stderr { .. }")
+    }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl Write for Stderr {
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
@@ -570,6 +605,13 @@ impl<'a> Write for StderrLock<'a> {
     }
 }
 
+#[stable(feature = "std_debug", since = "1.15.0")]
+impl<'a> fmt::Debug for StderrLock<'a> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.pad("StderrLock { .. }")
+    }
+}
+
 /// Resets the thread-local stderr handle to the specified writer
 ///
 /// This will replace the current thread's stderr handle, returning the old
@@ -638,8 +680,8 @@ pub fn _print(args: fmt::Arguments) {
         LocalKeyState::Destroyed => stdout().write_fmt(args),
         LocalKeyState::Valid => {
             LOCAL_STDOUT.with(|s| {
-                if s.borrow_state() == BorrowState::Unused {
-                    if let Some(w) = s.borrow_mut().as_mut() {
+                if let Ok(mut borrowed) = s.try_borrow_mut() {
+                    if let Some(w) = borrowed.as_mut() {
                         return w.write_fmt(args);
                     }
                 }
diff --git a/src/libstd/io/util.rs b/src/libstd/io/util.rs
index 2c6880281b5..436511031ef 100644
--- a/src/libstd/io/util.rs
+++ b/src/libstd/io/util.rs
@@ -10,6 +10,7 @@
 
 #![allow(missing_copy_implementations)]
 
+use fmt;
 use io::{self, Read, Write, ErrorKind, BufRead};
 
 /// Copies the entire contents of a reader into a writer.
@@ -97,6 +98,13 @@ impl BufRead for Empty {
     fn consume(&mut self, _n: usize) {}
 }
 
+#[stable(feature = "std_debug", since = "1.15.0")]
+impl fmt::Debug for Empty {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.pad("Empty { .. }")
+    }
+}
+
 /// A reader which yields one byte over and over and over and over and over and...
 ///
 /// This struct is generally created by calling [`repeat()`][repeat]. Please
@@ -133,6 +141,13 @@ impl Read for Repeat {
     }
 }
 
+#[stable(feature = "std_debug", since = "1.15.0")]
+impl fmt::Debug for Repeat {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.pad("Repeat { .. }")
+    }
+}
+
 /// A writer which will move data into the void.
 ///
 /// This struct is generally created by calling [`sink()`][sink]. Please
@@ -165,6 +180,13 @@ impl Write for Sink {
     fn flush(&mut self) -> io::Result<()> { Ok(()) }
 }
 
+#[stable(feature = "std_debug", since = "1.15.0")]
+impl fmt::Debug for Sink {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.pad("Sink { .. }")
+    }
+}
+
 #[cfg(test)]
 mod tests {
     use io::prelude::*;
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index 414f25fa5eb..fc5c6968544 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -214,6 +214,7 @@
 #![no_std]
 
 #![deny(missing_docs)]
+#![deny(missing_debug_implementations)]
 
 // Tell the compiler to link to either panic_abort or panic_unwind
 #![needs_panic_runtime]
@@ -276,6 +277,7 @@
 #![feature(panic_unwind)]
 #![feature(placement_in_syntax)]
 #![feature(prelude_import)]
+#![feature(pub_restricted)]
 #![feature(rand)]
 #![feature(raw)]
 #![feature(repr_simd)]
diff --git a/src/libstd/net/ip.rs b/src/libstd/net/ip.rs
index c1e610f33fb..6aab7486004 100644
--- a/src/libstd/net/ip.rs
+++ b/src/libstd/net/ip.rs
@@ -1068,6 +1068,14 @@ impl From<[u8; 16]> for Ipv6Addr {
     }
 }
 
+#[stable(feature = "ipv6_from_segments", since = "1.15.0")]
+impl From<[u16; 8]> for Ipv6Addr {
+    fn from(segments: [u16; 8]) -> Ipv6Addr {
+        let [a, b, c, d, e, f, g, h] = segments;
+        Ipv6Addr::new(a, b, c, d, e, f, g, h)
+    }
+}
+
 // Tests for this module
 #[cfg(all(test, not(target_os = "emscripten")))]
 mod tests {
@@ -1413,11 +1421,29 @@ mod tests {
     }
 
     #[test]
-    fn ipv4_from_u32_slice() {
+    fn ipv4_from_octets() {
         assert_eq!(Ipv4Addr::from([127, 0, 0, 1]), Ipv4Addr::new(127, 0, 0, 1))
     }
 
     #[test]
+    fn ipv6_from_segments() {
+        let from_u16s = Ipv6Addr::from([0x0011, 0x2233, 0x4455, 0x6677,
+                                        0x8899, 0xaabb, 0xccdd, 0xeeff]);
+        let new = Ipv6Addr::new(0x0011, 0x2233, 0x4455, 0x6677,
+                                0x8899, 0xaabb, 0xccdd, 0xeeff);
+        assert_eq!(new, from_u16s);
+    }
+
+    #[test]
+    fn ipv6_from_octets() {
+        let from_u16s = Ipv6Addr::from([0x0011, 0x2233, 0x4455, 0x6677,
+                                        0x8899, 0xaabb, 0xccdd, 0xeeff]);
+        let from_u8s = Ipv6Addr::from([0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+                                       0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff]);
+        assert_eq!(from_u16s, from_u8s);
+    }
+
+    #[test]
     fn ord() {
         assert!(Ipv4Addr::new(100, 64, 3, 3) < Ipv4Addr::new(192, 0, 2, 2));
         assert!("2001:db8:f00::1002".parse::<Ipv6Addr>().unwrap() <
diff --git a/src/libstd/net/mod.rs b/src/libstd/net/mod.rs
index 56286fbe253..cadf87f32b1 100644
--- a/src/libstd/net/mod.rs
+++ b/src/libstd/net/mod.rs
@@ -12,6 +12,7 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
+use fmt;
 use io::{self, Error, ErrorKind};
 use sys_common::net as net_imp;
 
@@ -105,6 +106,13 @@ impl Iterator for LookupHost {
     fn next(&mut self) -> Option<SocketAddr> { self.0.next() }
 }
 
+#[stable(feature = "std_debug", since = "1.15.0")]
+impl fmt::Debug for LookupHost {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.pad("LookupHost { .. }")
+    }
+}
+
 /// Resolve the host specified by `host` as a number of `SocketAddr` instances.
 ///
 /// This method may perform a DNS query to resolve `host` and may also inspect
diff --git a/src/libstd/net/tcp.rs b/src/libstd/net/tcp.rs
index be9636a0a19..63817c9f10f 100644
--- a/src/libstd/net/tcp.rs
+++ b/src/libstd/net/tcp.rs
@@ -76,6 +76,7 @@ pub struct TcpListener(net_imp::TcpListener);
 /// [`incoming`]: struct.TcpListener.html#method.incoming
 /// [`TcpListener`]: struct.TcpListener.html
 #[stable(feature = "rust1", since = "1.0.0")]
+#[derive(Debug)]
 pub struct Incoming<'a> { listener: &'a TcpListener }
 
 impl TcpStream {
diff --git a/src/libstd/net/udp.rs b/src/libstd/net/udp.rs
index b280f466dd4..f8a5ec0b379 100644
--- a/src/libstd/net/udp.rs
+++ b/src/libstd/net/udp.rs
@@ -499,6 +499,19 @@ impl UdpSocket {
     /// This will retrieve the stored error in the underlying socket, clearing
     /// the field in the process. This can be useful for checking errors between
     /// calls.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::net::UdpSocket;
+    ///
+    /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
+    /// match socket.take_error() {
+    ///     Ok(Some(error)) => println!("UdpSocket error: {:?}", error),
+    ///     Ok(None) => println!("No error"),
+    ///     Err(error) => println!("UdpSocket.take_error failed: {:?}", error),
+    /// }
+    /// ```
     #[stable(feature = "net2_mutators", since = "1.9.0")]
     pub fn take_error(&self) -> io::Result<Option<io::Error>> {
         self.0.take_error()
@@ -507,6 +520,15 @@ impl UdpSocket {
     /// Connects this UDP socket to a remote address, allowing the `send` and
     /// `recv` syscalls to be used to send data and also applies filters to only
     /// receive data from the specified address.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::net::UdpSocket;
+    ///
+    /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
+    /// socket.connect("127.0.0.1:8080").expect("connect function failed");
+    /// ```
     #[stable(feature = "net2_mutators", since = "1.9.0")]
     pub fn connect<A: ToSocketAddrs>(&self, addr: A) -> io::Result<()> {
         super::each_addr(addr, |addr| self.0.connect(addr))
@@ -514,8 +536,20 @@ impl UdpSocket {
 
     /// Sends data on the socket to the remote address to which it is connected.
     ///
-    /// The `connect` method will connect this socket to a remote address. This
+    /// The [`connect()`] method will connect this socket to a remote address. This
     /// method will fail if the socket is not connected.
+    ///
+    /// [`connect()`]: #method.connect
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::net::UdpSocket;
+    ///
+    /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
+    /// socket.connect("127.0.0.1:8080").expect("connect function failed");
+    /// socket.send(&[0, 1, 2]).expect("couldn't send message");
+    /// ```
     #[stable(feature = "net2_mutators", since = "1.9.0")]
     pub fn send(&self, buf: &[u8]) -> io::Result<usize> {
         self.0.send(buf)
@@ -526,6 +560,20 @@ impl UdpSocket {
     ///
     /// The `connect` method will connect this socket to a remote address. This
     /// method will fail if the socket is not connected.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::net::UdpSocket;
+    ///
+    /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
+    /// socket.connect("127.0.0.1:8080").expect("connect function failed");
+    /// let mut buf = [0; 10];
+    /// match socket.recv(&mut buf) {
+    ///     Ok(received) => println!("received {} bytes", received),
+    ///     Err(e) => println!("recv function failed: {:?}", e),
+    /// }
+    /// ```
     #[stable(feature = "net2_mutators", since = "1.9.0")]
     pub fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
         self.0.recv(buf)
@@ -535,6 +583,15 @@ impl UdpSocket {
     ///
     /// On Unix this corresponds to calling fcntl, and on Windows this
     /// corresponds to calling ioctlsocket.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::net::UdpSocket;
+    ///
+    /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address");
+    /// socket.set_nonblocking(true).expect("set_nonblocking call failed");
+    /// ```
     #[stable(feature = "net2_mutators", since = "1.9.0")]
     pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
         self.0.set_nonblocking(nonblocking)
diff --git a/src/libstd/os/linux/raw.rs b/src/libstd/os/linux/raw.rs
index e6a95bc831f..7c9274d0601 100644
--- a/src/libstd/os/linux/raw.rs
+++ b/src/libstd/os/linux/raw.rs
@@ -17,6 +17,7 @@
                               crates.io should be used instead for the correct \
                               definitions")]
 #![allow(deprecated)]
+#![allow(missing_debug_implementations)]
 
 use os::raw::c_ulong;
 
diff --git a/src/libstd/os/mod.rs b/src/libstd/os/mod.rs
index 366a1674156..e45af867055 100644
--- a/src/libstd/os/mod.rs
+++ b/src/libstd/os/mod.rs
@@ -11,9 +11,9 @@
 //! OS-specific functionality.
 
 #![stable(feature = "os", since = "1.0.0")]
-#![allow(missing_docs, bad_style)]
+#![allow(missing_docs, bad_style, missing_debug_implementations)]
 
-#[cfg(unix)]
+#[cfg(any(target_os = "redox", unix))]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use sys::ext as unix;
 #[cfg(windows)]
diff --git a/src/libstd/os/raw.rs b/src/libstd/os/raw.rs
index 2a918d8aeb7..cc154f7ab41 100644
--- a/src/libstd/os/raw.rs
+++ b/src/libstd/os/raw.rs
@@ -12,6 +12,8 @@
 
 #![stable(feature = "raw_os", since = "1.1.0")]
 
+use fmt;
+
 #[cfg(any(target_os = "android",
           target_os = "emscripten",
           all(target_os = "linux", any(target_arch = "aarch64",
@@ -71,6 +73,13 @@ pub enum c_void {
     #[doc(hidden)] __variant2,
 }
 
+#[stable(feature = "std_debug", since = "1.15.0")]
+impl fmt::Debug for c_void {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.pad("c_void")
+    }
+}
+
 #[cfg(test)]
 #[allow(unused_imports)]
 mod tests {
diff --git a/src/libstd/panic.rs b/src/libstd/panic.rs
index a7e8c4fab37..faf4949e861 100644
--- a/src/libstd/panic.rs
+++ b/src/libstd/panic.rs
@@ -14,6 +14,7 @@
 
 use any::Any;
 use cell::UnsafeCell;
+use fmt;
 use ops::{Deref, DerefMut};
 use panicking;
 use ptr::{Unique, Shared};
@@ -296,6 +297,15 @@ impl<R, F: FnOnce() -> R> FnOnce<()> for AssertUnwindSafe<F> {
     }
 }
 
+#[stable(feature = "std_debug", since = "1.15.0")]
+impl<T: fmt::Debug> fmt::Debug for AssertUnwindSafe<T> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.debug_tuple("AssertUnwindSafe")
+            .field(&self.0)
+            .finish()
+    }
+}
+
 /// Invokes a closure, capturing the cause of an unwinding panic if one occurs.
 ///
 /// This function will return `Ok` with the closure's result if the closure
diff --git a/src/libstd/panicking.rs b/src/libstd/panicking.rs
index 45a10d24528..e5edea241e1 100644
--- a/src/libstd/panicking.rs
+++ b/src/libstd/panicking.rs
@@ -177,6 +177,7 @@ pub fn take_hook() -> Box<Fn(&PanicInfo) + 'static + Sync + Send> {
 /// panic!("Normal panic");
 /// ```
 #[stable(feature = "panic_hooks", since = "1.10.0")]
+#[derive(Debug)]
 pub struct PanicInfo<'a> {
     payload: &'a (Any + Send),
     location: Location<'a>,
@@ -256,6 +257,7 @@ impl<'a> PanicInfo<'a> {
 ///
 /// panic!("Normal panic");
 /// ```
+#[derive(Debug)]
 #[stable(feature = "panic_hooks", since = "1.10.0")]
 pub struct Location<'a> {
     file: &'a str,
diff --git a/src/libstd/process.rs b/src/libstd/process.rs
index 858537dd2de..e15c37aaf24 100644
--- a/src/libstd/process.rs
+++ b/src/libstd/process.rs
@@ -114,6 +114,17 @@ impl IntoInner<imp::Process> for Child {
     fn into_inner(self) -> imp::Process { self.handle }
 }
 
+#[stable(feature = "std_debug", since = "1.15.0")]
+impl fmt::Debug for Child {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.debug_struct("Child")
+            .field("stdin", &self.stdin)
+            .field("stdout", &self.stdout)
+            .field("stderr", &self.stderr)
+            .finish()
+    }
+}
+
 /// A handle to a child process's stdin. This struct is used in the [`stdin`]
 /// field on [`Child`].
 ///
@@ -149,6 +160,13 @@ impl FromInner<AnonPipe> for ChildStdin {
     }
 }
 
+#[stable(feature = "std_debug", since = "1.15.0")]
+impl fmt::Debug for ChildStdin {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.pad("ChildStdin { .. }")
+    }
+}
+
 /// A handle to a child process's stdout. This struct is used in the [`stdout`]
 /// field on [`Child`].
 ///
@@ -183,6 +201,13 @@ impl FromInner<AnonPipe> for ChildStdout {
     }
 }
 
+#[stable(feature = "std_debug", since = "1.15.0")]
+impl fmt::Debug for ChildStdout {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.pad("ChildStdout { .. }")
+    }
+}
+
 /// A handle to a child process's stderr. This struct is used in the [`stderr`]
 /// field on [`Child`].
 ///
@@ -217,6 +242,13 @@ impl FromInner<AnonPipe> for ChildStderr {
     }
 }
 
+#[stable(feature = "std_debug", since = "1.15.0")]
+impl fmt::Debug for ChildStderr {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.pad("ChildStderr { .. }")
+    }
+}
+
 /// A process builder, providing fine-grained control
 /// over how a new process should be spawned.
 ///
@@ -622,6 +654,13 @@ impl FromInner<imp::Stdio> for Stdio {
     }
 }
 
+#[stable(feature = "std_debug", since = "1.15.0")]
+impl fmt::Debug for Stdio {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.pad("Stdio { .. }")
+    }
+}
+
 /// Describes the result of a process after it has terminated.
 #[derive(PartialEq, Eq, Clone, Copy, Debug)]
 #[stable(feature = "process", since = "1.0.0")]
@@ -828,6 +867,12 @@ impl Child {
 /// this function at a known point where there are no more destructors left
 /// to run.
 ///
+/// ## Platform-specific behavior
+///
+/// **Unix**: On Unix-like platforms, it is unlikely that all 32 bits of `exit`
+/// will be visible to a parent process inspecting the exit code. On most
+/// Unix-like platforms, only the eight least-significant bits are considered.
+///
 /// # Examples
 ///
 /// ```
@@ -835,6 +880,17 @@ impl Child {
 ///
 /// process::exit(0);
 /// ```
+///
+/// Due to [platform-specific behavior], the exit code for this example will be
+/// `0` on Linux, but `256` on Windows:
+///
+/// ```no_run
+/// use std::process;
+///
+/// process::exit(0x0f00);
+/// ```
+///
+/// [platform-specific behavior]: #platform-specific-behavior
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn exit(code: i32) -> ! {
     ::sys_common::cleanup();
diff --git a/src/libstd/rand/mod.rs b/src/libstd/rand/mod.rs
index f48325218fb..b853e83de5d 100644
--- a/src/libstd/rand/mod.rs
+++ b/src/libstd/rand/mod.rs
@@ -59,6 +59,7 @@
 #![unstable(feature = "rand", issue = "0")]
 
 use cell::RefCell;
+use fmt;
 use io;
 use mem;
 use rc::Rc;
@@ -143,6 +144,12 @@ pub struct ThreadRng {
     rng: Rc<RefCell<ThreadRngInner>>,
 }
 
+impl fmt::Debug for ThreadRng {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.pad("ThreadRng { .. }")
+    }
+}
+
 /// Retrieve the lazily-initialized thread-local random number
 /// generator, seeded by the system. Intended to be used in method
 /// chaining style, e.g. `thread_rng().gen::<isize>()`.
diff --git a/src/libstd/sync/barrier.rs b/src/libstd/sync/barrier.rs
index f46eab68484..b8e83dced8d 100644
--- a/src/libstd/sync/barrier.rs
+++ b/src/libstd/sync/barrier.rs
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use fmt;
 use sync::{Mutex, Condvar};
 
 /// A barrier enables multiple threads to synchronize the beginning
@@ -54,6 +55,13 @@ struct BarrierState {
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct BarrierWaitResult(bool);
 
+#[stable(feature = "std_debug", since = "1.15.0")]
+impl fmt::Debug for Barrier {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.pad("Barrier { .. }")
+    }
+}
+
 impl Barrier {
     /// Creates a new barrier that can block a given number of threads.
     ///
@@ -102,6 +110,15 @@ impl Barrier {
     }
 }
 
+#[stable(feature = "std_debug", since = "1.15.0")]
+impl fmt::Debug for BarrierWaitResult {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.debug_struct("BarrierWaitResult")
+            .field("is_leader", &self.is_leader())
+            .finish()
+    }
+}
+
 impl BarrierWaitResult {
     /// Returns whether this thread from `wait` is the "leader thread".
     ///
diff --git a/src/libstd/sync/condvar.rs b/src/libstd/sync/condvar.rs
index a983ae716a4..8ab30c51b28 100644
--- a/src/libstd/sync/condvar.rs
+++ b/src/libstd/sync/condvar.rs
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use fmt;
 use sync::atomic::{AtomicUsize, Ordering};
 use sync::{mutex, MutexGuard, PoisonError};
 use sys_common::condvar as sys;
@@ -239,6 +240,13 @@ impl Condvar {
     }
 }
 
+#[stable(feature = "std_debug", since = "1.15.0")]
+impl fmt::Debug for Condvar {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.pad("Condvar { .. }")
+    }
+}
+
 #[stable(feature = "condvar_default", since = "1.9.0")]
 impl Default for Condvar {
     /// Creates a `Condvar` which is ready to be waited on and notified.
diff --git a/src/libstd/sync/mpsc/mod.rs b/src/libstd/sync/mpsc/mod.rs
index ca6e46eb15a..aeeab170dea 100644
--- a/src/libstd/sync/mpsc/mod.rs
+++ b/src/libstd/sync/mpsc/mod.rs
@@ -306,6 +306,7 @@ impl<T> !Sync for Receiver<T> { }
 /// whenever `next` is called, waiting for a new message, and `None` will be
 /// returned when the corresponding channel has hung up.
 #[stable(feature = "rust1", since = "1.0.0")]
+#[derive(Debug)]
 pub struct Iter<'a, T: 'a> {
     rx: &'a Receiver<T>
 }
@@ -316,7 +317,8 @@ pub struct Iter<'a, T: 'a> {
 ///
 /// This Iterator will never block the caller in order to wait for data to
 /// become available. Instead, it will return `None`.
-#[unstable(feature = "receiver_try_iter", issue = "34931")]
+#[stable(feature = "receiver_try_iter", since = "1.15.0")]
+#[derive(Debug)]
 pub struct TryIter<'a, T: 'a> {
     rx: &'a Receiver<T>
 }
@@ -325,6 +327,7 @@ pub struct TryIter<'a, T: 'a> {
 /// whenever `next` is called, waiting for a new message, and `None` will be
 /// returned when the corresponding channel has hung up.
 #[stable(feature = "receiver_into_iter", since = "1.1.0")]
+#[derive(Debug)]
 pub struct IntoIter<T> {
     rx: Receiver<T>
 }
@@ -348,7 +351,7 @@ impl<T> !Sync for Sender<T> { }
 /// owned by one thread, but it can be cloned to send to other threads.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct SyncSender<T> {
-    inner: Arc<UnsafeCell<sync::Packet<T>>>,
+    inner: Arc<sync::Packet<T>>,
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -426,10 +429,10 @@ pub enum TrySendError<T> {
 }
 
 enum Flavor<T> {
-    Oneshot(Arc<UnsafeCell<oneshot::Packet<T>>>),
-    Stream(Arc<UnsafeCell<stream::Packet<T>>>),
-    Shared(Arc<UnsafeCell<shared::Packet<T>>>),
-    Sync(Arc<UnsafeCell<sync::Packet<T>>>),
+    Oneshot(Arc<oneshot::Packet<T>>),
+    Stream(Arc<stream::Packet<T>>),
+    Shared(Arc<shared::Packet<T>>),
+    Sync(Arc<sync::Packet<T>>),
 }
 
 #[doc(hidden)]
@@ -454,10 +457,16 @@ impl<T> UnsafeFlavor<T> for Receiver<T> {
 }
 
 /// Creates a new asynchronous channel, returning the sender/receiver halves.
-///
 /// All data sent on the sender will become available on the receiver, and no
 /// send will block the calling thread (this channel has an "infinite buffer").
 ///
+/// If the [`Receiver`] is disconnected while trying to [`send()`] with the
+/// [`Sender`], the [`send()`] method will return an error.
+///
+/// [`send()`]: ../../../std/sync/mpsc/struct.Sender.html#method.send
+/// [`Sender`]: ../../../std/sync/mpsc/struct.Sender.html
+/// [`Receiver`]: ../../../std/sync/mpsc/struct.Receiver.html
+///
 /// # Examples
 ///
 /// ```
@@ -481,24 +490,29 @@ impl<T> UnsafeFlavor<T> for Receiver<T> {
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn channel<T>() -> (Sender<T>, Receiver<T>) {
-    let a = Arc::new(UnsafeCell::new(oneshot::Packet::new()));
+    let a = Arc::new(oneshot::Packet::new());
     (Sender::new(Flavor::Oneshot(a.clone())), Receiver::new(Flavor::Oneshot(a)))
 }
 
 /// Creates a new synchronous, bounded channel.
 ///
-/// Like asynchronous channels, the `Receiver` will block until a message
+/// Like asynchronous channels, the [`Receiver`] will block until a message
 /// becomes available. These channels differ greatly in the semantics of the
 /// sender from asynchronous channels, however.
 ///
-/// This channel has an internal buffer on which messages will be queued. `bound`
-/// specifies the buffer size. When the internal buffer becomes full, future sends
-/// will *block* waiting for the buffer to open up. Note that a buffer size of 0
-/// is valid, in which case this becomes  "rendezvous channel" where each send will
-/// not return until a recv is paired with it.
+/// This channel has an internal buffer on which messages will be queued.
+/// `bound` specifies the buffer size. When the internal buffer becomes full,
+/// future sends will *block* waiting for the buffer to open up. Note that a
+/// buffer size of 0 is valid, in which case this becomes "rendezvous channel"
+/// where each [`send()`] will not return until a recv is paired with it.
 ///
-/// As with asynchronous channels, all senders will panic in `send` if the
-/// `Receiver` has been destroyed.
+/// Like asynchronous channels, if the [`Receiver`] is disconnected while
+/// trying to [`send()`] with the [`SyncSender`], the [`send()`] method will
+/// return an error.
+///
+/// [`send()`]: ../../../std/sync/mpsc/struct.SyncSender.html#method.send
+/// [`SyncSender`]: ../../../std/sync/mpsc/struct.SyncSender.html
+/// [`Receiver`]: ../../../std/sync/mpsc/struct.Receiver.html
 ///
 /// # Examples
 ///
@@ -521,7 +535,7 @@ pub fn channel<T>() -> (Sender<T>, Receiver<T>) {
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn sync_channel<T>(bound: usize) -> (SyncSender<T>, Receiver<T>) {
-    let a = Arc::new(UnsafeCell::new(sync::Packet::new(bound)));
+    let a = Arc::new(sync::Packet::new(bound));
     (SyncSender::new(a.clone()), Receiver::new(Flavor::Sync(a)))
 }
 
@@ -567,38 +581,30 @@ impl<T> Sender<T> {
     pub fn send(&self, t: T) -> Result<(), SendError<T>> {
         let (new_inner, ret) = match *unsafe { self.inner() } {
             Flavor::Oneshot(ref p) => {
-                unsafe {
-                    let p = p.get();
-                    if !(*p).sent() {
-                        return (*p).send(t).map_err(SendError);
-                    } else {
-                        let a =
-                            Arc::new(UnsafeCell::new(stream::Packet::new()));
-                        let rx = Receiver::new(Flavor::Stream(a.clone()));
-                        match (*p).upgrade(rx) {
-                            oneshot::UpSuccess => {
-                                let ret = (*a.get()).send(t);
-                                (a, ret)
-                            }
-                            oneshot::UpDisconnected => (a, Err(t)),
-                            oneshot::UpWoke(token) => {
-                                // This send cannot panic because the thread is
-                                // asleep (we're looking at it), so the receiver
-                                // can't go away.
-                                (*a.get()).send(t).ok().unwrap();
-                                token.signal();
-                                (a, Ok(()))
-                            }
+                if !p.sent() {
+                    return p.send(t).map_err(SendError);
+                } else {
+                    let a = Arc::new(stream::Packet::new());
+                    let rx = Receiver::new(Flavor::Stream(a.clone()));
+                    match p.upgrade(rx) {
+                        oneshot::UpSuccess => {
+                            let ret = a.send(t);
+                            (a, ret)
+                        }
+                        oneshot::UpDisconnected => (a, Err(t)),
+                        oneshot::UpWoke(token) => {
+                            // This send cannot panic because the thread is
+                            // asleep (we're looking at it), so the receiver
+                            // can't go away.
+                            a.send(t).ok().unwrap();
+                            token.signal();
+                            (a, Ok(()))
                         }
                     }
                 }
             }
-            Flavor::Stream(ref p) => return unsafe {
-                (*p.get()).send(t).map_err(SendError)
-            },
-            Flavor::Shared(ref p) => return unsafe {
-                (*p.get()).send(t).map_err(SendError)
-            },
+            Flavor::Stream(ref p) => return p.send(t).map_err(SendError),
+            Flavor::Shared(ref p) => return p.send(t).map_err(SendError),
             Flavor::Sync(..) => unreachable!(),
         };
 
@@ -613,41 +619,43 @@ impl<T> Sender<T> {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> Clone for Sender<T> {
     fn clone(&self) -> Sender<T> {
-        let (packet, sleeper, guard) = match *unsafe { self.inner() } {
+        let packet = match *unsafe { self.inner() } {
             Flavor::Oneshot(ref p) => {
-                let a = Arc::new(UnsafeCell::new(shared::Packet::new()));
-                unsafe {
-                    let guard = (*a.get()).postinit_lock();
+                let a = Arc::new(shared::Packet::new());
+                {
+                    let guard = a.postinit_lock();
                     let rx = Receiver::new(Flavor::Shared(a.clone()));
-                    match (*p.get()).upgrade(rx) {
+                    let sleeper = match p.upgrade(rx) {
                         oneshot::UpSuccess |
-                        oneshot::UpDisconnected => (a, None, guard),
-                        oneshot::UpWoke(task) => (a, Some(task), guard)
-                    }
+                        oneshot::UpDisconnected => None,
+                        oneshot::UpWoke(task) => Some(task),
+                    };
+                    a.inherit_blocker(sleeper, guard);
                 }
+                a
             }
             Flavor::Stream(ref p) => {
-                let a = Arc::new(UnsafeCell::new(shared::Packet::new()));
-                unsafe {
-                    let guard = (*a.get()).postinit_lock();
+                let a = Arc::new(shared::Packet::new());
+                {
+                    let guard = a.postinit_lock();
                     let rx = Receiver::new(Flavor::Shared(a.clone()));
-                    match (*p.get()).upgrade(rx) {
+                    let sleeper = match p.upgrade(rx) {
                         stream::UpSuccess |
-                        stream::UpDisconnected => (a, None, guard),
-                        stream::UpWoke(task) => (a, Some(task), guard),
-                    }
+                        stream::UpDisconnected => None,
+                        stream::UpWoke(task) => Some(task),
+                    };
+                    a.inherit_blocker(sleeper, guard);
                 }
+                a
             }
             Flavor::Shared(ref p) => {
-                unsafe { (*p.get()).clone_chan(); }
+                p.clone_chan();
                 return Sender::new(Flavor::Shared(p.clone()));
             }
             Flavor::Sync(..) => unreachable!(),
         };
 
         unsafe {
-            (*packet.get()).inherit_blocker(sleeper, guard);
-
             let tmp = Sender::new(Flavor::Shared(packet.clone()));
             mem::swap(self.inner_mut(), tmp.inner_mut());
         }
@@ -658,10 +666,10 @@ impl<T> Clone for Sender<T> {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> Drop for Sender<T> {
     fn drop(&mut self) {
-        match *unsafe { self.inner_mut() } {
-            Flavor::Oneshot(ref mut p) => unsafe { (*p.get()).drop_chan(); },
-            Flavor::Stream(ref mut p) => unsafe { (*p.get()).drop_chan(); },
-            Flavor::Shared(ref mut p) => unsafe { (*p.get()).drop_chan(); },
+        match *unsafe { self.inner() } {
+            Flavor::Oneshot(ref p) => p.drop_chan(),
+            Flavor::Stream(ref p) => p.drop_chan(),
+            Flavor::Shared(ref p) => p.drop_chan(),
             Flavor::Sync(..) => unreachable!(),
         }
     }
@@ -679,7 +687,7 @@ impl<T> fmt::Debug for Sender<T> {
 ////////////////////////////////////////////////////////////////////////////////
 
 impl<T> SyncSender<T> {
-    fn new(inner: Arc<UnsafeCell<sync::Packet<T>>>) -> SyncSender<T> {
+    fn new(inner: Arc<sync::Packet<T>>) -> SyncSender<T> {
         SyncSender { inner: inner }
     }
 
@@ -699,7 +707,7 @@ impl<T> SyncSender<T> {
     /// information.
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn send(&self, t: T) -> Result<(), SendError<T>> {
-        unsafe { (*self.inner.get()).send(t).map_err(SendError) }
+        self.inner.send(t).map_err(SendError)
     }
 
     /// Attempts to send a value on this channel without blocking.
@@ -713,14 +721,14 @@ impl<T> SyncSender<T> {
     /// receiver has received the data or not if this function is successful.
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn try_send(&self, t: T) -> Result<(), TrySendError<T>> {
-        unsafe { (*self.inner.get()).try_send(t) }
+        self.inner.try_send(t)
     }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> Clone for SyncSender<T> {
     fn clone(&self) -> SyncSender<T> {
-        unsafe { (*self.inner.get()).clone_chan(); }
+        self.inner.clone_chan();
         SyncSender::new(self.inner.clone())
     }
 }
@@ -728,7 +736,7 @@ impl<T> Clone for SyncSender<T> {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> Drop for SyncSender<T> {
     fn drop(&mut self) {
-        unsafe { (*self.inner.get()).drop_chan(); }
+        self.inner.drop_chan();
     }
 }
 
@@ -761,7 +769,7 @@ impl<T> Receiver<T> {
         loop {
             let new_port = match *unsafe { self.inner() } {
                 Flavor::Oneshot(ref p) => {
-                    match unsafe { (*p.get()).try_recv() } {
+                    match p.try_recv() {
                         Ok(t) => return Ok(t),
                         Err(oneshot::Empty) => return Err(TryRecvError::Empty),
                         Err(oneshot::Disconnected) => {
@@ -771,7 +779,7 @@ impl<T> Receiver<T> {
                     }
                 }
                 Flavor::Stream(ref p) => {
-                    match unsafe { (*p.get()).try_recv() } {
+                    match p.try_recv() {
                         Ok(t) => return Ok(t),
                         Err(stream::Empty) => return Err(TryRecvError::Empty),
                         Err(stream::Disconnected) => {
@@ -781,7 +789,7 @@ impl<T> Receiver<T> {
                     }
                 }
                 Flavor::Shared(ref p) => {
-                    match unsafe { (*p.get()).try_recv() } {
+                    match p.try_recv() {
                         Ok(t) => return Ok(t),
                         Err(shared::Empty) => return Err(TryRecvError::Empty),
                         Err(shared::Disconnected) => {
@@ -790,7 +798,7 @@ impl<T> Receiver<T> {
                     }
                 }
                 Flavor::Sync(ref p) => {
-                    match unsafe { (*p.get()).try_recv() } {
+                    match p.try_recv() {
                         Ok(t) => return Ok(t),
                         Err(sync::Empty) => return Err(TryRecvError::Empty),
                         Err(sync::Disconnected) => {
@@ -864,7 +872,7 @@ impl<T> Receiver<T> {
         loop {
             let new_port = match *unsafe { self.inner() } {
                 Flavor::Oneshot(ref p) => {
-                    match unsafe { (*p.get()).recv(None) } {
+                    match p.recv(None) {
                         Ok(t) => return Ok(t),
                         Err(oneshot::Disconnected) => return Err(RecvError),
                         Err(oneshot::Upgraded(rx)) => rx,
@@ -872,7 +880,7 @@ impl<T> Receiver<T> {
                     }
                 }
                 Flavor::Stream(ref p) => {
-                    match unsafe { (*p.get()).recv(None) } {
+                    match p.recv(None) {
                         Ok(t) => return Ok(t),
                         Err(stream::Disconnected) => return Err(RecvError),
                         Err(stream::Upgraded(rx)) => rx,
@@ -880,15 +888,13 @@ impl<T> Receiver<T> {
                     }
                 }
                 Flavor::Shared(ref p) => {
-                    match unsafe { (*p.get()).recv(None) } {
+                    match p.recv(None) {
                         Ok(t) => return Ok(t),
                         Err(shared::Disconnected) => return Err(RecvError),
                         Err(shared::Empty) => unreachable!(),
                     }
                 }
-                Flavor::Sync(ref p) => return unsafe {
-                    (*p.get()).recv(None).map_err(|_| RecvError)
-                }
+                Flavor::Sync(ref p) => return p.recv(None).map_err(|_| RecvError),
             };
             unsafe {
                 mem::swap(self.inner_mut(), new_port.inner_mut());
@@ -941,7 +947,7 @@ impl<T> Receiver<T> {
         loop {
             let port_or_empty = match *unsafe { self.inner() } {
                 Flavor::Oneshot(ref p) => {
-                    match unsafe { (*p.get()).recv(Some(deadline)) } {
+                    match p.recv(Some(deadline)) {
                         Ok(t) => return Ok(t),
                         Err(oneshot::Disconnected) => return Err(Disconnected),
                         Err(oneshot::Upgraded(rx)) => Some(rx),
@@ -949,7 +955,7 @@ impl<T> Receiver<T> {
                     }
                 }
                 Flavor::Stream(ref p) => {
-                    match unsafe { (*p.get()).recv(Some(deadline)) } {
+                    match p.recv(Some(deadline)) {
                         Ok(t) => return Ok(t),
                         Err(stream::Disconnected) => return Err(Disconnected),
                         Err(stream::Upgraded(rx)) => Some(rx),
@@ -957,14 +963,14 @@ impl<T> Receiver<T> {
                     }
                 }
                 Flavor::Shared(ref p) => {
-                    match unsafe { (*p.get()).recv(Some(deadline)) } {
+                    match p.recv(Some(deadline)) {
                         Ok(t) => return Ok(t),
                         Err(shared::Disconnected) => return Err(Disconnected),
                         Err(shared::Empty) => None,
                     }
                 }
                 Flavor::Sync(ref p) => {
-                    match unsafe { (*p.get()).recv(Some(deadline)) } {
+                    match p.recv(Some(deadline)) {
                         Ok(t) => return Ok(t),
                         Err(sync::Disconnected) => return Err(Disconnected),
                         Err(sync::Empty) => None,
@@ -997,7 +1003,7 @@ impl<T> Receiver<T> {
     /// It will return `None` if there are no more pending values or if the
     /// channel has hung up. The iterator will never `panic!` or block the
     /// user by waiting for values.
-    #[unstable(feature = "receiver_try_iter", issue = "34931")]
+    #[stable(feature = "receiver_try_iter", since = "1.15.0")]
     pub fn try_iter(&self) -> TryIter<T> {
         TryIter { rx: self }
     }
@@ -1009,23 +1015,19 @@ impl<T> select::Packet for Receiver<T> {
         loop {
             let new_port = match *unsafe { self.inner() } {
                 Flavor::Oneshot(ref p) => {
-                    match unsafe { (*p.get()).can_recv() } {
+                    match p.can_recv() {
                         Ok(ret) => return ret,
                         Err(upgrade) => upgrade,
                     }
                 }
                 Flavor::Stream(ref p) => {
-                    match unsafe { (*p.get()).can_recv() } {
+                    match p.can_recv() {
                         Ok(ret) => return ret,
                         Err(upgrade) => upgrade,
                     }
                 }
-                Flavor::Shared(ref p) => {
-                    return unsafe { (*p.get()).can_recv() };
-                }
-                Flavor::Sync(ref p) => {
-                    return unsafe { (*p.get()).can_recv() };
-                }
+                Flavor::Shared(ref p) => return p.can_recv(),
+                Flavor::Sync(ref p) => return p.can_recv(),
             };
             unsafe {
                 mem::swap(self.inner_mut(),
@@ -1038,25 +1040,21 @@ impl<T> select::Packet for Receiver<T> {
         loop {
             let (t, new_port) = match *unsafe { self.inner() } {
                 Flavor::Oneshot(ref p) => {
-                    match unsafe { (*p.get()).start_selection(token) } {
+                    match p.start_selection(token) {
                         oneshot::SelSuccess => return Installed,
                         oneshot::SelCanceled => return Abort,
                         oneshot::SelUpgraded(t, rx) => (t, rx),
                     }
                 }
                 Flavor::Stream(ref p) => {
-                    match unsafe { (*p.get()).start_selection(token) } {
+                    match p.start_selection(token) {
                         stream::SelSuccess => return Installed,
                         stream::SelCanceled => return Abort,
                         stream::SelUpgraded(t, rx) => (t, rx),
                     }
                 }
-                Flavor::Shared(ref p) => {
-                    return unsafe { (*p.get()).start_selection(token) };
-                }
-                Flavor::Sync(ref p) => {
-                    return unsafe { (*p.get()).start_selection(token) };
-                }
+                Flavor::Shared(ref p) => return p.start_selection(token),
+                Flavor::Sync(ref p) => return p.start_selection(token),
             };
             token = t;
             unsafe {
@@ -1069,16 +1067,10 @@ impl<T> select::Packet for Receiver<T> {
         let mut was_upgrade = false;
         loop {
             let result = match *unsafe { self.inner() } {
-                Flavor::Oneshot(ref p) => unsafe { (*p.get()).abort_selection() },
-                Flavor::Stream(ref p) => unsafe {
-                    (*p.get()).abort_selection(was_upgrade)
-                },
-                Flavor::Shared(ref p) => return unsafe {
-                    (*p.get()).abort_selection(was_upgrade)
-                },
-                Flavor::Sync(ref p) => return unsafe {
-                    (*p.get()).abort_selection()
-                },
+                Flavor::Oneshot(ref p) => p.abort_selection(),
+                Flavor::Stream(ref p) => p.abort_selection(was_upgrade),
+                Flavor::Shared(ref p) => return p.abort_selection(was_upgrade),
+                Flavor::Sync(ref p) => return p.abort_selection(),
             };
             let new_port = match result { Ok(b) => return b, Err(p) => p };
             was_upgrade = true;
@@ -1097,7 +1089,7 @@ impl<'a, T> Iterator for Iter<'a, T> {
     fn next(&mut self) -> Option<T> { self.rx.recv().ok() }
 }
 
-#[unstable(feature = "receiver_try_iter", issue = "34931")]
+#[stable(feature = "receiver_try_iter", since = "1.15.0")]
 impl<'a, T> Iterator for TryIter<'a, T> {
     type Item = T;
 
@@ -1131,11 +1123,11 @@ impl <T> IntoIterator for Receiver<T> {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> Drop for Receiver<T> {
     fn drop(&mut self) {
-        match *unsafe { self.inner_mut() } {
-            Flavor::Oneshot(ref mut p) => unsafe { (*p.get()).drop_port(); },
-            Flavor::Stream(ref mut p) => unsafe { (*p.get()).drop_port(); },
-            Flavor::Shared(ref mut p) => unsafe { (*p.get()).drop_port(); },
-            Flavor::Sync(ref mut p) => unsafe { (*p.get()).drop_port(); },
+        match *unsafe { self.inner() } {
+            Flavor::Oneshot(ref p) => p.drop_port(),
+            Flavor::Stream(ref p) => p.drop_port(),
+            Flavor::Shared(ref p) => p.drop_port(),
+            Flavor::Sync(ref p) => p.drop_port(),
         }
     }
 }
diff --git a/src/libstd/sync/mpsc/oneshot.rs b/src/libstd/sync/mpsc/oneshot.rs
index 767e9f96ac8..b8e50c9297b 100644
--- a/src/libstd/sync/mpsc/oneshot.rs
+++ b/src/libstd/sync/mpsc/oneshot.rs
@@ -39,7 +39,8 @@ use self::MyUpgrade::*;
 
 use sync::mpsc::Receiver;
 use sync::mpsc::blocking::{self, SignalToken};
-use core::mem;
+use cell::UnsafeCell;
+use ptr;
 use sync::atomic::{AtomicUsize, Ordering};
 use time::Instant;
 
@@ -57,10 +58,10 @@ pub struct Packet<T> {
     // Internal state of the chan/port pair (stores the blocked thread as well)
     state: AtomicUsize,
     // One-shot data slot location
-    data: Option<T>,
+    data: UnsafeCell<Option<T>>,
     // when used for the second time, a oneshot channel must be upgraded, and
     // this contains the slot for the upgrade
-    upgrade: MyUpgrade<T>,
+    upgrade: UnsafeCell<MyUpgrade<T>>,
 }
 
 pub enum Failure<T> {
@@ -90,42 +91,44 @@ enum MyUpgrade<T> {
 impl<T> Packet<T> {
     pub fn new() -> Packet<T> {
         Packet {
-            data: None,
-            upgrade: NothingSent,
+            data: UnsafeCell::new(None),
+            upgrade: UnsafeCell::new(NothingSent),
             state: AtomicUsize::new(EMPTY),
         }
     }
 
-    pub fn send(&mut self, t: T) -> Result<(), T> {
-        // Sanity check
-        match self.upgrade {
-            NothingSent => {}
-            _ => panic!("sending on a oneshot that's already sent on "),
-        }
-        assert!(self.data.is_none());
-        self.data = Some(t);
-        self.upgrade = SendUsed;
-
-        match self.state.swap(DATA, Ordering::SeqCst) {
-            // Sent the data, no one was waiting
-            EMPTY => Ok(()),
-
-            // Couldn't send the data, the port hung up first. Return the data
-            // back up the stack.
-            DISCONNECTED => {
-                self.state.swap(DISCONNECTED, Ordering::SeqCst);
-                self.upgrade = NothingSent;
-                Err(self.data.take().unwrap())
+    pub fn send(&self, t: T) -> Result<(), T> {
+        unsafe {
+            // Sanity check
+            match *self.upgrade.get() {
+                NothingSent => {}
+                _ => panic!("sending on a oneshot that's already sent on "),
             }
+            assert!((*self.data.get()).is_none());
+            ptr::write(self.data.get(), Some(t));
+            ptr::write(self.upgrade.get(), SendUsed);
+
+            match self.state.swap(DATA, Ordering::SeqCst) {
+                // Sent the data, no one was waiting
+                EMPTY => Ok(()),
+
+                // Couldn't send the data, the port hung up first. Return the data
+                // back up the stack.
+                DISCONNECTED => {
+                    self.state.swap(DISCONNECTED, Ordering::SeqCst);
+                    ptr::write(self.upgrade.get(), NothingSent);
+                    Err((&mut *self.data.get()).take().unwrap())
+                }
 
-            // Not possible, these are one-use channels
-            DATA => unreachable!(),
+                // Not possible, these are one-use channels
+                DATA => unreachable!(),
 
-            // There is a thread waiting on the other end. We leave the 'DATA'
-            // state inside so it'll pick it up on the other end.
-            ptr => unsafe {
-                SignalToken::cast_from_usize(ptr).signal();
-                Ok(())
+                // There is a thread waiting on the other end. We leave the 'DATA'
+                // state inside so it'll pick it up on the other end.
+                ptr => {
+                    SignalToken::cast_from_usize(ptr).signal();
+                    Ok(())
+                }
             }
         }
     }
@@ -133,13 +136,15 @@ impl<T> Packet<T> {
     // Just tests whether this channel has been sent on or not, this is only
     // safe to use from the sender.
     pub fn sent(&self) -> bool {
-        match self.upgrade {
-            NothingSent => false,
-            _ => true,
+        unsafe {
+            match *self.upgrade.get() {
+                NothingSent => false,
+                _ => true,
+            }
         }
     }
 
-    pub fn recv(&mut self, deadline: Option<Instant>) -> Result<T, Failure<T>> {
+    pub fn recv(&self, deadline: Option<Instant>) -> Result<T, Failure<T>> {
         // Attempt to not block the thread (it's a little expensive). If it looks
         // like we're not empty, then immediately go through to `try_recv`.
         if self.state.load(Ordering::SeqCst) == EMPTY {
@@ -167,73 +172,77 @@ impl<T> Packet<T> {
         self.try_recv()
     }
 
-    pub fn try_recv(&mut self) -> Result<T, Failure<T>> {
-        match self.state.load(Ordering::SeqCst) {
-            EMPTY => Err(Empty),
-
-            // We saw some data on the channel, but the channel can be used
-            // again to send us an upgrade. As a result, we need to re-insert
-            // into the channel that there's no data available (otherwise we'll
-            // just see DATA next time). This is done as a cmpxchg because if
-            // the state changes under our feet we'd rather just see that state
-            // change.
-            DATA => {
-                self.state.compare_and_swap(DATA, EMPTY, Ordering::SeqCst);
-                match self.data.take() {
-                    Some(data) => Ok(data),
-                    None => unreachable!(),
+    pub fn try_recv(&self) -> Result<T, Failure<T>> {
+        unsafe {
+            match self.state.load(Ordering::SeqCst) {
+                EMPTY => Err(Empty),
+
+                // We saw some data on the channel, but the channel can be used
+                // again to send us an upgrade. As a result, we need to re-insert
+                // into the channel that there's no data available (otherwise we'll
+                // just see DATA next time). This is done as a cmpxchg because if
+                // the state changes under our feet we'd rather just see that state
+                // change.
+                DATA => {
+                    self.state.compare_and_swap(DATA, EMPTY, Ordering::SeqCst);
+                    match (&mut *self.data.get()).take() {
+                        Some(data) => Ok(data),
+                        None => unreachable!(),
+                    }
                 }
-            }
 
-            // There's no guarantee that we receive before an upgrade happens,
-            // and an upgrade flags the channel as disconnected, so when we see
-            // this we first need to check if there's data available and *then*
-            // we go through and process the upgrade.
-            DISCONNECTED => {
-                match self.data.take() {
-                    Some(data) => Ok(data),
-                    None => {
-                        match mem::replace(&mut self.upgrade, SendUsed) {
-                            SendUsed | NothingSent => Err(Disconnected),
-                            GoUp(upgrade) => Err(Upgraded(upgrade))
+                // There's no guarantee that we receive before an upgrade happens,
+                // and an upgrade flags the channel as disconnected, so when we see
+                // this we first need to check if there's data available and *then*
+                // we go through and process the upgrade.
+                DISCONNECTED => {
+                    match (&mut *self.data.get()).take() {
+                        Some(data) => Ok(data),
+                        None => {
+                            match ptr::replace(self.upgrade.get(), SendUsed) {
+                                SendUsed | NothingSent => Err(Disconnected),
+                                GoUp(upgrade) => Err(Upgraded(upgrade))
+                            }
                         }
                     }
                 }
-            }
 
-            // We are the sole receiver; there cannot be a blocking
-            // receiver already.
-            _ => unreachable!()
+                // We are the sole receiver; there cannot be a blocking
+                // receiver already.
+                _ => unreachable!()
+            }
         }
     }
 
     // Returns whether the upgrade was completed. If the upgrade wasn't
     // completed, then the port couldn't get sent to the other half (it will
     // never receive it).
-    pub fn upgrade(&mut self, up: Receiver<T>) -> UpgradeResult {
-        let prev = match self.upgrade {
-            NothingSent => NothingSent,
-            SendUsed => SendUsed,
-            _ => panic!("upgrading again"),
-        };
-        self.upgrade = GoUp(up);
-
-        match self.state.swap(DISCONNECTED, Ordering::SeqCst) {
-            // If the channel is empty or has data on it, then we're good to go.
-            // Senders will check the data before the upgrade (in case we
-            // plastered over the DATA state).
-            DATA | EMPTY => UpSuccess,
-
-            // If the other end is already disconnected, then we failed the
-            // upgrade. Be sure to trash the port we were given.
-            DISCONNECTED => { self.upgrade = prev; UpDisconnected }
-
-            // If someone's waiting, we gotta wake them up
-            ptr => UpWoke(unsafe { SignalToken::cast_from_usize(ptr) })
+    pub fn upgrade(&self, up: Receiver<T>) -> UpgradeResult {
+        unsafe {
+            let prev = match *self.upgrade.get() {
+                NothingSent => NothingSent,
+                SendUsed => SendUsed,
+                _ => panic!("upgrading again"),
+            };
+            ptr::write(self.upgrade.get(), GoUp(up));
+
+            match self.state.swap(DISCONNECTED, Ordering::SeqCst) {
+                // If the channel is empty or has data on it, then we're good to go.
+                // Senders will check the data before the upgrade (in case we
+                // plastered over the DATA state).
+                DATA | EMPTY => UpSuccess,
+
+                // If the other end is already disconnected, then we failed the
+                // upgrade. Be sure to trash the port we were given.
+                DISCONNECTED => { ptr::replace(self.upgrade.get(), prev); UpDisconnected }
+
+                // If someone's waiting, we gotta wake them up
+                ptr => UpWoke(SignalToken::cast_from_usize(ptr))
+            }
         }
     }
 
-    pub fn drop_chan(&mut self) {
+    pub fn drop_chan(&self) {
         match self.state.swap(DISCONNECTED, Ordering::SeqCst) {
             DATA | DISCONNECTED | EMPTY => {}
 
@@ -244,7 +253,7 @@ impl<T> Packet<T> {
         }
     }
 
-    pub fn drop_port(&mut self) {
+    pub fn drop_port(&self) {
         match self.state.swap(DISCONNECTED, Ordering::SeqCst) {
             // An empty channel has nothing to do, and a remotely disconnected
             // channel also has nothing to do b/c we're about to run the drop
@@ -254,7 +263,7 @@ impl<T> Packet<T> {
             // There's data on the channel, so make sure we destroy it promptly.
             // This is why not using an arc is a little difficult (need the box
             // to stay valid while we take the data).
-            DATA => { self.data.take().unwrap(); }
+            DATA => unsafe { (&mut *self.data.get()).take().unwrap(); },
 
             // We're the only ones that can block on this port
             _ => unreachable!()
@@ -267,62 +276,66 @@ impl<T> Packet<T> {
 
     // If Ok, the value is whether this port has data, if Err, then the upgraded
     // port needs to be checked instead of this one.
-    pub fn can_recv(&mut self) -> Result<bool, Receiver<T>> {
-        match self.state.load(Ordering::SeqCst) {
-            EMPTY => Ok(false), // Welp, we tried
-            DATA => Ok(true),   // we have some un-acquired data
-            DISCONNECTED if self.data.is_some() => Ok(true), // we have data
-            DISCONNECTED => {
-                match mem::replace(&mut self.upgrade, SendUsed) {
-                    // The other end sent us an upgrade, so we need to
-                    // propagate upwards whether the upgrade can receive
-                    // data
-                    GoUp(upgrade) => Err(upgrade),
-
-                    // If the other end disconnected without sending an
-                    // upgrade, then we have data to receive (the channel is
-                    // disconnected).
-                    up => { self.upgrade = up; Ok(true) }
+    pub fn can_recv(&self) -> Result<bool, Receiver<T>> {
+        unsafe {
+            match self.state.load(Ordering::SeqCst) {
+                EMPTY => Ok(false), // Welp, we tried
+                DATA => Ok(true),   // we have some un-acquired data
+                DISCONNECTED if (*self.data.get()).is_some() => Ok(true), // we have data
+                DISCONNECTED => {
+                    match ptr::replace(self.upgrade.get(), SendUsed) {
+                        // The other end sent us an upgrade, so we need to
+                        // propagate upwards whether the upgrade can receive
+                        // data
+                        GoUp(upgrade) => Err(upgrade),
+
+                        // If the other end disconnected without sending an
+                        // upgrade, then we have data to receive (the channel is
+                        // disconnected).
+                        up => { ptr::write(self.upgrade.get(), up); Ok(true) }
+                    }
                 }
+                _ => unreachable!(), // we're the "one blocker"
             }
-            _ => unreachable!(), // we're the "one blocker"
         }
     }
 
     // Attempts to start selection on this port. This can either succeed, fail
     // because there is data, or fail because there is an upgrade pending.
-    pub fn start_selection(&mut self, token: SignalToken) -> SelectionResult<T> {
-        let ptr = unsafe { token.cast_to_usize() };
-        match self.state.compare_and_swap(EMPTY, ptr, Ordering::SeqCst) {
-            EMPTY => SelSuccess,
-            DATA => {
-                drop(unsafe { SignalToken::cast_from_usize(ptr) });
-                SelCanceled
-            }
-            DISCONNECTED if self.data.is_some() => {
-                drop(unsafe { SignalToken::cast_from_usize(ptr) });
-                SelCanceled
-            }
-            DISCONNECTED => {
-                match mem::replace(&mut self.upgrade, SendUsed) {
-                    // The other end sent us an upgrade, so we need to
-                    // propagate upwards whether the upgrade can receive
-                    // data
-                    GoUp(upgrade) => {
-                        SelUpgraded(unsafe { SignalToken::cast_from_usize(ptr) }, upgrade)
-                    }
+    pub fn start_selection(&self, token: SignalToken) -> SelectionResult<T> {
+        unsafe {
+            let ptr = token.cast_to_usize();
+            match self.state.compare_and_swap(EMPTY, ptr, Ordering::SeqCst) {
+                EMPTY => SelSuccess,
+                DATA => {
+                    drop(SignalToken::cast_from_usize(ptr));
+                    SelCanceled
+                }
+                DISCONNECTED if (*self.data.get()).is_some() => {
+                    drop(SignalToken::cast_from_usize(ptr));
+                    SelCanceled
+                }
+                DISCONNECTED => {
+                    match ptr::replace(self.upgrade.get(), SendUsed) {
+                        // The other end sent us an upgrade, so we need to
+                        // propagate upwards whether the upgrade can receive
+                        // data
+                        GoUp(upgrade) => {
+                            SelUpgraded(SignalToken::cast_from_usize(ptr), upgrade)
+                        }
 
-                    // If the other end disconnected without sending an
-                    // upgrade, then we have data to receive (the channel is
-                    // disconnected).
-                    up => {
-                        self.upgrade = up;
-                        drop(unsafe { SignalToken::cast_from_usize(ptr) });
-                        SelCanceled
+                        // If the other end disconnected without sending an
+                        // upgrade, then we have data to receive (the channel is
+                        // disconnected).
+                        up => {
+                            ptr::write(self.upgrade.get(), up);
+                            drop(SignalToken::cast_from_usize(ptr));
+                            SelCanceled
+                        }
                     }
                 }
+                _ => unreachable!(), // we're the "one blocker"
             }
-            _ => unreachable!(), // we're the "one blocker"
         }
     }
 
@@ -330,7 +343,7 @@ impl<T> Packet<T> {
     // blocked thread will no longer be visible to any other threads.
     //
     // The return value indicates whether there's data on this port.
-    pub fn abort_selection(&mut self) -> Result<bool, Receiver<T>> {
+    pub fn abort_selection(&self) -> Result<bool, Receiver<T>> {
         let state = match self.state.load(Ordering::SeqCst) {
             // Each of these states means that no further activity will happen
             // with regard to abortion selection
@@ -356,16 +369,16 @@ impl<T> Packet<T> {
             //
             // We then need to check to see if there was an upgrade requested,
             // and if so, the upgraded port needs to have its selection aborted.
-            DISCONNECTED => {
-                if self.data.is_some() {
+            DISCONNECTED => unsafe {
+                if (*self.data.get()).is_some() {
                     Ok(true)
                 } else {
-                    match mem::replace(&mut self.upgrade, SendUsed) {
+                    match ptr::replace(self.upgrade.get(), SendUsed) {
                         GoUp(port) => Err(port),
                         _ => Ok(true),
                     }
                 }
-            }
+            },
 
             // We woke ourselves up from select.
             ptr => unsafe {
diff --git a/src/libstd/sync/mpsc/shared.rs b/src/libstd/sync/mpsc/shared.rs
index 2a9618251ff..f9e02904164 100644
--- a/src/libstd/sync/mpsc/shared.rs
+++ b/src/libstd/sync/mpsc/shared.rs
@@ -24,6 +24,8 @@ use core::cmp;
 use core::intrinsics::abort;
 use core::isize;
 
+use cell::UnsafeCell;
+use ptr;
 use sync::atomic::{AtomicUsize, AtomicIsize, AtomicBool, Ordering};
 use sync::mpsc::blocking::{self, SignalToken};
 use sync::mpsc::mpsc_queue as mpsc;
@@ -44,7 +46,7 @@ const MAX_STEALS: isize = 1 << 20;
 pub struct Packet<T> {
     queue: mpsc::Queue<T>,
     cnt: AtomicIsize, // How many items are on this channel
-    steals: isize, // How many times has a port received without blocking?
+    steals: UnsafeCell<isize>, // How many times has a port received without blocking?
     to_wake: AtomicUsize, // SignalToken for wake up
 
     // The number of channels which are currently using this packet.
@@ -72,7 +74,7 @@ impl<T> Packet<T> {
         Packet {
             queue: mpsc::Queue::new(),
             cnt: AtomicIsize::new(0),
-            steals: 0,
+            steals: UnsafeCell::new(0),
             to_wake: AtomicUsize::new(0),
             channels: AtomicUsize::new(2),
             port_dropped: AtomicBool::new(false),
@@ -95,7 +97,7 @@ impl<T> Packet<T> {
     // threads in select().
     //
     // This can only be called at channel-creation time
-    pub fn inherit_blocker(&mut self,
+    pub fn inherit_blocker(&self,
                            token: Option<SignalToken>,
                            guard: MutexGuard<()>) {
         token.map(|token| {
@@ -122,7 +124,7 @@ impl<T> Packet<T> {
             // To offset this bad increment, we initially set the steal count to
             // -1. You'll find some special code in abort_selection() as well to
             // ensure that this -1 steal count doesn't escape too far.
-            self.steals = -1;
+            unsafe { *self.steals.get() = -1; }
         });
 
         // When the shared packet is constructed, we grabbed this lock. The
@@ -133,7 +135,7 @@ impl<T> Packet<T> {
         drop(guard);
     }
 
-    pub fn send(&mut self, t: T) -> Result<(), T> {
+    pub fn send(&self, t: T) -> Result<(), T> {
         // See Port::drop for what's going on
         if self.port_dropped.load(Ordering::SeqCst) { return Err(t) }
 
@@ -218,7 +220,7 @@ impl<T> Packet<T> {
         Ok(())
     }
 
-    pub fn recv(&mut self, deadline: Option<Instant>) -> Result<T, Failure> {
+    pub fn recv(&self, deadline: Option<Instant>) -> Result<T, Failure> {
         // This code is essentially the exact same as that found in the stream
         // case (see stream.rs)
         match self.try_recv() {
@@ -239,37 +241,38 @@ impl<T> Packet<T> {
         }
 
         match self.try_recv() {
-            data @ Ok(..) => { self.steals -= 1; data }
+            data @ Ok(..) => unsafe { *self.steals.get() -= 1; data },
             data => data,
         }
     }
 
     // Essentially the exact same thing as the stream decrement function.
     // Returns true if blocking should proceed.
-    fn decrement(&mut self, token: SignalToken) -> StartResult {
-        assert_eq!(self.to_wake.load(Ordering::SeqCst), 0);
-        let ptr = unsafe { token.cast_to_usize() };
-        self.to_wake.store(ptr, Ordering::SeqCst);
-
-        let steals = self.steals;
-        self.steals = 0;
-
-        match self.cnt.fetch_sub(1 + steals, Ordering::SeqCst) {
-            DISCONNECTED => { self.cnt.store(DISCONNECTED, Ordering::SeqCst); }
-            // If we factor in our steals and notice that the channel has no
-            // data, we successfully sleep
-            n => {
-                assert!(n >= 0);
-                if n - steals <= 0 { return Installed }
+    fn decrement(&self, token: SignalToken) -> StartResult {
+        unsafe {
+            assert_eq!(self.to_wake.load(Ordering::SeqCst), 0);
+            let ptr = token.cast_to_usize();
+            self.to_wake.store(ptr, Ordering::SeqCst);
+
+            let steals = ptr::replace(self.steals.get(), 0);
+
+            match self.cnt.fetch_sub(1 + steals, Ordering::SeqCst) {
+                DISCONNECTED => { self.cnt.store(DISCONNECTED, Ordering::SeqCst); }
+                // If we factor in our steals and notice that the channel has no
+                // data, we successfully sleep
+                n => {
+                    assert!(n >= 0);
+                    if n - steals <= 0 { return Installed }
+                }
             }
-        }
 
-        self.to_wake.store(0, Ordering::SeqCst);
-        drop(unsafe { SignalToken::cast_from_usize(ptr) });
-        Abort
+            self.to_wake.store(0, Ordering::SeqCst);
+            drop(SignalToken::cast_from_usize(ptr));
+            Abort
+        }
     }
 
-    pub fn try_recv(&mut self) -> Result<T, Failure> {
+    pub fn try_recv(&self) -> Result<T, Failure> {
         let ret = match self.queue.pop() {
             mpsc::Data(t) => Some(t),
             mpsc::Empty => None,
@@ -303,23 +306,23 @@ impl<T> Packet<T> {
         match ret {
             // See the discussion in the stream implementation for why we
             // might decrement steals.
-            Some(data) => {
-                if self.steals > MAX_STEALS {
+            Some(data) => unsafe {
+                if *self.steals.get() > MAX_STEALS {
                     match self.cnt.swap(0, Ordering::SeqCst) {
                         DISCONNECTED => {
                             self.cnt.store(DISCONNECTED, Ordering::SeqCst);
                         }
                         n => {
-                            let m = cmp::min(n, self.steals);
-                            self.steals -= m;
+                            let m = cmp::min(n, *self.steals.get());
+                            *self.steals.get() -= m;
                             self.bump(n - m);
                         }
                     }
-                    assert!(self.steals >= 0);
+                    assert!(*self.steals.get() >= 0);
                 }
-                self.steals += 1;
+                *self.steals.get() += 1;
                 Ok(data)
-            }
+            },
 
             // See the discussion in the stream implementation for why we try
             // again.
@@ -341,7 +344,7 @@ impl<T> Packet<T> {
 
     // Prepares this shared packet for a channel clone, essentially just bumping
     // a refcount.
-    pub fn clone_chan(&mut self) {
+    pub fn clone_chan(&self) {
         let old_count = self.channels.fetch_add(1, Ordering::SeqCst);
 
         // See comments on Arc::clone() on why we do this (for `mem::forget`).
@@ -355,7 +358,7 @@ impl<T> Packet<T> {
     // Decrement the reference count on a channel. This is called whenever a
     // Chan is dropped and may end up waking up a receiver. It's the receiver's
     // responsibility on the other end to figure out that we've disconnected.
-    pub fn drop_chan(&mut self) {
+    pub fn drop_chan(&self) {
         match self.channels.fetch_sub(1, Ordering::SeqCst) {
             1 => {}
             n if n > 1 => return,
@@ -371,9 +374,9 @@ impl<T> Packet<T> {
 
     // See the long discussion inside of stream.rs for why the queue is drained,
     // and why it is done in this fashion.
-    pub fn drop_port(&mut self) {
+    pub fn drop_port(&self) {
         self.port_dropped.store(true, Ordering::SeqCst);
-        let mut steals = self.steals;
+        let mut steals = unsafe { *self.steals.get() };
         while {
             let cnt = self.cnt.compare_and_swap(steals, DISCONNECTED, Ordering::SeqCst);
             cnt != DISCONNECTED && cnt != steals
@@ -390,7 +393,7 @@ impl<T> Packet<T> {
     }
 
     // Consumes ownership of the 'to_wake' field.
-    fn take_to_wake(&mut self) -> SignalToken {
+    fn take_to_wake(&self) -> SignalToken {
         let ptr = self.to_wake.load(Ordering::SeqCst);
         self.to_wake.store(0, Ordering::SeqCst);
         assert!(ptr != 0);
@@ -406,13 +409,13 @@ impl<T> Packet<T> {
     //
     // This is different than the stream version because there's no need to peek
     // at the queue, we can just look at the local count.
-    pub fn can_recv(&mut self) -> bool {
+    pub fn can_recv(&self) -> bool {
         let cnt = self.cnt.load(Ordering::SeqCst);
-        cnt == DISCONNECTED || cnt - self.steals > 0
+        cnt == DISCONNECTED || cnt - unsafe { *self.steals.get() } > 0
     }
 
     // increment the count on the channel (used for selection)
-    fn bump(&mut self, amt: isize) -> isize {
+    fn bump(&self, amt: isize) -> isize {
         match self.cnt.fetch_add(amt, Ordering::SeqCst) {
             DISCONNECTED => {
                 self.cnt.store(DISCONNECTED, Ordering::SeqCst);
@@ -427,7 +430,7 @@ impl<T> Packet<T> {
     //
     // The code here is the same as in stream.rs, except that it doesn't need to
     // peek at the channel to see if an upgrade is pending.
-    pub fn start_selection(&mut self, token: SignalToken) -> StartResult {
+    pub fn start_selection(&self, token: SignalToken) -> StartResult {
         match self.decrement(token) {
             Installed => Installed,
             Abort => {
@@ -443,7 +446,7 @@ impl<T> Packet<T> {
     //
     // This is similar to the stream implementation (hence fewer comments), but
     // uses a different value for the "steals" variable.
-    pub fn abort_selection(&mut self, _was_upgrade: bool) -> bool {
+    pub fn abort_selection(&self, _was_upgrade: bool) -> bool {
         // Before we do anything else, we bounce on this lock. The reason for
         // doing this is to ensure that any upgrade-in-progress is gone and
         // done with. Without this bounce, we can race with inherit_blocker
@@ -477,12 +480,15 @@ impl<T> Packet<T> {
                     thread::yield_now();
                 }
             }
-            // if the number of steals is -1, it was the pre-emptive -1 steal
-            // count from when we inherited a blocker. This is fine because
-            // we're just going to overwrite it with a real value.
-            assert!(self.steals == 0 || self.steals == -1);
-            self.steals = steals;
-            prev >= 0
+            unsafe {
+                // if the number of steals is -1, it was the pre-emptive -1 steal
+                // count from when we inherited a blocker. This is fine because
+                // we're just going to overwrite it with a real value.
+                let old = self.steals.get();
+                assert!(*old == 0 || *old == -1);
+                *old = steals;
+                prev >= 0
+            }
         }
     }
 }
diff --git a/src/libstd/sync/mpsc/stream.rs b/src/libstd/sync/mpsc/stream.rs
index 61c8316467d..47cd8977fda 100644
--- a/src/libstd/sync/mpsc/stream.rs
+++ b/src/libstd/sync/mpsc/stream.rs
@@ -22,8 +22,10 @@ pub use self::UpgradeResult::*;
 pub use self::SelectionResult::*;
 use self::Message::*;
 
+use cell::UnsafeCell;
 use core::cmp;
 use core::isize;
+use ptr;
 use thread;
 use time::Instant;
 
@@ -42,7 +44,7 @@ pub struct Packet<T> {
     queue: spsc::Queue<Message<T>>, // internal queue for all message
 
     cnt: AtomicIsize, // How many items are on this channel
-    steals: isize, // How many times has a port received without blocking?
+    steals: UnsafeCell<isize>, // How many times has a port received without blocking?
     to_wake: AtomicUsize, // SignalToken for the blocked thread to wake up
 
     port_dropped: AtomicBool, // flag if the channel has been destroyed.
@@ -79,14 +81,14 @@ impl<T> Packet<T> {
             queue: unsafe { spsc::Queue::new(128) },
 
             cnt: AtomicIsize::new(0),
-            steals: 0,
+            steals: UnsafeCell::new(0),
             to_wake: AtomicUsize::new(0),
 
             port_dropped: AtomicBool::new(false),
         }
     }
 
-    pub fn send(&mut self, t: T) -> Result<(), T> {
+    pub fn send(&self, t: T) -> Result<(), T> {
         // If the other port has deterministically gone away, then definitely
         // must return the data back up the stack. Otherwise, the data is
         // considered as being sent.
@@ -99,7 +101,7 @@ impl<T> Packet<T> {
         Ok(())
     }
 
-    pub fn upgrade(&mut self, up: Receiver<T>) -> UpgradeResult {
+    pub fn upgrade(&self, up: Receiver<T>) -> UpgradeResult {
         // If the port has gone away, then there's no need to proceed any
         // further.
         if self.port_dropped.load(Ordering::SeqCst) { return UpDisconnected }
@@ -107,7 +109,7 @@ impl<T> Packet<T> {
         self.do_send(GoUp(up))
     }
 
-    fn do_send(&mut self, t: Message<T>) -> UpgradeResult {
+    fn do_send(&self, t: Message<T>) -> UpgradeResult {
         self.queue.push(t);
         match self.cnt.fetch_add(1, Ordering::SeqCst) {
             // As described in the mod's doc comment, -1 == wakeup
@@ -141,7 +143,7 @@ impl<T> Packet<T> {
     }
 
     // Consumes ownership of the 'to_wake' field.
-    fn take_to_wake(&mut self) -> SignalToken {
+    fn take_to_wake(&self) -> SignalToken {
         let ptr = self.to_wake.load(Ordering::SeqCst);
         self.to_wake.store(0, Ordering::SeqCst);
         assert!(ptr != 0);
@@ -151,13 +153,12 @@ impl<T> Packet<T> {
     // Decrements the count on the channel for a sleeper, returning the sleeper
     // back if it shouldn't sleep. Note that this is the location where we take
     // steals into account.
-    fn decrement(&mut self, token: SignalToken) -> Result<(), SignalToken> {
+    fn decrement(&self, token: SignalToken) -> Result<(), SignalToken> {
         assert_eq!(self.to_wake.load(Ordering::SeqCst), 0);
         let ptr = unsafe { token.cast_to_usize() };
         self.to_wake.store(ptr, Ordering::SeqCst);
 
-        let steals = self.steals;
-        self.steals = 0;
+        let steals = unsafe { ptr::replace(self.steals.get(), 0) };
 
         match self.cnt.fetch_sub(1 + steals, Ordering::SeqCst) {
             DISCONNECTED => { self.cnt.store(DISCONNECTED, Ordering::SeqCst); }
@@ -173,7 +174,7 @@ impl<T> Packet<T> {
         Err(unsafe { SignalToken::cast_from_usize(ptr) })
     }
 
-    pub fn recv(&mut self, deadline: Option<Instant>) -> Result<T, Failure<T>> {
+    pub fn recv(&self, deadline: Option<Instant>) -> Result<T, Failure<T>> {
         // Optimistic preflight check (scheduling is expensive).
         match self.try_recv() {
             Err(Empty) => {}
@@ -199,16 +200,16 @@ impl<T> Packet<T> {
             // a steal, so offset the decrement here (we already have our
             // "steal" factored into the channel count above).
             data @ Ok(..) |
-            data @ Err(Upgraded(..)) => {
-                self.steals -= 1;
+            data @ Err(Upgraded(..)) => unsafe {
+                *self.steals.get() -= 1;
                 data
-            }
+            },
 
             data => data,
         }
     }
 
-    pub fn try_recv(&mut self) -> Result<T, Failure<T>> {
+    pub fn try_recv(&self) -> Result<T, Failure<T>> {
         match self.queue.pop() {
             // If we stole some data, record to that effect (this will be
             // factored into cnt later on).
@@ -221,26 +222,26 @@ impl<T> Packet<T> {
             // a pretty slow operation, of swapping 0 into cnt, taking steals
             // down as much as possible (without going negative), and then
             // adding back in whatever we couldn't factor into steals.
-            Some(data) => {
-                if self.steals > MAX_STEALS {
+            Some(data) => unsafe {
+                if *self.steals.get() > MAX_STEALS {
                     match self.cnt.swap(0, Ordering::SeqCst) {
                         DISCONNECTED => {
                             self.cnt.store(DISCONNECTED, Ordering::SeqCst);
                         }
                         n => {
-                            let m = cmp::min(n, self.steals);
-                            self.steals -= m;
+                            let m = cmp::min(n, *self.steals.get());
+                            *self.steals.get() -= m;
                             self.bump(n - m);
                         }
                     }
-                    assert!(self.steals >= 0);
+                    assert!(*self.steals.get() >= 0);
                 }
-                self.steals += 1;
+                *self.steals.get() += 1;
                 match data {
                     Data(t) => Ok(t),
                     GoUp(up) => Err(Upgraded(up)),
                 }
-            }
+            },
 
             None => {
                 match self.cnt.load(Ordering::SeqCst) {
@@ -269,7 +270,7 @@ impl<T> Packet<T> {
         }
     }
 
-    pub fn drop_chan(&mut self) {
+    pub fn drop_chan(&self) {
         // Dropping a channel is pretty simple, we just flag it as disconnected
         // and then wakeup a blocker if there is one.
         match self.cnt.swap(DISCONNECTED, Ordering::SeqCst) {
@@ -279,7 +280,7 @@ impl<T> Packet<T> {
         }
     }
 
-    pub fn drop_port(&mut self) {
+    pub fn drop_port(&self) {
         // Dropping a port seems like a fairly trivial thing. In theory all we
         // need to do is flag that we're disconnected and then everything else
         // can take over (we don't have anyone to wake up).
@@ -309,7 +310,7 @@ impl<T> Packet<T> {
         // continue to fail while active senders send data while we're dropping
         // data, but eventually we're guaranteed to break out of this loop
         // (because there is a bounded number of senders).
-        let mut steals = self.steals;
+        let mut steals = unsafe { *self.steals.get() };
         while {
             let cnt = self.cnt.compare_and_swap(
                             steals, DISCONNECTED, Ordering::SeqCst);
@@ -332,7 +333,7 @@ impl<T> Packet<T> {
     // Tests to see whether this port can receive without blocking. If Ok is
     // returned, then that's the answer. If Err is returned, then the returned
     // port needs to be queried instead (an upgrade happened)
-    pub fn can_recv(&mut self) -> Result<bool, Receiver<T>> {
+    pub fn can_recv(&self) -> Result<bool, Receiver<T>> {
         // We peek at the queue to see if there's anything on it, and we use
         // this return value to determine if we should pop from the queue and
         // upgrade this channel immediately. If it looks like we've got an
@@ -351,7 +352,7 @@ impl<T> Packet<T> {
     }
 
     // increment the count on the channel (used for selection)
-    fn bump(&mut self, amt: isize) -> isize {
+    fn bump(&self, amt: isize) -> isize {
         match self.cnt.fetch_add(amt, Ordering::SeqCst) {
             DISCONNECTED => {
                 self.cnt.store(DISCONNECTED, Ordering::SeqCst);
@@ -363,7 +364,7 @@ impl<T> Packet<T> {
 
     // Attempts to start selecting on this port. Like a oneshot, this can fail
     // immediately because of an upgrade.
-    pub fn start_selection(&mut self, token: SignalToken) -> SelectionResult<T> {
+    pub fn start_selection(&self, token: SignalToken) -> SelectionResult<T> {
         match self.decrement(token) {
             Ok(()) => SelSuccess,
             Err(token) => {
@@ -387,7 +388,7 @@ impl<T> Packet<T> {
     }
 
     // Removes a previous thread from being blocked in this port
-    pub fn abort_selection(&mut self,
+    pub fn abort_selection(&self,
                            was_upgrade: bool) -> Result<bool, Receiver<T>> {
         // If we're aborting selection after upgrading from a oneshot, then
         // we're guarantee that no one is waiting. The only way that we could
@@ -403,7 +404,7 @@ impl<T> Packet<T> {
         // this end. This is fine because we know it's a small bounded windows
         // of time until the data is actually sent.
         if was_upgrade {
-            assert_eq!(self.steals, 0);
+            assert_eq!(unsafe { *self.steals.get() }, 0);
             assert_eq!(self.to_wake.load(Ordering::SeqCst), 0);
             return Ok(true)
         }
@@ -444,8 +445,10 @@ impl<T> Packet<T> {
                     thread::yield_now();
                 }
             }
-            assert_eq!(self.steals, 0);
-            self.steals = steals;
+            unsafe {
+                assert_eq!(*self.steals.get(), 0);
+                *self.steals.get() = steals;
+            }
 
             // if we were previously positive, then there's surely data to
             // receive
diff --git a/src/libstd/sync/mutex.rs b/src/libstd/sync/mutex.rs
index df4a3746a49..f6dbe01d7bd 100644
--- a/src/libstd/sync/mutex.rs
+++ b/src/libstd/sync/mutex.rs
@@ -351,6 +351,15 @@ impl<'a, T: ?Sized> Drop for MutexGuard<'a, T> {
     }
 }
 
+#[stable(feature = "std_debug", since = "1.15.0")]
+impl<'a, T: ?Sized + fmt::Debug> fmt::Debug for MutexGuard<'a, T> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.debug_struct("MutexGuard")
+            .field("lock", &self.__lock)
+            .finish()
+    }
+}
+
 pub fn guard_lock<'a, T: ?Sized>(guard: &MutexGuard<'a, T>) -> &'a sys::Mutex {
     &guard.__lock.inner
 }
diff --git a/src/libstd/sync/once.rs b/src/libstd/sync/once.rs
index 71e163321ae..a9747639aac 100644
--- a/src/libstd/sync/once.rs
+++ b/src/libstd/sync/once.rs
@@ -64,6 +64,7 @@
 // You'll find a few more details in the implementation, but that's the gist of
 // it!
 
+use fmt;
 use marker;
 use ptr;
 use sync::atomic::{AtomicUsize, AtomicBool, Ordering};
@@ -103,6 +104,7 @@ unsafe impl Send for Once {}
 /// State yielded to the `call_once_force` method which can be used to query
 /// whether the `Once` was previously poisoned or not.
 #[unstable(feature = "once_poison", issue = "33577")]
+#[derive(Debug)]
 pub struct OnceState {
     poisoned: bool,
 }
@@ -328,6 +330,13 @@ impl Once {
     }
 }
 
+#[stable(feature = "std_debug", since = "1.15.0")]
+impl fmt::Debug for Once {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.pad("Once { .. }")
+    }
+}
+
 impl Drop for Finish {
     fn drop(&mut self) {
         // Swap out our state with however we finished. We should only ever see
diff --git a/src/libstd/sync/rwlock.rs b/src/libstd/sync/rwlock.rs
index f83cf7ba9c2..0a11c71706b 100644
--- a/src/libstd/sync/rwlock.rs
+++ b/src/libstd/sync/rwlock.rs
@@ -362,6 +362,24 @@ impl<'rwlock, T: ?Sized> RwLockWriteGuard<'rwlock, T> {
     }
 }
 
+#[stable(feature = "std_debug", since = "1.15.0")]
+impl<'a, T: fmt::Debug> fmt::Debug for RwLockReadGuard<'a, T> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.debug_struct("RwLockReadGuard")
+            .field("lock", &self.__lock)
+            .finish()
+    }
+}
+
+#[stable(feature = "std_debug", since = "1.15.0")]
+impl<'a, T: fmt::Debug> fmt::Debug for RwLockWriteGuard<'a, T> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.debug_struct("RwLockWriteGuard")
+            .field("lock", &self.__lock)
+            .finish()
+    }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'rwlock, T: ?Sized> Deref for RwLockReadGuard<'rwlock, T> {
     type Target = T;
diff --git a/src/libstd/sys/mod.rs b/src/libstd/sys/mod.rs
index 0c45ab8a887..14da376efa9 100644
--- a/src/libstd/sys/mod.rs
+++ b/src/libstd/sys/mod.rs
@@ -30,8 +30,14 @@
 //! inter-dependencies within `std` that will be a challenging goal to
 //! achieve.
 
+#![allow(missing_debug_implementations)]
+
 pub use self::imp::*;
 
+#[cfg(target_os = "redox")]
+#[path = "redox/mod.rs"]
+mod imp;
+
 #[cfg(unix)]
 #[path = "unix/mod.rs"]
 mod imp;
diff --git a/src/libstd/sys/redox/args.rs b/src/libstd/sys/redox/args.rs
new file mode 100644
index 00000000000..f6fea2f1076
--- /dev/null
+++ b/src/libstd/sys/redox/args.rs
@@ -0,0 +1,109 @@
+// 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.
+
+//! Global initialization and retreival of command line arguments.
+//!
+//! On some platforms these are stored during runtime startup,
+//! and on some they are retrieved from the system on demand.
+
+#![allow(dead_code)] // runtime init functions not used during testing
+
+use ffi::OsString;
+use marker::PhantomData;
+use vec;
+
+/// One-time global initialization.
+pub unsafe fn init(argc: isize, argv: *const *const u8) { imp::init(argc, argv) }
+
+/// One-time global cleanup.
+pub unsafe fn cleanup() { imp::cleanup() }
+
+/// Returns the command line arguments
+pub fn args() -> Args {
+    imp::args()
+}
+
+pub struct Args {
+    iter: vec::IntoIter<OsString>,
+    _dont_send_or_sync_me: PhantomData<*mut ()>,
+}
+
+impl Iterator for Args {
+    type Item = OsString;
+    fn next(&mut self) -> Option<OsString> { self.iter.next() }
+    fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
+}
+
+impl ExactSizeIterator for Args {
+    fn len(&self) -> usize { self.iter.len() }
+}
+
+impl DoubleEndedIterator for Args {
+    fn next_back(&mut self) -> Option<OsString> { self.iter.next_back() }
+}
+
+mod imp {
+    use os::unix::prelude::*;
+    use mem;
+    use ffi::OsString;
+    use marker::PhantomData;
+    use slice;
+    use str;
+    use super::Args;
+
+    use sys_common::mutex::Mutex;
+
+    static mut GLOBAL_ARGS_PTR: usize = 0;
+    static LOCK: Mutex = Mutex::new();
+
+    pub unsafe fn init(argc: isize, argv: *const *const u8) {
+        let mut args: Vec<Vec<u8>> = Vec::new();
+        for i in 0..argc {
+            let len = *(argv.offset(i * 2)) as usize;
+            let ptr = *(argv.offset(i * 2 + 1));
+            args.push(slice::from_raw_parts(ptr, len).to_vec());
+        }
+
+        LOCK.lock();
+        let ptr = get_global_ptr();
+        assert!((*ptr).is_none());
+        (*ptr) = Some(box args);
+        LOCK.unlock();
+    }
+
+    pub unsafe fn cleanup() {
+        LOCK.lock();
+        *get_global_ptr() = None;
+        LOCK.unlock();
+    }
+
+    pub fn args() -> Args {
+        let bytes = clone().unwrap_or(Vec::new());
+        let v: Vec<OsString> = bytes.into_iter().map(|v| {
+            OsStringExt::from_vec(v)
+        }).collect();
+        Args { iter: v.into_iter(), _dont_send_or_sync_me: PhantomData }
+    }
+
+    fn clone() -> Option<Vec<Vec<u8>>> {
+        unsafe {
+            LOCK.lock();
+            let ptr = get_global_ptr();
+            let ret = (*ptr).as_ref().map(|s| (**s).clone());
+            LOCK.unlock();
+            return ret
+        }
+    }
+
+    fn get_global_ptr() -> *mut Option<Box<Vec<Vec<u8>>>> {
+        unsafe { mem::transmute(&GLOBAL_ARGS_PTR) }
+    }
+
+}
diff --git a/src/libstd/sys/redox/backtrace.rs b/src/libstd/sys/redox/backtrace.rs
new file mode 100644
index 00000000000..6f53841502a
--- /dev/null
+++ b/src/libstd/sys/redox/backtrace.rs
@@ -0,0 +1,18 @@
+// 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.
+
+use libc;
+use io;
+use sys_common::backtrace::output;
+
+#[inline(never)]
+pub fn write(w: &mut io::Write) -> io::Result<()> {
+    output(w, 0, 0 as *mut libc::c_void, None)
+}
diff --git a/src/libstd/sys/redox/condvar.rs b/src/libstd/sys/redox/condvar.rs
new file mode 100644
index 00000000000..0ca0987b245
--- /dev/null
+++ b/src/libstd/sys/redox/condvar.rs
@@ -0,0 +1,106 @@
+// 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.
+
+use cell::UnsafeCell;
+use intrinsics::{atomic_cxchg, atomic_xadd, atomic_xchg};
+use ptr;
+use time::Duration;
+
+use sys::mutex::{mutex_lock, mutex_unlock, Mutex};
+use sys::syscall::{futex, FUTEX_WAIT, FUTEX_WAKE, FUTEX_REQUEUE};
+
+pub struct Condvar {
+    lock: UnsafeCell<*mut i32>,
+    seq: UnsafeCell<i32>
+}
+
+impl Condvar {
+    pub const fn new() -> Condvar {
+        Condvar {
+            lock: UnsafeCell::new(ptr::null_mut()),
+            seq: UnsafeCell::new(0)
+        }
+    }
+
+    #[inline]
+    pub unsafe fn init(&self) {
+        *self.lock.get() = ptr::null_mut();
+        *self.seq.get() = 0;
+    }
+
+    #[inline]
+    pub fn notify_one(&self) {
+        unsafe {
+            let seq = self.seq.get();
+
+            atomic_xadd(seq, 1);
+
+            let _ = futex(seq, FUTEX_WAKE, 1, 0, ptr::null_mut());
+        }
+    }
+
+    #[inline]
+    pub fn notify_all(&self) {
+        unsafe {
+            let lock = self.lock.get();
+            let seq = self.seq.get();
+
+            if *lock == ptr::null_mut() {
+                return;
+            }
+
+            atomic_xadd(seq, 1);
+
+            let _ = futex(seq, FUTEX_REQUEUE, 1, ::usize::MAX, *lock);
+        }
+    }
+
+    #[inline]
+    pub fn wait(&self, mutex: &Mutex) {
+        unsafe {
+            let lock = self.lock.get();
+            let seq = self.seq.get();
+
+            if *lock != mutex.lock.get() {
+                if *lock != ptr::null_mut() {
+                    panic!("Condvar used with more than one Mutex");
+                }
+
+                atomic_cxchg(lock as *mut usize, 0, mutex.lock.get() as usize);
+            }
+
+            mutex_unlock(*lock);
+
+            let _ = futex(seq, FUTEX_WAIT, *seq, 0, ptr::null_mut());
+
+            while atomic_xchg(*lock, 2) != 0 {
+                let _ = futex(*lock, FUTEX_WAIT, 2, 0, ptr::null_mut());
+            }
+
+            mutex_lock(*lock);
+        }
+    }
+
+    #[inline]
+    pub fn wait_timeout(&self, _mutex: &Mutex, _dur: Duration) -> bool {
+        ::sys_common::util::dumb_print(format_args!("condvar wait_timeout\n"));
+        unimplemented!();
+    }
+
+    #[inline]
+    pub unsafe fn destroy(&self) {
+        *self.lock.get() = ptr::null_mut();
+        *self.seq.get() = 0;
+    }
+}
+
+unsafe impl Send for Condvar {}
+
+unsafe impl Sync for Condvar {}
diff --git a/src/libstd/sys/redox/env.rs b/src/libstd/sys/redox/env.rs
new file mode 100644
index 00000000000..669b7520df8
--- /dev/null
+++ b/src/libstd/sys/redox/env.rs
@@ -0,0 +1,19 @@
+// 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.
+
+pub mod os {
+    pub const FAMILY: &'static str = "redox";
+    pub const OS: &'static str = "redox";
+    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/redox/ext/ffi.rs b/src/libstd/sys/redox/ext/ffi.rs
new file mode 100644
index 00000000000..d59b4fc0b70
--- /dev/null
+++ b/src/libstd/sys/redox/ext/ffi.rs
@@ -0,0 +1,61 @@
+// Copyright 2015 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.
+
+//! Unix-specific extension to the primitives in the `std::ffi` module
+
+#![stable(feature = "rust1", since = "1.0.0")]
+
+use ffi::{OsStr, OsString};
+use mem;
+use sys::os_str::Buf;
+use sys_common::{FromInner, IntoInner, AsInner};
+
+/// Unix-specific extensions to `OsString`.
+#[stable(feature = "rust1", since = "1.0.0")]
+pub trait OsStringExt {
+    /// Creates an `OsString` from a byte vector.
+    #[stable(feature = "rust1", since = "1.0.0")]
+    fn from_vec(vec: Vec<u8>) -> Self;
+
+    /// Yields the underlying byte vector of this `OsString`.
+    #[stable(feature = "rust1", since = "1.0.0")]
+    fn into_vec(self) -> Vec<u8>;
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl OsStringExt for OsString {
+    fn from_vec(vec: Vec<u8>) -> OsString {
+        FromInner::from_inner(Buf { inner: vec })
+    }
+    fn into_vec(self) -> Vec<u8> {
+        self.into_inner().inner
+    }
+}
+
+/// Unix-specific extensions to `OsStr`.
+#[stable(feature = "rust1", since = "1.0.0")]
+pub trait OsStrExt {
+    #[stable(feature = "rust1", since = "1.0.0")]
+    fn from_bytes(slice: &[u8]) -> &Self;
+
+    /// Gets the underlying byte view of the `OsStr` slice.
+    #[stable(feature = "rust1", since = "1.0.0")]
+    fn as_bytes(&self) -> &[u8];
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl OsStrExt for OsStr {
+    fn from_bytes(slice: &[u8]) -> &OsStr {
+        unsafe { mem::transmute(slice) }
+    }
+    fn as_bytes(&self) -> &[u8] {
+        &self.as_inner().inner
+    }
+}
diff --git a/src/libstd/sys/redox/ext/fs.rs b/src/libstd/sys/redox/ext/fs.rs
new file mode 100644
index 00000000000..b4e220971fd
--- /dev/null
+++ b/src/libstd/sys/redox/ext/fs.rs
@@ -0,0 +1,298 @@
+// 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.
+
+//! Unix-specific extensions to primitives in the `std::fs` module.
+
+#![stable(feature = "rust1", since = "1.0.0")]
+
+use fs::{self, Permissions, OpenOptions};
+use io;
+use path::Path;
+use sys;
+use sys_common::{FromInner, AsInner, AsInnerMut};
+
+/// Unix-specific extensions to `Permissions`
+#[stable(feature = "fs_ext", since = "1.1.0")]
+pub trait PermissionsExt {
+    /// Returns the underlying raw `mode_t` bits that are the standard Unix
+    /// permissions for this file.
+    ///
+    /// # Examples
+    ///
+    /// ```rust,ignore
+    /// use std::fs::File;
+    /// use std::os::unix::fs::PermissionsExt;
+    ///
+    /// let f = try!(File::create("foo.txt"));
+    /// let metadata = try!(f.metadata());
+    /// let permissions = metadata.permissions();
+    ///
+    /// println!("permissions: {}", permissions.mode());
+    /// ```
+    #[stable(feature = "fs_ext", since = "1.1.0")]
+    fn mode(&self) -> u32;
+
+    /// Sets the underlying raw bits for this set of permissions.
+    ///
+    /// # Examples
+    ///
+    /// ```rust,ignore
+    /// use std::fs::File;
+    /// use std::os::unix::fs::PermissionsExt;
+    ///
+    /// let f = try!(File::create("foo.txt"));
+    /// let metadata = try!(f.metadata());
+    /// let mut permissions = metadata.permissions();
+    ///
+    /// permissions.set_mode(0o644); // Read/write for owner and read for others.
+    /// assert_eq!(permissions.mode(), 0o644);
+    /// ```
+    #[stable(feature = "fs_ext", since = "1.1.0")]
+    fn set_mode(&mut self, mode: u32);
+
+    /// Creates a new instance of `Permissions` from the given set of Unix
+    /// permission bits.
+    ///
+    /// # Examples
+    ///
+    /// ```rust,ignore
+    /// use std::fs::Permissions;
+    /// use std::os::unix::fs::PermissionsExt;
+    ///
+    /// // Read/write for owner and read for others.
+    /// let permissions = Permissions::from_mode(0o644);
+    /// assert_eq!(permissions.mode(), 0o644);
+    /// ```
+    #[stable(feature = "fs_ext", since = "1.1.0")]
+    fn from_mode(mode: u32) -> Self;
+}
+
+#[stable(feature = "fs_ext", since = "1.1.0")]
+impl PermissionsExt for Permissions {
+    fn mode(&self) -> u32 {
+        self.as_inner().mode()
+    }
+
+    fn set_mode(&mut self, mode: u32) {
+        *self = Permissions::from_inner(FromInner::from_inner(mode));
+    }
+
+    fn from_mode(mode: u32) -> Permissions {
+        Permissions::from_inner(FromInner::from_inner(mode))
+    }
+}
+
+/// Unix-specific extensions to `OpenOptions`
+#[stable(feature = "fs_ext", since = "1.1.0")]
+pub trait OpenOptionsExt {
+    /// Sets the mode bits that a new file will be created with.
+    ///
+    /// If a new file is created as part of a `File::open_opts` call then this
+    /// specified `mode` will be used as the permission bits for the new file.
+    /// If no `mode` is set, the default of `0o666` will be used.
+    /// The operating system masks out bits with the systems `umask`, to produce
+    /// the final permissions.
+    ///
+    /// # Examples
+    ///
+    /// ```rust,ignore
+    /// extern crate libc;
+    /// use std::fs::OpenOptions;
+    /// use std::os::unix::fs::OpenOptionsExt;
+    ///
+    /// let mut options = OpenOptions::new();
+    /// options.mode(0o644); // Give read/write for owner and read for others.
+    /// let file = options.open("foo.txt");
+    /// ```
+    #[stable(feature = "fs_ext", since = "1.1.0")]
+    fn mode(&mut self, mode: u32) -> &mut Self;
+
+    /// Pass custom flags to the `flags` agument of `open`.
+    ///
+    /// The bits that define the access mode are masked out with `O_ACCMODE`, to
+    /// ensure they do not interfere with the access mode set by Rusts options.
+    ///
+    /// Custom flags can only set flags, not remove flags set by Rusts options.
+    /// This options overwrites any previously set custom flags.
+    ///
+    /// # Examples
+    ///
+    /// ```rust,ignore
+    /// extern crate libc;
+    /// use std::fs::OpenOptions;
+    /// use std::os::unix::fs::OpenOptionsExt;
+    ///
+    /// let mut options = OpenOptions::new();
+    /// options.write(true);
+    /// if cfg!(unix) {
+    ///     options.custom_flags(libc::O_NOFOLLOW);
+    /// }
+    /// let file = options.open("foo.txt");
+    /// ```
+    #[stable(feature = "open_options_ext", since = "1.10.0")]
+    fn custom_flags(&mut self, flags: i32) -> &mut Self;
+}
+
+#[stable(feature = "fs_ext", since = "1.1.0")]
+impl OpenOptionsExt for OpenOptions {
+    fn mode(&mut self, mode: u32) -> &mut OpenOptions {
+        self.as_inner_mut().mode(mode); self
+    }
+
+    fn custom_flags(&mut self, flags: i32) -> &mut OpenOptions {
+        self.as_inner_mut().custom_flags(flags); self
+    }
+}
+
+// Hm, why are there casts here to the returned type, shouldn't the types always
+// be the same? Right you are! Turns out, however, on android at least the types
+// in the raw `stat` structure are not the same as the types being returned. Who
+// knew!
+//
+// As a result to make sure this compiles for all platforms we do the manual
+// casts and rely on manual lowering to `stat` if the raw type is desired.
+#[stable(feature = "metadata_ext", since = "1.1.0")]
+pub trait MetadataExt {
+    #[stable(feature = "metadata_ext", since = "1.1.0")]
+    fn mode(&self) -> u32;
+    #[stable(feature = "metadata_ext", since = "1.1.0")]
+    fn uid(&self) -> u32;
+    #[stable(feature = "metadata_ext", since = "1.1.0")]
+    fn gid(&self) -> u32;
+    #[stable(feature = "metadata_ext", since = "1.1.0")]
+    fn size(&self) -> u64;
+    #[stable(feature = "metadata_ext", since = "1.1.0")]
+    fn atime(&self) -> i64;
+    #[stable(feature = "metadata_ext", since = "1.1.0")]
+    fn atime_nsec(&self) -> i64;
+    #[stable(feature = "metadata_ext", since = "1.1.0")]
+    fn mtime(&self) -> i64;
+    #[stable(feature = "metadata_ext", since = "1.1.0")]
+    fn mtime_nsec(&self) -> i64;
+    #[stable(feature = "metadata_ext", since = "1.1.0")]
+    fn ctime(&self) -> i64;
+    #[stable(feature = "metadata_ext", since = "1.1.0")]
+    fn ctime_nsec(&self) -> i64;
+}
+
+#[stable(feature = "metadata_ext", since = "1.1.0")]
+impl MetadataExt for fs::Metadata {
+    fn mode(&self) -> u32 {
+        self.as_inner().as_inner().st_mode as u32
+    }
+    fn uid(&self) -> u32 {
+        self.as_inner().as_inner().st_uid as u32
+    }
+    fn gid(&self) -> u32 {
+        self.as_inner().as_inner().st_gid as u32
+    }
+    fn size(&self) -> u64 {
+        self.as_inner().as_inner().st_size as u64
+    }
+    fn atime(&self) -> i64 {
+        self.as_inner().as_inner().st_atime as i64
+    }
+    fn atime_nsec(&self) -> i64 {
+        self.as_inner().as_inner().st_atime_nsec as i64
+    }
+    fn mtime(&self) -> i64 {
+        self.as_inner().as_inner().st_mtime as i64
+    }
+    fn mtime_nsec(&self) -> i64 {
+        self.as_inner().as_inner().st_mtime_nsec as i64
+    }
+    fn ctime(&self) -> i64 {
+        self.as_inner().as_inner().st_ctime as i64
+    }
+    fn ctime_nsec(&self) -> i64 {
+        self.as_inner().as_inner().st_ctime_nsec as i64
+    }
+}
+
+/// Add special unix types (block/char device, fifo and socket)
+#[stable(feature = "file_type_ext", since = "1.5.0")]
+pub trait FileTypeExt {
+    /// Returns whether this file type is a block device.
+    #[stable(feature = "file_type_ext", since = "1.5.0")]
+    fn is_block_device(&self) -> bool;
+    /// Returns whether this file type is a char device.
+    #[stable(feature = "file_type_ext", since = "1.5.0")]
+    fn is_char_device(&self) -> bool;
+    /// Returns whether this file type is a fifo.
+    #[stable(feature = "file_type_ext", since = "1.5.0")]
+    fn is_fifo(&self) -> bool;
+    /// Returns whether this file type is a socket.
+    #[stable(feature = "file_type_ext", since = "1.5.0")]
+    fn is_socket(&self) -> bool;
+}
+
+#[stable(feature = "file_type_ext", since = "1.5.0")]
+impl FileTypeExt for fs::FileType {
+    fn is_block_device(&self) -> bool { false /*FIXME: Implement block device mode*/ }
+    fn is_char_device(&self) -> bool { false /*FIXME: Implement char device mode*/ }
+    fn is_fifo(&self) -> bool { false /*FIXME: Implement fifo mode*/ }
+    fn is_socket(&self) -> bool { false /*FIXME: Implement socket mode*/ }
+}
+
+/// Creates a new symbolic link on the filesystem.
+///
+/// The `dst` path will be a symbolic link pointing to the `src` path.
+///
+/// # Note
+///
+/// On Windows, you must specify whether a symbolic link points to a file
+/// or directory.  Use `os::windows::fs::symlink_file` to create a
+/// symbolic link to a file, or `os::windows::fs::symlink_dir` to create a
+/// symbolic link to a directory.  Additionally, the process must have
+/// `SeCreateSymbolicLinkPrivilege` in order to be able to create a
+/// symbolic link.
+///
+/// # Examples
+///
+/// ```
+/// use std::os::unix::fs;
+///
+/// # fn foo() -> std::io::Result<()> {
+/// try!(fs::symlink("a.txt", "b.txt"));
+/// # Ok(())
+/// # }
+/// ```
+#[stable(feature = "symlink", since = "1.1.0")]
+pub fn symlink<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> io::Result<()>
+{
+    sys::fs::symlink(src.as_ref(), dst.as_ref())
+}
+
+#[stable(feature = "dir_builder", since = "1.6.0")]
+/// An extension trait for `fs::DirBuilder` for unix-specific options.
+pub trait DirBuilderExt {
+    /// Sets the mode to create new directories with. This option defaults to
+    /// 0o777.
+    ///
+    /// # Examples
+    ///
+    /// ```ignore
+    /// use std::fs::DirBuilder;
+    /// use std::os::unix::fs::DirBuilderExt;
+    ///
+    /// let mut builder = DirBuilder::new();
+    /// builder.mode(0o755);
+    /// ```
+    #[stable(feature = "dir_builder", since = "1.6.0")]
+    fn mode(&mut self, mode: u32) -> &mut Self;
+}
+
+#[stable(feature = "dir_builder", since = "1.6.0")]
+impl DirBuilderExt for fs::DirBuilder {
+    fn mode(&mut self, mode: u32) -> &mut fs::DirBuilder {
+        self.as_inner_mut().set_mode(mode);
+        self
+    }
+}
diff --git a/src/libstd/sys/redox/ext/io.rs b/src/libstd/sys/redox/ext/io.rs
new file mode 100644
index 00000000000..8e7cc593dbd
--- /dev/null
+++ b/src/libstd/sys/redox/ext/io.rs
@@ -0,0 +1,151 @@
+// 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.
+
+//! Unix-specific extensions to general I/O primitives
+
+#![stable(feature = "rust1", since = "1.0.0")]
+
+use fs;
+use net;
+use sys;
+use sys_common::{self, AsInner, FromInner, IntoInner};
+
+/// Raw file descriptors.
+#[stable(feature = "rust1", since = "1.0.0")]
+pub type RawFd = usize;
+
+/// A trait to extract the raw unix file descriptor from an underlying
+/// object.
+///
+/// This is only available on unix platforms and must be imported in order
+/// to call the method. Windows platforms have a corresponding `AsRawHandle`
+/// and `AsRawSocket` set of traits.
+#[stable(feature = "rust1", since = "1.0.0")]
+pub trait AsRawFd {
+    /// Extracts the raw file descriptor.
+    ///
+    /// This method does **not** pass ownership of the raw file descriptor
+    /// to the caller. The descriptor is only guaranteed to be valid while
+    /// the original object has not yet been destroyed.
+    #[stable(feature = "rust1", since = "1.0.0")]
+    fn as_raw_fd(&self) -> RawFd;
+}
+
+/// A trait to express the ability to construct an object from a raw file
+/// descriptor.
+#[stable(feature = "from_raw_os", since = "1.1.0")]
+pub trait FromRawFd {
+    /// Constructs a new instances of `Self` from the given raw file
+    /// descriptor.
+    ///
+    /// This function **consumes ownership** of the specified file
+    /// descriptor. The returned object will take responsibility for closing
+    /// it when the object goes out of scope.
+    ///
+    /// This function is also unsafe as the primitives currently returned
+    /// have the contract that they are the sole owner of the file
+    /// descriptor they are wrapping. Usage of this function could
+    /// accidentally allow violating this contract which can cause memory
+    /// unsafety in code that relies on it being true.
+    #[stable(feature = "from_raw_os", since = "1.1.0")]
+    unsafe fn from_raw_fd(fd: RawFd) -> Self;
+}
+
+/// A trait to express the ability to consume an object and acquire ownership of
+/// its raw file descriptor.
+#[stable(feature = "into_raw_os", since = "1.4.0")]
+pub trait IntoRawFd {
+    /// Consumes this object, returning the raw underlying file descriptor.
+    ///
+    /// This function **transfers ownership** of the underlying file descriptor
+    /// to the caller. Callers are then the unique owners of the file descriptor
+    /// and must close the descriptor once it's no longer needed.
+    #[stable(feature = "into_raw_os", since = "1.4.0")]
+    fn into_raw_fd(self) -> RawFd;
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl AsRawFd for fs::File {
+    fn as_raw_fd(&self) -> RawFd {
+        self.as_inner().fd().raw()
+    }
+}
+#[stable(feature = "from_raw_os", since = "1.1.0")]
+impl FromRawFd for fs::File {
+    unsafe fn from_raw_fd(fd: RawFd) -> fs::File {
+        fs::File::from_inner(sys::fs::File::from_inner(fd))
+    }
+}
+#[stable(feature = "into_raw_os", since = "1.4.0")]
+impl IntoRawFd for fs::File {
+    fn into_raw_fd(self) -> RawFd {
+        self.into_inner().into_fd().into_raw()
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl AsRawFd for net::TcpStream {
+    fn as_raw_fd(&self) -> RawFd {
+        self.as_inner().as_inner().fd().raw()
+    }
+}
+#[stable(feature = "rust1", since = "1.0.0")]
+impl AsRawFd for net::TcpListener {
+    fn as_raw_fd(&self) -> RawFd {
+        self.as_inner().as_inner().fd().raw()
+    }
+}
+#[stable(feature = "rust1", since = "1.0.0")]
+impl AsRawFd for net::UdpSocket {
+    fn as_raw_fd(&self) -> RawFd {
+        self.as_inner().as_inner().fd().raw()
+    }
+}
+
+#[stable(feature = "from_raw_os", since = "1.1.0")]
+impl FromRawFd for net::TcpStream {
+    unsafe fn from_raw_fd(fd: RawFd) -> net::TcpStream {
+        let file = sys::fs::File::from_inner(fd);
+        net::TcpStream::from_inner(sys_common::net::TcpStream::from_inner(file))
+    }
+}
+#[stable(feature = "from_raw_os", since = "1.1.0")]
+impl FromRawFd for net::TcpListener {
+    unsafe fn from_raw_fd(fd: RawFd) -> net::TcpListener {
+        let file = sys::fs::File::from_inner(fd);
+        net::TcpListener::from_inner(sys_common::net::TcpListener::from_inner(file))
+    }
+}
+#[stable(feature = "from_raw_os", since = "1.1.0")]
+impl FromRawFd for net::UdpSocket {
+    unsafe fn from_raw_fd(fd: RawFd) -> net::UdpSocket {
+        let file = sys::fs::File::from_inner(fd);
+        net::UdpSocket::from_inner(sys_common::net::UdpSocket::from_inner(file))
+    }
+}
+
+#[stable(feature = "into_raw_os", since = "1.4.0")]
+impl IntoRawFd for net::TcpStream {
+    fn into_raw_fd(self) -> RawFd {
+        self.into_inner().into_inner().into_fd().into_raw()
+    }
+}
+#[stable(feature = "into_raw_os", since = "1.4.0")]
+impl IntoRawFd for net::TcpListener {
+    fn into_raw_fd(self) -> RawFd {
+        self.into_inner().into_inner().into_fd().into_raw()
+    }
+}
+#[stable(feature = "into_raw_os", since = "1.4.0")]
+impl IntoRawFd for net::UdpSocket {
+    fn into_raw_fd(self) -> RawFd {
+        self.into_inner().into_inner().into_fd().into_raw()
+    }
+}
diff --git a/src/libstd/sys/redox/ext/mod.rs b/src/libstd/sys/redox/ext/mod.rs
new file mode 100644
index 00000000000..513ef272e97
--- /dev/null
+++ b/src/libstd/sys/redox/ext/mod.rs
@@ -0,0 +1,50 @@
+// 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.
+
+//! Experimental extensions to `std` for Unix platforms.
+//!
+//! For now, this module is limited to extracting file descriptors,
+//! but its functionality will grow over time.
+//!
+//! # Example
+//!
+//! ```no_run
+//! use std::fs::File;
+//! use std::os::unix::prelude::*;
+//!
+//! fn main() {
+//!     let f = File::create("foo.txt").unwrap();
+//!     let fd = f.as_raw_fd();
+//!
+//!     // use fd with native unix bindings
+//! }
+//! ```
+
+#![stable(feature = "rust1", since = "1.0.0")]
+
+pub mod ffi;
+pub mod fs;
+pub mod io;
+pub mod process;
+
+/// A prelude for conveniently writing platform-specific code.
+///
+/// Includes all extension traits, and some important type definitions.
+#[stable(feature = "rust1", since = "1.0.0")]
+pub mod prelude {
+    #[doc(no_inline)] #[stable(feature = "rust1", since = "1.0.0")]
+    pub use super::io::{RawFd, AsRawFd, FromRawFd, IntoRawFd};
+    #[doc(no_inline)] #[stable(feature = "rust1", since = "1.0.0")]
+    pub use super::ffi::{OsStrExt, OsStringExt};
+    #[doc(no_inline)] #[stable(feature = "rust1", since = "1.0.0")]
+    pub use super::fs::{FileTypeExt, PermissionsExt, OpenOptionsExt, MetadataExt};
+    #[doc(no_inline)] #[stable(feature = "rust1", since = "1.0.0")]
+    pub use super::process::{CommandExt, ExitStatusExt};
+}
diff --git a/src/libstd/sys/redox/ext/process.rs b/src/libstd/sys/redox/ext/process.rs
new file mode 100644
index 00000000000..c59524974bf
--- /dev/null
+++ b/src/libstd/sys/redox/ext/process.rs
@@ -0,0 +1,183 @@
+// 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.
+
+//! Unix-specific extensions to primitives in the `std::process` module.
+
+#![stable(feature = "rust1", since = "1.0.0")]
+
+use io;
+use os::unix::io::{FromRawFd, RawFd, AsRawFd, IntoRawFd};
+use process;
+use sys;
+use sys_common::{AsInnerMut, AsInner, FromInner, IntoInner};
+
+/// Unix-specific extensions to the `std::process::Command` builder
+#[stable(feature = "rust1", since = "1.0.0")]
+pub trait CommandExt {
+    /// Sets the child process's user id. This translates to a
+    /// `setuid` call in the child process. Failure in the `setuid`
+    /// call will cause the spawn to fail.
+    #[stable(feature = "rust1", since = "1.0.0")]
+    fn uid(&mut self, id: u32) -> &mut process::Command;
+
+    /// Similar to `uid`, but sets the group id of the child process. This has
+    /// the same semantics as the `uid` field.
+    #[stable(feature = "rust1", since = "1.0.0")]
+    fn gid(&mut self, id: u32) -> &mut process::Command;
+
+    /// Schedules a closure to be run just before the `exec` function is
+    /// invoked.
+    ///
+    /// The closure is allowed to return an I/O error whose OS error code will
+    /// be communicated back to the parent and returned as an error from when
+    /// the spawn was requested.
+    ///
+    /// Multiple closures can be registered and they will be called in order of
+    /// their registration. If a closure returns `Err` then no further closures
+    /// will be called and the spawn operation will immediately return with a
+    /// failure.
+    ///
+    /// # Notes
+    ///
+    /// This closure will be run in the context of the child process after a
+    /// `fork`. This primarily means that any modificatons made to memory on
+    /// behalf of this closure will **not** be visible to the parent process.
+    /// This is often a very constrained environment where normal operations
+    /// like `malloc` or acquiring a mutex are not guaranteed to work (due to
+    /// other threads perhaps still running when the `fork` was run).
+    ///
+    /// When this closure is run, aspects such as the stdio file descriptors and
+    /// working directory have successfully been changed, so output to these
+    /// locations may not appear where intended.
+    #[stable(feature = "process_exec", since = "1.15.0")]
+    fn before_exec<F>(&mut self, f: F) -> &mut process::Command
+        where F: FnMut() -> io::Result<()> + Send + Sync + 'static;
+
+    /// Performs all the required setup by this `Command`, followed by calling
+    /// the `execvp` syscall.
+    ///
+    /// On success this function will not return, and otherwise it will return
+    /// an error indicating why the exec (or another part of the setup of the
+    /// `Command`) failed.
+    ///
+    /// This function, unlike `spawn`, will **not** `fork` the process to create
+    /// a new child. Like spawn, however, the default behavior for the stdio
+    /// descriptors will be to inherited from the current process.
+    ///
+    /// # Notes
+    ///
+    /// The process may be in a "broken state" if this function returns in
+    /// error. For example the working directory, environment variables, signal
+    /// handling settings, various user/group information, or aspects of stdio
+    /// file descriptors may have changed. If a "transactional spawn" is
+    /// required to gracefully handle errors it is recommended to use the
+    /// cross-platform `spawn` instead.
+    #[stable(feature = "process_exec2", since = "1.9.0")]
+    fn exec(&mut self) -> io::Error;
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl CommandExt for process::Command {
+    fn uid(&mut self, id: u32) -> &mut process::Command {
+        self.as_inner_mut().uid(id);
+        self
+    }
+
+    fn gid(&mut self, id: u32) -> &mut process::Command {
+        self.as_inner_mut().gid(id);
+        self
+    }
+
+    fn before_exec<F>(&mut self, f: F) -> &mut process::Command
+        where F: FnMut() -> io::Result<()> + Send + Sync + 'static
+    {
+        self.as_inner_mut().before_exec(Box::new(f));
+        self
+    }
+
+    fn exec(&mut self) -> io::Error {
+        self.as_inner_mut().exec(sys::process::Stdio::Inherit)
+    }
+}
+
+/// Unix-specific extensions to `std::process::ExitStatus`
+#[stable(feature = "rust1", since = "1.0.0")]
+pub trait ExitStatusExt {
+    /// Creates a new `ExitStatus` from the raw underlying `i32` return value of
+    /// a process.
+    #[stable(feature = "exit_status_from", since = "1.12.0")]
+    fn from_raw(raw: i32) -> Self;
+
+    /// If the process was terminated by a signal, returns that signal.
+    #[stable(feature = "rust1", since = "1.0.0")]
+    fn signal(&self) -> Option<i32>;
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl ExitStatusExt for process::ExitStatus {
+    fn from_raw(raw: i32) -> Self {
+        process::ExitStatus::from_inner(From::from(raw))
+    }
+
+    fn signal(&self) -> Option<i32> {
+        self.as_inner().signal()
+    }
+}
+
+#[stable(feature = "process_extensions", since = "1.2.0")]
+impl FromRawFd for process::Stdio {
+    unsafe fn from_raw_fd(fd: RawFd) -> process::Stdio {
+        let fd = sys::fd::FileDesc::new(fd);
+        let io = sys::process::Stdio::Fd(fd);
+        process::Stdio::from_inner(io)
+    }
+}
+
+#[stable(feature = "process_extensions", since = "1.2.0")]
+impl AsRawFd for process::ChildStdin {
+    fn as_raw_fd(&self) -> RawFd {
+        self.as_inner().fd().raw()
+    }
+}
+
+#[stable(feature = "process_extensions", since = "1.2.0")]
+impl AsRawFd for process::ChildStdout {
+    fn as_raw_fd(&self) -> RawFd {
+        self.as_inner().fd().raw()
+    }
+}
+
+#[stable(feature = "process_extensions", since = "1.2.0")]
+impl AsRawFd for process::ChildStderr {
+    fn as_raw_fd(&self) -> RawFd {
+        self.as_inner().fd().raw()
+    }
+}
+
+#[stable(feature = "into_raw_os", since = "1.4.0")]
+impl IntoRawFd for process::ChildStdin {
+    fn into_raw_fd(self) -> RawFd {
+        self.into_inner().into_fd().into_raw()
+    }
+}
+
+#[stable(feature = "into_raw_os", since = "1.4.0")]
+impl IntoRawFd for process::ChildStdout {
+    fn into_raw_fd(self) -> RawFd {
+        self.into_inner().into_fd().into_raw()
+    }
+}
+
+#[stable(feature = "into_raw_os", since = "1.4.0")]
+impl IntoRawFd for process::ChildStderr {
+    fn into_raw_fd(self) -> RawFd {
+        self.into_inner().into_fd().into_raw()
+    }
+}
diff --git a/src/libstd/sys/redox/fast_thread_local.rs b/src/libstd/sys/redox/fast_thread_local.rs
new file mode 100644
index 00000000000..6eeae2d90ea
--- /dev/null
+++ b/src/libstd/sys/redox/fast_thread_local.rs
@@ -0,0 +1,116 @@
+// 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(target_thread_local)]
+#![unstable(feature = "thread_local_internals", issue = "0")]
+
+use cell::{Cell, UnsafeCell};
+use intrinsics;
+use ptr;
+
+pub struct Key<T> {
+    inner: UnsafeCell<Option<T>>,
+
+    // Metadata to keep track of the state of the destructor. Remember that
+    // these variables are thread-local, not global.
+    dtor_registered: Cell<bool>,
+    dtor_running: Cell<bool>,
+}
+
+unsafe impl<T> ::marker::Sync for Key<T> { }
+
+impl<T> Key<T> {
+    pub const fn new() -> Key<T> {
+        Key {
+            inner: UnsafeCell::new(None),
+            dtor_registered: Cell::new(false),
+            dtor_running: Cell::new(false)
+        }
+    }
+
+    pub fn get(&'static self) -> Option<&'static UnsafeCell<Option<T>>> {
+        unsafe {
+            if intrinsics::needs_drop::<T>() && self.dtor_running.get() {
+                return None
+            }
+            self.register_dtor();
+        }
+        Some(&self.inner)
+    }
+
+    unsafe fn register_dtor(&self) {
+        if !intrinsics::needs_drop::<T>() || self.dtor_registered.get() {
+            return
+        }
+
+        register_dtor(self as *const _ as *mut u8,
+                      destroy_value::<T>);
+        self.dtor_registered.set(true);
+    }
+}
+
+unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern fn(*mut u8)) {
+    // The fallback implementation uses a vanilla OS-based TLS key to track
+    // the list of destructors that need to be run for this thread. The key
+    // then has its own destructor which runs all the other destructors.
+    //
+    // The destructor for DTORS is a little special in that it has a `while`
+    // loop to continuously drain the list of registered destructors. It
+    // *should* be the case that this loop always terminates because we
+    // provide the guarantee that a TLS key cannot be set after it is
+    // flagged for destruction.
+    use sys_common::thread_local as os;
+
+    static DTORS: os::StaticKey = os::StaticKey::new(Some(run_dtors));
+    type List = Vec<(*mut u8, unsafe extern fn(*mut u8))>;
+    if DTORS.get().is_null() {
+        let v: Box<List> = box Vec::new();
+        DTORS.set(Box::into_raw(v) as *mut u8);
+    }
+    let list: &mut List = &mut *(DTORS.get() as *mut List);
+    list.push((t, dtor));
+
+    unsafe extern fn run_dtors(mut ptr: *mut u8) {
+        while !ptr.is_null() {
+            let list: Box<List> = Box::from_raw(ptr as *mut List);
+            for &(ptr, dtor) in list.iter() {
+                dtor(ptr);
+            }
+            ptr = DTORS.get();
+            DTORS.set(ptr::null_mut());
+        }
+    }
+}
+
+pub unsafe extern fn destroy_value<T>(ptr: *mut u8) {
+    let ptr = ptr as *mut Key<T>;
+    // Right before we run the user destructor be sure to flag the
+    // destructor as running for this thread so calls to `get` will return
+    // `None`.
+    (*ptr).dtor_running.set(true);
+
+    // The OSX implementation of TLS apparently had an odd aspect to it
+    // where the pointer we have may be overwritten while this destructor
+    // is running. Specifically if a TLS destructor re-accesses TLS it may
+    // trigger a re-initialization of all TLS variables, paving over at
+    // least some destroyed ones with initial values.
+    //
+    // This means that if we drop a TLS value in place on OSX that we could
+    // revert the value to its original state halfway through the
+    // destructor, which would be bad!
+    //
+    // Hence, we use `ptr::read` on OSX (to move to a "safe" location)
+    // instead of drop_in_place.
+    if cfg!(target_os = "macos") {
+        ptr::read((*ptr).inner.get());
+    } else {
+        ptr::drop_in_place((*ptr).inner.get());
+    }
+}
diff --git a/src/libstd/sys/redox/fd.rs b/src/libstd/sys/redox/fd.rs
new file mode 100644
index 00000000000..b6de68a9dc1
--- /dev/null
+++ b/src/libstd/sys/redox/fd.rs
@@ -0,0 +1,100 @@
+// 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.
+
+#![unstable(reason = "not public", issue = "0", feature = "fd")]
+
+use io::{self, Read};
+use mem;
+use sys::{cvt, syscall};
+use sys_common::AsInner;
+use sys_common::io::read_to_end_uninitialized;
+
+pub struct FileDesc {
+    fd: usize,
+}
+
+impl FileDesc {
+    pub fn new(fd: usize) -> FileDesc {
+        FileDesc { fd: fd }
+    }
+
+    pub fn raw(&self) -> usize { self.fd }
+
+    /// Extracts the actual filedescriptor without closing it.
+    pub fn into_raw(self) -> usize {
+        let fd = self.fd;
+        mem::forget(self);
+        fd
+    }
+
+    pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
+        cvt(syscall::read(self.fd, buf))
+    }
+
+    pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> {
+        let mut me = self;
+        (&mut me).read_to_end(buf)
+    }
+
+    pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
+        cvt(syscall::write(self.fd, buf))
+    }
+
+    pub fn duplicate(&self) -> io::Result<FileDesc> {
+        let new_fd = cvt(syscall::dup(self.fd, &[]))?;
+        Ok(FileDesc::new(new_fd))
+    }
+
+    pub fn nonblocking(&self) -> io::Result<bool> {
+        let flags = cvt(syscall::fcntl(self.fd, syscall::F_GETFL, 0))?;
+        Ok(flags & syscall::O_NONBLOCK == syscall::O_NONBLOCK)
+    }
+
+    pub fn set_cloexec(&self) -> io::Result<()> {
+        let mut flags = cvt(syscall::fcntl(self.fd, syscall::F_GETFL, 0))?;
+        flags |= syscall::O_CLOEXEC;
+        cvt(syscall::fcntl(self.fd, syscall::F_SETFL, flags)).and(Ok(()))
+    }
+
+    pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
+        let mut flags = cvt(syscall::fcntl(self.fd, syscall::F_GETFL, 0))?;
+        if nonblocking {
+            flags |= syscall::O_NONBLOCK;
+        } else {
+            flags &= !syscall::O_NONBLOCK;
+        }
+        cvt(syscall::fcntl(self.fd, syscall::F_SETFL, flags)).and(Ok(()))
+    }
+}
+
+impl<'a> Read for &'a FileDesc {
+    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
+        (**self).read(buf)
+    }
+
+    fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
+        unsafe { read_to_end_uninitialized(self, buf) }
+    }
+}
+
+impl AsInner<usize> for FileDesc {
+    fn as_inner(&self) -> &usize { &self.fd }
+}
+
+impl Drop for FileDesc {
+    fn drop(&mut self) {
+        // Note that errors are ignored when closing a file descriptor. The
+        // reason for this is that if an error occurs we don't actually know if
+        // the file descriptor was closed or not, and if we retried (for
+        // something like EINTR), we might close another valid file descriptor
+        // (opened after we closed ours.
+        let _ = syscall::close(self.fd);
+    }
+}
diff --git a/src/libstd/sys/redox/fs.rs b/src/libstd/sys/redox/fs.rs
new file mode 100644
index 00000000000..a8391d2b898
--- /dev/null
+++ b/src/libstd/sys/redox/fs.rs
@@ -0,0 +1,470 @@
+// 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.
+
+use os::unix::prelude::*;
+
+use ffi::{OsString, OsStr};
+use fmt;
+use io::{self, Error, ErrorKind, SeekFrom};
+use path::{Path, PathBuf};
+use sync::Arc;
+use sys::fd::FileDesc;
+use sys::time::SystemTime;
+use sys::{cvt, syscall};
+use sys_common::{AsInner, FromInner};
+
+pub struct File(FileDesc);
+
+#[derive(Clone)]
+pub struct FileAttr {
+    stat: syscall::Stat,
+}
+
+pub struct ReadDir {
+    data: Vec<u8>,
+    i: usize,
+    root: Arc<PathBuf>,
+}
+
+struct Dir(FileDesc);
+
+unsafe impl Send for Dir {}
+unsafe impl Sync for Dir {}
+
+pub struct DirEntry {
+    root: Arc<PathBuf>,
+    name: Box<[u8]>
+}
+
+#[derive(Clone, Debug)]
+pub struct OpenOptions {
+    // generic
+    read: bool,
+    write: bool,
+    append: bool,
+    truncate: bool,
+    create: bool,
+    create_new: bool,
+    // system-specific
+    custom_flags: i32,
+    mode: u16,
+}
+
+#[derive(Clone, PartialEq, Eq, Debug)]
+pub struct FilePermissions { mode: u16 }
+
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
+pub struct FileType { mode: u16 }
+
+#[derive(Debug)]
+pub struct DirBuilder { mode: u16 }
+
+impl FileAttr {
+    pub fn size(&self) -> u64 { self.stat.st_size as u64 }
+    pub fn perm(&self) -> FilePermissions {
+        FilePermissions { mode: (self.stat.st_mode as u16) & 0o777 }
+    }
+
+    pub fn file_type(&self) -> FileType {
+        FileType { mode: self.stat.st_mode as u16 }
+    }
+}
+
+impl FileAttr {
+    pub fn modified(&self) -> io::Result<SystemTime> {
+        Ok(SystemTime::from(syscall::TimeSpec {
+            tv_sec: self.stat.st_mtime as i64,
+            tv_nsec: self.stat.st_mtime_nsec as i32,
+        }))
+    }
+
+    pub fn accessed(&self) -> io::Result<SystemTime> {
+        Ok(SystemTime::from(syscall::TimeSpec {
+            tv_sec: self.stat.st_atime as i64,
+            tv_nsec: self.stat.st_atime_nsec as i32,
+        }))
+    }
+
+    pub fn created(&self) -> io::Result<SystemTime> {
+        Ok(SystemTime::from(syscall::TimeSpec {
+            tv_sec: self.stat.st_ctime as i64,
+            tv_nsec: self.stat.st_ctime_nsec as i32,
+        }))
+    }
+}
+
+impl AsInner<syscall::Stat> for FileAttr {
+    fn as_inner(&self) -> &syscall::Stat { &self.stat }
+}
+
+impl FilePermissions {
+    pub fn readonly(&self) -> bool { self.mode & 0o222 == 0 }
+    pub fn set_readonly(&mut self, readonly: bool) {
+        if readonly {
+            self.mode &= !0o222;
+        } else {
+            self.mode |= 0o222;
+        }
+    }
+    pub fn mode(&self) -> u32 { self.mode as u32 }
+}
+
+impl FileType {
+    pub fn is_dir(&self) -> bool { self.is(syscall::MODE_DIR) }
+    pub fn is_file(&self) -> bool { self.is(syscall::MODE_FILE) }
+    pub fn is_symlink(&self) -> bool { false /*FIXME: Implement symlink mode*/ }
+
+    pub fn is(&self, mode: u16) -> bool {
+        self.mode & (syscall::MODE_DIR | syscall::MODE_FILE) == mode
+    }
+}
+
+impl FromInner<u32> for FilePermissions {
+    fn from_inner(mode: u32) -> FilePermissions {
+        FilePermissions { mode: mode as u16 }
+    }
+}
+
+impl fmt::Debug for ReadDir {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        // This will only be called from std::fs::ReadDir, which will add a "ReadDir()" frame.
+        // Thus the result will be e g 'ReadDir("/home")'
+        fmt::Debug::fmt(&*self.root, f)
+    }
+}
+
+impl Iterator for ReadDir {
+    type Item = io::Result<DirEntry>;
+
+    fn next(&mut self) -> Option<io::Result<DirEntry>> {
+        loop {
+            let start = self.i;
+            let mut i = self.i;
+            while i < self.data.len() {
+                self.i += 1;
+                if self.data[i] == b'\n' {
+                    break;
+                }
+                i += 1;
+            }
+            if start < self.i {
+                let ret = DirEntry {
+                    name: self.data[start .. i].to_owned().into_boxed_slice(),
+                    root: self.root.clone()
+                };
+                if ret.name_bytes() != b"." && ret.name_bytes() != b".." {
+                    return Some(Ok(ret))
+                }
+            } else {
+                return None;
+            }
+        }
+    }
+}
+
+impl DirEntry {
+    pub fn path(&self) -> PathBuf {
+        self.root.join(OsStr::from_bytes(self.name_bytes()))
+    }
+
+    pub fn file_name(&self) -> OsString {
+        OsStr::from_bytes(self.name_bytes()).to_os_string()
+    }
+
+    pub fn metadata(&self) -> io::Result<FileAttr> {
+        lstat(&self.path())
+    }
+
+    pub fn file_type(&self) -> io::Result<FileType> {
+        lstat(&self.path()).map(|m| m.file_type())
+    }
+
+    fn name_bytes(&self) -> &[u8] {
+        &*self.name
+    }
+}
+
+impl OpenOptions {
+    pub fn new() -> OpenOptions {
+        OpenOptions {
+            // generic
+            read: false,
+            write: false,
+            append: false,
+            truncate: false,
+            create: false,
+            create_new: false,
+            // system-specific
+            custom_flags: 0,
+            mode: 0o666,
+        }
+    }
+
+    pub fn read(&mut self, read: bool) { self.read = read; }
+    pub fn write(&mut self, write: bool) { self.write = write; }
+    pub fn append(&mut self, append: bool) { self.append = append; }
+    pub fn truncate(&mut self, truncate: bool) { self.truncate = truncate; }
+    pub fn create(&mut self, create: bool) { self.create = create; }
+    pub fn create_new(&mut self, create_new: bool) { self.create_new = create_new; }
+
+    pub fn custom_flags(&mut self, flags: i32) { self.custom_flags = flags; }
+    pub fn mode(&mut self, mode: u32) { self.mode = mode as u16; }
+
+    fn get_access_mode(&self) -> io::Result<usize> {
+        match (self.read, self.write, self.append) {
+            (true,  false, false) => Ok(syscall::O_RDONLY),
+            (false, true,  false) => Ok(syscall::O_WRONLY),
+            (true,  true,  false) => Ok(syscall::O_RDWR),
+            (false, _,     true)  => Ok(syscall::O_WRONLY | syscall::O_APPEND),
+            (true,  _,     true)  => Ok(syscall::O_RDWR | syscall::O_APPEND),
+            (false, false, false) => Err(Error::from_raw_os_error(syscall::EINVAL)),
+        }
+    }
+
+    fn get_creation_mode(&self) -> io::Result<usize> {
+        match (self.write, self.append) {
+            (true, false) => {}
+            (false, false) =>
+                if self.truncate || self.create || self.create_new {
+                    return Err(Error::from_raw_os_error(syscall::EINVAL));
+                },
+            (_, true) =>
+                if self.truncate && !self.create_new {
+                    return Err(Error::from_raw_os_error(syscall::EINVAL));
+                },
+        }
+
+        Ok(match (self.create, self.truncate, self.create_new) {
+                (false, false, false) => 0,
+                (true,  false, false) => syscall::O_CREAT,
+                (false, true,  false) => syscall::O_TRUNC,
+                (true,  true,  false) => syscall::O_CREAT | syscall::O_TRUNC,
+                (_,      _,    true)  => syscall::O_CREAT | syscall::O_EXCL,
+           })
+    }
+}
+
+impl File {
+    pub fn open(path: &Path, opts: &OpenOptions) -> io::Result<File> {
+        let flags = syscall::O_CLOEXEC |
+                    opts.get_access_mode()? as usize |
+                    opts.get_creation_mode()? as usize |
+                    (opts.custom_flags as usize & !syscall::O_ACCMODE);
+        let fd = cvt(syscall::open(path.to_str().unwrap(), flags | opts.mode as usize))?;
+        Ok(File(FileDesc::new(fd)))
+    }
+
+    pub fn file_attr(&self) -> io::Result<FileAttr> {
+        let mut stat = syscall::Stat::default();
+        cvt(syscall::fstat(self.0.raw(), &mut stat))?;
+        Ok(FileAttr { stat: stat })
+    }
+
+    pub fn fsync(&self) -> io::Result<()> {
+        cvt(syscall::fsync(self.0.raw()))?;
+        Ok(())
+    }
+
+    pub fn datasync(&self) -> io::Result<()> {
+        self.fsync()
+    }
+
+    pub fn truncate(&self, size: u64) -> io::Result<()> {
+        cvt(syscall::ftruncate(self.0.raw(), size as usize))?;
+        Ok(())
+    }
+
+    pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
+        self.0.read(buf)
+    }
+
+    pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> {
+        self.0.read_to_end(buf)
+    }
+
+    pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
+        self.0.write(buf)
+    }
+
+    pub fn flush(&self) -> io::Result<()> { Ok(()) }
+
+    pub fn seek(&self, pos: SeekFrom) -> io::Result<u64> {
+        let (whence, pos) = match pos {
+            // Casting to `i64` is fine, too large values will end up as
+            // negative which will cause an error in `lseek64`.
+            SeekFrom::Start(off) => (syscall::SEEK_SET, off as i64),
+            SeekFrom::End(off) => (syscall::SEEK_END, off),
+            SeekFrom::Current(off) => (syscall::SEEK_CUR, off),
+        };
+        let n = cvt(syscall::lseek(self.0.raw(), pos as isize, whence))?;
+        Ok(n as u64)
+    }
+
+    pub fn duplicate(&self) -> io::Result<File> {
+        self.0.duplicate().map(File)
+    }
+
+    pub fn dup(&self, buf: &[u8]) -> io::Result<File> {
+        let fd = cvt(syscall::dup(*self.fd().as_inner() as usize, buf))?;
+        Ok(File(FileDesc::new(fd)))
+    }
+
+    pub fn set_permissions(&self, perm: FilePermissions) -> io::Result<()> {
+        set_perm(&self.path()?, perm)
+    }
+
+    pub fn path(&self) -> io::Result<PathBuf> {
+        let mut buf: [u8; 4096] = [0; 4096];
+        let count = cvt(syscall::fpath(*self.fd().as_inner() as usize, &mut buf))?;
+        Ok(PathBuf::from(unsafe { String::from_utf8_unchecked(Vec::from(&buf[..count])) }))
+    }
+
+    pub fn fd(&self) -> &FileDesc { &self.0 }
+
+    pub fn into_fd(self) -> FileDesc { self.0 }
+}
+
+impl DirBuilder {
+    pub fn new() -> DirBuilder {
+        DirBuilder { mode: 0o777 }
+    }
+
+    pub fn mkdir(&self, p: &Path) -> io::Result<()> {
+        let flags = syscall::O_CREAT | syscall::O_CLOEXEC | syscall::O_DIRECTORY | syscall::O_EXCL;
+        let fd = cvt(syscall::open(p.to_str().unwrap(), flags | (self.mode as usize & 0o777)))?;
+        let _ = syscall::close(fd);
+        Ok(())
+    }
+
+    pub fn set_mode(&mut self, mode: u32) {
+        self.mode = mode as u16;
+    }
+}
+
+impl FromInner<usize> for File {
+    fn from_inner(fd: usize) -> File {
+        File(FileDesc::new(fd))
+    }
+}
+
+impl fmt::Debug for File {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        let mut b = f.debug_struct("File");
+        b.field("fd", &self.0.raw());
+        if let Ok(path) = self.path() {
+            b.field("path", &path);
+        }
+        /*
+        if let Some((read, write)) = get_mode(fd) {
+            b.field("read", &read).field("write", &write);
+        }
+        */
+        b.finish()
+    }
+}
+
+pub fn readdir(p: &Path) -> io::Result<ReadDir> {
+    let root = Arc::new(p.to_path_buf());
+
+    let flags = syscall::O_CLOEXEC | syscall::O_RDONLY | syscall::O_DIRECTORY;
+    let fd = cvt(syscall::open(p.to_str().unwrap(), flags))?;
+    let file = FileDesc::new(fd);
+    let mut data = Vec::new();
+    file.read_to_end(&mut data)?;
+
+    Ok(ReadDir { data: data, i: 0, root: root })
+}
+
+pub fn unlink(p: &Path) -> io::Result<()> {
+    cvt(syscall::unlink(p.to_str().unwrap()))?;
+    Ok(())
+}
+
+pub fn rename(_old: &Path, _new: &Path) -> io::Result<()> {
+    ::sys_common::util::dumb_print(format_args!("Rename\n"));
+    unimplemented!();
+}
+
+pub fn set_perm(p: &Path, perm: FilePermissions) -> io::Result<()> {
+    cvt(syscall::chmod(p.to_str().unwrap(), perm.mode as usize))?;
+    Ok(())
+}
+
+pub fn rmdir(p: &Path) -> io::Result<()> {
+    cvt(syscall::rmdir(p.to_str().unwrap()))?;
+    Ok(())
+}
+
+pub fn remove_dir_all(path: &Path) -> io::Result<()> {
+    let filetype = lstat(path)?.file_type();
+    if filetype.is_symlink() {
+        unlink(path)
+    } else {
+        remove_dir_all_recursive(path)
+    }
+}
+
+fn remove_dir_all_recursive(path: &Path) -> io::Result<()> {
+    for child in readdir(path)? {
+        let child = child?;
+        if child.file_type()?.is_dir() {
+            remove_dir_all_recursive(&child.path())?;
+        } else {
+            unlink(&child.path())?;
+        }
+    }
+    rmdir(path)
+}
+
+pub fn readlink(p: &Path) -> io::Result<PathBuf> {
+    canonicalize(p)
+}
+
+pub fn symlink(_src: &Path, _dst: &Path) -> io::Result<()> {
+    ::sys_common::util::dumb_print(format_args!("Symlink\n"));
+    unimplemented!();
+}
+
+pub fn link(_src: &Path, _dst: &Path) -> io::Result<()> {
+    ::sys_common::util::dumb_print(format_args!("Link\n"));
+    unimplemented!();
+}
+
+pub fn stat(p: &Path) -> io::Result<FileAttr> {
+    let fd = cvt(syscall::open(p.to_str().unwrap(), syscall::O_CLOEXEC | syscall::O_STAT))?;
+    let file = File(FileDesc::new(fd));
+    file.file_attr()
+}
+
+pub fn lstat(p: &Path) -> io::Result<FileAttr> {
+    stat(p)
+}
+
+pub fn canonicalize(p: &Path) -> io::Result<PathBuf> {
+    let fd = cvt(syscall::open(p.to_str().unwrap(), syscall::O_CLOEXEC | syscall::O_STAT))?;
+    let file = File(FileDesc::new(fd));
+    file.path()
+}
+
+pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
+    use fs::{File, set_permissions};
+    if !from.is_file() {
+        return Err(Error::new(ErrorKind::InvalidInput,
+                              "the source path is not an existing regular file"))
+    }
+
+    let mut reader = File::open(from)?;
+    let mut writer = File::create(to)?;
+    let perm = reader.metadata()?.permissions();
+
+    let ret = io::copy(&mut reader, &mut writer)?;
+    set_permissions(to, perm)?;
+    Ok(ret)
+}
diff --git a/src/libstd/sys/redox/memchr.rs b/src/libstd/sys/redox/memchr.rs
new file mode 100644
index 00000000000..4c314b7a472
--- /dev/null
+++ b/src/libstd/sys/redox/memchr.rs
@@ -0,0 +1,14 @@
+// Copyright 2015 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.
+//
+// Original implementation taken from rust-memchr
+// Copyright 2015 Andrew Gallant, bluss and Nicolas Koch
+
+pub use sys_common::memchr::fallback::{memchr, memrchr};
diff --git a/src/libstd/sys/redox/mod.rs b/src/libstd/sys/redox/mod.rs
new file mode 100644
index 00000000000..5982bdd6549
--- /dev/null
+++ b/src/libstd/sys/redox/mod.rs
@@ -0,0 +1,95 @@
+// 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.
+
+#![allow(dead_code, missing_docs, bad_style)]
+
+use io::{self, ErrorKind};
+
+pub mod args;
+#[cfg(any(not(cargobuild), feature = "backtrace"))]
+pub mod backtrace;
+pub mod condvar;
+pub mod env;
+pub mod ext;
+pub mod fast_thread_local;
+pub mod fd;
+pub mod fs;
+pub mod memchr;
+pub mod mutex;
+pub mod net;
+pub mod os;
+pub mod os_str;
+pub mod path;
+pub mod pipe;
+pub mod process;
+pub mod rand;
+pub mod rwlock;
+pub mod stack_overflow;
+pub mod stdio;
+pub mod syscall;
+pub mod thread;
+pub mod thread_local;
+pub mod time;
+
+#[cfg(not(test))]
+pub fn init() {
+    use alloc::oom;
+
+    oom::set_oom_handler(oom_handler);
+
+    // A nicer handler for out-of-memory situations than the default one. This
+    // one prints a message to stderr before aborting. It is critical that this
+    // code does not allocate any memory since we are in an OOM situation. Any
+    // errors are ignored while printing since there's nothing we can do about
+    // them and we are about to exit anyways.
+    fn oom_handler() -> ! {
+        use intrinsics;
+        let msg = "fatal runtime error: out of memory\n";
+        unsafe {
+            let _ = syscall::write(2, msg.as_bytes());
+            intrinsics::abort();
+        }
+    }
+}
+
+pub fn decode_error_kind(errno: i32) -> ErrorKind {
+    match errno {
+        syscall::ECONNREFUSED => ErrorKind::ConnectionRefused,
+        syscall::ECONNRESET => ErrorKind::ConnectionReset,
+        syscall::EPERM | syscall::EACCES => ErrorKind::PermissionDenied,
+        syscall::EPIPE => ErrorKind::BrokenPipe,
+        syscall::ENOTCONN => ErrorKind::NotConnected,
+        syscall::ECONNABORTED => ErrorKind::ConnectionAborted,
+        syscall::EADDRNOTAVAIL => ErrorKind::AddrNotAvailable,
+        syscall::EADDRINUSE => ErrorKind::AddrInUse,
+        syscall::ENOENT => ErrorKind::NotFound,
+        syscall::EINTR => ErrorKind::Interrupted,
+        syscall::EINVAL => ErrorKind::InvalidInput,
+        syscall::ETIMEDOUT => ErrorKind::TimedOut,
+        syscall::EEXIST => ErrorKind::AlreadyExists,
+
+        // These two constants can have the same value on some systems,
+        // but different values on others, so we can't use a match
+        // clause
+        x if x == syscall::EAGAIN || x == syscall::EWOULDBLOCK =>
+            ErrorKind::WouldBlock,
+
+        _ => ErrorKind::Other,
+    }
+}
+
+pub fn cvt(result: Result<usize, syscall::Error>) -> io::Result<usize> {
+    result.map_err(|err| io::Error::from_raw_os_error(err.errno))
+}
+
+/// On Redox, use an illegal instruction to abort
+pub unsafe fn abort_internal() -> ! {
+    ::core::intrinsics::abort();
+}
diff --git a/src/libstd/sys/redox/mutex.rs b/src/libstd/sys/redox/mutex.rs
new file mode 100644
index 00000000000..a995f597fc4
--- /dev/null
+++ b/src/libstd/sys/redox/mutex.rs
@@ -0,0 +1,179 @@
+// 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.
+
+use cell::UnsafeCell;
+use intrinsics::{atomic_cxchg, atomic_xchg};
+use ptr;
+
+use sys::syscall::{futex, getpid, FUTEX_WAIT, FUTEX_WAKE};
+
+pub unsafe fn mutex_try_lock(m: *mut i32) -> bool {
+    atomic_cxchg(m, 0, 1).0 == 0
+}
+
+pub unsafe fn mutex_lock(m: *mut i32) {
+    let mut c = 0;
+    //Set to larger value for longer spin test
+    for _i in 0..100 {
+        c = atomic_cxchg(m, 0, 1).0;
+        if c == 0 {
+            break;
+        }
+        //cpu_relax()
+    }
+    if c == 1 {
+        c = atomic_xchg(m, 2);
+    }
+    while c != 0 {
+        let _ = futex(m, FUTEX_WAIT, 2, 0, ptr::null_mut());
+        c = atomic_xchg(m, 2);
+    }
+}
+
+pub unsafe fn mutex_unlock(m: *mut i32) {
+    if *m == 2 {
+        *m = 0;
+    } else if atomic_xchg(m, 0) == 1 {
+        return;
+    }
+    //Set to larger value for longer spin test
+    for _i in 0..100 {
+        if *m != 0 {
+            if atomic_cxchg(m, 1, 2).0 != 0 {
+                return;
+            }
+        }
+        //cpu_relax()
+    }
+    let _ = futex(m, FUTEX_WAKE, 1, 0, ptr::null_mut());
+}
+
+pub struct Mutex {
+    pub lock: UnsafeCell<i32>,
+}
+
+impl Mutex {
+    /// Create a new mutex.
+    pub const fn new() -> Self {
+        Mutex {
+            lock: UnsafeCell::new(0),
+        }
+    }
+
+    #[inline]
+    pub unsafe fn init(&self) {
+        *self.lock.get() = 0;
+    }
+
+    /// Try to lock the mutex
+    #[inline]
+    pub unsafe fn try_lock(&self) -> bool {
+        mutex_try_lock(self.lock.get())
+    }
+
+    /// Lock the mutex
+    #[inline]
+    pub unsafe fn lock(&self) {
+        mutex_lock(self.lock.get());
+    }
+
+    /// Unlock the mutex
+    #[inline]
+    pub unsafe fn unlock(&self) {
+        mutex_unlock(self.lock.get());
+    }
+
+    #[inline]
+    pub unsafe fn destroy(&self) {
+        *self.lock.get() = 0;
+    }
+}
+
+unsafe impl Send for Mutex {}
+
+unsafe impl Sync for Mutex {}
+
+pub struct ReentrantMutex {
+    pub lock: UnsafeCell<i32>,
+    pub owner: UnsafeCell<usize>,
+    pub own_count: UnsafeCell<usize>,
+}
+
+impl ReentrantMutex {
+    pub const fn uninitialized() -> Self {
+        ReentrantMutex {
+            lock: UnsafeCell::new(0),
+            owner: UnsafeCell::new(0),
+            own_count: UnsafeCell::new(0),
+        }
+    }
+
+    #[inline]
+    pub unsafe fn init(&mut self) {
+        *self.lock.get() = 0;
+        *self.owner.get() = 0;
+        *self.own_count.get() = 0;
+    }
+
+    /// Try to lock the mutex
+    #[inline]
+    pub unsafe fn try_lock(&self) -> bool {
+        let pid = getpid().unwrap();
+        if *self.own_count.get() > 0 && *self.owner.get() == pid {
+            *self.own_count.get() += 1;
+            true
+        } else {
+            if mutex_try_lock(self.lock.get()) {
+                *self.owner.get() = pid;
+                *self.own_count.get() = 1;
+                true
+            } else {
+                false
+            }
+        }
+    }
+
+    /// Lock the mutex
+    #[inline]
+    pub unsafe fn lock(&self) {
+        let pid = getpid().unwrap();
+        if *self.own_count.get() > 0 && *self.owner.get() == pid {
+            *self.own_count.get() += 1;
+        } else {
+            mutex_lock(self.lock.get());
+            *self.owner.get() = pid;
+            *self.own_count.get() = 1;
+        }
+    }
+
+    /// Unlock the mutex
+    #[inline]
+    pub unsafe fn unlock(&self) {
+        let pid = getpid().unwrap();
+        if *self.own_count.get() > 0 && *self.owner.get() == pid {
+            *self.own_count.get() -= 1;
+            if *self.own_count.get() == 0 {
+                *self.owner.get() = 0;
+                mutex_unlock(self.lock.get());
+            }
+        }
+    }
+
+    #[inline]
+    pub unsafe fn destroy(&self) {
+        *self.lock.get() = 0;
+        *self.owner.get() = 0;
+        *self.own_count.get() = 0;
+    }
+}
+
+unsafe impl Send for ReentrantMutex {}
+
+unsafe impl Sync for ReentrantMutex {}
diff --git a/src/libstd/sys/redox/net/dns/answer.rs b/src/libstd/sys/redox/net/dns/answer.rs
new file mode 100644
index 00000000000..8e6aaeb0293
--- /dev/null
+++ b/src/libstd/sys/redox/net/dns/answer.rs
@@ -0,0 +1,22 @@
+// 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.
+
+use string::String;
+use vec::Vec;
+
+#[derive(Clone, Debug)]
+pub struct DnsAnswer {
+    pub name: String,
+    pub a_type: u16,
+    pub a_class: u16,
+    pub ttl_a: u16,
+    pub ttl_b: u16,
+    pub data: Vec<u8>
+}
diff --git a/src/libstd/sys/redox/net/dns/mod.rs b/src/libstd/sys/redox/net/dns/mod.rs
new file mode 100644
index 00000000000..43c4fe7ac9d
--- /dev/null
+++ b/src/libstd/sys/redox/net/dns/mod.rs
@@ -0,0 +1,217 @@
+// 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.
+
+pub use self::answer::DnsAnswer;
+pub use self::query::DnsQuery;
+
+use slice;
+use u16;
+use string::String;
+use vec::Vec;
+
+mod answer;
+mod query;
+
+#[unstable(feature = "n16", issue="0")]
+#[allow(non_camel_case_types)]
+#[derive(Copy, Clone, Debug, Default)]
+#[repr(packed)]
+pub struct n16 {
+    inner: u16
+}
+
+impl n16 {
+    #[unstable(feature = "n16", issue="0")]
+    pub fn as_bytes(&self) -> &[u8] {
+        unsafe { slice::from_raw_parts((&self.inner as *const u16) as *const u8, 2) }
+    }
+
+    #[unstable(feature = "n16", issue="0")]
+    pub fn from_bytes(bytes: &[u8]) -> Self {
+        n16 {
+            inner: unsafe { slice::from_raw_parts(bytes.as_ptr() as *const u16, bytes.len()/2)[0] }
+        }
+    }
+}
+
+#[unstable(feature = "n16", issue="0")]
+impl From<u16> for n16 {
+    fn from(value: u16) -> Self {
+        n16 {
+            inner: value.to_be()
+        }
+    }
+}
+
+#[unstable(feature = "n16", issue="0")]
+impl From<n16> for u16 {
+    fn from(value: n16) -> Self {
+        u16::from_be(value.inner)
+    }
+}
+
+#[derive(Clone, Debug)]
+pub struct Dns {
+    pub transaction_id: u16,
+    pub flags: u16,
+    pub queries: Vec<DnsQuery>,
+    pub answers: Vec<DnsAnswer>
+}
+
+impl Dns {
+    pub fn compile(&self) -> Vec<u8> {
+        let mut data = Vec::new();
+
+        macro_rules! push_u8 {
+            ($value:expr) => {
+                data.push($value);
+            };
+        };
+
+        macro_rules! push_n16 {
+            ($value:expr) => {
+                data.extend_from_slice(n16::from($value).as_bytes());
+            };
+        };
+
+        push_n16!(self.transaction_id);
+        push_n16!(self.flags);
+        push_n16!(self.queries.len() as u16);
+        push_n16!(self.answers.len() as u16);
+        push_n16!(0);
+        push_n16!(0);
+
+        for query in self.queries.iter() {
+            for part in query.name.split('.') {
+                push_u8!(part.len() as u8);
+                data.extend_from_slice(part.as_bytes());
+            }
+            push_u8!(0);
+            push_n16!(query.q_type);
+            push_n16!(query.q_class);
+        }
+
+        data
+    }
+
+    pub fn parse(data: &[u8]) -> Result<Self, String> {
+        let mut i = 0;
+
+        macro_rules! pop_u8 {
+            () => {
+                {
+                    i += 1;
+                    if i > data.len() {
+                        return Err(format!("{}: {}: pop_u8", file!(), line!()));
+                    }
+                    data[i - 1]
+                }
+            };
+        };
+
+        macro_rules! pop_n16 {
+            () => {
+                {
+                    i += 2;
+                    if i > data.len() {
+                        return Err(format!("{}: {}: pop_n16", file!(), line!()));
+                    }
+                    u16::from(n16::from_bytes(&data[i - 2 .. i]))
+                }
+            };
+        };
+
+        macro_rules! pop_data {
+            () => {
+                {
+                    let mut data = Vec::new();
+
+                    let data_len = pop_n16!();
+                    for _data_i in 0..data_len {
+                        data.push(pop_u8!());
+                    }
+
+                    data
+                }
+            };
+        };
+
+        macro_rules! pop_name {
+            () => {
+                {
+                    let mut name = String::new();
+
+                    loop {
+                        let name_len = pop_u8!();
+                        if name_len == 0 {
+                            break;
+                        }
+                        if ! name.is_empty() {
+                            name.push('.');
+                        }
+                        for _name_i in 0..name_len {
+                            name.push(pop_u8!() as char);
+                        }
+                    }
+
+                    name
+                }
+            };
+        };
+
+        let transaction_id = pop_n16!();
+        let flags = pop_n16!();
+        let queries_len = pop_n16!();
+        let answers_len = pop_n16!();
+        pop_n16!();
+        pop_n16!();
+
+        let mut queries = Vec::new();
+        for _query_i in 0..queries_len {
+            queries.push(DnsQuery {
+                name: pop_name!(),
+                q_type: pop_n16!(),
+                q_class: pop_n16!()
+            });
+        }
+
+        let mut answers = Vec::new();
+        for _answer_i in 0..answers_len {
+            let name_ind = 0b11000000;
+            let name_test = pop_u8!();
+            i -= 1;
+
+            answers.push(DnsAnswer {
+                name: if name_test & name_ind == name_ind {
+                    let name_off = pop_n16!() - ((name_ind as u16) << 8);
+                    let old_i = i;
+                    i = name_off as usize;
+                    let name = pop_name!();
+                    i = old_i;
+                    name
+                } else {
+                    pop_name!()
+                },
+                a_type: pop_n16!(),
+                a_class: pop_n16!(),
+                ttl_a: pop_n16!(),
+                ttl_b: pop_n16!(),
+                data: pop_data!()
+            });
+        }
+
+        Ok(Dns {
+            transaction_id: transaction_id,
+            flags: flags,
+            queries: queries,
+            answers: answers,
+        })
+    }
+}
diff --git a/src/libstd/sys/redox/net/dns/query.rs b/src/libstd/sys/redox/net/dns/query.rs
new file mode 100644
index 00000000000..b0dcdcb624a
--- /dev/null
+++ b/src/libstd/sys/redox/net/dns/query.rs
@@ -0,0 +1,18 @@
+// 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.
+
+use string::String;
+
+#[derive(Clone, Debug)]
+pub struct DnsQuery {
+    pub name: String,
+    pub q_type: u16,
+    pub q_class: u16
+}
diff --git a/src/libstd/sys/redox/net/mod.rs b/src/libstd/sys/redox/net/mod.rs
new file mode 100644
index 00000000000..3fdf61cfed8
--- /dev/null
+++ b/src/libstd/sys/redox/net/mod.rs
@@ -0,0 +1,113 @@
+// 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.
+
+use fs::File;
+use io::{Error, Result, Read};
+use iter::Iterator;
+use net::{Ipv4Addr, SocketAddr, SocketAddrV4};
+use str::FromStr;
+use string::{String, ToString};
+use sys::syscall::EINVAL;
+use time;
+use vec::{IntoIter, Vec};
+
+use self::dns::{Dns, DnsQuery};
+
+pub use self::tcp::{TcpStream, TcpListener};
+pub use self::udp::UdpSocket;
+
+pub mod netc;
+
+mod dns;
+mod tcp;
+mod udp;
+
+pub struct LookupHost(IntoIter<SocketAddr>);
+
+impl Iterator for LookupHost {
+    type Item = SocketAddr;
+    fn next(&mut self) -> Option<Self::Item> {
+        self.0.next()
+    }
+}
+
+pub fn lookup_host(host: &str) -> Result<LookupHost> {
+    let mut ip_string = String::new();
+    File::open("/etc/net/ip")?.read_to_string(&mut ip_string)?;
+    let ip: Vec<u8> = ip_string.trim().split(".").map(|part| part.parse::<u8>()
+                               .unwrap_or(0)).collect();
+
+    let mut dns_string = String::new();
+    File::open("/etc/net/dns")?.read_to_string(&mut dns_string)?;
+    let dns: Vec<u8> = dns_string.trim().split(".").map(|part| part.parse::<u8>()
+                                 .unwrap_or(0)).collect();
+
+    if ip.len() == 4 && dns.len() == 4 {
+        let time = time::SystemTime::now().duration_since(time::UNIX_EPOCH).unwrap();
+        let tid = (time.subsec_nanos() >> 16) as u16;
+
+        let packet = Dns {
+            transaction_id: tid,
+            flags: 0x0100,
+            queries: vec![DnsQuery {
+                name: host.to_string(),
+                q_type: 0x0001,
+                q_class: 0x0001,
+            }],
+            answers: vec![]
+        };
+
+        let packet_data = packet.compile();
+
+        let my_ip = Ipv4Addr::new(ip[0], ip[1], ip[2], ip[3]);
+        let dns_ip = Ipv4Addr::new(dns[0], dns[1], dns[2], dns[3]);
+        let socket = UdpSocket::bind(&SocketAddr::V4(SocketAddrV4::new(my_ip, 0)))?;
+        socket.connect(&SocketAddr::V4(SocketAddrV4::new(dns_ip, 53)))?;
+        socket.send(&packet_data)?;
+
+        let mut buf = [0; 65536];
+        let count = socket.recv(&mut buf)?;
+
+        match Dns::parse(&buf[.. count]) {
+            Ok(response) => {
+                let mut addrs = vec![];
+                for answer in response.answers.iter() {
+                    if answer.a_type == 0x0001 && answer.a_class == 0x0001
+                       && answer.data.len() == 4
+                    {
+                        let answer_ip = Ipv4Addr::new(answer.data[0],
+                                                      answer.data[1],
+                                                      answer.data[2],
+                                                      answer.data[3]);
+                        addrs.push(SocketAddr::V4(SocketAddrV4::new(answer_ip, 0)));
+                    }
+                }
+                Ok(LookupHost(addrs.into_iter()))
+            },
+            Err(_err) => Err(Error::from_raw_os_error(EINVAL))
+        }
+    } else {
+        Err(Error::from_raw_os_error(EINVAL))
+    }
+}
+
+fn path_to_peer_addr(path_str: &str) -> SocketAddr {
+    let mut parts = path_str.split('/').next().unwrap_or("").split(':').skip(1);
+    let host = Ipv4Addr::from_str(parts.next().unwrap_or("")).unwrap_or(Ipv4Addr::new(0, 0, 0, 0));
+    let port = parts.next().unwrap_or("").parse::<u16>().unwrap_or(0);
+    SocketAddr::V4(SocketAddrV4::new(host, port))
+}
+
+fn path_to_local_addr(path_str: &str) -> SocketAddr {
+    let mut parts = path_str.split('/').nth(1).unwrap_or("").split(':');
+    let host = Ipv4Addr::from_str(parts.next().unwrap_or("")).unwrap_or(Ipv4Addr::new(0, 0, 0, 0));
+    let port = parts.next().unwrap_or("").parse::<u16>().unwrap_or(0);
+    SocketAddr::V4(SocketAddrV4::new(host, port))
+}
diff --git a/src/libstd/sys/redox/net/netc.rs b/src/libstd/sys/redox/net/netc.rs
new file mode 100644
index 00000000000..03e1c9fffa4
--- /dev/null
+++ b/src/libstd/sys/redox/net/netc.rs
@@ -0,0 +1,57 @@
+// 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.
+
+pub type in_addr_t = u32;
+pub type in_port_t = u16;
+
+pub type socklen_t = u32;
+pub type sa_family_t = u16;
+
+pub const AF_INET: sa_family_t = 1;
+pub const AF_INET6: sa_family_t = 2;
+
+#[derive(Copy, Clone)]
+#[repr(C)]
+pub struct in_addr {
+    pub s_addr: in_addr_t,
+}
+
+#[derive(Copy, Clone)]
+#[repr(C)]
+pub struct in6_addr {
+    pub s6_addr: [u8; 16],
+    __align: [u32; 0],
+}
+
+#[derive(Copy, Clone)]
+#[repr(C)]
+pub struct sockaddr {
+    pub sa_family: sa_family_t,
+    pub sa_data: [u8; 14],
+}
+
+#[derive(Copy, Clone)]
+#[repr(C)]
+pub struct sockaddr_in {
+    pub sin_family: sa_family_t,
+    pub sin_port: in_port_t,
+    pub sin_addr: in_addr,
+    pub sin_zero: [u8; 8],
+}
+
+#[derive(Copy, Clone)]
+#[repr(C)]
+pub struct sockaddr_in6 {
+    pub sin6_family: sa_family_t,
+    pub sin6_port: in_port_t,
+    pub sin6_flowinfo: u32,
+    pub sin6_addr: in6_addr,
+    pub sin6_scope_id: u32,
+}
diff --git a/src/libstd/sys/redox/net/tcp.rs b/src/libstd/sys/redox/net/tcp.rs
new file mode 100644
index 00000000000..d5362c9f131
--- /dev/null
+++ b/src/libstd/sys/redox/net/tcp.rs
@@ -0,0 +1,199 @@
+// 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.
+
+use io::{Error, ErrorKind, Result};
+use net::{SocketAddr, Shutdown};
+use path::Path;
+use sys::fs::{File, OpenOptions};
+use sys_common::{AsInner, FromInner, IntoInner};
+use time::Duration;
+use vec::Vec;
+
+use super::{path_to_peer_addr, path_to_local_addr};
+
+#[derive(Debug)]
+pub struct TcpStream(File);
+
+impl TcpStream {
+    pub fn connect(addr: &SocketAddr) -> Result<TcpStream> {
+        let path = format!("tcp:{}", addr);
+        let mut options = OpenOptions::new();
+        options.read(true);
+        options.write(true);
+        Ok(TcpStream(File::open(&Path::new(path.as_str()), &options)?))
+    }
+
+    pub fn duplicate(&self) -> Result<TcpStream> {
+        Ok(TcpStream(self.0.dup(&[])?))
+    }
+
+    pub fn read(&self, buf: &mut [u8]) -> Result<usize> {
+        self.0.read(buf)
+    }
+
+    pub fn read_to_end(&self, buf: &mut Vec<u8>) -> Result<usize> {
+        self.0.read_to_end(buf)
+    }
+
+    pub fn write(&self, buf: &[u8]) -> Result<usize> {
+        self.0.write(buf)
+    }
+
+    pub fn take_error(&self) -> Result<Option<Error>> {
+        Ok(None)
+    }
+
+    pub fn peer_addr(&self) -> Result<SocketAddr> {
+        let path = self.0.path()?;
+        Ok(path_to_peer_addr(path.to_str().unwrap_or("")))
+    }
+
+    pub fn socket_addr(&self) -> Result<SocketAddr> {
+        let path = self.0.path()?;
+        Ok(path_to_local_addr(path.to_str().unwrap_or("")))
+    }
+
+    pub fn shutdown(&self, _how: Shutdown) -> Result<()> {
+        Err(Error::new(ErrorKind::Other, "TcpStream::shutdown not implemented"))
+    }
+
+    pub fn nodelay(&self) -> Result<bool> {
+        Err(Error::new(ErrorKind::Other, "TcpStream::nodelay not implemented"))
+    }
+
+    pub fn nonblocking(&self) -> Result<bool> {
+        self.0.fd().nonblocking()
+    }
+
+    pub fn only_v6(&self) -> Result<bool> {
+        Err(Error::new(ErrorKind::Other, "TcpStream::only_v6 not implemented"))
+    }
+
+    pub fn ttl(&self) -> Result<u32> {
+        Err(Error::new(ErrorKind::Other, "TcpStream::ttl not implemented"))
+    }
+
+    pub fn read_timeout(&self) -> Result<Option<Duration>> {
+        Err(Error::new(ErrorKind::Other, "TcpStream::read_timeout not implemented"))
+    }
+
+    pub fn write_timeout(&self) -> Result<Option<Duration>> {
+        Err(Error::new(ErrorKind::Other, "TcpStream::write_timeout not implemented"))
+    }
+
+    pub fn set_nodelay(&self, _nodelay: bool) -> Result<()> {
+        Err(Error::new(ErrorKind::Other, "TcpStream::set_nodelay not implemented"))
+    }
+
+    pub fn set_nonblocking(&self, nonblocking: bool) -> Result<()> {
+        self.0.fd().set_nonblocking(nonblocking)
+    }
+
+    pub fn set_only_v6(&self, _only_v6: bool) -> Result<()> {
+        Err(Error::new(ErrorKind::Other, "TcpStream::set_only_v6 not implemented"))
+    }
+
+    pub fn set_ttl(&self, _ttl: u32) -> Result<()> {
+        Err(Error::new(ErrorKind::Other, "TcpStream::set_ttl not implemented"))
+    }
+
+    pub fn set_read_timeout(&self, _dur: Option<Duration>) -> Result<()> {
+        Err(Error::new(ErrorKind::Other, "TcpStream::set_read_timeout not implemented"))
+    }
+
+    pub fn set_write_timeout(&self, _dur: Option<Duration>) -> Result<()> {
+        Err(Error::new(ErrorKind::Other, "TcpStream::set_write_timeout not implemented"))
+    }
+}
+
+impl AsInner<File> for TcpStream {
+    fn as_inner(&self) -> &File { &self.0 }
+}
+
+impl FromInner<File> for TcpStream {
+    fn from_inner(file: File) -> TcpStream {
+        TcpStream(file)
+    }
+}
+
+impl IntoInner<File> for TcpStream {
+    fn into_inner(self) -> File { self.0 }
+}
+
+#[derive(Debug)]
+pub struct TcpListener(File);
+
+impl TcpListener {
+    pub fn bind(addr: &SocketAddr) -> Result<TcpListener> {
+        let path = format!("tcp:/{}", addr);
+        let mut options = OpenOptions::new();
+        options.read(true);
+        options.write(true);
+        Ok(TcpListener(File::open(&Path::new(path.as_str()), &options)?))
+    }
+
+    pub fn accept(&self) -> Result<(TcpStream, SocketAddr)> {
+        let file = self.0.dup(b"listen")?;
+        let path = file.path()?;
+        let peer_addr = path_to_peer_addr(path.to_str().unwrap_or(""));
+        Ok((TcpStream(file), peer_addr))
+    }
+
+    pub fn duplicate(&self) -> Result<TcpListener> {
+        Ok(TcpListener(self.0.dup(&[])?))
+    }
+
+    pub fn take_error(&self) -> Result<Option<Error>> {
+        Ok(None)
+    }
+
+    pub fn socket_addr(&self) -> Result<SocketAddr> {
+        let path = self.0.path()?;
+        Ok(path_to_local_addr(path.to_str().unwrap_or("")))
+    }
+
+    pub fn nonblocking(&self) -> Result<bool> {
+        Err(Error::new(ErrorKind::Other, "TcpListener::nonblocking not implemented"))
+    }
+
+    pub fn only_v6(&self) -> Result<bool> {
+        Err(Error::new(ErrorKind::Other, "TcpListener::only_v6 not implemented"))
+    }
+
+    pub fn ttl(&self) -> Result<u32> {
+        Err(Error::new(ErrorKind::Other, "TcpListener::ttl not implemented"))
+    }
+
+    pub fn set_nonblocking(&self, _nonblocking: bool) -> Result<()> {
+        Err(Error::new(ErrorKind::Other, "TcpListener::set_nonblocking not implemented"))
+    }
+
+    pub fn set_only_v6(&self, _only_v6: bool) -> Result<()> {
+        Err(Error::new(ErrorKind::Other, "TcpListener::set_only_v6 not implemented"))
+    }
+
+    pub fn set_ttl(&self, _ttl: u32) -> Result<()> {
+        Err(Error::new(ErrorKind::Other, "TcpListener::set_ttl not implemented"))
+    }
+}
+
+impl AsInner<File> for TcpListener {
+    fn as_inner(&self) -> &File { &self.0 }
+}
+
+impl FromInner<File> for TcpListener {
+    fn from_inner(file: File) -> TcpListener {
+        TcpListener(file)
+    }
+}
+
+impl IntoInner<File> for TcpListener {
+    fn into_inner(self) -> File { self.0 }
+}
diff --git a/src/libstd/sys/redox/net/udp.rs b/src/libstd/sys/redox/net/udp.rs
new file mode 100644
index 00000000000..607c66c2ba7
--- /dev/null
+++ b/src/libstd/sys/redox/net/udp.rs
@@ -0,0 +1,188 @@
+// 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.
+
+use cell::UnsafeCell;
+use io::{Error, ErrorKind, Result};
+use net::{SocketAddr, Ipv4Addr, Ipv6Addr};
+use path::Path;
+use sys::fs::{File, OpenOptions};
+use sys_common::{AsInner, FromInner, IntoInner};
+use time::Duration;
+
+use super::{path_to_peer_addr, path_to_local_addr};
+
+#[derive(Debug)]
+pub struct UdpSocket(File, UnsafeCell<Option<SocketAddr>>);
+
+impl UdpSocket {
+    pub fn bind(addr: &SocketAddr) -> Result<UdpSocket> {
+        let path = format!("udp:/{}", addr);
+        let mut options = OpenOptions::new();
+        options.read(true);
+        options.write(true);
+        Ok(UdpSocket(File::open(&Path::new(path.as_str()), &options)?, UnsafeCell::new(None)))
+    }
+
+    fn get_conn(&self) -> &mut Option<SocketAddr> {
+        unsafe { &mut *(self.1.get()) }
+    }
+
+    pub fn connect(&self, addr: &SocketAddr) -> Result<()> {
+        unsafe { *self.1.get() = Some(*addr) };
+        Ok(())
+    }
+
+    pub fn duplicate(&self) -> Result<UdpSocket> {
+        let new_bind = self.0.dup(&[])?;
+        let new_conn = *self.get_conn();
+        Ok(UdpSocket(new_bind, UnsafeCell::new(new_conn)))
+    }
+
+    pub fn recv_from(&self, buf: &mut [u8]) -> Result<(usize, SocketAddr)> {
+        let from = self.0.dup(b"listen")?;
+        let path = from.path()?;
+        let peer_addr = path_to_peer_addr(path.to_str().unwrap_or(""));
+        let count = from.read(buf)?;
+        Ok((count, peer_addr))
+    }
+
+    pub fn recv(&self, buf: &mut [u8]) -> Result<usize> {
+        if let Some(addr) = *self.get_conn() {
+            let from = self.0.dup(format!("{}", addr).as_bytes())?;
+            from.read(buf)
+        } else {
+            Err(Error::new(ErrorKind::Other, "UdpSocket::recv not connected"))
+        }
+    }
+
+    pub fn send_to(&self, buf: &[u8], addr: &SocketAddr) -> Result<usize> {
+        let to = self.0.dup(format!("{}", addr).as_bytes())?;
+        to.write(buf)
+    }
+
+    pub fn send(&self, buf: &[u8]) -> Result<usize> {
+        if let Some(addr) = *self.get_conn() {
+            self.send_to(buf, &addr)
+        } else {
+            Err(Error::new(ErrorKind::Other, "UdpSocket::send not connected"))
+        }
+    }
+
+    pub fn take_error(&self) -> Result<Option<Error>> {
+        Ok(None)
+    }
+
+    pub fn socket_addr(&self) -> Result<SocketAddr> {
+        let path = self.0.path()?;
+        Ok(path_to_local_addr(path.to_str().unwrap_or("")))
+    }
+
+    pub fn broadcast(&self) -> Result<bool> {
+        Err(Error::new(ErrorKind::Other, "UdpSocket::broadcast not implemented"))
+    }
+
+    pub fn multicast_loop_v4(&self) -> Result<bool> {
+        Err(Error::new(ErrorKind::Other, "UdpSocket::multicast_loop_v4 not implemented"))
+    }
+
+    pub fn multicast_loop_v6(&self) -> Result<bool> {
+        Err(Error::new(ErrorKind::Other, "UdpSocket::multicast_loop_v6 not implemented"))
+    }
+
+    pub fn multicast_ttl_v4(&self) -> Result<u32> {
+        Err(Error::new(ErrorKind::Other, "UdpSocket::multicast_ttl_v4 not implemented"))
+    }
+
+    pub fn nonblocking(&self) -> Result<bool> {
+        self.0.fd().nonblocking()
+    }
+
+    pub fn only_v6(&self) -> Result<bool> {
+        Err(Error::new(ErrorKind::Other, "UdpSocket::only_v6 not implemented"))
+    }
+
+    pub fn ttl(&self) -> Result<u32> {
+        Err(Error::new(ErrorKind::Other, "UdpSocket::ttl not implemented"))
+    }
+
+    pub fn read_timeout(&self) -> Result<Option<Duration>> {
+        Err(Error::new(ErrorKind::Other, "UdpSocket::read_timeout not implemented"))
+    }
+
+    pub fn write_timeout(&self) -> Result<Option<Duration>> {
+        Err(Error::new(ErrorKind::Other, "UdpSocket::write_timeout not implemented"))
+    }
+
+    pub fn set_broadcast(&self, _broadcast: bool) -> Result<()> {
+        Err(Error::new(ErrorKind::Other, "UdpSocket::set_broadcast not implemented"))
+    }
+
+    pub fn set_multicast_loop_v4(&self, _multicast_loop_v4: bool) -> Result<()> {
+        Err(Error::new(ErrorKind::Other, "UdpSocket::set_multicast_loop_v4 not implemented"))
+    }
+
+    pub fn set_multicast_loop_v6(&self, _multicast_loop_v6: bool) -> Result<()> {
+        Err(Error::new(ErrorKind::Other, "UdpSocket::set_multicast_loop_v6 not implemented"))
+    }
+
+    pub fn set_multicast_ttl_v4(&self, _multicast_ttl_v4: u32) -> Result<()> {
+        Err(Error::new(ErrorKind::Other, "UdpSocket::set_multicast_ttl_v4 not implemented"))
+    }
+
+    pub fn set_nonblocking(&self, nonblocking: bool) -> Result<()> {
+        self.0.fd().set_nonblocking(nonblocking)
+    }
+
+    pub fn set_only_v6(&self, _only_v6: bool) -> Result<()> {
+        Err(Error::new(ErrorKind::Other, "UdpSocket::set_only_v6 not implemented"))
+    }
+
+    pub fn set_ttl(&self, _ttl: u32) -> Result<()> {
+        Err(Error::new(ErrorKind::Other, "UdpSocket::set_ttl not implemented"))
+    }
+
+    pub fn set_read_timeout(&self, _dur: Option<Duration>) -> Result<()> {
+        Err(Error::new(ErrorKind::Other, "UdpSocket::set_read_timeout not implemented"))
+    }
+
+    pub fn set_write_timeout(&self, _dur: Option<Duration>) -> Result<()> {
+        Err(Error::new(ErrorKind::Other, "UdpSocket::set_write_timeout not implemented"))
+    }
+
+    pub fn join_multicast_v4(&self, _multiaddr: &Ipv4Addr, _interface: &Ipv4Addr) -> Result<()> {
+        Err(Error::new(ErrorKind::Other, "UdpSocket::join_multicast_v4 not implemented"))
+    }
+
+    pub fn join_multicast_v6(&self, _multiaddr: &Ipv6Addr, _interface: u32) -> Result<()> {
+        Err(Error::new(ErrorKind::Other, "UdpSocket::join_multicast_v6 not implemented"))
+    }
+
+    pub fn leave_multicast_v4(&self, _multiaddr: &Ipv4Addr, _interface: &Ipv4Addr) -> Result<()> {
+        Err(Error::new(ErrorKind::Other, "UdpSocket::leave_multicast_v4 not implemented"))
+    }
+
+    pub fn leave_multicast_v6(&self, _multiaddr: &Ipv6Addr, _interface: u32) -> Result<()> {
+        Err(Error::new(ErrorKind::Other, "UdpSocket::leave_multicast_v6 not implemented"))
+    }
+}
+
+impl AsInner<File> for UdpSocket {
+    fn as_inner(&self) -> &File { &self.0 }
+}
+
+impl FromInner<File> for UdpSocket {
+    fn from_inner(file: File) -> UdpSocket {
+        UdpSocket(file, UnsafeCell::new(None))
+    }
+}
+
+impl IntoInner<File> for UdpSocket {
+    fn into_inner(self) -> File { self.0 }
+}
diff --git a/src/libstd/sys/redox/os.rs b/src/libstd/sys/redox/os.rs
new file mode 100644
index 00000000000..135e972bca4
--- /dev/null
+++ b/src/libstd/sys/redox/os.rs
@@ -0,0 +1,204 @@
+// 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.
+
+//! Implementation of `std::os` functionality for unix systems
+
+#![allow(unused_imports)] // lots of cfg code here
+
+use os::unix::prelude::*;
+
+use error::Error as StdError;
+use ffi::{OsString, OsStr};
+use fmt;
+use io::{self, Read, Write};
+use iter;
+use marker::PhantomData;
+use mem;
+use memchr;
+use path::{self, PathBuf};
+use ptr;
+use slice;
+use str;
+use sys_common::mutex::Mutex;
+use sys::{cvt, fd, syscall};
+use vec;
+
+const TMPBUF_SZ: usize = 128;
+static ENV_LOCK: Mutex = Mutex::new();
+
+/// Returns the platform-specific value of errno
+pub fn errno() -> i32 {
+    0
+}
+
+/// Gets a detailed string description for the given error number.
+pub fn error_string(errno: i32) -> String {
+    if let Some(string) = syscall::STR_ERROR.get(errno as usize) {
+        string.to_string()
+    } else {
+        "unknown error".to_string()
+    }
+}
+
+pub fn getcwd() -> io::Result<PathBuf> {
+    let mut buf = [0; 4096];
+    let count = cvt(syscall::getcwd(&mut buf))?;
+    Ok(PathBuf::from(OsString::from_vec(buf[.. count].to_vec())))
+}
+
+pub fn chdir(p: &path::Path) -> io::Result<()> {
+    cvt(syscall::chdir(p.to_str().unwrap())).and(Ok(()))
+}
+
+pub struct SplitPaths<'a> {
+    iter: iter::Map<slice::Split<'a, u8, fn(&u8) -> bool>,
+                    fn(&'a [u8]) -> PathBuf>,
+}
+
+pub fn split_paths(unparsed: &OsStr) -> SplitPaths {
+    fn bytes_to_path(b: &[u8]) -> PathBuf {
+        PathBuf::from(<OsStr as OsStrExt>::from_bytes(b))
+    }
+    fn is_colon(b: &u8) -> bool { *b == b':' }
+    let unparsed = unparsed.as_bytes();
+    SplitPaths {
+        iter: unparsed.split(is_colon as fn(&u8) -> bool)
+                      .map(bytes_to_path as fn(&[u8]) -> PathBuf)
+    }
+}
+
+impl<'a> Iterator for SplitPaths<'a> {
+    type Item = PathBuf;
+    fn next(&mut self) -> Option<PathBuf> { self.iter.next() }
+    fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
+}
+
+#[derive(Debug)]
+pub struct JoinPathsError;
+
+pub fn join_paths<I, T>(paths: I) -> Result<OsString, JoinPathsError>
+    where I: Iterator<Item=T>, T: AsRef<OsStr>
+{
+    let mut joined = Vec::new();
+    let sep = b':';
+
+    for (i, path) in paths.enumerate() {
+        let path = path.as_ref().as_bytes();
+        if i > 0 { joined.push(sep) }
+        if path.contains(&sep) {
+            return Err(JoinPathsError)
+        }
+        joined.extend_from_slice(path);
+    }
+    Ok(OsStringExt::from_vec(joined))
+}
+
+impl fmt::Display for JoinPathsError {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        "path segment contains separator `:`".fmt(f)
+    }
+}
+
+impl StdError for JoinPathsError {
+    fn description(&self) -> &str { "failed to join paths" }
+}
+
+pub fn current_exe() -> io::Result<PathBuf> {
+    use fs::File;
+
+    let mut file = File::open("sys:exe")?;
+
+    let mut path = String::new();
+    file.read_to_string(&mut path)?;
+
+    if path.ends_with('\n') {
+        path.pop();
+    }
+
+    Ok(PathBuf::from(path))
+}
+
+pub struct Env {
+    iter: vec::IntoIter<(OsString, OsString)>,
+    _dont_send_or_sync_me: PhantomData<*mut ()>,
+}
+
+impl Iterator for Env {
+    type Item = (OsString, OsString);
+    fn next(&mut self) -> Option<(OsString, OsString)> { self.iter.next() }
+    fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
+}
+
+/// Returns a vector of (variable, value) byte-vector pairs for all the
+/// environment variables of the current process.
+pub fn env() -> Env {
+    let mut variables: Vec<(OsString, OsString)> = Vec::new();
+    if let Ok(mut file) = ::fs::File::open("env:") {
+        let mut string = String::new();
+        if file.read_to_string(&mut string).is_ok() {
+            for line in string.lines() {
+                let mut parts = line.splitn(2, '=');
+                if let Some(name) = parts.next() {
+                    let value = parts.next().unwrap_or("");
+                    variables.push((OsString::from(name.to_string()),
+                                    OsString::from(value.to_string())));
+                }
+            }
+        }
+    }
+    Env { iter: variables.into_iter(), _dont_send_or_sync_me: PhantomData }
+}
+
+pub fn getenv(key: &OsStr) -> io::Result<Option<OsString>> {
+    if ! key.is_empty() {
+        if let Ok(mut file) = ::fs::File::open(&("env:".to_owned() + key.to_str().unwrap())) {
+            let mut string = String::new();
+            file.read_to_string(&mut string)?;
+            Ok(Some(OsString::from(string)))
+        } else {
+            Ok(None)
+        }
+    } else {
+        Ok(None)
+    }
+}
+
+pub fn setenv(key: &OsStr, value: &OsStr) -> io::Result<()> {
+    if ! key.is_empty() {
+        let mut file = ::fs::File::open(&("env:".to_owned() + key.to_str().unwrap()))?;
+        file.write_all(value.as_bytes())?;
+        file.set_len(value.len() as u64)?;
+    }
+    Ok(())
+}
+
+pub fn unsetenv(key: &OsStr) -> io::Result<()> {
+    ::fs::remove_file(&("env:".to_owned() + key.to_str().unwrap()))?;
+    Ok(())
+}
+
+pub fn page_size() -> usize {
+    4096
+}
+
+pub fn temp_dir() -> PathBuf {
+    ::env::var_os("TMPDIR").map(PathBuf::from).unwrap_or_else(|| {
+        PathBuf::from("/tmp")
+    })
+}
+
+pub fn home_dir() -> Option<PathBuf> {
+    return ::env::var_os("HOME").map(PathBuf::from);
+}
+
+pub fn exit(code: i32) -> ! {
+    let _ = syscall::exit(code as usize);
+    unreachable!();
+}
diff --git a/src/libstd/sys/redox/os_str.rs b/src/libstd/sys/redox/os_str.rs
new file mode 100644
index 00000000000..8922bf04f56
--- /dev/null
+++ b/src/libstd/sys/redox/os_str.rs
@@ -0,0 +1,119 @@
+// 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.
+
+/// The underlying OsString/OsStr implementation on Unix systems: just
+/// a `Vec<u8>`/`[u8]`.
+
+use borrow::Cow;
+use fmt::{self, Debug};
+use str;
+use mem;
+use sys_common::{AsInner, IntoInner};
+
+#[derive(Clone, Hash)]
+pub struct Buf {
+    pub inner: Vec<u8>
+}
+
+pub struct Slice {
+    pub inner: [u8]
+}
+
+impl Debug for Slice {
+    fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
+        self.to_string_lossy().fmt(formatter)
+    }
+}
+
+impl Debug for Buf {
+    fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
+        self.as_slice().fmt(formatter)
+    }
+}
+
+impl IntoInner<Vec<u8>> for Buf {
+    fn into_inner(self) -> Vec<u8> {
+        self.inner
+    }
+}
+
+impl AsInner<[u8]> for Buf {
+    fn as_inner(&self) -> &[u8] {
+        &self.inner
+    }
+}
+
+
+impl Buf {
+    pub fn from_string(s: String) -> Buf {
+        Buf { inner: s.into_bytes() }
+    }
+
+    #[inline]
+    pub fn with_capacity(capacity: usize) -> Buf {
+        Buf {
+            inner: Vec::with_capacity(capacity)
+        }
+    }
+
+    #[inline]
+    pub fn clear(&mut self) {
+        self.inner.clear()
+    }
+
+    #[inline]
+    pub fn capacity(&self) -> usize {
+        self.inner.capacity()
+    }
+
+    #[inline]
+    pub fn reserve(&mut self, additional: usize) {
+        self.inner.reserve(additional)
+    }
+
+    #[inline]
+    pub fn reserve_exact(&mut self, additional: usize) {
+        self.inner.reserve_exact(additional)
+    }
+
+    pub fn as_slice(&self) -> &Slice {
+        unsafe { mem::transmute(&*self.inner) }
+    }
+
+    pub fn into_string(self) -> Result<String, Buf> {
+        String::from_utf8(self.inner).map_err(|p| Buf { inner: p.into_bytes() } )
+    }
+
+    pub fn push_slice(&mut self, s: &Slice) {
+        self.inner.extend_from_slice(&s.inner)
+    }
+}
+
+impl Slice {
+    fn from_u8_slice(s: &[u8]) -> &Slice {
+        unsafe { mem::transmute(s) }
+    }
+
+    pub fn from_str(s: &str) -> &Slice {
+        Slice::from_u8_slice(s.as_bytes())
+    }
+
+    pub fn to_str(&self) -> Option<&str> {
+        str::from_utf8(&self.inner).ok()
+    }
+
+    pub fn to_string_lossy(&self) -> Cow<str> {
+        String::from_utf8_lossy(&self.inner)
+    }
+
+    pub fn to_owned(&self) -> Buf {
+        Buf { inner: self.inner.to_vec() }
+    }
+}
diff --git a/src/libstd/sys/redox/path.rs b/src/libstd/sys/redox/path.rs
new file mode 100644
index 00000000000..e6a267dd5d9
--- /dev/null
+++ b/src/libstd/sys/redox/path.rs
@@ -0,0 +1,39 @@
+// 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.
+
+use ffi::OsStr;
+use path::Prefix;
+
+#[inline]
+pub fn is_sep_byte(b: u8) -> bool {
+    b == b'/'
+}
+
+#[inline]
+pub fn is_verbatim_sep(b: u8) -> bool {
+    b == b'/'
+}
+
+pub fn parse_prefix(path: &OsStr) -> Option<Prefix> {
+    if let Some(path_str) = path.to_str() {
+        if let Some(_i) = path_str.find(':') {
+            // FIXME: Redox specific prefix
+            // Some(Prefix::Verbatim(OsStr::new(&path_str[..i])))
+            None
+        } else {
+            None
+        }
+    } else {
+        None
+    }
+}
+
+pub const MAIN_SEP_STR: &'static str = "/";
+pub const MAIN_SEP: char = '/';
diff --git a/src/libstd/sys/redox/pipe.rs b/src/libstd/sys/redox/pipe.rs
new file mode 100644
index 00000000000..e7240fbe7bf
--- /dev/null
+++ b/src/libstd/sys/redox/pipe.rs
@@ -0,0 +1,107 @@
+// 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.
+
+use io;
+use sys::{cvt, syscall};
+use sys::fd::FileDesc;
+
+////////////////////////////////////////////////////////////////////////////////
+// Anonymous pipes
+////////////////////////////////////////////////////////////////////////////////
+
+pub struct AnonPipe(FileDesc);
+
+pub fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> {
+    let mut fds = [0; 2];
+    cvt(syscall::pipe2(&mut fds, syscall::O_CLOEXEC))?;
+    Ok((AnonPipe(FileDesc::new(fds[0])), AnonPipe(FileDesc::new(fds[1]))))
+}
+
+impl AnonPipe {
+    pub fn from_fd(fd: FileDesc) -> io::Result<AnonPipe> {
+        fd.set_cloexec()?;
+        Ok(AnonPipe(fd))
+    }
+
+    pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
+        self.0.read(buf)
+    }
+
+    pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> {
+        self.0.read_to_end(buf)
+    }
+
+    pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
+        self.0.write(buf)
+    }
+
+    pub fn fd(&self) -> &FileDesc { &self.0 }
+    pub fn into_fd(self) -> FileDesc { self.0 }
+}
+
+pub fn read2(p1: AnonPipe,
+             v1: &mut Vec<u8>,
+             p2: AnonPipe,
+             v2: &mut Vec<u8>) -> io::Result<()> {
+    //FIXME: Use event based I/O multiplexing
+    //unimplemented!()
+
+    p1.read_to_end(v1)?;
+    p2.read_to_end(v2)?;
+
+    Ok(())
+
+    /*
+    // Set both pipes into nonblocking mode as we're gonna be reading from both
+    // in the `select` loop below, and we wouldn't want one to block the other!
+    let p1 = p1.into_fd();
+    let p2 = p2.into_fd();
+    p1.set_nonblocking(true)?;
+    p2.set_nonblocking(true)?;
+
+    loop {
+        // wait for either pipe to become readable using `select`
+        cvt_r(|| unsafe {
+            let mut read: libc::fd_set = mem::zeroed();
+            libc::FD_SET(p1.raw(), &mut read);
+            libc::FD_SET(p2.raw(), &mut read);
+            libc::select(max + 1, &mut read, ptr::null_mut(), ptr::null_mut(),
+                         ptr::null_mut())
+        })?;
+
+        // Read as much as we can from each pipe, ignoring EWOULDBLOCK or
+        // EAGAIN. If we hit EOF, then this will happen because the underlying
+        // reader will return Ok(0), in which case we'll see `Ok` ourselves. In
+        // this case we flip the other fd back into blocking mode and read
+        // whatever's leftover on that file descriptor.
+        let read = |fd: &FileDesc, dst: &mut Vec<u8>| {
+            match fd.read_to_end(dst) {
+                Ok(_) => Ok(true),
+                Err(e) => {
+                    if e.raw_os_error() == Some(libc::EWOULDBLOCK) ||
+                       e.raw_os_error() == Some(libc::EAGAIN) {
+                        Ok(false)
+                    } else {
+                        Err(e)
+                    }
+                }
+            }
+        };
+        if read(&p1, v1)? {
+            p2.set_nonblocking(false)?;
+            return p2.read_to_end(v2).map(|_| ());
+        }
+        if read(&p2, v2)? {
+            p1.set_nonblocking(false)?;
+            return p1.read_to_end(v1).map(|_| ());
+        }
+    }
+    */
+}
diff --git a/src/libstd/sys/redox/process.rs b/src/libstd/sys/redox/process.rs
new file mode 100644
index 00000000000..849f51013e6
--- /dev/null
+++ b/src/libstd/sys/redox/process.rs
@@ -0,0 +1,504 @@
+// 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.
+
+use collections::hash_map::HashMap;
+use env;
+use ffi::OsStr;
+use fmt;
+use io::{self, Error, ErrorKind};
+use path::Path;
+use sys::fd::FileDesc;
+use sys::fs::{File, OpenOptions};
+use sys::pipe::{self, AnonPipe};
+use sys::{cvt, syscall};
+
+////////////////////////////////////////////////////////////////////////////////
+// Command
+////////////////////////////////////////////////////////////////////////////////
+
+pub struct Command {
+    // Currently we try hard to ensure that the call to `.exec()` doesn't
+    // actually allocate any memory. While many platforms try to ensure that
+    // memory allocation works after a fork in a multithreaded process, it's
+    // been observed to be buggy and somewhat unreliable, so we do our best to
+    // just not do it at all!
+    //
+    // Along those lines, the `argv` and `envp` raw pointers here are exactly
+    // what's gonna get passed to `execvp`. The `argv` array starts with the
+    // `program` and ends with a NULL, and the `envp` pointer, if present, is
+    // also null-terminated.
+    //
+    // Right now we don't support removing arguments, so there's no much fancy
+    // support there, but we support adding and removing environment variables,
+    // so a side table is used to track where in the `envp` array each key is
+    // located. Whenever we add a key we update it in place if it's already
+    // present, and whenever we remove a key we update the locations of all
+    // other keys.
+    program: String,
+    args: Vec<String>,
+    env: HashMap<String, String>,
+
+    cwd: Option<String>,
+    uid: Option<u32>,
+    gid: Option<u32>,
+    saw_nul: bool,
+    closures: Vec<Box<FnMut() -> io::Result<()> + Send + Sync>>,
+    stdin: Option<Stdio>,
+    stdout: Option<Stdio>,
+    stderr: Option<Stdio>,
+}
+
+// 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>,
+}
+
+// passed to do_exec() with configuration of what the child stdio should look
+// like
+struct ChildPipes {
+    stdin: ChildStdio,
+    stdout: ChildStdio,
+    stderr: ChildStdio,
+}
+
+enum ChildStdio {
+    Inherit,
+    Explicit(usize),
+    Owned(FileDesc),
+}
+
+pub enum Stdio {
+    Inherit,
+    Null,
+    MakePipe,
+    Fd(FileDesc),
+}
+
+impl Command {
+    pub fn new(program: &OsStr) -> Command {
+        Command {
+            program: program.to_str().unwrap().to_owned(),
+            args: Vec::new(),
+            env: HashMap::new(),
+            cwd: None,
+            uid: None,
+            gid: None,
+            saw_nul: false,
+            closures: Vec::new(),
+            stdin: None,
+            stdout: None,
+            stderr: None,
+        }
+    }
+
+    pub fn arg(&mut self, arg: &OsStr) {
+        self.args.push(arg.to_str().unwrap().to_owned());
+    }
+
+    pub fn env(&mut self, key: &OsStr, val: &OsStr) {
+        self.env.insert(key.to_str().unwrap().to_owned(), val.to_str().unwrap().to_owned());
+    }
+
+    pub fn env_remove(&mut self, key: &OsStr) {
+        self.env.remove(key.to_str().unwrap());
+    }
+
+    pub fn env_clear(&mut self) {
+        self.env.clear();
+    }
+
+    pub fn cwd(&mut self, dir: &OsStr) {
+        self.cwd = Some(dir.to_str().unwrap().to_owned());
+    }
+    pub fn uid(&mut self, id: u32) {
+        self.uid = Some(id);
+    }
+    pub fn gid(&mut self, id: u32) {
+        self.gid = Some(id);
+    }
+
+    pub fn before_exec(&mut self,
+                       f: Box<FnMut() -> io::Result<()> + Send + Sync>) {
+        self.closures.push(f);
+    }
+
+    pub fn stdin(&mut self, stdin: Stdio) {
+        self.stdin = Some(stdin);
+    }
+    pub fn stdout(&mut self, stdout: Stdio) {
+        self.stdout = Some(stdout);
+    }
+    pub fn stderr(&mut self, stderr: Stdio) {
+        self.stderr = Some(stderr);
+    }
+
+    pub fn spawn(&mut self, default: Stdio, needs_stdin: bool)
+                 -> io::Result<(Process, StdioPipes)> {
+         const CLOEXEC_MSG_FOOTER: &'static [u8] = b"NOEX";
+
+         if self.saw_nul {
+             return Err(io::Error::new(ErrorKind::InvalidInput,
+                                       "nul byte found in provided data"));
+         }
+
+         let (ours, theirs) = self.setup_io(default, needs_stdin)?;
+         let (input, output) = pipe::anon_pipe()?;
+
+         let pid = unsafe {
+             match cvt(syscall::clone(0))? {
+                 0 => {
+                     drop(input);
+                     let err = self.do_exec(theirs);
+                     let errno = err.raw_os_error().unwrap_or(syscall::EINVAL) as u32;
+                     let bytes = [
+                         (errno >> 24) as u8,
+                         (errno >> 16) as u8,
+                         (errno >>  8) as u8,
+                         (errno >>  0) as u8,
+                         CLOEXEC_MSG_FOOTER[0], CLOEXEC_MSG_FOOTER[1],
+                         CLOEXEC_MSG_FOOTER[2], CLOEXEC_MSG_FOOTER[3]
+                     ];
+                     // pipe I/O up to PIPE_BUF bytes should be atomic, and then
+                     // we want to be sure we *don't* run at_exit destructors as
+                     // we're being torn down regardless
+                     assert!(output.write(&bytes).is_ok());
+                     let _ = syscall::exit(1);
+                     panic!("failed to exit");
+                 }
+                 n => n,
+             }
+         };
+
+         let mut p = Process { pid: pid, status: None };
+         drop(output);
+         let mut bytes = [0; 8];
+
+         // loop to handle EINTR
+         loop {
+             match input.read(&mut bytes) {
+                 Ok(0) => return Ok((p, ours)),
+                 Ok(8) => {
+                     assert!(combine(CLOEXEC_MSG_FOOTER) == combine(&bytes[4.. 8]),
+                             "Validation on the CLOEXEC pipe failed: {:?}", bytes);
+                     let errno = combine(&bytes[0.. 4]);
+                     assert!(p.wait().is_ok(),
+                             "wait() should either return Ok or panic");
+                     return Err(Error::from_raw_os_error(errno))
+                 }
+                 Err(ref e) if e.kind() == ErrorKind::Interrupted => {}
+                 Err(e) => {
+                     assert!(p.wait().is_ok(),
+                             "wait() should either return Ok or panic");
+                     panic!("the CLOEXEC pipe failed: {:?}", e)
+                 },
+                 Ok(..) => { // pipe I/O up to PIPE_BUF bytes should be atomic
+                     assert!(p.wait().is_ok(),
+                             "wait() should either return Ok or panic");
+                     panic!("short read on the CLOEXEC pipe")
+                 }
+             }
+         }
+
+         fn combine(arr: &[u8]) -> i32 {
+             let a = arr[0] as u32;
+             let b = arr[1] as u32;
+             let c = arr[2] as u32;
+             let d = arr[3] as u32;
+
+             ((a << 24) | (b << 16) | (c << 8) | (d << 0)) as i32
+         }
+    }
+
+    pub fn exec(&mut self, default: Stdio) -> io::Error {
+        if self.saw_nul {
+            return io::Error::new(ErrorKind::InvalidInput,
+                                  "nul byte found in provided data")
+        }
+
+        match self.setup_io(default, true) {
+            Ok((_, theirs)) => unsafe { self.do_exec(theirs) },
+            Err(e) => e,
+        }
+    }
+
+    // And at this point we've reached a special time in the life of the
+    // child. The child must now be considered hamstrung and unable to
+    // do anything other than syscalls really. Consider the following
+    // scenario:
+    //
+    //      1. Thread A of process 1 grabs the malloc() mutex
+    //      2. Thread B of process 1 forks(), creating thread C
+    //      3. Thread C of process 2 then attempts to malloc()
+    //      4. The memory of process 2 is the same as the memory of
+    //         process 1, so the mutex is locked.
+    //
+    // This situation looks a lot like deadlock, right? It turns out
+    // that this is what pthread_atfork() takes care of, which is
+    // presumably implemented across platforms. The first thing that
+    // threads to *before* forking is to do things like grab the malloc
+    // mutex, and then after the fork they unlock it.
+    //
+    // Despite this information, libnative's spawn has been witnessed to
+    // deadlock on both OSX and FreeBSD. I'm not entirely sure why, but
+    // all collected backtraces point at malloc/free traffic in the
+    // child spawned process.
+    //
+    // For this reason, the block of code below should contain 0
+    // invocations of either malloc of free (or their related friends).
+    //
+    // As an example of not having malloc/free traffic, we don't close
+    // this file descriptor by dropping the FileDesc (which contains an
+    // allocation). Instead we just close it manually. This will never
+    // have the drop glue anyway because this code never returns (the
+    // child will either exec() or invoke syscall::exit)
+    unsafe fn do_exec(&mut self, stdio: ChildPipes) -> io::Error {
+        macro_rules! t {
+            ($e:expr) => (match $e {
+                Ok(e) => e,
+                Err(e) => return e,
+            })
+        }
+
+        if let Some(fd) = stdio.stderr.fd() {
+            let _ = syscall::close(2);
+            t!(cvt(syscall::dup(fd, &[])));
+            let _ = syscall::close(fd);
+        }
+        if let Some(fd) = stdio.stdout.fd() {
+            let _ = syscall::close(1);
+            t!(cvt(syscall::dup(fd, &[])));
+            let _ = syscall::close(fd);
+        }
+        if let Some(fd) = stdio.stdin.fd() {
+            let _ = syscall::close(0);
+            t!(cvt(syscall::dup(fd, &[])));
+            let _ = syscall::close(fd);
+        }
+
+        if let Some(g) = self.gid {
+            t!(cvt(syscall::setregid(g as usize, g as usize)));
+        }
+        if let Some(u) = self.uid {
+            t!(cvt(syscall::setreuid(u as usize, u as usize)));
+        }
+        if let Some(ref cwd) = self.cwd {
+            t!(cvt(syscall::chdir(cwd)));
+        }
+
+        for callback in self.closures.iter_mut() {
+            t!(callback());
+        }
+
+        let mut args: Vec<[usize; 2]> = Vec::new();
+        args.push([self.program.as_ptr() as usize, self.program.len()]);
+        for arg in self.args.iter() {
+            args.push([arg.as_ptr() as usize, arg.len()]);
+        }
+
+        for (key, val) in self.env.iter() {
+            env::set_var(key, val);
+        }
+
+        let program = if self.program.contains(':') || self.program.contains('/') {
+            self.program.to_owned()
+        } else {
+            let mut path_env = ::env::var("PATH").unwrap_or(".".to_string());
+
+            if ! path_env.ends_with('/') {
+                path_env.push('/');
+            }
+
+            path_env.push_str(&self.program);
+
+            path_env
+        };
+
+        if let Err(err) = syscall::execve(&program, &args) {
+            io::Error::from_raw_os_error(err.errno as i32)
+        } else {
+            panic!("return from exec without err");
+        }
+    }
+
+
+    fn setup_io(&self, default: Stdio, needs_stdin: bool)
+                -> io::Result<(StdioPipes, ChildPipes)> {
+        let null = Stdio::Null;
+        let default_stdin = if needs_stdin {&default} else {&null};
+        let stdin = self.stdin.as_ref().unwrap_or(default_stdin);
+        let stdout = self.stdout.as_ref().unwrap_or(&default);
+        let stderr = self.stderr.as_ref().unwrap_or(&default);
+        let (their_stdin, our_stdin) = stdin.to_child_stdio(true)?;
+        let (their_stdout, our_stdout) = stdout.to_child_stdio(false)?;
+        let (their_stderr, our_stderr) = stderr.to_child_stdio(false)?;
+        let ours = StdioPipes {
+            stdin: our_stdin,
+            stdout: our_stdout,
+            stderr: our_stderr,
+        };
+        let theirs = ChildPipes {
+            stdin: their_stdin,
+            stdout: their_stdout,
+            stderr: their_stderr,
+        };
+        Ok((ours, theirs))
+    }
+}
+
+impl Stdio {
+    fn to_child_stdio(&self, readable: bool)
+                      -> io::Result<(ChildStdio, Option<AnonPipe>)> {
+        match *self {
+            Stdio::Inherit => Ok((ChildStdio::Inherit, None)),
+
+            // Make sure that the source descriptors are not an stdio
+            // descriptor, otherwise the order which we set the child's
+            // descriptors may blow away a descriptor which we are hoping to
+            // save. For example, suppose we want the child's stderr to be the
+            // parent's stdout, and the child's stdout to be the parent's
+            // stderr. No matter which we dup first, the second will get
+            // overwritten prematurely.
+            Stdio::Fd(ref fd) => {
+                if fd.raw() <= 2 {
+                    Ok((ChildStdio::Owned(fd.duplicate()?), None))
+                } else {
+                    Ok((ChildStdio::Explicit(fd.raw()), None))
+                }
+            }
+
+            Stdio::MakePipe => {
+                let (reader, writer) = pipe::anon_pipe()?;
+                let (ours, theirs) = if readable {
+                    (writer, reader)
+                } else {
+                    (reader, writer)
+                };
+                Ok((ChildStdio::Owned(theirs.into_fd()), Some(ours)))
+            }
+
+            Stdio::Null => {
+                let mut opts = OpenOptions::new();
+                opts.read(readable);
+                opts.write(!readable);
+                let fd = File::open(&Path::new("null:"), &opts)?;
+                Ok((ChildStdio::Owned(fd.into_fd()), None))
+            }
+        }
+    }
+}
+
+impl ChildStdio {
+    fn fd(&self) -> Option<usize> {
+        match *self {
+            ChildStdio::Inherit => None,
+            ChildStdio::Explicit(fd) => Some(fd),
+            ChildStdio::Owned(ref fd) => Some(fd.raw()),
+        }
+    }
+}
+
+impl fmt::Debug for Command {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "{:?}", self.program)?;
+        for arg in &self.args {
+            write!(f, " {:?}", arg)?;
+        }
+        Ok(())
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Processes
+////////////////////////////////////////////////////////////////////////////////
+
+/// Unix exit statuses
+#[derive(PartialEq, Eq, Clone, Copy, Debug)]
+pub struct ExitStatus(i32);
+
+impl ExitStatus {
+    fn exited(&self) -> bool {
+        self.0 & 0x7F == 0
+    }
+
+    pub fn success(&self) -> bool {
+        self.code() == Some(0)
+    }
+
+    pub fn code(&self) -> Option<i32> {
+        if self.exited() {
+            Some((self.0 >> 8) & 0xFF)
+        } else {
+            None
+        }
+    }
+
+    pub fn signal(&self) -> Option<i32> {
+        if !self.exited() {
+            Some(self.0 & 0x7F)
+        } else {
+            None
+        }
+    }
+}
+
+impl From<i32> for ExitStatus {
+    fn from(a: i32) -> ExitStatus {
+        ExitStatus(a)
+    }
+}
+
+impl fmt::Display for ExitStatus {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        if let Some(code) = self.code() {
+            write!(f, "exit code: {}", code)
+        } else {
+            let signal = self.signal().unwrap();
+            write!(f, "signal: {}", signal)
+        }
+    }
+}
+
+/// The unique id of the process (this should never be negative).
+pub struct Process {
+    pid: usize,
+    status: Option<ExitStatus>,
+}
+
+impl Process {
+    pub fn id(&self) -> u32 {
+        self.pid as u32
+    }
+
+    pub fn kill(&mut self) -> io::Result<()> {
+        // If we've already waited on this process then the pid can be recycled
+        // and used for another process, and we probably shouldn't be killing
+        // random processes, so just return an error.
+        if self.status.is_some() {
+            Err(Error::new(ErrorKind::InvalidInput,
+                           "invalid argument: can't kill an exited process"))
+        } else {
+            cvt(syscall::kill(self.pid, syscall::SIGKILL))?;
+            Ok(())
+        }
+    }
+
+    pub fn wait(&mut self) -> io::Result<ExitStatus> {
+        if let Some(status) = self.status {
+            return Ok(status)
+        }
+        let mut status = 0;
+        cvt(syscall::waitpid(self.pid, &mut status, 0))?;
+        self.status = Some(ExitStatus(status as i32));
+        Ok(ExitStatus(status as i32))
+    }
+}
diff --git a/src/libstd/sys/redox/rand.rs b/src/libstd/sys/redox/rand.rs
new file mode 100644
index 00000000000..eb28eca38bc
--- /dev/null
+++ b/src/libstd/sys/redox/rand.rs
@@ -0,0 +1,57 @@
+// 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.
+
+use io;
+use rand::Rng;
+
+// FIXME: Use rand:
+pub struct OsRng {
+    state: [u64; 2]
+}
+
+impl OsRng {
+    /// Create a new `OsRng`.
+    pub fn new() -> io::Result<OsRng> {
+        Ok(OsRng {
+            state: [0xBADF00D1, 0xDEADBEEF]
+        })
+    }
+}
+
+impl Rng for OsRng {
+    fn next_u32(&mut self) -> u32 {
+        self.next_u64() as u32
+    }
+    fn next_u64(&mut self) -> u64 {
+        // Store the first and second part.
+        let mut x = self.state[0];
+        let y = self.state[1];
+
+        // Put the second part into the first slot.
+        self.state[0] = y;
+        // Twist the first slot.
+        x ^= x << 23;
+        // Update the second slot.
+        self.state[1] = x ^ y ^ (x >> 17) ^ (y >> 26);
+
+        // Generate the final integer.
+        self.state[1].wrapping_add(y)
+
+    }
+    fn fill_bytes(&mut self, buf: &mut [u8]) {
+        for chunk in buf.chunks_mut(8) {
+            let mut rand: u64 = self.next_u64();
+            for b in chunk.iter_mut() {
+                *b = rand as u8;
+                rand = rand >> 8;
+            }
+        }
+    }
+}
diff --git a/src/libstd/sys/redox/rwlock.rs b/src/libstd/sys/redox/rwlock.rs
new file mode 100644
index 00000000000..d74b614ba47
--- /dev/null
+++ b/src/libstd/sys/redox/rwlock.rs
@@ -0,0 +1,61 @@
+// 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.
+
+use super::mutex::Mutex;
+
+pub struct RWLock {
+    mutex: Mutex
+}
+
+unsafe impl Send for RWLock {}
+unsafe impl Sync for RWLock {}
+
+impl RWLock {
+    pub const fn new() -> RWLock {
+        RWLock {
+            mutex: Mutex::new()
+        }
+    }
+
+    #[inline]
+    pub unsafe fn read(&self) {
+        self.mutex.lock();
+    }
+
+    #[inline]
+    pub unsafe fn try_read(&self) -> bool {
+        self.mutex.try_lock()
+    }
+
+    #[inline]
+    pub unsafe fn write(&self) {
+        self.mutex.lock();
+    }
+
+    #[inline]
+    pub unsafe fn try_write(&self) -> bool {
+        self.mutex.try_lock()
+    }
+
+    #[inline]
+    pub unsafe fn read_unlock(&self) {
+        self.mutex.unlock();
+    }
+
+    #[inline]
+    pub unsafe fn write_unlock(&self) {
+        self.mutex.unlock();
+    }
+
+    #[inline]
+    pub unsafe fn destroy(&self) {
+        self.mutex.destroy();
+    }
+}
diff --git a/src/libstd/sys/redox/stack_overflow.rs b/src/libstd/sys/redox/stack_overflow.rs
new file mode 100644
index 00000000000..760fe06c57f
--- /dev/null
+++ b/src/libstd/sys/redox/stack_overflow.rs
@@ -0,0 +1,27 @@
+// 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/redox/stdio.rs b/src/libstd/sys/redox/stdio.rs
new file mode 100644
index 00000000000..607eef051d6
--- /dev/null
+++ b/src/libstd/sys/redox/stdio.rs
@@ -0,0 +1,81 @@
+// 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.
+
+use io;
+use sys::{cvt, syscall};
+use sys::fd::FileDesc;
+
+pub struct Stdin(());
+pub struct Stdout(());
+pub struct Stderr(());
+
+impl Stdin {
+    pub fn new() -> io::Result<Stdin> { Ok(Stdin(())) }
+
+    pub fn read(&self, data: &mut [u8]) -> io::Result<usize> {
+        let fd = FileDesc::new(0);
+        let ret = fd.read(data);
+        fd.into_raw();
+        ret
+    }
+
+    pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> {
+        let fd = FileDesc::new(0);
+        let ret = fd.read_to_end(buf);
+        fd.into_raw();
+        ret
+    }
+}
+
+impl Stdout {
+    pub fn new() -> io::Result<Stdout> { Ok(Stdout(())) }
+
+    pub fn write(&self, data: &[u8]) -> io::Result<usize> {
+        let fd = FileDesc::new(1);
+        let ret = fd.write(data);
+        fd.into_raw();
+        ret
+    }
+
+    pub fn flush(&self) -> io::Result<()> {
+        cvt(syscall::fsync(1)).and(Ok(()))
+    }
+}
+
+impl Stderr {
+    pub fn new() -> io::Result<Stderr> { Ok(Stderr(())) }
+
+    pub fn write(&self, data: &[u8]) -> io::Result<usize> {
+        let fd = FileDesc::new(2);
+        let ret = fd.write(data);
+        fd.into_raw();
+        ret
+    }
+
+    pub fn flush(&self) -> io::Result<()> {
+        cvt(syscall::fsync(2)).and(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 const EBADF_ERR: i32 = ::sys::syscall::EBADF;
+pub const STDIN_BUF_SIZE: usize = ::sys_common::io::DEFAULT_BUF_SIZE;
diff --git a/src/libstd/sys/redox/syscall/arch/arm.rs b/src/libstd/sys/redox/syscall/arch/arm.rs
new file mode 100644
index 00000000000..9fb3961486d
--- /dev/null
+++ b/src/libstd/sys/redox/syscall/arch/arm.rs
@@ -0,0 +1,83 @@
+// 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.
+
+use super::error::{Error, Result};
+
+pub unsafe fn syscall0(mut a: usize) -> Result<usize> {
+    asm!("swi $$0"
+        : "={r0}"(a)
+        : "{r7}"(a)
+        : "memory"
+        : "volatile");
+
+    Error::demux(a)
+}
+
+pub unsafe fn syscall1(mut a: usize, b: usize) -> Result<usize> {
+    asm!("swi $$0"
+        : "={r0}"(a)
+        : "{r7}"(a), "{r0}"(b)
+        : "memory"
+        : "volatile");
+
+    Error::demux(a)
+}
+
+// Clobbers all registers - special for clone
+pub unsafe fn syscall1_clobber(mut a: usize, b: usize) -> Result<usize> {
+    asm!("swi $$0"
+        : "={r0}"(a)
+        : "{r7}"(a), "{r0}"(b)
+        : "memory", "r0", "r1", "r2", "r3", "r4"
+        : "volatile");
+
+    Error::demux(a)
+}
+
+pub unsafe fn syscall2(mut a: usize, b: usize, c: usize) -> Result<usize> {
+    asm!("swi $$0"
+        : "={r0}"(a)
+        : "{r7}"(a), "{r0}"(b), "{r1}"(c)
+        : "memory"
+        : "volatile");
+
+    Error::demux(a)
+}
+
+pub unsafe fn syscall3(mut a: usize, b: usize, c: usize, d: usize) -> Result<usize> {
+    asm!("swi $$0"
+        : "={r0}"(a)
+        : "{r7}"(a), "{r0}"(b), "{r1}"(c), "{r2}"(d)
+        : "memory"
+        : "volatile");
+
+    Error::demux(a)
+}
+
+pub unsafe fn syscall4(mut a: usize, b: usize, c: usize, d: usize, e: usize) -> Result<usize> {
+    asm!("swi $$0"
+        : "={r0}"(a)
+        : "{r7}"(a), "{r0}"(b), "{r1}"(c), "{r2}"(d), "{r3}"(e)
+        : "memory"
+        : "volatile");
+
+    Error::demux(a)
+}
+
+pub unsafe fn syscall5(mut a: usize, b: usize, c: usize, d: usize, e: usize, f: usize)
+                       -> Result<usize> {
+    asm!("swi $$0"
+        : "={r0}"(a)
+        : "{r7}"(a), "{r0}"(b), "{r1}"(c), "{r2}"(d), "{r3}"(e), "{r4}"(f)
+        : "memory"
+        : "volatile");
+
+    Error::demux(a)
+}
diff --git a/src/libstd/sys/redox/syscall/arch/x86.rs b/src/libstd/sys/redox/syscall/arch/x86.rs
new file mode 100644
index 00000000000..724a6b927f4
--- /dev/null
+++ b/src/libstd/sys/redox/syscall/arch/x86.rs
@@ -0,0 +1,83 @@
+// 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.
+
+use super::error::{Error, Result};
+
+pub unsafe fn syscall0(mut a: usize) -> Result<usize> {
+    asm!("int 0x80"
+        : "={eax}"(a)
+        : "{eax}"(a)
+        : "memory"
+        : "intel", "volatile");
+
+    Error::demux(a)
+}
+
+pub unsafe fn syscall1(mut a: usize, b: usize) -> Result<usize> {
+    asm!("int 0x80"
+        : "={eax}"(a)
+        : "{eax}"(a), "{ebx}"(b)
+        : "memory"
+        : "intel", "volatile");
+
+    Error::demux(a)
+}
+
+// Clobbers all registers - special for clone
+pub unsafe fn syscall1_clobber(mut a: usize, b: usize) -> Result<usize> {
+    asm!("int 0x80"
+        : "={eax}"(a)
+        : "{eax}"(a), "{ebx}"(b)
+        : "memory", "ebx", "ecx", "edx", "esi", "edi"
+        : "intel", "volatile");
+
+    Error::demux(a)
+}
+
+pub unsafe fn syscall2(mut a: usize, b: usize, c: usize) -> Result<usize> {
+    asm!("int 0x80"
+        : "={eax}"(a)
+        : "{eax}"(a), "{ebx}"(b), "{ecx}"(c)
+        : "memory"
+        : "intel", "volatile");
+
+    Error::demux(a)
+}
+
+pub unsafe fn syscall3(mut a: usize, b: usize, c: usize, d: usize) -> Result<usize> {
+    asm!("int 0x80"
+        : "={eax}"(a)
+        : "{eax}"(a), "{ebx}"(b), "{ecx}"(c), "{edx}"(d)
+        : "memory"
+        : "intel", "volatile");
+
+    Error::demux(a)
+}
+
+pub unsafe fn syscall4(mut a: usize, b: usize, c: usize, d: usize, e: usize) -> Result<usize> {
+    asm!("int 0x80"
+        : "={eax}"(a)
+        : "{eax}"(a), "{ebx}"(b), "{ecx}"(c), "{edx}"(d), "{esi}"(e)
+        : "memory"
+        : "intel", "volatile");
+
+    Error::demux(a)
+}
+
+pub unsafe fn syscall5(mut a: usize, b: usize, c: usize, d: usize, e: usize, f: usize)
+                       -> Result<usize> {
+    asm!("int 0x80"
+        : "={eax}"(a)
+        : "{eax}"(a), "{ebx}"(b), "{ecx}"(c), "{edx}"(d), "{esi}"(e), "{edi}"(f)
+        : "memory"
+        : "intel", "volatile");
+
+    Error::demux(a)
+}
diff --git a/src/libstd/sys/redox/syscall/arch/x86_64.rs b/src/libstd/sys/redox/syscall/arch/x86_64.rs
new file mode 100644
index 00000000000..a321c31f207
--- /dev/null
+++ b/src/libstd/sys/redox/syscall/arch/x86_64.rs
@@ -0,0 +1,84 @@
+// 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.
+
+use super::error::{Error, Result};
+
+pub unsafe fn syscall0(mut a: usize) -> Result<usize> {
+    asm!("int 0x80"
+        : "={rax}"(a)
+        : "{rax}"(a)
+        : "memory"
+        : "intel", "volatile");
+
+    Error::demux(a)
+}
+
+pub unsafe fn syscall1(mut a: usize, b: usize) -> Result<usize> {
+    asm!("int 0x80"
+        : "={rax}"(a)
+        : "{rax}"(a), "{rbx}"(b)
+        : "memory"
+        : "intel", "volatile");
+
+    Error::demux(a)
+}
+
+// Clobbers all registers - special for clone
+pub unsafe fn syscall1_clobber(mut a: usize, b: usize) -> Result<usize> {
+    asm!("int 0x80"
+        : "={rax}"(a)
+        : "{rax}"(a), "{rbx}"(b)
+        : "memory", "rbx", "rcx", "rdx", "rsi", "rdi", "r8",
+          "r9", "r10", "r11", "r12", "r13", "r14", "r15"
+        : "intel", "volatile");
+
+    Error::demux(a)
+}
+
+pub unsafe fn syscall2(mut a: usize, b: usize, c: usize) -> Result<usize> {
+    asm!("int 0x80"
+        : "={rax}"(a)
+        : "{rax}"(a), "{rbx}"(b), "{rcx}"(c)
+        : "memory"
+        : "intel", "volatile");
+
+    Error::demux(a)
+}
+
+pub unsafe fn syscall3(mut a: usize, b: usize, c: usize, d: usize) -> Result<usize> {
+    asm!("int 0x80"
+        : "={rax}"(a)
+        : "{rax}"(a), "{rbx}"(b), "{rcx}"(c), "{rdx}"(d)
+        : "memory"
+        : "intel", "volatile");
+
+    Error::demux(a)
+}
+
+pub unsafe fn syscall4(mut a: usize, b: usize, c: usize, d: usize, e: usize) -> Result<usize> {
+    asm!("int 0x80"
+        : "={rax}"(a)
+        : "{rax}"(a), "{rbx}"(b), "{rcx}"(c), "{rdx}"(d), "{rsi}"(e)
+        : "memory"
+        : "intel", "volatile");
+
+    Error::demux(a)
+}
+
+pub unsafe fn syscall5(mut a: usize, b: usize, c: usize, d: usize, e: usize, f: usize)
+                       -> Result<usize> {
+    asm!("int 0x80"
+        : "={rax}"(a)
+        : "{rax}"(a), "{rbx}"(b), "{rcx}"(c), "{rdx}"(d), "{rsi}"(e), "{rdi}"(f)
+        : "memory"
+        : "intel", "volatile");
+
+    Error::demux(a)
+}
diff --git a/src/libstd/sys/redox/syscall/call.rs b/src/libstd/sys/redox/syscall/call.rs
new file mode 100644
index 00000000000..f58c240f31e
--- /dev/null
+++ b/src/libstd/sys/redox/syscall/call.rs
@@ -0,0 +1,300 @@
+// 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.
+
+use super::arch::*;
+use super::data::{Stat, StatVfs, TimeSpec};
+use super::error::Result;
+use super::number::*;
+
+use core::mem;
+
+/// Set the end of the process's heap
+///
+/// When `addr` is `0`, this function will return the current break.
+///
+/// When `addr` is nonzero, this function will attempt to set the end of the process's
+/// heap to `addr` and return the new program break. The new program break should be
+/// checked by the allocator, it may not be exactly `addr`, as it may be aligned to a page
+/// boundary.
+///
+/// On error, `Err(ENOMEM)` will be returned indicating that no memory is available
+pub unsafe fn brk(addr: usize) -> Result<usize> {
+    syscall1(SYS_BRK, addr)
+}
+
+/// Change the process's working directory
+///
+/// This function will attempt to set the process's working directory to `path`, which can be
+/// either a relative, scheme relative, or absolute path.
+///
+/// On success, `Ok(0)` will be returned. On error, one of the following errors will be returned.
+///
+/// # Errors
+///
+/// * `EACCES` - permission is denied for one of the components of `path`, or `path`
+/// * `EFAULT` - `path` does not point to the process's addressible memory
+/// * `EIO` - an I/O error occured
+/// * `ENOENT` - `path` does not exit
+/// * `ENOTDIR` - `path` is not a directory
+pub fn chdir(path: &str) -> Result<usize> {
+    unsafe { syscall2(SYS_CHDIR, path.as_ptr() as usize, path.len()) }
+}
+
+pub fn chmod(path: &str, mode: usize) -> Result<usize> {
+    unsafe { syscall3(SYS_CHMOD, path.as_ptr() as usize, path.len(), mode) }
+}
+
+/// Produce a fork of the current process, or a new process thread
+pub unsafe fn clone(flags: usize) -> Result<usize> {
+    syscall1_clobber(SYS_CLONE, flags)
+}
+
+/// Close a file
+pub fn close(fd: usize) -> Result<usize> {
+    unsafe { syscall1(SYS_CLOSE, fd) }
+}
+
+/// Get the current system time
+pub fn clock_gettime(clock: usize, tp: &mut TimeSpec) -> Result<usize> {
+    unsafe { syscall2(SYS_CLOCK_GETTIME, clock, tp as *mut TimeSpec as usize) }
+}
+
+/// Copy and transform a file descriptor
+pub fn dup(fd: usize, buf: &[u8]) -> Result<usize> {
+    unsafe { syscall3(SYS_DUP, fd, buf.as_ptr() as usize, buf.len()) }
+}
+
+/// Replace the current process with a new executable
+pub fn execve(path: &str, args: &[[usize; 2]]) -> Result<usize> {
+    unsafe { syscall4(SYS_EXECVE, path.as_ptr() as usize, path.len(),
+                                  args.as_ptr() as usize, args.len()) }
+}
+
+/// Exit the current process
+pub fn exit(status: usize) -> Result<usize> {
+    unsafe { syscall1(SYS_EXIT, status) }
+}
+
+/// Register a file for event-based I/O
+pub fn fcntl(fd: usize, cmd: usize, arg: usize) -> Result<usize> {
+    unsafe { syscall3(SYS_FCNTL, fd, cmd, arg) }
+}
+
+/// Register a file for event-based I/O
+pub fn fevent(fd: usize, flags: usize) -> Result<usize> {
+    unsafe { syscall2(SYS_FEVENT, fd, flags) }
+}
+
+/// Map a file into memory
+pub unsafe fn fmap(fd: usize, offset: usize, size: usize) -> Result<usize> {
+    syscall3(SYS_FMAP, fd, offset, size)
+}
+
+/// Unmap a memory-mapped file
+pub unsafe fn funmap(addr: usize) -> Result<usize> {
+    syscall1(SYS_FUNMAP, addr)
+}
+
+/// Retrieve the canonical path of a file
+pub fn fpath(fd: usize, buf: &mut [u8]) -> Result<usize> {
+    unsafe { syscall3(SYS_FPATH, fd, buf.as_mut_ptr() as usize, buf.len()) }
+}
+
+/// Get metadata about a file
+pub fn fstat(fd: usize, stat: &mut Stat) -> Result<usize> {
+    unsafe { syscall3(SYS_FSTAT, fd, stat as *mut Stat as usize, mem::size_of::<Stat>()) }
+}
+
+/// Get metadata about a filesystem
+pub fn fstatvfs(fd: usize, stat: &mut StatVfs) -> Result<usize> {
+    unsafe { syscall3(SYS_FSTATVFS, fd, stat as *mut StatVfs as usize, mem::size_of::<StatVfs>()) }
+}
+
+/// Sync a file descriptor to its underlying medium
+pub fn fsync(fd: usize) -> Result<usize> {
+    unsafe { syscall1(SYS_FSYNC, fd) }
+}
+
+/// Truncate or extend a file to a specified length
+pub fn ftruncate(fd: usize, len: usize) -> Result<usize> {
+    unsafe { syscall2(SYS_FTRUNCATE, fd, len) }
+}
+
+/// Fast userspace mutex
+pub unsafe fn futex(addr: *mut i32, op: usize, val: i32, val2: usize, addr2: *mut i32)
+                    -> Result<usize> {
+    syscall5(SYS_FUTEX, addr as usize, op, (val as isize) as usize, val2, addr2 as usize)
+}
+
+/// Get the current working directory
+pub fn getcwd(buf: &mut [u8]) -> Result<usize> {
+    unsafe { syscall2(SYS_GETCWD, buf.as_mut_ptr() as usize, buf.len()) }
+}
+
+/// Get the effective group ID
+pub fn getegid() -> Result<usize> {
+    unsafe { syscall0(SYS_GETEGID) }
+}
+
+/// Get the effective namespace
+pub fn getens() -> Result<usize> {
+    unsafe { syscall0(SYS_GETENS) }
+}
+
+/// Get the effective user ID
+pub fn geteuid() -> Result<usize> {
+    unsafe { syscall0(SYS_GETEUID) }
+}
+
+/// Get the current group ID
+pub fn getgid() -> Result<usize> {
+    unsafe { syscall0(SYS_GETGID) }
+}
+
+/// Get the current namespace
+pub fn getns() -> Result<usize> {
+    unsafe { syscall0(SYS_GETNS) }
+}
+
+/// Get the current process ID
+pub fn getpid() -> Result<usize> {
+    unsafe { syscall0(SYS_GETPID) }
+}
+
+/// Get the current user ID
+pub fn getuid() -> Result<usize> {
+    unsafe { syscall0(SYS_GETUID) }
+}
+
+/// Set the I/O privilege level
+pub unsafe fn iopl(level: usize) -> Result<usize> {
+    syscall1(SYS_IOPL, level)
+}
+
+/// Send a signal `sig` to the process identified by `pid`
+pub fn kill(pid: usize, sig: usize) -> Result<usize> {
+    unsafe { syscall2(SYS_KILL, pid, sig) }
+}
+
+/// Create a link to a file
+pub unsafe fn link(old: *const u8, new: *const u8) -> Result<usize> {
+    syscall2(SYS_LINK, old as usize, new as usize)
+}
+
+/// Seek to `offset` bytes in a file descriptor
+pub fn lseek(fd: usize, offset: isize, whence: usize) -> Result<usize> {
+    unsafe { syscall3(SYS_LSEEK, fd, offset as usize, whence) }
+}
+
+/// Make a new scheme namespace
+pub fn mkns(schemes: &[[usize; 2]]) -> Result<usize> {
+    unsafe { syscall2(SYS_MKNS, schemes.as_ptr() as usize, schemes.len()) }
+}
+
+/// Sleep for the time specified in `req`
+pub fn nanosleep(req: &TimeSpec, rem: &mut TimeSpec) -> Result<usize> {
+    unsafe { syscall2(SYS_NANOSLEEP, req as *const TimeSpec as usize,
+                                     rem as *mut TimeSpec as usize) }
+}
+
+/// Open a file
+pub fn open(path: &str, flags: usize) -> Result<usize> {
+    unsafe { syscall3(SYS_OPEN, path.as_ptr() as usize, path.len(), flags) }
+}
+
+/// Allocate pages, linearly in physical memory
+pub unsafe fn physalloc(size: usize) -> Result<usize> {
+    syscall1(SYS_PHYSALLOC, size)
+}
+
+/// Free physically allocated pages
+pub unsafe fn physfree(physical_address: usize, size: usize) -> Result<usize> {
+    syscall2(SYS_PHYSFREE, physical_address, size)
+}
+
+/// Map physical memory to virtual memory
+pub unsafe fn physmap(physical_address: usize, size: usize, flags: usize) -> Result<usize> {
+    syscall3(SYS_PHYSMAP, physical_address, size, flags)
+}
+
+/// Unmap previously mapped physical memory
+pub unsafe fn physunmap(virtual_address: usize) -> Result<usize> {
+    syscall1(SYS_PHYSUNMAP, virtual_address)
+}
+
+/// Create a pair of file descriptors referencing the read and write ends of a pipe
+pub fn pipe2(fds: &mut [usize; 2], flags: usize) -> Result<usize> {
+    unsafe { syscall2(SYS_PIPE2, fds.as_ptr() as usize, flags) }
+}
+
+/// Read from a file descriptor into a buffer
+pub fn read(fd: usize, buf: &mut [u8]) -> Result<usize> {
+    unsafe { syscall3(SYS_READ, fd, buf.as_mut_ptr() as usize, buf.len()) }
+}
+
+/// Remove a directory
+pub fn rmdir(path: &str) -> Result<usize> {
+    unsafe { syscall2(SYS_RMDIR, path.as_ptr() as usize, path.len()) }
+}
+
+/// Set the current process group IDs
+pub fn setregid(rgid: usize, egid: usize) -> Result<usize> {
+    unsafe { syscall2(SYS_SETREGID, rgid, egid) }
+}
+
+/// Make a new scheme namespace
+pub fn setrens(rns: usize, ens: usize) -> Result<usize> {
+    unsafe { syscall2(SYS_SETRENS, rns, ens) }
+}
+
+/// Set the current process user IDs
+pub fn setreuid(ruid: usize, euid: usize) -> Result<usize> {
+    unsafe { syscall2(SYS_SETREUID, ruid, euid) }
+}
+
+/// Remove a file
+pub fn unlink(path: &str) -> Result<usize> {
+    unsafe { syscall2(SYS_UNLINK, path.as_ptr() as usize, path.len()) }
+}
+
+/// Convert a virtual address to a physical one
+pub unsafe fn virttophys(virtual_address: usize) -> Result<usize> {
+    syscall1(SYS_VIRTTOPHYS, virtual_address)
+}
+
+/// Check if a child process has exited or received a signal
+pub fn waitpid(pid: usize, status: &mut usize, options: usize) -> Result<usize> {
+    unsafe { syscall3(SYS_WAITPID, pid, status as *mut usize as usize, options) }
+}
+
+/// Write a buffer to a file descriptor
+///
+/// The kernel will attempt to write the bytes in `buf` to the file descriptor `fd`, returning
+/// either an `Err`, explained below, or `Ok(count)` where `count` is the number of bytes which
+/// were written.
+///
+/// # Errors
+///
+/// * `EAGAIN` - the file descriptor was opened with `O_NONBLOCK` and writing would block
+/// * `EBADF` - the file descriptor is not valid or is not open for writing
+/// * `EFAULT` - `buf` does not point to the process's addressible memory
+/// * `EIO` - an I/O error occured
+/// * `ENOSPC` - the device containing the file descriptor has no room for data
+/// * `EPIPE` - the file descriptor refers to a pipe or socket whose reading end is closed
+pub fn write(fd: usize, buf: &[u8]) -> Result<usize> {
+    unsafe { syscall3(SYS_WRITE, fd, buf.as_ptr() as usize, buf.len()) }
+}
+
+/// Yield the process's time slice to the kernel
+///
+/// This function will return Ok(0) on success
+pub fn sched_yield() -> Result<usize> {
+    unsafe { syscall0(SYS_YIELD) }
+}
diff --git a/src/libstd/sys/redox/syscall/data.rs b/src/libstd/sys/redox/syscall/data.rs
new file mode 100644
index 00000000000..ac3946672a3
--- /dev/null
+++ b/src/libstd/sys/redox/syscall/data.rs
@@ -0,0 +1,86 @@
+// 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.
+
+use core::ops::{Deref, DerefMut};
+use core::{mem, slice};
+
+#[derive(Copy, Clone, Debug, Default)]
+#[repr(packed)]
+pub struct Stat {
+    pub st_dev: u64,
+    pub st_ino: u64,
+    pub st_mode: u16,
+    pub st_nlink: u32,
+    pub st_uid: u32,
+    pub st_gid: u32,
+    pub st_size: u64,
+    pub st_blksize: u32,
+    pub st_blocks: u64,
+    pub st_mtime: u64,
+    pub st_mtime_nsec: u32,
+    pub st_atime: u64,
+    pub st_atime_nsec: u32,
+    pub st_ctime: u64,
+    pub st_ctime_nsec: u32,
+}
+
+impl Deref for Stat {
+    type Target = [u8];
+    fn deref(&self) -> &[u8] {
+        unsafe {
+            slice::from_raw_parts(self as *const Stat as *const u8,
+                                  mem::size_of::<Stat>()) as &[u8]
+        }
+    }
+}
+
+impl DerefMut for Stat {
+    fn deref_mut(&mut self) -> &mut [u8] {
+        unsafe {
+            slice::from_raw_parts_mut(self as *mut Stat as *mut u8,
+                                      mem::size_of::<Stat>()) as &mut [u8]
+        }
+    }
+}
+
+#[derive(Copy, Clone, Debug, Default)]
+#[repr(packed)]
+pub struct StatVfs {
+    pub f_bsize: u32,
+    pub f_blocks: u64,
+    pub f_bfree: u64,
+    pub f_bavail: u64,
+}
+
+impl Deref for StatVfs {
+    type Target = [u8];
+    fn deref(&self) -> &[u8] {
+        unsafe {
+            slice::from_raw_parts(self as *const StatVfs as *const u8,
+                                  mem::size_of::<StatVfs>()) as &[u8]
+        }
+    }
+}
+
+impl DerefMut for StatVfs {
+    fn deref_mut(&mut self) -> &mut [u8] {
+        unsafe {
+            slice::from_raw_parts_mut(self as *mut StatVfs as *mut u8,
+                                      mem::size_of::<StatVfs>()) as &mut [u8]
+        }
+    }
+}
+
+#[derive(Copy, Clone, Debug, Default)]
+#[repr(packed)]
+pub struct TimeSpec {
+    pub tv_sec: i64,
+    pub tv_nsec: i32,
+}
diff --git a/src/libstd/sys/redox/syscall/error.rs b/src/libstd/sys/redox/syscall/error.rs
new file mode 100644
index 00000000000..d8d78d55016
--- /dev/null
+++ b/src/libstd/sys/redox/syscall/error.rs
@@ -0,0 +1,325 @@
+// 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.
+
+use core::{fmt, result};
+
+#[derive(Eq, PartialEq)]
+pub struct Error {
+    pub errno: i32,
+}
+
+pub type Result<T> = result::Result<T, Error>;
+
+impl Error {
+    pub fn new(errno: i32) -> Error {
+        Error { errno: errno }
+    }
+
+    pub fn mux(result: Result<usize>) -> usize {
+        match result {
+            Ok(value) => value,
+            Err(error) => -error.errno as usize,
+        }
+    }
+
+    pub fn demux(value: usize) -> Result<usize> {
+        let errno = -(value as i32);
+        if errno >= 1 && errno < STR_ERROR.len() as i32 {
+            Err(Error::new(errno))
+        } else {
+            Ok(value)
+        }
+    }
+
+    pub fn text(&self) -> &str {
+        if let Some(description) = STR_ERROR.get(self.errno as usize) {
+            description
+        } else {
+            "Unknown Error"
+        }
+    }
+}
+
+impl fmt::Debug for Error {
+    fn fmt(&self, f: &mut fmt::Formatter) -> result::Result<(), fmt::Error> {
+        f.write_str(self.text())
+    }
+}
+
+impl fmt::Display for Error {
+    fn fmt(&self, f: &mut fmt::Formatter) -> result::Result<(), fmt::Error> {
+        f.write_str(self.text())
+    }
+}
+
+pub const EPERM: i32 = 1;  /* Operation not permitted */
+pub const ENOENT: i32 = 2;  /* No such file or directory */
+pub const ESRCH: i32 = 3;  /* No such process */
+pub const EINTR: i32 = 4;  /* Interrupted system call */
+pub const EIO: i32 = 5;  /* I/O error */
+pub const ENXIO: i32 = 6;  /* No such device or address */
+pub const E2BIG: i32 = 7;  /* Argument list too long */
+pub const ENOEXEC: i32 = 8;  /* Exec format error */
+pub const EBADF: i32 = 9;  /* Bad file number */
+pub const ECHILD: i32 = 10;  /* No child processes */
+pub const EAGAIN: i32 = 11;  /* Try again */
+pub const ENOMEM: i32 = 12;  /* Out of memory */
+pub const EACCES: i32 = 13;  /* Permission denied */
+pub const EFAULT: i32 = 14;  /* Bad address */
+pub const ENOTBLK: i32 = 15;  /* Block device required */
+pub const EBUSY: i32 = 16;  /* Device or resource busy */
+pub const EEXIST: i32 = 17;  /* File exists */
+pub const EXDEV: i32 = 18;  /* Cross-device link */
+pub const ENODEV: i32 = 19;  /* No such device */
+pub const ENOTDIR: i32 = 20;  /* Not a directory */
+pub const EISDIR: i32 = 21;  /* Is a directory */
+pub const EINVAL: i32 = 22;  /* Invalid argument */
+pub const ENFILE: i32 = 23;  /* File table overflow */
+pub const EMFILE: i32 = 24;  /* Too many open files */
+pub const ENOTTY: i32 = 25;  /* Not a typewriter */
+pub const ETXTBSY: i32 = 26;  /* Text file busy */
+pub const EFBIG: i32 = 27;  /* File too large */
+pub const ENOSPC: i32 = 28;  /* No space left on device */
+pub const ESPIPE: i32 = 29;  /* Illegal seek */
+pub const EROFS: i32 = 30;  /* Read-only file system */
+pub const EMLINK: i32 = 31;  /* Too many links */
+pub const EPIPE: i32 = 32;  /* Broken pipe */
+pub const EDOM: i32 = 33;  /* Math argument out of domain of func */
+pub const ERANGE: i32 = 34;  /* Math result not representable */
+pub const EDEADLK: i32 = 35;  /* Resource deadlock would occur */
+pub const ENAMETOOLONG: i32 = 36;  /* File name too long */
+pub const ENOLCK: i32 = 37;  /* No record locks available */
+pub const ENOSYS: i32 = 38;  /* Function not implemented */
+pub const ENOTEMPTY: i32 = 39;  /* Directory not empty */
+pub const ELOOP: i32 = 40;  /* Too many symbolic links encountered */
+pub const EWOULDBLOCK: i32 = 41;  /* Operation would block */
+pub const ENOMSG: i32 = 42;  /* No message of desired type */
+pub const EIDRM: i32 = 43;  /* Identifier removed */
+pub const ECHRNG: i32 = 44;  /* Channel number out of range */
+pub const EL2NSYNC: i32 = 45;  /* Level 2 not synchronized */
+pub const EL3HLT: i32 = 46;  /* Level 3 halted */
+pub const EL3RST: i32 = 47;  /* Level 3 reset */
+pub const ELNRNG: i32 = 48;  /* Link number out of range */
+pub const EUNATCH: i32 = 49;  /* Protocol driver not attached */
+pub const ENOCSI: i32 = 50;  /* No CSI structure available */
+pub const EL2HLT: i32 = 51;  /* Level 2 halted */
+pub const EBADE: i32 = 52;  /* Invalid exchange */
+pub const EBADR: i32 = 53;  /* Invalid request descriptor */
+pub const EXFULL: i32 = 54;  /* Exchange full */
+pub const ENOANO: i32 = 55;  /* No anode */
+pub const EBADRQC: i32 = 56;  /* Invalid request code */
+pub const EBADSLT: i32 = 57;  /* Invalid slot */
+pub const EDEADLOCK: i32 = 58; /* Resource deadlock would occur */
+pub const EBFONT: i32 = 59;  /* Bad font file format */
+pub const ENOSTR: i32 = 60;  /* Device not a stream */
+pub const ENODATA: i32 = 61;  /* No data available */
+pub const ETIME: i32 = 62;  /* Timer expired */
+pub const ENOSR: i32 = 63;  /* Out of streams resources */
+pub const ENONET: i32 = 64;  /* Machine is not on the network */
+pub const ENOPKG: i32 = 65;  /* Package not installed */
+pub const EREMOTE: i32 = 66;  /* Object is remote */
+pub const ENOLINK: i32 = 67;  /* Link has been severed */
+pub const EADV: i32 = 68;  /* Advertise error */
+pub const ESRMNT: i32 = 69;  /* Srmount error */
+pub const ECOMM: i32 = 70;  /* Communication error on send */
+pub const EPROTO: i32 = 71;  /* Protocol error */
+pub const EMULTIHOP: i32 = 72;  /* Multihop attempted */
+pub const EDOTDOT: i32 = 73;  /* RFS specific error */
+pub const EBADMSG: i32 = 74;  /* Not a data message */
+pub const EOVERFLOW: i32 = 75;  /* Value too large for defined data type */
+pub const ENOTUNIQ: i32 = 76;  /* Name not unique on network */
+pub const EBADFD: i32 = 77;  /* File descriptor in bad state */
+pub const EREMCHG: i32 = 78;  /* Remote address changed */
+pub const ELIBACC: i32 = 79;  /* Can not access a needed shared library */
+pub const ELIBBAD: i32 = 80;  /* Accessing a corrupted shared library */
+pub const ELIBSCN: i32 = 81;  /* .lib section in a.out corrupted */
+pub const ELIBMAX: i32 = 82;  /* Attempting to link in too many shared libraries */
+pub const ELIBEXEC: i32 = 83;  /* Cannot exec a shared library directly */
+pub const EILSEQ: i32 = 84;  /* Illegal byte sequence */
+pub const ERESTART: i32 = 85;  /* Interrupted system call should be restarted */
+pub const ESTRPIPE: i32 = 86;  /* Streams pipe error */
+pub const EUSERS: i32 = 87;  /* Too many users */
+pub const ENOTSOCK: i32 = 88;  /* Socket operation on non-socket */
+pub const EDESTADDRREQ: i32 = 89;  /* Destination address required */
+pub const EMSGSIZE: i32 = 90;  /* Message too long */
+pub const EPROTOTYPE: i32 = 91;  /* Protocol wrong type for socket */
+pub const ENOPROTOOPT: i32 = 92;  /* Protocol not available */
+pub const EPROTONOSUPPORT: i32 = 93;  /* Protocol not supported */
+pub const ESOCKTNOSUPPORT: i32 = 94;  /* Socket type not supported */
+pub const EOPNOTSUPP: i32 = 95;  /* Operation not supported on transport endpoint */
+pub const EPFNOSUPPORT: i32 = 96;  /* Protocol family not supported */
+pub const EAFNOSUPPORT: i32 = 97;  /* Address family not supported by protocol */
+pub const EADDRINUSE: i32 = 98;  /* Address already in use */
+pub const EADDRNOTAVAIL: i32 = 99;  /* Cannot assign requested address */
+pub const ENETDOWN: i32 = 100; /* Network is down */
+pub const ENETUNREACH: i32 = 101; /* Network is unreachable */
+pub const ENETRESET: i32 = 102; /* Network dropped connection because of reset */
+pub const ECONNABORTED: i32 = 103; /* Software caused connection abort */
+pub const ECONNRESET: i32 = 104; /* Connection reset by peer */
+pub const ENOBUFS: i32 = 105; /* No buffer space available */
+pub const EISCONN: i32 = 106; /* Transport endpoint is already connected */
+pub const ENOTCONN: i32 = 107; /* Transport endpoint is not connected */
+pub const ESHUTDOWN: i32 = 108; /* Cannot send after transport endpoint shutdown */
+pub const ETOOMANYREFS: i32 = 109; /* Too many references: cannot splice */
+pub const ETIMEDOUT: i32 = 110; /* Connection timed out */
+pub const ECONNREFUSED: i32 = 111; /* Connection refused */
+pub const EHOSTDOWN: i32 = 112; /* Host is down */
+pub const EHOSTUNREACH: i32 = 113; /* No route to host */
+pub const EALREADY: i32 = 114; /* Operation already in progress */
+pub const EINPROGRESS: i32 = 115; /* Operation now in progress */
+pub const ESTALE: i32 = 116; /* Stale NFS file handle */
+pub const EUCLEAN: i32 = 117; /* Structure needs cleaning */
+pub const ENOTNAM: i32 = 118; /* Not a XENIX named type file */
+pub const ENAVAIL: i32 = 119; /* No XENIX semaphores available */
+pub const EISNAM: i32 = 120; /* Is a named type file */
+pub const EREMOTEIO: i32 = 121; /* Remote I/O error */
+pub const EDQUOT: i32 = 122; /* Quota exceeded */
+pub const ENOMEDIUM: i32 = 123; /* No medium found */
+pub const EMEDIUMTYPE: i32 = 124; /* Wrong medium type */
+pub const ECANCELED: i32 = 125; /* Operation Canceled */
+pub const ENOKEY: i32 = 126; /* Required key not available */
+pub const EKEYEXPIRED: i32 = 127; /* Key has expired */
+pub const EKEYREVOKED: i32 = 128; /* Key has been revoked */
+pub const EKEYREJECTED: i32 = 129; /* Key was rejected by service */
+pub const EOWNERDEAD: i32 = 130; /* Owner died */
+pub const ENOTRECOVERABLE: i32 = 131; /* State not recoverable */
+
+pub static STR_ERROR: [&'static str; 132] = ["Success",
+                                             "Operation not permitted",
+                                             "No such file or directory",
+                                             "No such process",
+                                             "Interrupted system call",
+                                             "I/O error",
+                                             "No such device or address",
+                                             "Argument list too long",
+                                             "Exec format error",
+                                             "Bad file number",
+                                             "No child processes",
+                                             "Try again",
+                                             "Out of memory",
+                                             "Permission denied",
+                                             "Bad address",
+                                             "Block device required",
+                                             "Device or resource busy",
+                                             "File exists",
+                                             "Cross-device link",
+                                             "No such device",
+                                             "Not a directory",
+                                             "Is a directory",
+                                             "Invalid argument",
+                                             "File table overflow",
+                                             "Too many open files",
+                                             "Not a typewriter",
+                                             "Text file busy",
+                                             "File too large",
+                                             "No space left on device",
+                                             "Illegal seek",
+                                             "Read-only file system",
+                                             "Too many links",
+                                             "Broken pipe",
+                                             "Math argument out of domain of func",
+                                             "Math result not representable",
+                                             "Resource deadlock would occur",
+                                             "File name too long",
+                                             "No record locks available",
+                                             "Function not implemented",
+                                             "Directory not empty",
+                                             "Too many symbolic links encountered",
+                                             "Operation would block",
+                                             "No message of desired type",
+                                             "Identifier removed",
+                                             "Channel number out of range",
+                                             "Level 2 not synchronized",
+                                             "Level 3 halted",
+                                             "Level 3 reset",
+                                             "Link number out of range",
+                                             "Protocol driver not attached",
+                                             "No CSI structure available",
+                                             "Level 2 halted",
+                                             "Invalid exchange",
+                                             "Invalid request descriptor",
+                                             "Exchange full",
+                                             "No anode",
+                                             "Invalid request code",
+                                             "Invalid slot",
+                                             "Resource deadlock would occur",
+                                             "Bad font file format",
+                                             "Device not a stream",
+                                             "No data available",
+                                             "Timer expired",
+                                             "Out of streams resources",
+                                             "Machine is not on the network",
+                                             "Package not installed",
+                                             "Object is remote",
+                                             "Link has been severed",
+                                             "Advertise error",
+                                             "Srmount error",
+                                             "Communication error on send",
+                                             "Protocol error",
+                                             "Multihop attempted",
+                                             "RFS specific error",
+                                             "Not a data message",
+                                             "Value too large for defined data type",
+                                             "Name not unique on network",
+                                             "File descriptor in bad state",
+                                             "Remote address changed",
+                                             "Can not access a needed shared library",
+                                             "Accessing a corrupted shared library",
+                                             ".lib section in a.out corrupted",
+                                             "Attempting to link in too many shared libraries",
+                                             "Cannot exec a shared library directly",
+                                             "Illegal byte sequence",
+                                             "Interrupted system call should be restarted",
+                                             "Streams pipe error",
+                                             "Too many users",
+                                             "Socket operation on non-socket",
+                                             "Destination address required",
+                                             "Message too long",
+                                             "Protocol wrong type for socket",
+                                             "Protocol not available",
+                                             "Protocol not supported",
+                                             "Socket type not supported",
+                                             "Operation not supported on transport endpoint",
+                                             "Protocol family not supported",
+                                             "Address family not supported by protocol",
+                                             "Address already in use",
+                                             "Cannot assign requested address",
+                                             "Network is down",
+                                             "Network is unreachable",
+                                             "Network dropped connection because of reset",
+                                             "Software caused connection abort",
+                                             "Connection reset by peer",
+                                             "No buffer space available",
+                                             "Transport endpoint is already connected",
+                                             "Transport endpoint is not connected",
+                                             "Cannot send after transport endpoint shutdown",
+                                             "Too many references: cannot splice",
+                                             "Connection timed out",
+                                             "Connection refused",
+                                             "Host is down",
+                                             "No route to host",
+                                             "Operation already in progress",
+                                             "Operation now in progress",
+                                             "Stale NFS file handle",
+                                             "Structure needs cleaning",
+                                             "Not a XENIX named type file",
+                                             "No XENIX semaphores available",
+                                             "Is a named type file",
+                                             "Remote I/O error",
+                                             "Quota exceeded",
+                                             "No medium found",
+                                             "Wrong medium type",
+                                             "Operation Canceled",
+                                             "Required key not available",
+                                             "Key has expired",
+                                             "Key has been revoked",
+                                             "Key was rejected by service",
+                                             "Owner died",
+                                             "State not recoverable"];
diff --git a/src/libstd/sys/redox/syscall/flag.rs b/src/libstd/sys/redox/syscall/flag.rs
new file mode 100644
index 00000000000..9f0d3e6f779
--- /dev/null
+++ b/src/libstd/sys/redox/syscall/flag.rs
@@ -0,0 +1,94 @@
+// 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.
+
+pub const CLONE_VM: usize = 0x100;
+pub const CLONE_FS: usize = 0x200;
+pub const CLONE_FILES: usize = 0x400;
+pub const CLONE_VFORK: usize = 0x4000;
+
+pub const CLOCK_REALTIME: usize = 1;
+pub const CLOCK_MONOTONIC: usize = 4;
+
+pub const EVENT_NONE: usize = 0;
+pub const EVENT_READ: usize = 1;
+pub const EVENT_WRITE: usize = 2;
+
+pub const F_GETFL: usize = 1;
+pub const F_SETFL: usize = 2;
+
+pub const FUTEX_WAIT: usize = 0;
+pub const FUTEX_WAKE: usize = 1;
+pub const FUTEX_REQUEUE: usize = 2;
+
+pub const MAP_WRITE: usize = 1;
+pub const MAP_WRITE_COMBINE: usize = 2;
+
+pub const MODE_TYPE: u16 = 0xF000;
+pub const MODE_DIR: u16 = 0x4000;
+pub const MODE_FILE: u16 = 0x8000;
+
+pub const MODE_PERM: u16 = 0x0FFF;
+pub const MODE_SETUID: u16 = 0o4000;
+pub const MODE_SETGID: u16 = 0o2000;
+
+pub const O_RDONLY: usize =     0x0001_0000;
+pub const O_WRONLY: usize =     0x0002_0000;
+pub const O_RDWR: usize =       0x0003_0000;
+pub const O_NONBLOCK: usize =   0x0004_0000;
+pub const O_APPEND: usize =     0x0008_0000;
+pub const O_SHLOCK: usize =     0x0010_0000;
+pub const O_EXLOCK: usize =     0x0020_0000;
+pub const O_ASYNC: usize =      0x0040_0000;
+pub const O_FSYNC: usize =      0x0080_0000;
+pub const O_CLOEXEC: usize =    0x0100_0000;
+pub const O_CREAT: usize =      0x0200_0000;
+pub const O_TRUNC: usize =      0x0400_0000;
+pub const O_EXCL: usize =       0x0800_0000;
+pub const O_DIRECTORY: usize =  0x1000_0000;
+pub const O_STAT: usize =       0x2000_0000;
+pub const O_ACCMODE: usize =    O_RDONLY | O_WRONLY | O_RDWR;
+
+pub const SEEK_SET: usize = 0;
+pub const SEEK_CUR: usize = 1;
+pub const SEEK_END: usize = 2;
+
+pub const SIGHUP: usize =   1;
+pub const SIGINT: usize =   2;
+pub const SIGQUIT: usize =  3;
+pub const SIGILL: usize =   4;
+pub const SIGTRAP: usize =  5;
+pub const SIGABRT: usize =  6;
+pub const SIGBUS: usize =   7;
+pub const SIGFPE: usize =   8;
+pub const SIGKILL: usize =  9;
+pub const SIGUSR1: usize =  10;
+pub const SIGSEGV: usize =  11;
+pub const SIGUSR2: usize =  12;
+pub const SIGPIPE: usize =  13;
+pub const SIGALRM: usize =  14;
+pub const SIGTERM: usize =  15;
+pub const SIGSTKFLT: usize= 16;
+pub const SIGCHLD: usize =  17;
+pub const SIGCONT: usize =  18;
+pub const SIGSTOP: usize =  19;
+pub const SIGTSTP: usize =  20;
+pub const SIGTTIN: usize =  21;
+pub const SIGTTOU: usize =  22;
+pub const SIGURG: usize =   23;
+pub const SIGXCPU: usize =  24;
+pub const SIGXFSZ: usize =  25;
+pub const SIGVTALRM: usize= 26;
+pub const SIGPROF: usize =  27;
+pub const SIGWINCH: usize = 28;
+pub const SIGIO: usize =    29;
+pub const SIGPWR: usize =   30;
+pub const SIGSYS: usize =   31;
+
+pub const WNOHANG: usize = 1;
diff --git a/src/libstd/sys/redox/syscall/mod.rs b/src/libstd/sys/redox/syscall/mod.rs
new file mode 100644
index 00000000000..ce789c269a7
--- /dev/null
+++ b/src/libstd/sys/redox/syscall/mod.rs
@@ -0,0 +1,43 @@
+// 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.
+
+pub use self::arch::*;
+pub use self::call::*;
+pub use self::data::*;
+pub use self::error::*;
+pub use self::flag::*;
+pub use self::number::*;
+
+#[cfg(target_arch = "arm")]
+#[path="arch/arm.rs"]
+mod arch;
+
+#[cfg(target_arch = "x86")]
+#[path="arch/x86.rs"]
+mod arch;
+
+#[cfg(target_arch = "x86_64")]
+#[path="arch/x86_64.rs"]
+mod arch;
+
+/// Function definitions
+pub mod call;
+
+/// Complex structures that are used for some system calls
+pub mod data;
+
+/// All errors that can be generated by a system call
+pub mod error;
+
+/// Flags used as an argument to many system calls
+pub mod flag;
+
+/// Call numbers used by each system call
+pub mod number;
diff --git a/src/libstd/sys/redox/syscall/number.rs b/src/libstd/sys/redox/syscall/number.rs
new file mode 100644
index 00000000000..358746cd20a
--- /dev/null
+++ b/src/libstd/sys/redox/syscall/number.rs
@@ -0,0 +1,73 @@
+// 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.
+
+pub const SYS_CLASS: usize =    0xF000_0000;
+pub const SYS_CLASS_PATH: usize=0x1000_0000;
+pub const SYS_CLASS_FILE: usize=0x2000_0000;
+
+pub const SYS_ARG: usize =      0x0F00_0000;
+pub const SYS_ARG_SLICE: usize =0x0100_0000;
+pub const SYS_ARG_MSLICE: usize=0x0200_0000;
+pub const SYS_ARG_PATH: usize = 0x0300_0000;
+
+pub const SYS_RET: usize =      0x00F0_0000;
+pub const SYS_RET_FILE: usize = 0x0010_0000;
+
+pub const SYS_LINK: usize =     SYS_CLASS_PATH | SYS_ARG_PATH | 9;
+pub const SYS_OPEN: usize =     SYS_CLASS_PATH | SYS_RET_FILE | 5;
+pub const SYS_CHMOD: usize =    SYS_CLASS_PATH | 15;
+pub const SYS_RMDIR: usize =    SYS_CLASS_PATH | 84;
+pub const SYS_UNLINK: usize =   SYS_CLASS_PATH | 10;
+
+pub const SYS_CLOSE: usize =    SYS_CLASS_FILE | 6;
+pub const SYS_DUP: usize =      SYS_CLASS_FILE | SYS_RET_FILE | 41;
+pub const SYS_READ: usize =     SYS_CLASS_FILE | SYS_ARG_MSLICE | 3;
+pub const SYS_WRITE: usize =    SYS_CLASS_FILE | SYS_ARG_SLICE | 4;
+pub const SYS_LSEEK: usize =    SYS_CLASS_FILE | 19;
+pub const SYS_FCNTL: usize =    SYS_CLASS_FILE | 55;
+pub const SYS_FEVENT: usize =   SYS_CLASS_FILE | 927;
+pub const SYS_FMAP: usize =     SYS_CLASS_FILE | 90;
+pub const SYS_FUNMAP: usize =   SYS_CLASS_FILE | 91;
+pub const SYS_FPATH: usize =    SYS_CLASS_FILE | SYS_ARG_MSLICE | 928;
+pub const SYS_FSTAT: usize =    SYS_CLASS_FILE | SYS_ARG_MSLICE | 28;
+pub const SYS_FSTATVFS: usize = SYS_CLASS_FILE | SYS_ARG_MSLICE | 100;
+pub const SYS_FSYNC: usize =    SYS_CLASS_FILE | 118;
+pub const SYS_FTRUNCATE: usize =SYS_CLASS_FILE | 93;
+
+pub const SYS_BRK: usize =      45;
+pub const SYS_CHDIR: usize =    12;
+pub const SYS_CLOCK_GETTIME: usize = 265;
+pub const SYS_CLONE: usize =    120;
+pub const SYS_EXECVE: usize =   11;
+pub const SYS_EXIT: usize =     1;
+pub const SYS_FUTEX: usize =    240;
+pub const SYS_GETCWD: usize =   183;
+pub const SYS_GETEGID: usize =  202;
+pub const SYS_GETENS: usize =   951;
+pub const SYS_GETEUID: usize =  201;
+pub const SYS_GETGID: usize =   200;
+pub const SYS_GETNS: usize =    950;
+pub const SYS_GETPID: usize =   20;
+pub const SYS_GETUID: usize =   199;
+pub const SYS_IOPL: usize =     110;
+pub const SYS_KILL: usize =     37;
+pub const SYS_MKNS: usize =     984;
+pub const SYS_NANOSLEEP: usize =162;
+pub const SYS_PHYSALLOC: usize =945;
+pub const SYS_PHYSFREE: usize = 946;
+pub const SYS_PHYSMAP: usize =  947;
+pub const SYS_PHYSUNMAP: usize =948;
+pub const SYS_VIRTTOPHYS: usize=949;
+pub const SYS_PIPE2: usize =    331;
+pub const SYS_SETREGID: usize = 204;
+pub const SYS_SETRENS: usize =  952;
+pub const SYS_SETREUID: usize = 203;
+pub const SYS_WAITPID: usize =  7;
+pub const SYS_YIELD: usize =    158;
diff --git a/src/libstd/sys/redox/thread.rs b/src/libstd/sys/redox/thread.rs
new file mode 100644
index 00000000000..b2c0e285f06
--- /dev/null
+++ b/src/libstd/sys/redox/thread.rs
@@ -0,0 +1,91 @@
+// 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.
+
+use alloc::boxed::FnBox;
+use ffi::CStr;
+use io;
+use mem;
+use sys_common::thread::start_thread;
+use sys::{cvt, syscall};
+use time::Duration;
+
+pub struct Thread {
+    id: usize,
+}
+
+// Some platforms may have 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 id = cvt(syscall::clone(syscall::CLONE_VM | syscall::CLONE_FS | syscall::CLONE_FILES))?;
+        if id == 0 {
+            start_thread(&*p as *const _ as *mut _);
+            let _ = syscall::exit(0);
+            panic!("thread failed to exit");
+        } else {
+            mem::forget(p);
+            Ok(Thread { id: id })
+        }
+    }
+
+    pub fn yield_now() {
+        let ret = syscall::sched_yield().expect("failed to sched_yield");
+        debug_assert_eq!(ret, 0);
+    }
+
+    pub fn set_name(_name: &CStr) {
+
+    }
+
+    pub fn sleep(dur: Duration) {
+        let mut secs = dur.as_secs();
+        let mut nsecs = dur.subsec_nanos() as i32;
+
+        // If we're awoken with a signal then the return value will be -1 and
+        // nanosleep will fill in `ts` with the remaining time.
+        while secs > 0 || nsecs > 0 {
+            let req = syscall::TimeSpec {
+                tv_sec: secs as i64,
+                tv_nsec: nsecs,
+            };
+            secs -= req.tv_sec as u64;
+            let mut rem = syscall::TimeSpec::default();
+            if syscall::nanosleep(&req, &mut rem).is_err() {
+                secs += rem.tv_sec as u64;
+                nsecs = rem.tv_nsec;
+            } else {
+                nsecs = 0;
+            }
+        }
+    }
+
+    pub fn join(self) {
+        let mut status = 0;
+        syscall::waitpid(self.id, &mut status, 0).unwrap();
+    }
+
+    pub fn id(&self) -> usize { self.id }
+
+    pub fn into_id(self) -> usize {
+        let id = self.id;
+        mem::forget(self);
+        id
+    }
+}
+
+pub mod guard {
+    pub unsafe fn current() -> Option<usize> { None }
+    pub unsafe fn init() -> Option<usize> { None }
+}
diff --git a/src/libstd/sys/redox/thread_local.rs b/src/libstd/sys/redox/thread_local.rs
new file mode 100644
index 00000000000..abdd9ace795
--- /dev/null
+++ b/src/libstd/sys/redox/thread_local.rs
@@ -0,0 +1,66 @@
+// 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.
+
+#![allow(dead_code)] // not used on all platforms
+
+use collections::BTreeMap;
+use ptr;
+use sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
+
+pub type Key = usize;
+
+type Dtor = unsafe extern fn(*mut u8);
+
+static NEXT_KEY: AtomicUsize = ATOMIC_USIZE_INIT;
+
+static mut KEYS: *mut BTreeMap<Key, Option<Dtor>> = ptr::null_mut();
+
+#[thread_local]
+static mut LOCALS: *mut BTreeMap<Key, *mut u8> = ptr::null_mut();
+
+unsafe fn keys() -> &'static mut BTreeMap<Key, Option<Dtor>> {
+    if KEYS == ptr::null_mut() {
+        KEYS = Box::into_raw(Box::new(BTreeMap::new()));
+    }
+    &mut *KEYS
+}
+
+unsafe fn locals() -> &'static mut BTreeMap<Key, *mut u8> {
+    if LOCALS == ptr::null_mut() {
+        LOCALS = Box::into_raw(Box::new(BTreeMap::new()));
+    }
+    &mut *LOCALS
+}
+
+#[inline]
+pub unsafe fn create(dtor: Option<Dtor>) -> Key {
+    let key = NEXT_KEY.fetch_add(1, Ordering::SeqCst);
+    keys().insert(key, dtor);
+    key
+}
+
+#[inline]
+pub unsafe fn get(key: Key) -> *mut u8 {
+    if let Some(&entry) = locals().get(&key) {
+        entry
+    } else {
+        ptr::null_mut()
+    }
+}
+
+#[inline]
+pub unsafe fn set(key: Key, value: *mut u8) {
+    locals().insert(key, value);
+}
+
+#[inline]
+pub unsafe fn destroy(key: Key) {
+    keys().remove(&key);
+}
diff --git a/src/libstd/sys/redox/time.rs b/src/libstd/sys/redox/time.rs
new file mode 100644
index 00000000000..dea406efe6c
--- /dev/null
+++ b/src/libstd/sys/redox/time.rs
@@ -0,0 +1,198 @@
+// 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.
+
+use cmp::Ordering;
+use fmt;
+use sys::{cvt, syscall};
+use time::Duration;
+
+const NSEC_PER_SEC: u64 = 1_000_000_000;
+
+#[derive(Copy, Clone)]
+struct Timespec {
+    t: syscall::TimeSpec,
+}
+
+impl Timespec {
+    fn sub_timespec(&self, other: &Timespec) -> Result<Duration, Duration> {
+        if self >= other {
+            Ok(if self.t.tv_nsec >= other.t.tv_nsec {
+                Duration::new((self.t.tv_sec - other.t.tv_sec) as u64,
+                              (self.t.tv_nsec - other.t.tv_nsec) as u32)
+            } else {
+                Duration::new((self.t.tv_sec - 1 - other.t.tv_sec) as u64,
+                              self.t.tv_nsec as u32 + (NSEC_PER_SEC as u32) -
+                              other.t.tv_nsec as u32)
+            })
+        } else {
+            match other.sub_timespec(self) {
+                Ok(d) => Err(d),
+                Err(d) => Ok(d),
+            }
+        }
+    }
+
+    fn add_duration(&self, other: &Duration) -> Timespec {
+        let secs = (self.t.tv_sec as i64).checked_add(other.as_secs() as i64);
+        let mut secs = secs.expect("overflow when adding duration to time");
+
+        // Nano calculations can't overflow because nanos are <1B which fit
+        // in a u32.
+        let mut nsec = other.subsec_nanos() + self.t.tv_nsec as u32;
+        if nsec >= NSEC_PER_SEC as u32 {
+            nsec -= NSEC_PER_SEC as u32;
+            secs = secs.checked_add(1).expect("overflow when adding \
+                                               duration to time");
+        }
+        Timespec {
+            t: syscall::TimeSpec {
+                tv_sec: secs as i64,
+                tv_nsec: nsec as i32,
+            },
+        }
+    }
+
+    fn sub_duration(&self, other: &Duration) -> Timespec {
+        let secs = (self.t.tv_sec as i64).checked_sub(other.as_secs() as i64);
+        let mut secs = secs.expect("overflow when subtracting duration \
+                                    from time");
+
+        // Similar to above, nanos can't overflow.
+        let mut nsec = self.t.tv_nsec as i32 - other.subsec_nanos() as i32;
+        if nsec < 0 {
+            nsec += NSEC_PER_SEC as i32;
+            secs = secs.checked_sub(1).expect("overflow when subtracting \
+                                               duration from time");
+        }
+        Timespec {
+            t: syscall::TimeSpec {
+                tv_sec: secs as i64,
+                tv_nsec: nsec as i32,
+            },
+        }
+    }
+}
+
+impl PartialEq for Timespec {
+    fn eq(&self, other: &Timespec) -> bool {
+        self.t.tv_sec == other.t.tv_sec && self.t.tv_nsec == other.t.tv_nsec
+    }
+}
+
+impl Eq for Timespec {}
+
+impl PartialOrd for Timespec {
+    fn partial_cmp(&self, other: &Timespec) -> Option<Ordering> {
+        Some(self.cmp(other))
+    }
+}
+
+impl Ord for Timespec {
+    fn cmp(&self, other: &Timespec) -> Ordering {
+        let me = (self.t.tv_sec, self.t.tv_nsec);
+        let other = (other.t.tv_sec, other.t.tv_nsec);
+        me.cmp(&other)
+    }
+}
+
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
+pub struct Instant {
+    t: Timespec,
+}
+
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
+pub struct SystemTime {
+    t: Timespec,
+}
+
+pub const UNIX_EPOCH: SystemTime = SystemTime {
+    t: Timespec {
+        t: syscall::TimeSpec {
+            tv_sec: 0,
+            tv_nsec: 0,
+        },
+    },
+};
+
+impl Instant {
+    pub fn now() -> Instant {
+        Instant { t: now(syscall::CLOCK_MONOTONIC) }
+    }
+
+    pub fn sub_instant(&self, other: &Instant) -> Duration {
+        self.t.sub_timespec(&other.t).unwrap_or_else(|_| {
+            panic!("other was less than the current instant")
+        })
+    }
+
+    pub fn add_duration(&self, other: &Duration) -> Instant {
+        Instant { t: self.t.add_duration(other) }
+    }
+
+    pub fn sub_duration(&self, other: &Duration) -> Instant {
+        Instant { t: self.t.sub_duration(other) }
+    }
+}
+
+impl fmt::Debug for Instant {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.debug_struct("Instant")
+         .field("tv_sec", &self.t.t.tv_sec)
+         .field("tv_nsec", &self.t.t.tv_nsec)
+         .finish()
+    }
+}
+
+impl SystemTime {
+    pub fn now() -> SystemTime {
+        SystemTime { t: now(syscall::CLOCK_REALTIME) }
+    }
+
+    pub fn sub_time(&self, other: &SystemTime)
+                    -> Result<Duration, Duration> {
+        self.t.sub_timespec(&other.t)
+    }
+
+    pub fn add_duration(&self, other: &Duration) -> SystemTime {
+        SystemTime { t: self.t.add_duration(other) }
+    }
+
+    pub fn sub_duration(&self, other: &Duration) -> SystemTime {
+        SystemTime { t: self.t.sub_duration(other) }
+    }
+}
+
+impl From<syscall::TimeSpec> for SystemTime {
+    fn from(t: syscall::TimeSpec) -> SystemTime {
+        SystemTime { t: Timespec { t: t } }
+    }
+}
+
+impl fmt::Debug for SystemTime {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.debug_struct("SystemTime")
+         .field("tv_sec", &self.t.t.tv_sec)
+         .field("tv_nsec", &self.t.t.tv_nsec)
+         .finish()
+    }
+}
+
+pub type clock_t = usize;
+
+fn now(clock: clock_t) -> Timespec {
+    let mut t = Timespec {
+        t: syscall::TimeSpec {
+            tv_sec: 0,
+            tv_nsec: 0,
+        }
+    };
+    cvt(syscall::clock_gettime(clock, &mut t.t)).unwrap();
+    t
+}
diff --git a/src/libstd/sys/unix/ext/fs.rs b/src/libstd/sys/unix/ext/fs.rs
index fcfab051588..900f463fa83 100644
--- a/src/libstd/sys/unix/ext/fs.rs
+++ b/src/libstd/sys/unix/ext/fs.rs
@@ -21,7 +21,7 @@ use sys_common::{FromInner, AsInner, AsInnerMut};
 use sys::platform::fs::MetadataExt as UnixMetadataExt;
 
 /// Unix-specific extensions to `File`
-#[unstable(feature = "file_offset", issue = "35918")]
+#[stable(feature = "file_offset", since = "1.15.0")]
 pub trait FileExt {
     /// Reads a number of bytes starting from a given offset.
     ///
@@ -34,7 +34,7 @@ pub trait FileExt {
     ///
     /// Note that similar to `File::read`, it is not an error to return with a
     /// short read.
-    #[unstable(feature = "file_offset", issue = "35918")]
+    #[stable(feature = "file_offset", since = "1.15.0")]
     fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize>;
 
     /// Writes a number of bytes starting from a given offset.
@@ -51,11 +51,11 @@ pub trait FileExt {
     ///
     /// Note that similar to `File::write`, it is not an error to return a
     /// short write.
-    #[unstable(feature = "file_offset", issue = "35918")]
+    #[stable(feature = "file_offset", since = "1.15.0")]
     fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize>;
 }
 
-#[unstable(feature = "file_offset", issue = "35918")]
+#[stable(feature = "file_offset", since = "1.15.0")]
 impl FileExt for fs::File {
     fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
         self.as_inner().read_at(buf, offset)
diff --git a/src/libstd/sys/unix/ext/mod.rs b/src/libstd/sys/unix/ext/mod.rs
index b2483f4e209..1be9f11b92c 100644
--- a/src/libstd/sys/unix/ext/mod.rs
+++ b/src/libstd/sys/unix/ext/mod.rs
@@ -50,7 +50,7 @@ pub mod prelude {
     pub use super::fs::{PermissionsExt, OpenOptionsExt, MetadataExt, FileTypeExt};
     #[doc(no_inline)] #[stable(feature = "rust1", since = "1.0.0")]
     pub use super::fs::DirEntryExt;
-    #[doc(no_inline)] #[unstable(feature = "file_offset", issue = "35918")]
+    #[doc(no_inline)] #[stable(feature = "file_offset", since = "1.15.0")]
     pub use super::fs::FileExt;
     #[doc(no_inline)] #[stable(feature = "rust1", since = "1.0.0")]
     pub use super::thread::JoinHandleExt;
diff --git a/src/libstd/sys/unix/ext/net.rs b/src/libstd/sys/unix/ext/net.rs
index 80f53da1cef..1ba4a104e51 100644
--- a/src/libstd/sys/unix/ext/net.rs
+++ b/src/libstd/sys/unix/ext/net.rs
@@ -85,6 +85,21 @@ enum AddressKind<'a> {
 }
 
 /// An address associated with a Unix socket.
+///
+/// # Examples
+///
+/// ```
+/// use std::os::unix::net::UnixListener;
+///
+/// let socket = match UnixListener::bind("/tmp/sock") {
+///     Ok(sock) => sock,
+///     Err(e) => {
+///         println!("Couldn't bind: {:?}", e);
+///         return
+///     }
+/// };
+/// let addr = socket.local_addr().expect("Couldn't get local address");
+/// ```
 #[derive(Clone)]
 #[stable(feature = "unix_socket", since = "1.10.0")]
 pub struct SocketAddr {
@@ -121,6 +136,28 @@ impl SocketAddr {
     }
 
     /// Returns true if and only if the address is unnamed.
+    ///
+    /// # Examples
+    ///
+    /// A named address:
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixListener;
+    ///
+    /// let socket = UnixListener::bind("/tmp/sock").unwrap();
+    /// let addr = socket.local_addr().expect("Couldn't get local address");
+    /// assert_eq!(addr.is_unnamed(), false);
+    /// ```
+    ///
+    /// An unnamed address:
+    ///
+    /// ```
+    /// use std::os::unix::net::UnixDatagram;
+    ///
+    /// let socket = UnixDatagram::unbound().unwrap();
+    /// let addr = socket.local_addr().expect("Couldn't get local address");
+    /// assert_eq!(addr.is_unnamed(), true);
+    /// ```
     #[stable(feature = "unix_socket", since = "1.10.0")]
     pub fn is_unnamed(&self) -> bool {
         if let AddressKind::Unnamed = self.address() {
@@ -131,6 +168,29 @@ impl SocketAddr {
     }
 
     /// Returns the contents of this address if it is a `pathname` address.
+    ///
+    /// # Examples
+    ///
+    /// With a pathname:
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixListener;
+    /// use std::path::Path;
+    ///
+    /// let socket = UnixListener::bind("/tmp/sock").unwrap();
+    /// let addr = socket.local_addr().expect("Couldn't get local address");
+    /// assert_eq!(addr.as_pathname(), Some(Path::new("/tmp/sock")));
+    /// ```
+    ///
+    /// Without a pathname:
+    ///
+    /// ```
+    /// use std::os::unix::net::UnixDatagram;
+    ///
+    /// let socket = UnixDatagram::unbound().unwrap();
+    /// let addr = socket.local_addr().expect("Couldn't get local address");
+    /// assert_eq!(addr.as_pathname(), None);
+    /// ```
     #[stable(feature = "unix_socket", since = "1.10.0")]
     pub fn as_pathname(&self) -> Option<&Path> {
         if let AddressKind::Pathname(path) = self.address() {
@@ -182,7 +242,7 @@ impl<'a> fmt::Display for AsciiEscaped<'a> {
 ///
 /// # Examples
 ///
-/// ```rust,no_run
+/// ```no_run
 /// use std::os::unix::net::UnixStream;
 /// use std::io::prelude::*;
 ///
@@ -212,6 +272,20 @@ impl fmt::Debug for UnixStream {
 
 impl UnixStream {
     /// Connects to the socket named by `path`.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixStream;
+    ///
+    /// let socket = match UnixStream::connect("/tmp/sock") {
+    ///     Ok(sock) => sock,
+    ///     Err(e) => {
+    ///         println!("Couldn't connect: {:?}", e);
+    ///         return
+    ///     }
+    /// };
+    /// ```
     #[stable(feature = "unix_socket", since = "1.10.0")]
     pub fn connect<P: AsRef<Path>>(path: P) -> io::Result<UnixStream> {
         fn inner(path: &Path) -> io::Result<UnixStream> {
@@ -229,6 +303,20 @@ impl UnixStream {
     /// Creates an unnamed pair of connected sockets.
     ///
     /// Returns two `UnixStream`s which are connected to each other.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixStream;
+    ///
+    /// let (sock1, sock2) = match UnixStream::pair() {
+    ///     Ok((sock1, sock2)) => (sock1, sock2),
+    ///     Err(e) => {
+    ///         println!("Couldn't create a pair of sockets: {:?}", e);
+    ///         return
+    ///     }
+    /// };
+    /// ```
     #[stable(feature = "unix_socket", since = "1.10.0")]
     pub fn pair() -> io::Result<(UnixStream, UnixStream)> {
         let (i1, i2) = Socket::new_pair(libc::AF_UNIX, libc::SOCK_STREAM)?;
@@ -241,18 +329,45 @@ impl UnixStream {
     /// object references. Both handles will read and write the same stream of
     /// data, and options set on one stream will be propogated to the other
     /// stream.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixStream;
+    ///
+    /// let socket = UnixStream::connect("/tmp/sock").unwrap();
+    /// let sock_copy = socket.try_clone().expect("Couldn't clone socket");
+    /// ```
     #[stable(feature = "unix_socket", since = "1.10.0")]
     pub fn try_clone(&self) -> io::Result<UnixStream> {
         self.0.duplicate().map(UnixStream)
     }
 
     /// Returns the socket address of the local half of this connection.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixStream;
+    ///
+    /// let socket = UnixStream::connect("/tmp/sock").unwrap();
+    /// let addr = socket.local_addr().expect("Couldn't get local address");
+    /// ```
     #[stable(feature = "unix_socket", since = "1.10.0")]
     pub fn local_addr(&self) -> io::Result<SocketAddr> {
         SocketAddr::new(|addr, len| unsafe { libc::getsockname(*self.0.as_inner(), addr, len) })
     }
 
     /// Returns the socket address of the remote half of this connection.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixStream;
+    ///
+    /// let socket = UnixStream::connect("/tmp/sock").unwrap();
+    /// let addr = socket.peer_addr().expect("Couldn't get peer address");
+    /// ```
     #[stable(feature = "unix_socket", since = "1.10.0")]
     pub fn peer_addr(&self) -> io::Result<SocketAddr> {
         SocketAddr::new(|addr, len| unsafe { libc::getpeername(*self.0.as_inner(), addr, len) })
@@ -260,9 +375,23 @@ impl UnixStream {
 
     /// Sets the read timeout for the socket.
     ///
-    /// If the provided value is `None`, then `read` calls will block
-    /// indefinitely. It is an error to pass the zero `Duration` to this
+    /// If the provided value is [`None`], then [`read()`] calls will block
+    /// indefinitely. It is an error to pass the zero [`Duration`] to this
     /// method.
+    ///
+    /// [`None`]: ../../../../std/option/enum.Option.html#variant.None
+    /// [`read()`]: ../../../../std/io/trait.Read.html#tymethod.read
+    /// [`Duration`]: ../../../../std/time/struct.Duration.html
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixStream;
+    /// use std::time::Duration;
+    ///
+    /// let socket = UnixStream::connect("/tmp/sock").unwrap();
+    /// socket.set_read_timeout(Some(Duration::new(1, 0))).expect("Couldn't set read timeout");
+    /// ```
     #[stable(feature = "unix_socket", since = "1.10.0")]
     pub fn set_read_timeout(&self, timeout: Option<Duration>) -> io::Result<()> {
         self.0.set_timeout(timeout, libc::SO_RCVTIMEO)
@@ -270,33 +399,89 @@ impl UnixStream {
 
     /// Sets the write timeout for the socket.
     ///
-    /// If the provided value is `None`, then `write` calls will block
-    /// indefinitely. It is an error to pass the zero `Duration` to this
+    /// If the provided value is [`None`], then [`write()`] calls will block
+    /// indefinitely. It is an error to pass the zero [`Duration`] to this
     /// method.
+    ///
+    /// [`None`]: ../../../../std/option/enum.Option.html#variant.None
+    /// [`read()`]: ../../../../std/io/trait.Write.html#tymethod.write
+    /// [`Duration`]: ../../../../std/time/struct.Duration.html
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixStream;
+    /// use std::time::Duration;
+    ///
+    /// let socket = UnixStream::connect("/tmp/sock").unwrap();
+    /// socket.set_write_timeout(Some(Duration::new(1, 0))).expect("Couldn't set write timeout");
+    /// ```
     #[stable(feature = "unix_socket", since = "1.10.0")]
     pub fn set_write_timeout(&self, timeout: Option<Duration>) -> io::Result<()> {
         self.0.set_timeout(timeout, libc::SO_SNDTIMEO)
     }
 
     /// Returns the read timeout of this socket.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixStream;
+    /// use std::time::Duration;
+    ///
+    /// let socket = UnixStream::connect("/tmp/sock").unwrap();
+    /// socket.set_read_timeout(Some(Duration::new(1, 0))).expect("Couldn't set read timeout");
+    /// assert_eq!(socket.read_timeout().unwrap(), Some(Duration::new(1, 0)));
+    /// ```
     #[stable(feature = "unix_socket", since = "1.10.0")]
     pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
         self.0.timeout(libc::SO_RCVTIMEO)
     }
 
     /// Returns the write timeout of this socket.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixStream;
+    /// use std::time::Duration;
+    ///
+    /// let socket = UnixStream::connect("/tmp/sock").unwrap();
+    /// socket.set_write_timeout(Some(Duration::new(1, 0))).expect("Couldn't set write timeout");
+    /// assert_eq!(socket.write_timeout().unwrap(), Some(Duration::new(1, 0)));
+    /// ```
     #[stable(feature = "unix_socket", since = "1.10.0")]
     pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
         self.0.timeout(libc::SO_SNDTIMEO)
     }
 
     /// Moves the socket into or out of nonblocking mode.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixStream;
+    ///
+    /// let socket = UnixStream::connect("/tmp/sock").unwrap();
+    /// socket.set_nonblocking(true).expect("Couldn't set nonblocking");
+    /// ```
     #[stable(feature = "unix_socket", since = "1.10.0")]
     pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
         self.0.set_nonblocking(nonblocking)
     }
 
     /// Returns the value of the `SO_ERROR` option.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixStream;
+    ///
+    /// let socket = UnixStream::connect("/tmp/sock").unwrap();
+    /// if let Ok(Some(err)) = socket.take_error() {
+    ///     println!("Got error: {:?}", err);
+    /// }
+    /// ```
     #[stable(feature = "unix_socket", since = "1.10.0")]
     pub fn take_error(&self) -> io::Result<Option<io::Error>> {
         self.0.take_error()
@@ -306,7 +491,19 @@ impl UnixStream {
     ///
     /// This function will cause all pending and future I/O calls on the
     /// specified portions to immediately return with an appropriate value
-    /// (see the documentation of `Shutdown`).
+    /// (see the documentation of [`Shutdown`]).
+    ///
+    /// [`Shutdown`]: ../../../../std/net/enum.Shutdown.html
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixStream;
+    /// use std::net::Shutdown;
+    ///
+    /// let socket = UnixStream::connect("/tmp/sock").unwrap();
+    /// socket.shutdown(Shutdown::Both).expect("shutdown function failed");
+    /// ```
     #[stable(feature = "unix_socket", since = "1.10.0")]
     pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
         self.0.shutdown(how)
@@ -382,7 +579,7 @@ impl IntoRawFd for UnixStream {
 ///
 /// # Examples
 ///
-/// ```rust,no_run
+/// ```no_run
 /// use std::thread;
 /// use std::os::unix::net::{UnixStream, UnixListener};
 ///
@@ -405,9 +602,6 @@ impl IntoRawFd for UnixStream {
 ///         }
 ///     }
 /// }
-///
-/// // close the listener socket
-/// drop(listener);
 /// ```
 #[stable(feature = "unix_socket", since = "1.10.0")]
 pub struct UnixListener(Socket);
@@ -426,6 +620,20 @@ impl fmt::Debug for UnixListener {
 
 impl UnixListener {
     /// Creates a new `UnixListener` bound to the specified socket.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixListener;
+    ///
+    /// let listener = match UnixListener::bind("/path/to/the/socket") {
+    ///     Ok(sock) => sock,
+    ///     Err(e) => {
+    ///         println!("Couldn't connect: {:?}", e);
+    ///         return
+    ///     }
+    /// };
+    /// ```
     #[stable(feature = "unix_socket", since = "1.10.0")]
     pub fn bind<P: AsRef<Path>>(path: P) -> io::Result<UnixListener> {
         fn inner(path: &Path) -> io::Result<UnixListener> {
@@ -445,8 +653,23 @@ impl UnixListener {
     /// Accepts a new incoming connection to this listener.
     ///
     /// This function will block the calling thread until a new Unix connection
-    /// is established. When established, the corersponding `UnixStream` and
+    /// is established. When established, the corersponding [`UnixStream`] and
     /// the remote peer's address will be returned.
+    ///
+    /// [`UnixStream`]: ../../../../std/os/unix/net/struct.UnixStream.html
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixListener;
+    ///
+    /// let listener = UnixListener::bind("/path/to/the/socket").unwrap();
+    ///
+    /// match listener.accept() {
+    ///     Ok((socket, addr)) => println!("Got a client: {:?}", addr),
+    ///     Err(e) => println!("accept function failed: {:?}", e),
+    /// }
+    /// ```
     #[stable(feature = "unix_socket", since = "1.10.0")]
     pub fn accept(&self) -> io::Result<(UnixStream, SocketAddr)> {
         let mut storage: libc::sockaddr_un = unsafe { mem::zeroed() };
@@ -461,24 +684,66 @@ impl UnixListener {
     /// The returned `UnixListener` is a reference to the same socket that this
     /// object references. Both handles can be used to accept incoming
     /// connections and options set on one listener will affect the other.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixListener;
+    ///
+    /// let listener = UnixListener::bind("/path/to/the/socket").unwrap();
+    ///
+    /// let listener_copy = listener.try_clone().expect("try_clone failed");
+    /// ```
     #[stable(feature = "unix_socket", since = "1.10.0")]
     pub fn try_clone(&self) -> io::Result<UnixListener> {
         self.0.duplicate().map(UnixListener)
     }
 
     /// Returns the local socket address of this listener.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixListener;
+    ///
+    /// let listener = UnixListener::bind("/path/to/the/socket").unwrap();
+    ///
+    /// let addr = listener.local_addr().expect("Couldn't get local address");
+    /// ```
     #[stable(feature = "unix_socket", since = "1.10.0")]
     pub fn local_addr(&self) -> io::Result<SocketAddr> {
         SocketAddr::new(|addr, len| unsafe { libc::getsockname(*self.0.as_inner(), addr, len) })
     }
 
     /// Moves the socket into or out of nonblocking mode.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixListener;
+    ///
+    /// let listener = UnixListener::bind("/path/to/the/socket").unwrap();
+    ///
+    /// listener.set_nonblocking(true).expect("Couldn't set non blocking");
+    /// ```
     #[stable(feature = "unix_socket", since = "1.10.0")]
     pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
         self.0.set_nonblocking(nonblocking)
     }
 
     /// Returns the value of the `SO_ERROR` option.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixListener;
+    ///
+    /// let listener = UnixListener::bind("/tmp/sock").unwrap();
+    ///
+    /// if let Ok(Some(err)) = listener.take_error() {
+    ///     println!("Got error: {:?}", err);
+    /// }
+    /// ```
     #[stable(feature = "unix_socket", since = "1.10.0")]
     pub fn take_error(&self) -> io::Result<Option<io::Error>> {
         self.0.take_error()
@@ -486,8 +751,35 @@ impl UnixListener {
 
     /// Returns an iterator over incoming connections.
     ///
-    /// The iterator will never return `None` and will also not yield the
-    /// peer's `SocketAddr` structure.
+    /// The iterator will never return [`None`] and will also not yield the
+    /// peer's [`SocketAddr`] structure.
+    ///
+    /// [`None`]: ../../../../std/option/enum.Option.html#variant.None
+    /// [`SocketAddr`]: struct.SocketAddr.html
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::thread;
+    /// use std::os::unix::net::{UnixStream, UnixListener};
+    ///
+    /// fn handle_client(stream: UnixStream) {
+    ///     // ...
+    /// }
+    ///
+    /// let listener = UnixListener::bind("/path/to/the/socket").unwrap();
+    ///
+    /// for stream in listener.incoming() {
+    ///     match stream {
+    ///         Ok(stream) => {
+    ///             thread::spawn(|| handle_client(stream));
+    ///         }
+    ///         Err(err) => {
+    ///             break;
+    ///         }
+    ///     }
+    /// }
+    /// ```
     #[stable(feature = "unix_socket", since = "1.10.0")]
     pub fn incoming<'a>(&'a self) -> Incoming<'a> {
         Incoming { listener: self }
@@ -525,9 +817,36 @@ impl<'a> IntoIterator for &'a UnixListener {
     }
 }
 
-/// An iterator over incoming connections to a `UnixListener`.
+/// An iterator over incoming connections to a [`UnixListener`].
+///
+/// It will never return [`None`].
+///
+/// [`None`]: ../../../../std/option/enum.Option.html#variant.None
+/// [`UnixListener`]: struct.UnixListener.html
+///
+/// # Examples
 ///
-/// It will never return `None`.
+/// ```no_run
+/// use std::thread;
+/// use std::os::unix::net::{UnixStream, UnixListener};
+///
+/// fn handle_client(stream: UnixStream) {
+///     // ...
+/// }
+///
+/// let listener = UnixListener::bind("/path/to/the/socket").unwrap();
+///
+/// for stream in listener.incoming() {
+///     match stream {
+///         Ok(stream) => {
+///             thread::spawn(|| handle_client(stream));
+///         }
+///         Err(err) => {
+///             break;
+///         }
+///     }
+/// }
+/// ```
 #[derive(Debug)]
 #[stable(feature = "unix_socket", since = "1.10.0")]
 pub struct Incoming<'a> {
@@ -551,7 +870,7 @@ impl<'a> Iterator for Incoming<'a> {
 ///
 /// # Examples
 ///
-/// ```rust,no_run
+/// ```no_run
 /// use std::os::unix::net::UnixDatagram;
 ///
 /// let socket = UnixDatagram::bind("/path/to/my/socket").unwrap();
@@ -580,6 +899,20 @@ impl fmt::Debug for UnixDatagram {
 
 impl UnixDatagram {
     /// Creates a Unix datagram socket bound to the given path.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixDatagram;
+    ///
+    /// let sock = match UnixDatagram::bind("/path/to/the/socket") {
+    ///     Ok(sock) => sock,
+    ///     Err(e) => {
+    ///         println!("Couldn't bind: {:?}", e);
+    ///         return
+    ///     }
+    /// };
+    /// ```
     #[stable(feature = "unix_socket", since = "1.10.0")]
     pub fn bind<P: AsRef<Path>>(path: P) -> io::Result<UnixDatagram> {
         fn inner(path: &Path) -> io::Result<UnixDatagram> {
@@ -596,6 +929,20 @@ impl UnixDatagram {
     }
 
     /// Creates a Unix Datagram socket which is not bound to any address.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixDatagram;
+    ///
+    /// let sock = match UnixDatagram::unbound() {
+    ///     Ok(sock) => sock,
+    ///     Err(e) => {
+    ///         println!("Couldn't unbound: {:?}", e);
+    ///         return
+    ///     }
+    /// };
+    /// ```
     #[stable(feature = "unix_socket", since = "1.10.0")]
     pub fn unbound() -> io::Result<UnixDatagram> {
         let inner = Socket::new_raw(libc::AF_UNIX, libc::SOCK_DGRAM)?;
@@ -605,6 +952,20 @@ impl UnixDatagram {
     /// Create an unnamed pair of connected sockets.
     ///
     /// Returns two `UnixDatagrams`s which are connected to each other.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixDatagram;
+    ///
+    /// let (sock1, sock2) = match UnixDatagram::pair() {
+    ///     Ok((sock1, sock2)) => (sock1, sock2),
+    ///     Err(e) => {
+    ///         println!("Couldn't unbound: {:?}", e);
+    ///         return
+    ///     }
+    /// };
+    /// ```
     #[stable(feature = "unix_socket", since = "1.10.0")]
     pub fn pair() -> io::Result<(UnixDatagram, UnixDatagram)> {
         let (i1, i2) = Socket::new_pair(libc::AF_UNIX, libc::SOCK_DGRAM)?;
@@ -613,8 +974,27 @@ impl UnixDatagram {
 
     /// Connects the socket to the specified address.
     ///
-    /// The `send` method may be used to send data to the specified address.
-    /// `recv` and `recv_from` will only receive data from that address.
+    /// The [`send()`] method may be used to send data to the specified address.
+    /// [`recv()`] and [`recv_from()`] will only receive data from that address.
+    ///
+    /// [`send()`]: #method.send
+    /// [`recv()`]: #method.recv
+    /// [`recv_from()`]: #method.recv_from
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixDatagram;
+    ///
+    /// let sock = UnixDatagram::unbound().unwrap();
+    /// match sock.connect("/path/to/the/socket") {
+    ///     Ok(sock) => sock,
+    ///     Err(e) => {
+    ///         println!("Couldn't connect: {:?}", e);
+    ///         return
+    ///     }
+    /// };
+    /// ```
     #[stable(feature = "unix_socket", since = "1.10.0")]
     pub fn connect<P: AsRef<Path>>(&self, path: P) -> io::Result<()> {
         fn inner(d: &UnixDatagram, path: &Path) -> io::Result<()> {
@@ -631,15 +1011,35 @@ impl UnixDatagram {
 
     /// Creates a new independently owned handle to the underlying socket.
     ///
-    /// The returned `UnixListener` is a reference to the same socket that this
+    /// The returned `UnixDatagram` is a reference to the same socket that this
     /// object references. Both handles can be used to accept incoming
-    /// connections and options set on one listener will affect the other.
+    /// connections and options set on one side will affect the other.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixDatagram;
+    ///
+    /// let sock = UnixDatagram::bind("/path/to/the/socket").unwrap();
+    ///
+    /// let sock_copy = sock.try_clone().expect("try_clone failed");
+    /// ```
     #[stable(feature = "unix_socket", since = "1.10.0")]
     pub fn try_clone(&self) -> io::Result<UnixDatagram> {
         self.0.duplicate().map(UnixDatagram)
     }
 
     /// Returns the address of this socket.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixDatagram;
+    ///
+    /// let sock = UnixDatagram::bind("/path/to/the/socket").unwrap();
+    ///
+    /// let addr = sock.local_addr().expect("Couldn't get local address");
+    /// ```
     #[stable(feature = "unix_socket", since = "1.10.0")]
     pub fn local_addr(&self) -> io::Result<SocketAddr> {
         SocketAddr::new(|addr, len| unsafe { libc::getsockname(*self.0.as_inner(), addr, len) })
@@ -647,7 +1047,20 @@ impl UnixDatagram {
 
     /// Returns the address of this socket's peer.
     ///
-    /// The `connect` method will connect the socket to a peer.
+    /// The [`connect()`] method will connect the socket to a peer.
+    ///
+    /// [`connect()`]: #method.connect
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixDatagram;
+    ///
+    /// let sock = UnixDatagram::unbound().unwrap();
+    /// sock.connect("/path/to/the/socket").unwrap();
+    ///
+    /// let addr = sock.peer_addr().expect("Couldn't get peer address");
+    /// ```
     #[stable(feature = "unix_socket", since = "1.10.0")]
     pub fn peer_addr(&self) -> io::Result<SocketAddr> {
         SocketAddr::new(|addr, len| unsafe { libc::getpeername(*self.0.as_inner(), addr, len) })
@@ -657,6 +1070,19 @@ impl UnixDatagram {
     ///
     /// On success, returns the number of bytes read and the address from
     /// whence the data came.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixDatagram;
+    ///
+    /// let sock = UnixDatagram::unbound().unwrap();
+    /// let mut buf = vec![0; 10];
+    /// match sock.recv_from(buf.as_mut_slice()) {
+    ///     Ok((size, sender)) => println!("received {} bytes from {:?}", size, sender),
+    ///     Err(e) => println!("recv_from function failed: {:?}", e),
+    /// }
+    /// ```
     #[stable(feature = "unix_socket", since = "1.10.0")]
     pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
         let mut count = 0;
@@ -684,6 +1110,16 @@ impl UnixDatagram {
     /// Receives data from the socket.
     ///
     /// On success, returns the number of bytes read.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixDatagram;
+    ///
+    /// let sock = UnixDatagram::bind("/path/to/the/socket").unwrap();
+    /// let mut buf = vec![0; 10];
+    /// sock.recv(buf.as_mut_slice()).expect("recv function failed");
+    /// ```
     #[stable(feature = "unix_socket", since = "1.10.0")]
     pub fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
         self.0.read(buf)
@@ -692,6 +1128,15 @@ impl UnixDatagram {
     /// Sends data on the socket to the specified address.
     ///
     /// On success, returns the number of bytes written.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixDatagram;
+    ///
+    /// let sock = UnixDatagram::unbound().unwrap();
+    /// sock.send_to(b"omelette au fromage", "/some/sock").expect("send_to function failed");
+    /// ```
     #[stable(feature = "unix_socket", since = "1.10.0")]
     pub fn send_to<P: AsRef<Path>>(&self, buf: &[u8], path: P) -> io::Result<usize> {
         fn inner(d: &UnixDatagram, buf: &[u8], path: &Path) -> io::Result<usize> {
@@ -716,6 +1161,16 @@ impl UnixDatagram {
     /// will return an error if the socket has not already been connected.
     ///
     /// On success, returns the number of bytes written.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixDatagram;
+    ///
+    /// let sock = UnixDatagram::unbound().unwrap();
+    /// sock.connect("/some/sock").expect("Couldn't connect");
+    /// sock.send(b"omelette au fromage").expect("send_to function failed");
+    /// ```
     #[stable(feature = "unix_socket", since = "1.10.0")]
     pub fn send(&self, buf: &[u8]) -> io::Result<usize> {
         self.0.write(buf)
@@ -723,9 +1178,24 @@ impl UnixDatagram {
 
     /// Sets the read timeout for the socket.
     ///
-    /// If the provided value is `None`, then `recv` and `recv_from` calls will
-    /// block indefinitely. It is an error to pass the zero `Duration` to this
+    /// If the provided value is [`None`], then [`recv()`] and [`recv_from()`] calls will
+    /// block indefinitely. It is an error to pass the zero [`Duration`] to this
     /// method.
+    ///
+    /// [`None`]: ../../../../std/option/enum.Option.html#variant.None
+    /// [`recv()`]: #method.recv
+    /// [`recv_from()`]: #method.recv_from
+    /// [`Duration`]: ../../../../std/time/struct.Duration.html
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::os::unix::net::UnixDatagram;
+    /// use std::time::Duration;
+    ///
+    /// let sock = UnixDatagram::unbound().unwrap();
+    /// sock.set_read_timeout(Some(Duration::new(1, 0))).expect("set_read_timeout function failed");
+    /// ```
     #[stable(feature = "unix_socket", since = "1.10.0")]
     pub fn set_read_timeout(&self, timeout: Option<Duration>) -> io::Result<()> {
         self.0.set_timeout(timeout, libc::SO_RCVTIMEO)
@@ -733,33 +1203,92 @@ impl UnixDatagram {
 
     /// Sets the write timeout for the socket.
     ///
-    /// If the provided value is `None`, then `send` and `send_to` calls will
-    /// block indefinitely. It is an error to pass the zero `Duration` to this
+    /// If the provided value is [`None`], then [`send()`] and [`send_to()`] calls will
+    /// block indefinitely. It is an error to pass the zero [`Duration`] to this
     /// method.
+    ///
+    /// [`None`]: ../../../../std/option/enum.Option.html#variant.None
+    /// [`send()`]: #method.send
+    /// [`send_to()`]: #method.send_to
+    /// [`Duration`]: ../../../../std/time/struct.Duration.html
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::os::unix::net::UnixDatagram;
+    /// use std::time::Duration;
+    ///
+    /// let sock = UnixDatagram::unbound().unwrap();
+    /// sock.set_write_timeout(Some(Duration::new(1, 0)))
+    ///     .expect("set_write_timeout function failed");
+    /// ```
     #[stable(feature = "unix_socket", since = "1.10.0")]
     pub fn set_write_timeout(&self, timeout: Option<Duration>) -> io::Result<()> {
         self.0.set_timeout(timeout, libc::SO_SNDTIMEO)
     }
 
     /// Returns the read timeout of this socket.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::os::unix::net::UnixDatagram;
+    /// use std::time::Duration;
+    ///
+    /// let sock = UnixDatagram::unbound().unwrap();
+    /// sock.set_read_timeout(Some(Duration::new(1, 0))).expect("set_read_timeout function failed");
+    /// assert_eq!(sock.read_timeout().unwrap(), Some(Duration::new(1, 0)));
+    /// ```
     #[stable(feature = "unix_socket", since = "1.10.0")]
     pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
         self.0.timeout(libc::SO_RCVTIMEO)
     }
 
     /// Returns the write timeout of this socket.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::os::unix::net::UnixDatagram;
+    /// use std::time::Duration;
+    ///
+    /// let sock = UnixDatagram::unbound().unwrap();
+    /// sock.set_write_timeout(Some(Duration::new(1, 0)))
+    ///     .expect("set_write_timeout function failed");
+    /// assert_eq!(sock.write_timeout().unwrap(), Some(Duration::new(1, 0)));
+    /// ```
     #[stable(feature = "unix_socket", since = "1.10.0")]
     pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
         self.0.timeout(libc::SO_SNDTIMEO)
     }
 
     /// Moves the socket into or out of nonblocking mode.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::os::unix::net::UnixDatagram;
+    ///
+    /// let sock = UnixDatagram::unbound().unwrap();
+    /// sock.set_nonblocking(true).expect("set_nonblocking function failed");
+    /// ```
     #[stable(feature = "unix_socket", since = "1.10.0")]
     pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
         self.0.set_nonblocking(nonblocking)
     }
 
     /// Returns the value of the `SO_ERROR` option.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixDatagram;
+    ///
+    /// let sock = UnixDatagram::unbound().unwrap();
+    /// if let Ok(Some(err)) = sock.take_error() {
+    ///     println!("Got error: {:?}", err);
+    /// }
+    /// ```
     #[stable(feature = "unix_socket", since = "1.10.0")]
     pub fn take_error(&self) -> io::Result<Option<io::Error>> {
         self.0.take_error()
@@ -769,7 +1298,17 @@ impl UnixDatagram {
     ///
     /// This function will cause all pending and future I/O calls on the
     /// specified portions to immediately return with an appropriate value
-    /// (see the documentation of `Shutdown`).
+    /// (see the documentation of [`Shutdown`]).
+    ///
+    /// [`Shutdown`]: ../../../../std/net/enum.Shutdown.html
+    ///
+    /// ```no_run
+    /// use std::os::unix::net::UnixDatagram;
+    /// use std::net::Shutdown;
+    ///
+    /// let sock = UnixDatagram::unbound().unwrap();
+    /// sock.shutdown(Shutdown::Both).expect("shutdown function failed");
+    /// ```
     #[stable(feature = "unix_socket", since = "1.10.0")]
     pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
         self.0.shutdown(how)
diff --git a/src/libstd/sys/unix/ext/process.rs b/src/libstd/sys/unix/ext/process.rs
index 3a7c59d4e6d..585dcbb9a34 100644
--- a/src/libstd/sys/unix/ext/process.rs
+++ b/src/libstd/sys/unix/ext/process.rs
@@ -56,7 +56,7 @@ pub trait CommandExt {
     /// When this closure is run, aspects such as the stdio file descriptors and
     /// working directory have successfully been changed, so output to these
     /// locations may not appear where intended.
-    #[unstable(feature = "process_exec", issue = "31398")]
+    #[stable(feature = "process_exec", since = "1.15.0")]
     fn before_exec<F>(&mut self, f: F) -> &mut process::Command
         where F: FnMut() -> io::Result<()> + Send + Sync + 'static;
 
diff --git a/src/libstd/sys/unix/fast_thread_local.rs b/src/libstd/sys/unix/fast_thread_local.rs
index 0c625e7add9..f4f73646e1b 100644
--- a/src/libstd/sys/unix/fast_thread_local.rs
+++ b/src/libstd/sys/unix/fast_thread_local.rs
@@ -12,6 +12,7 @@
 #![unstable(feature = "thread_local_internals", issue = "0")]
 
 use cell::{Cell, UnsafeCell};
+use fmt;
 use intrinsics;
 use ptr;
 
@@ -24,6 +25,12 @@ pub struct Key<T> {
     dtor_running: Cell<bool>,
 }
 
+impl<T> fmt::Debug for Key<T> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.pad("Key { .. }")
+    }
+}
+
 unsafe impl<T> ::marker::Sync for Key<T> { }
 
 impl<T> Key<T> {
diff --git a/src/libstd/sys/unix/fd.rs b/src/libstd/sys/unix/fd.rs
index 61eb60da486..2384d959881 100644
--- a/src/libstd/sys/unix/fd.rs
+++ b/src/libstd/sys/unix/fd.rs
@@ -18,6 +18,7 @@ use sys::cvt;
 use sys_common::AsInner;
 use sys_common::io::read_to_end_uninitialized;
 
+#[derive(Debug)]
 pub struct FileDesc {
     fd: c_int,
 }
diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs
index 9ee0458b5da..8b5c0c04276 100644
--- a/src/libstd/sys/unix/fs.rs
+++ b/src/libstd/sys/unix/fs.rs
@@ -66,7 +66,7 @@ pub struct DirEntry {
     name: Box<[u8]>
 }
 
-#[derive(Clone)]
+#[derive(Clone, Debug)]
 pub struct OpenOptions {
     // generic
     read: bool,
@@ -86,6 +86,7 @@ pub struct FilePermissions { mode: mode_t }
 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
 pub struct FileType { mode: mode_t }
 
+#[derive(Debug)]
 pub struct DirBuilder { mode: mode_t }
 
 impl FileAttr {
diff --git a/src/libstd/sys/unix/process/magenta.rs b/src/libstd/sys/unix/process/magenta.rs
index 319fbce35cd..2bb005be4ec 100644
--- a/src/libstd/sys/unix/process/magenta.rs
+++ b/src/libstd/sys/unix/process/magenta.rs
@@ -23,7 +23,6 @@ pub type mx_rights_t = u32;
 pub type mx_status_t = i32;
 
 pub type mx_size_t = usize;
-pub type mx_ssize_t = isize;
 
 pub const MX_HANDLE_INVALID: mx_handle_t = 0;
 
diff --git a/src/libstd/sys/unix/stdio.rs b/src/libstd/sys/unix/stdio.rs
index 273341b1918..6d38b00b39e 100644
--- a/src/libstd/sys/unix/stdio.rs
+++ b/src/libstd/sys/unix/stdio.rs
@@ -43,6 +43,10 @@ impl Stdout {
         fd.into_raw();
         ret
     }
+
+    pub fn flush(&self) -> io::Result<()> {
+        Ok(())
+    }
 }
 
 impl Stderr {
@@ -54,6 +58,10 @@ impl Stderr {
         fd.into_raw();
         ret
     }
+
+    pub fn flush(&self) -> io::Result<()> {
+        Ok(())
+    }
 }
 
 // FIXME: right now this raw stderr handle is used in a few places because
@@ -63,7 +71,10 @@ impl io::Write for Stderr {
     fn write(&mut self, data: &[u8]) -> io::Result<usize> {
         Stderr::write(self, data)
     }
-    fn flush(&mut self) -> io::Result<()> { Ok(()) }
+
+    fn flush(&mut self) -> io::Result<()> {
+        Stderr::flush(self)
+    }
 }
 
 pub const EBADF_ERR: i32 = ::libc::EBADF as i32;
diff --git a/src/libstd/sys/windows/c.rs b/src/libstd/sys/windows/c.rs
index 1a563127f7f..d1c404195bc 100644
--- a/src/libstd/sys/windows/c.rs
+++ b/src/libstd/sys/windows/c.rs
@@ -47,7 +47,9 @@ pub type CHAR = c_char;
 pub type HCRYPTPROV = LONG_PTR;
 pub type ULONG_PTR = c_ulonglong;
 pub type ULONG = c_ulong;
+#[cfg(target_arch = "x86_64")]
 pub type ULONGLONG = u64;
+#[cfg(target_arch = "x86_64")]
 pub type DWORDLONG = ULONGLONG;
 
 pub type LPBOOL = *mut BOOL;
@@ -66,7 +68,6 @@ pub type LPVOID = *mut c_void;
 pub type LPWCH = *mut WCHAR;
 pub type LPWIN32_FIND_DATAW = *mut WIN32_FIND_DATAW;
 pub type LPWSADATA = *mut WSADATA;
-pub type LPWSAPROTOCOLCHAIN = *mut WSAPROTOCOLCHAIN;
 pub type LPWSAPROTOCOL_INFO = *mut WSAPROTOCOL_INFO;
 pub type LPWSTR = *mut WCHAR;
 pub type LPFILETIME = *mut FILETIME;
@@ -311,8 +312,6 @@ pub struct WSADATA {
     pub szSystemStatus: [u8; WSASYS_STATUS_LEN + 1],
 }
 
-pub type WSAEVENT = HANDLE;
-
 #[repr(C)]
 pub struct WSAPROTOCOL_INFO {
     pub dwServiceFlags1: DWORD,
@@ -819,6 +818,16 @@ pub enum EXCEPTION_DISPOSITION {
     ExceptionCollidedUnwind
 }
 
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub struct CONSOLE_READCONSOLE_CONTROL {
+    pub nLength: ULONG,
+    pub nInitialChars: ULONG,
+    pub dwCtrlWakeupMask: ULONG,
+    pub dwControlKeyState: ULONG,
+}
+pub type PCONSOLE_READCONSOLE_CONTROL = *mut CONSOLE_READCONSOLE_CONTROL;
+
 #[link(name = "ws2_32")]
 #[link(name = "userenv")]
 #[link(name = "shell32")]
@@ -849,12 +858,11 @@ extern "system" {
     pub fn LeaveCriticalSection(CriticalSection: *mut CRITICAL_SECTION);
     pub fn DeleteCriticalSection(CriticalSection: *mut CRITICAL_SECTION);
 
-    // FIXME - pInputControl should be PCONSOLE_READCONSOLE_CONTROL
     pub fn ReadConsoleW(hConsoleInput: HANDLE,
                         lpBuffer: LPVOID,
                         nNumberOfCharsToRead: DWORD,
                         lpNumberOfCharsRead: LPDWORD,
-                        pInputControl: LPVOID) -> BOOL;
+                        pInputControl: PCONSOLE_READCONSOLE_CONTROL) -> BOOL;
 
     pub fn WriteConsoleW(hConsoleOutput: HANDLE,
                          lpBuffer: LPCVOID,
diff --git a/src/libstd/sys/windows/ext/fs.rs b/src/libstd/sys/windows/ext/fs.rs
index 1e2b8bf38fa..7fc04ad69d6 100644
--- a/src/libstd/sys/windows/ext/fs.rs
+++ b/src/libstd/sys/windows/ext/fs.rs
@@ -19,7 +19,7 @@ use sys;
 use sys_common::{AsInnerMut, AsInner};
 
 /// Windows-specific extensions to `File`
-#[unstable(feature = "file_offset", issue = "35918")]
+#[stable(feature = "file_offset", since = "1.15.0")]
 pub trait FileExt {
     /// Seeks to a given position and reads a number of bytes.
     ///
@@ -35,7 +35,7 @@ pub trait FileExt {
     /// Note that similar to `File::read`, it is not an error to return with a
     /// short read. When returning from such a short read, the file pointer is
     /// still updated.
-    #[unstable(feature = "file_offset", issue = "35918")]
+    #[stable(feature = "file_offset", since = "1.15.0")]
     fn seek_read(&self, buf: &mut [u8], offset: u64) -> io::Result<usize>;
 
     /// Seeks to a given position and writes a number of bytes.
@@ -52,11 +52,11 @@ pub trait FileExt {
     /// Note that similar to `File::write`, it is not an error to return a
     /// short write. When returning from such a short write, the file pointer
     /// is still updated.
-    #[unstable(feature = "file_offset", issue = "35918")]
+    #[stable(feature = "file_offset", since = "1.15.0")]
     fn seek_write(&self, buf: &[u8], offset: u64) -> io::Result<usize>;
 }
 
-#[unstable(feature = "file_offset", issue = "35918")]
+#[stable(feature = "file_offset", since = "1.15.0")]
 impl FileExt for fs::File {
     fn seek_read(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
         self.as_inner().read_at(buf, offset)
diff --git a/src/libstd/sys/windows/ext/mod.rs b/src/libstd/sys/windows/ext/mod.rs
index 932bb5e9564..f12e50cc923 100644
--- a/src/libstd/sys/windows/ext/mod.rs
+++ b/src/libstd/sys/windows/ext/mod.rs
@@ -36,6 +36,6 @@ pub mod prelude {
     pub use super::ffi::{OsStrExt, OsStringExt};
     #[doc(no_inline)] #[stable(feature = "rust1", since = "1.0.0")]
     pub use super::fs::{OpenOptionsExt, MetadataExt};
-    #[doc(no_inline)] #[unstable(feature = "file_offset", issue = "35918")]
+    #[doc(no_inline)] #[stable(feature = "file_offset", since = "1.15.0")]
     pub use super::fs::FileExt;
 }
diff --git a/src/libstd/sys/windows/fs.rs b/src/libstd/sys/windows/fs.rs
index 7d7d78bbd87..c410fcd1ee0 100644
--- a/src/libstd/sys/windows/fs.rs
+++ b/src/libstd/sys/windows/fs.rs
@@ -58,7 +58,7 @@ pub struct DirEntry {
     data: c::WIN32_FIND_DATAW,
 }
 
-#[derive(Clone)]
+#[derive(Clone, Debug)]
 pub struct OpenOptions {
     // generic
     read: bool,
@@ -79,6 +79,7 @@ pub struct OpenOptions {
 #[derive(Clone, PartialEq, Eq, Debug)]
 pub struct FilePermissions { attrs: c::DWORD }
 
+#[derive(Debug)]
 pub struct DirBuilder;
 
 impl fmt::Debug for ReadDir {
diff --git a/src/libstd/sys/windows/stdio.rs b/src/libstd/sys/windows/stdio.rs
index 72788776ded..b1a57c349fb 100644
--- a/src/libstd/sys/windows/stdio.rs
+++ b/src/libstd/sys/windows/stdio.rs
@@ -111,19 +111,27 @@ impl Stdin {
         if utf8.position() as usize == utf8.get_ref().len() {
             let mut utf16 = vec![0u16; 0x1000];
             let mut num = 0;
+            let mut input_control = readconsole_input_control(CTRL_Z_MASK);
             cvt(unsafe {
                 c::ReadConsoleW(handle,
                                 utf16.as_mut_ptr() as c::LPVOID,
                                 utf16.len() as u32,
                                 &mut num,
-                                ptr::null_mut())
+                                &mut input_control as c::PCONSOLE_READCONSOLE_CONTROL)
             })?;
             utf16.truncate(num as usize);
             // FIXME: what to do about this data that has already been read?
-            let data = match String::from_utf16(&utf16) {
+            let mut data = match String::from_utf16(&utf16) {
                 Ok(utf8) => utf8.into_bytes(),
                 Err(..) => return Err(invalid_encoding()),
             };
+            if let Output::Console(_) = self.handle {
+                if let Some(&last_byte) = data.last() {
+                    if last_byte == CTRL_Z {
+                        data.pop();
+                    }
+                }
+            }
             *utf8 = Cursor::new(data);
         }
 
@@ -156,6 +164,10 @@ impl Stdout {
     pub fn write(&self, data: &[u8]) -> io::Result<usize> {
         write(&self.0, data)
     }
+
+    pub fn flush(&self) -> io::Result<()> {
+        Ok(())
+    }
 }
 
 impl Stderr {
@@ -166,6 +178,10 @@ impl Stderr {
     pub fn write(&self, data: &[u8]) -> io::Result<usize> {
         write(&self.0, data)
     }
+
+    pub fn flush(&self) -> io::Result<()> {
+        Ok(())
+    }
 }
 
 // FIXME: right now this raw stderr handle is used in a few places because
@@ -175,7 +191,10 @@ impl io::Write for Stderr {
     fn write(&mut self, data: &[u8]) -> io::Result<usize> {
         Stderr::write(self, data)
     }
-    fn flush(&mut self) -> io::Result<()> { Ok(()) }
+
+    fn flush(&mut self) -> io::Result<()> {
+        Stderr::flush(self)
+    }
 }
 
 impl NoClose {
@@ -206,6 +225,18 @@ fn invalid_encoding() -> io::Error {
     io::Error::new(io::ErrorKind::InvalidData, "text was not valid unicode")
 }
 
+fn readconsole_input_control(wakeup_mask: c::ULONG) -> c::CONSOLE_READCONSOLE_CONTROL {
+    c::CONSOLE_READCONSOLE_CONTROL {
+        nLength: ::mem::size_of::<c::CONSOLE_READCONSOLE_CONTROL>() as c::ULONG,
+        nInitialChars: 0,
+        dwCtrlWakeupMask: wakeup_mask,
+        dwControlKeyState: 0,
+    }
+}
+
+const CTRL_Z: u8 = 0x1A;
+const CTRL_Z_MASK: c::ULONG = 0x4000000; //1 << 0x1A
+
 pub const EBADF_ERR: i32 = ::sys::c::ERROR_INVALID_HANDLE as i32;
 // The default buffer capacity is 64k, but apparently windows
 // doesn't like 64k reads on stdin. See #13304 for details, but the
diff --git a/src/libstd/sys_common/mod.rs b/src/libstd/sys_common/mod.rs
index fe17d8cb5e5..634d6258885 100644
--- a/src/libstd/sys_common/mod.rs
+++ b/src/libstd/sys_common/mod.rs
@@ -23,6 +23,7 @@
 //! `std::sys` from the standard library.
 
 #![allow(missing_docs)]
+#![allow(missing_debug_implementations)]
 
 use sync::Once;
 use sys;
@@ -34,7 +35,6 @@ pub mod condvar;
 pub mod io;
 pub mod memchr;
 pub mod mutex;
-pub mod net;
 pub mod poison;
 pub mod remutex;
 pub mod rwlock;
@@ -44,6 +44,12 @@ pub mod thread_local;
 pub mod util;
 pub mod wtf8;
 
+#[cfg(target_os = "redox")]
+pub use sys::net;
+
+#[cfg(not(target_os = "redox"))]
+pub mod net;
+
 #[cfg(any(not(cargobuild), feature = "backtrace"))]
 #[cfg(any(all(unix, not(any(target_os = "macos", target_os = "ios", target_os = "emscripten"))),
           all(windows, target_env = "gnu")))]
diff --git a/src/libstd/thread/local.rs b/src/libstd/thread/local.rs
index f74dd592495..01584979aab 100644
--- a/src/libstd/thread/local.rs
+++ b/src/libstd/thread/local.rs
@@ -13,6 +13,7 @@
 #![unstable(feature = "thread_local_internals", issue = "0")]
 
 use cell::UnsafeCell;
+use fmt;
 use mem;
 
 /// A thread local storage key which owns its contents.
@@ -98,6 +99,13 @@ pub struct LocalKey<T: 'static> {
     init: fn() -> T,
 }
 
+#[stable(feature = "std_debug", since = "1.15.0")]
+impl<T: 'static> fmt::Debug for LocalKey<T> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.pad("LocalKey { .. }")
+    }
+}
+
 /// Declare a new thread local storage key of type `std::thread::LocalKey`.
 ///
 /// # Syntax
@@ -184,7 +192,7 @@ macro_rules! __thread_local_inner {
 #[unstable(feature = "thread_local_state",
            reason = "state querying was recently added",
            issue = "27716")]
-#[derive(Eq, PartialEq, Copy, Clone)]
+#[derive(Debug, Eq, PartialEq, Copy, Clone)]
 pub enum LocalKeyState {
     /// All keys are in this state whenever a thread starts. Keys will
     /// transition to the `Valid` state once the first call to `with` happens
@@ -313,6 +321,7 @@ impl<T: 'static> LocalKey<T> {
 #[doc(hidden)]
 pub mod os {
     use cell::{Cell, UnsafeCell};
+    use fmt;
     use marker;
     use ptr;
     use sys_common::thread_local::StaticKey as OsStaticKey;
@@ -323,6 +332,13 @@ pub mod os {
         marker: marker::PhantomData<Cell<T>>,
     }
 
+    #[stable(feature = "std_debug", since = "1.15.0")]
+    impl<T> fmt::Debug for Key<T> {
+        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+            f.pad("Key { .. }")
+        }
+    }
+
     unsafe impl<T> ::marker::Sync for Key<T> { }
 
     struct Value<T: 'static> {
diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs
index 255cd2a9bc0..6d8b3cc93d9 100644
--- a/src/libstd/thread/mod.rs
+++ b/src/libstd/thread/mod.rs
@@ -17,13 +17,11 @@
 //! provide some built-in support for low-level synchronization.
 //!
 //! Communication between threads can be done through
-//! [channels](../../std/sync/mpsc/index.html), Rust's message-passing
-//! types, along with [other forms of thread
+//! [channels], Rust's message-passing types, along with [other forms of thread
 //! synchronization](../../std/sync/index.html) and shared-memory data
 //! structures. In particular, types that are guaranteed to be
 //! threadsafe are easily shared between threads using the
-//! atomically-reference-counted container,
-//! [`Arc`](../../std/sync/struct.Arc.html).
+//! atomically-reference-counted container, [`Arc`].
 //!
 //! Fatal logic errors in Rust cause *thread panic*, during which
 //! a thread will unwind the stack, running destructors and freeing
@@ -40,7 +38,7 @@
 //!
 //! ## Spawning a thread
 //!
-//! A new thread can be spawned using the `thread::spawn` function:
+//! A new thread can be spawned using the [`thread::spawn`][`spawn`] function:
 //!
 //! ```rust
 //! use std::thread;
@@ -55,7 +53,7 @@
 //! it), unless this parent is the main thread.
 //!
 //! The parent thread can also wait on the completion of the child
-//! thread; a call to `spawn` produces a `JoinHandle`, which provides
+//! thread; a call to [`spawn`] produces a [`JoinHandle`], which provides
 //! a `join` method for waiting:
 //!
 //! ```rust
@@ -68,13 +66,13 @@
 //! let res = child.join();
 //! ```
 //!
-//! The `join` method returns a `Result` containing `Ok` of the final
-//! value produced by the child thread, or `Err` of the value given to
-//! a call to `panic!` if the child panicked.
+//! The [`join`] method returns a [`Result`] containing [`Ok`] of the final
+//! value produced by the child thread, or [`Err`] of the value given to
+//! a call to [`panic!`] if the child panicked.
 //!
 //! ## Configuring threads
 //!
-//! A new thread can be configured before it is spawned via the `Builder` type,
+//! A new thread can be configured before it is spawned via the [`Builder`] type,
 //! which currently allows you to set the name and stack size for the child thread:
 //!
 //! ```rust
@@ -88,43 +86,43 @@
 //!
 //! ## The `Thread` type
 //!
-//! Threads are represented via the `Thread` type, which you can get in one of
+//! Threads are represented via the [`Thread`] type, which you can get in one of
 //! two ways:
 //!
-//! * By spawning a new thread, e.g. using the `thread::spawn` function, and
-//!   calling `thread()` on the `JoinHandle`.
-//! * By requesting the current thread, using the `thread::current` function.
+//! * By spawning a new thread, e.g. using the [`thread::spawn`][`spawn`]
+//!   function, and calling [`thread()`] on the [`JoinHandle`].
+//! * By requesting the current thread, using the [`thread::current()`] function.
 //!
-//! The `thread::current()` function is available even for threads not spawned
+//! The [`thread::current()`] function is available even for threads not spawned
 //! by the APIs of this module.
 //!
 //! ## Blocking support: park and unpark
 //!
 //! Every thread is equipped with some basic low-level blocking support, via the
-//! `thread::park()` function and `thread::Thread::unpark()` method. `park()`
-//! blocks the current thread, which can then be resumed from another thread by
-//! calling the `unpark()` method on the blocked thread's handle.
+//! [`thread::park()`][`park()`] function and [`thread::Thread::unpark()`][`unpark()`]
+//! method. [`park()`] blocks the current thread, which can then be resumed from
+//! another thread by calling the [`unpark()`] method on the blocked thread's handle.
 //!
-//! Conceptually, each `Thread` handle has an associated token, which is
+//! Conceptually, each [`Thread`] handle has an associated token, which is
 //! initially not present:
 //!
-//! * The `thread::park()` function blocks the current thread unless or until
+//! * The [`thread::park()`][`park()`] function blocks the current thread unless or until
 //!   the token is available for its thread handle, at which point it atomically
 //!   consumes the token. It may also return *spuriously*, without consuming the
-//!   token. `thread::park_timeout()` does the same, but allows specifying a
+//!   token. [`thread::park_timeout()`] does the same, but allows specifying a
 //!   maximum time to block the thread for.
 //!
-//! * The `unpark()` method on a `Thread` atomically makes the token available
+//! * The [`unpark()`] method on a [`Thread`] atomically makes the token available
 //!   if it wasn't already.
 //!
-//! In other words, each `Thread` acts a bit like a semaphore with initial count
+//! In other words, each [`Thread`] acts a bit like a semaphore with initial count
 //! 0, except that the semaphore is *saturating* (the count cannot go above 1),
 //! and can return spuriously.
 //!
 //! The API is typically used by acquiring a handle to the current thread,
 //! placing that handle in a shared data structure so that other threads can
 //! find it, and then `park`ing. When some desired condition is met, another
-//! thread calls `unpark` on the handle.
+//! thread calls [`unpark()`] on the handle.
 //!
 //! The motivation for this design is twofold:
 //!
@@ -149,6 +147,22 @@
 //! will want to make use of some form of **interior mutability** through the
 //! [`Cell`] or [`RefCell`] types.
 //!
+//! [channels]: ../../std/sync/mpsc/index.html
+//! [`Arc`]: ../../std/sync/struct.Arc.html
+//! [`spawn`]: ../../std/thread/fn.spawn.html
+//! [`JoinHandle`]: ../../std/thread/struct.JoinHandle.html
+//! [`thread()`]: ../../std/thread/struct.JoinHandle.html#method.thread
+//! [`join`]: ../../std/thread/struct.JoinHandle.html#method.join
+//! [`Result`]: ../../std/result/enum.Result.html
+//! [`Ok`]: ../../std/result/enum.Result.html#variant.Ok
+//! [`Err`]: ../../std/result/enum.Result.html#variant.Err
+//! [`panic!`]: ../../std/macro.panic.html
+//! [`Builder`]: ../../std/thread/struct.Builder.html
+//! [`thread::current()`]: ../../std/thread/fn.spawn.html
+//! [`Thread`]: ../../std/thread/struct.Thread.html
+//! [`park()`]: ../../std/thread/fn.park.html
+//! [`unpark()`]: ../../std/thread/struct.Thread.html#method.unpark
+//! [`thread::park_timeout()`]: ../../std/thread/fn.park_timeout.html
 //! [`Cell`]: ../cell/struct.Cell.html
 //! [`RefCell`]: ../cell/struct.RefCell.html
 //! [`thread_local!`]: ../macro.thread_local.html
@@ -203,6 +217,7 @@ pub use self::local::{LocalKey, LocalKeyState};
 /// Thread configuration. Provides detailed control over the properties
 /// and behavior of new threads.
 #[stable(feature = "rust1", since = "1.0.0")]
+#[derive(Debug)]
 pub struct Builder {
     // A name for the thread-to-be, for identification in panic messages
     name: Option<String>,
@@ -303,20 +318,38 @@ impl Builder {
 // Free functions
 ////////////////////////////////////////////////////////////////////////////////
 
-/// Spawns a new thread, returning a `JoinHandle` for it.
+/// Spawns a new thread, returning a [`JoinHandle`] for it.
 ///
 /// The join handle will implicitly *detach* the child thread upon being
 /// dropped. In this case, the child thread may outlive the parent (unless
 /// the parent thread is the main thread; the whole process is terminated when
-/// the main thread finishes.) Additionally, the join handle provides a `join`
+/// the main thread finishes). Additionally, the join handle provides a [`join`]
 /// method that can be used to join the child thread. If the child thread
-/// panics, `join` will return an `Err` containing the argument given to
-/// `panic`.
+/// panics, [`join`] will return an [`Err`] containing the argument given to
+/// [`panic`].
 ///
 /// # Panics
 ///
-/// Panics if the OS fails to create a thread; use `Builder::spawn`
+/// Panics if the OS fails to create a thread; use [`Builder::spawn`]
 /// to recover from such errors.
+///
+/// [`JoinHandle`]: ../../std/thread/struct.JoinHandle.html
+/// [`join`]: ../../std/thread/struct.JoinHandle.html#method.join
+/// [`Err`]: ../../std/result/enum.Result.html#variant.Err
+/// [`panic!`]: ../../std/macro.panic.html
+/// [`Builder::spawn`]: ../../std/thread/struct.Builder.html#method.spawn
+///
+/// # Examples
+///
+/// ```
+/// use std::thread;
+///
+/// let handler = thread::spawn(|| {
+///     // thread code
+/// });
+///
+/// handler.join().unwrap();
+/// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn spawn<F, T>(f: F) -> JoinHandle<T> where
     F: FnOnce() -> T, F: Send + 'static, T: Send + 'static
@@ -326,7 +359,7 @@ pub fn spawn<F, T>(f: F) -> JoinHandle<T> where
 
 /// Gets a handle to the thread that invokes it.
 ///
-/// #Examples
+/// # Examples
 ///
 /// Getting a handle to the current thread with `thread::current()`:
 ///
@@ -351,6 +384,14 @@ pub fn current() -> Thread {
 }
 
 /// Cooperatively gives up a timeslice to the OS scheduler.
+///
+/// # Examples
+///
+/// ```
+/// use std::thread;
+///
+/// thread::yield_now();
+/// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn yield_now() {
     imp::Thread::yield_now()
@@ -360,7 +401,7 @@ pub fn yield_now() {
 ///
 /// # Examples
 ///
-/// ```rust,should_panic
+/// ```should_panic
 /// use std::thread;
 ///
 /// struct SomeStruct;
@@ -398,6 +439,15 @@ pub fn panicking() -> bool {
 /// specifics or platform-dependent functionality. Note that on unix platforms
 /// this function will not return early due to a signal being received or a
 /// spurious wakeup.
+///
+/// # Examples
+///
+/// ```no_run
+/// use std::thread;
+///
+/// // Let's sleep for 2 seconds:
+/// thread::sleep_ms(2000);
+/// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_deprecated(since = "1.6.0", reason = "replaced by `std::thread::sleep`")]
 pub fn sleep_ms(ms: u32) {
@@ -418,7 +468,7 @@ pub fn sleep_ms(ms: u32) {
 ///
 /// # Examples
 ///
-/// ```rust,no_run
+/// ```no_run
 /// use std::{thread, time};
 ///
 /// let ten_millis = time::Duration::from_millis(10);
@@ -573,6 +623,13 @@ impl ThreadId {
     }
 }
 
+#[stable(feature = "std_debug", since = "1.15.0")]
+impl fmt::Debug for ThreadId {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.pad("ThreadId { .. }")
+    }
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // Thread
 ////////////////////////////////////////////////////////////////////////////////
@@ -727,7 +784,7 @@ impl<T> JoinInner<T> {
 ///
 /// A `JoinHandle` *detaches* the child thread when it is dropped.
 ///
-/// Due to platform restrictions, it is not possible to `Clone` this
+/// Due to platform restrictions, it is not possible to [`Clone`] this
 /// handle: the ability to join a child thread is a uniquely-owned
 /// permission.
 ///
@@ -738,7 +795,7 @@ impl<T> JoinInner<T> {
 ///
 /// Creation from [`thread::spawn`]:
 ///
-/// ```rust
+/// ```
 /// use std::thread;
 ///
 /// let join_handle: thread::JoinHandle<_> = thread::spawn(|| {
@@ -748,7 +805,7 @@ impl<T> JoinInner<T> {
 ///
 /// Creation from [`thread::Builder::spawn`]:
 ///
-/// ```rust
+/// ```
 /// use std::thread;
 ///
 /// let builder = thread::Builder::new();
@@ -758,13 +815,31 @@ impl<T> JoinInner<T> {
 /// }).unwrap();
 /// ```
 ///
+/// [`Clone`]: ../../std/clone/trait.Clone.html
 /// [`thread::spawn`]: fn.spawn.html
 /// [`thread::Builder::spawn`]: struct.Builder.html#method.spawn
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct JoinHandle<T>(JoinInner<T>);
 
 impl<T> JoinHandle<T> {
-    /// Extracts a handle to the underlying thread
+    /// Extracts a handle to the underlying thread.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(thread_id)]
+    ///
+    /// use std::thread;
+    ///
+    /// let builder = thread::Builder::new();
+    ///
+    /// let join_handle: thread::JoinHandle<_> = builder.spawn(|| {
+    ///     // some work here
+    /// }).unwrap();
+    ///
+    /// let thread = join_handle.thread();
+    /// println!("thread id: {:?}", thread.id());
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn thread(&self) -> &Thread {
         &self.0.thread
@@ -772,8 +847,24 @@ impl<T> JoinHandle<T> {
 
     /// Waits for the associated thread to finish.
     ///
-    /// If the child thread panics, `Err` is returned with the parameter given
-    /// to `panic`.
+    /// If the child thread panics, [`Err`] is returned with the parameter given
+    /// to [`panic`].
+    ///
+    /// [`Err`]: ../../std/result/enum.Result.html#variant.Err
+    /// [`panic!`]: ../../std/macro.panic.html
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::thread;
+    ///
+    /// let builder = thread::Builder::new();
+    ///
+    /// let join_handle: thread::JoinHandle<_> = builder.spawn(|| {
+    ///     // some work here
+    /// }).unwrap();
+    /// join_handle.join().expect("Couldn't join on the associated thread");
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn join(mut self) -> Result<T> {
         self.0.join()
@@ -788,6 +879,13 @@ impl<T> IntoInner<imp::Thread> for JoinHandle<T> {
     fn into_inner(self) -> imp::Thread { self.0.native.unwrap() }
 }
 
+#[stable(feature = "std_debug", since = "1.15.0")]
+impl<T> fmt::Debug for JoinHandle<T> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.pad("JoinHandle { .. }")
+    }
+}
+
 fn _assert_sync_and_send() {
     fn _assert_both<T: Send + Sync>() {}
     _assert_both::<JoinHandle<()>>();
diff --git a/src/libstd/time/duration.rs b/src/libstd/time/duration.rs
index 41d675b6f88..162ce530f17 100644
--- a/src/libstd/time/duration.rs
+++ b/src/libstd/time/duration.rs
@@ -14,16 +14,19 @@ const NANOS_PER_SEC: u32 = 1_000_000_000;
 const NANOS_PER_MILLI: u32 = 1_000_000;
 const MILLIS_PER_SEC: u64 = 1_000;
 
-/// A duration type to represent a span of time, typically used for system
+/// A `Duration` type to represent a span of time, typically used for system
 /// timeouts.
 ///
-/// Each duration is composed of a number of seconds and nanosecond precision.
+/// Each `Duration` is composed of a number of seconds and nanosecond precision.
 /// APIs binding a system timeout will typically round up the nanosecond
 /// precision if the underlying system does not support that level of precision.
 ///
-/// Durations implement many common traits, including `Add`, `Sub`, and other
-/// ops traits. Currently a duration may only be inspected for its number of
-/// seconds and its nanosecond precision.
+/// `Duration`s implement many common traits, including [`Add`], [`Sub`], and other
+/// [`ops`] traits.
+///
+/// [`Add`]: ../../std/ops/trait.Add.html
+/// [`Sub`]: ../../std/ops/trait.Sub.html
+/// [`ops`]: ../../std/ops/index.html
 ///
 /// # Examples
 ///
@@ -56,6 +59,14 @@ impl Duration {
     ///
     /// This constructor will panic if the carry from the nanoseconds overflows
     /// the seconds counter.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::time::Duration;
+    ///
+    /// let five_seconds = Duration::new(5, 0);
+    /// ```
     #[stable(feature = "duration", since = "1.3.0")]
     #[inline]
     pub fn new(secs: u64, nanos: u32) -> Duration {
@@ -66,6 +77,14 @@ impl Duration {
     }
 
     /// Creates a new `Duration` from the specified number of seconds.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::time::Duration;
+    ///
+    /// let five_seconds = Duration::from_secs(5);
+    /// ```
     #[stable(feature = "duration", since = "1.3.0")]
     #[inline]
     pub fn from_secs(secs: u64) -> Duration {
@@ -73,6 +92,14 @@ impl Duration {
     }
 
     /// Creates a new `Duration` from the specified number of milliseconds.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::time::Duration;
+    ///
+    /// let five_seconds = Duration::from_millis(5000);
+    /// ```
     #[stable(feature = "duration", since = "1.3.0")]
     #[inline]
     pub fn from_millis(millis: u64) -> Duration {
@@ -81,26 +108,46 @@ impl Duration {
         Duration { secs: secs, nanos: nanos }
     }
 
-    /// Returns the number of whole seconds represented by this duration.
+    /// Returns the number of whole seconds represented by this `Duration`.
     ///
     /// The extra precision represented by this duration is ignored (i.e. extra
     /// nanoseconds are not represented in the returned value).
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::time::Duration;
+    ///
+    /// let five_seconds = Duration::new(5, 0);
+    /// assert_eq!(five_seconds.as_secs(), 5);
+    /// ```
     #[stable(feature = "duration", since = "1.3.0")]
     #[inline]
     pub fn as_secs(&self) -> u64 { self.secs }
 
-    /// Returns the nanosecond precision represented by this duration.
+    /// Returns the nanosecond precision represented by this `Duration`.
     ///
     /// This method does **not** return the length of the duration when
     /// represented by nanoseconds. The returned number always represents a
     /// fractional portion of a second (i.e. it is less than one billion).
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::time::Duration;
+    ///
+    /// let duration = Duration::from_millis(5010);
+    /// assert_eq!(duration.subsec_nanos(), 10000000);
+    /// ```
     #[stable(feature = "duration", since = "1.3.0")]
     #[inline]
     pub fn subsec_nanos(&self) -> u32 { self.nanos }
 
-    /// Checked duration addition. Computes `self + other`, returning `None`
+    /// Checked `Duration` addition. Computes `self + other`, returning [`None`]
     /// if overflow occurred.
     ///
+    /// [`None`]: ../../std/option/enum.Option.html#variant.None
+    ///
     /// # Examples
     ///
     /// Basic usage:
@@ -136,9 +183,11 @@ impl Duration {
         }
     }
 
-    /// Checked duration subtraction. Computes `self + other`, returning `None`
+    /// Checked `Duration` subtraction. Computes `self - other`, returning [`None`]
     /// if the result would be negative or if underflow occurred.
     ///
+    /// [`None`]: ../../std/option/enum.Option.html#variant.None
+    ///
     /// # Examples
     ///
     /// Basic usage:
@@ -172,8 +221,10 @@ impl Duration {
         }
     }
 
-    /// Checked duration multiplication. Computes `self * other`, returning
-    /// `None` if underflow or overflow occurred.
+    /// Checked `Duration` multiplication. Computes `self * other`, returning
+    /// [`None`] if overflow occurred.
+    ///
+    /// [`None`]: ../../std/option/enum.Option.html#variant.None
     ///
     /// # Examples
     ///
@@ -207,8 +258,10 @@ impl Duration {
         }
     }
 
-    /// Checked duration division. Computes `self / other`, returning `None`
-    /// if `other == 0` or the operation results in underflow or overflow.
+    /// Checked `Duration` division. Computes `self / other`, returning [`None`]
+    /// if `other == 0`.
+    ///
+    /// [`None`]: ../../std/option/enum.Option.html#variant.None
     ///
     /// # Examples
     ///