about summary refs log tree commit diff
path: root/src/libstd/sys
diff options
context:
space:
mode:
authorJohannes Hoff <johshoff@gmail.com>2014-12-24 13:22:11 +0100
committerJohannes Hoff <johshoff@gmail.com>2014-12-24 13:22:11 +0100
commit0128159c95d0544e0c30b8b52ce3e7ce348fc114 (patch)
tree8af4db0f2758f86434b895169122a9962fb79b21 /src/libstd/sys
parent8f827d33cab1be648120fc8ac34651d9cc079b5e (diff)
parente64a8193b02ce72ef183274994a25eae281cb89c (diff)
downloadrust-0128159c95d0544e0c30b8b52ce3e7ce348fc114.tar.gz
rust-0128159c95d0544e0c30b8b52ce3e7ce348fc114.zip
Merge branch 'master' into cfg_tmp_dir
Conflicts:
	src/etc/rustup.sh
Diffstat (limited to 'src/libstd/sys')
-rw-r--r--src/libstd/sys/common/backtrace.rs136
-rw-r--r--src/libstd/sys/common/condvar.rs67
-rw-r--r--src/libstd/sys/common/helper_thread.rs40
-rw-r--r--src/libstd/sys/common/mod.rs23
-rw-r--r--src/libstd/sys/common/mutex.rs62
-rw-r--r--src/libstd/sys/common/net.rs53
-rw-r--r--src/libstd/sys/common/rwlock.rs86
-rw-r--r--src/libstd/sys/common/stack.rs325
-rw-r--r--src/libstd/sys/common/thread.rs35
-rw-r--r--src/libstd/sys/common/thread_info.rs68
-rw-r--r--src/libstd/sys/common/thread_local.rs284
-rw-r--r--src/libstd/sys/unix/backtrace.rs493
-rw-r--r--src/libstd/sys/unix/condvar.rs83
-rw-r--r--src/libstd/sys/unix/ext.rs107
-rw-r--r--src/libstd/sys/unix/fs.rs19
-rw-r--r--src/libstd/sys/unix/mod.rs28
-rw-r--r--src/libstd/sys/unix/mutex.rs52
-rw-r--r--src/libstd/sys/unix/os.rs137
-rw-r--r--src/libstd/sys/unix/pipe.rs22
-rw-r--r--src/libstd/sys/unix/process.rs79
-rw-r--r--src/libstd/sys/unix/rwlock.rs57
-rw-r--r--src/libstd/sys/unix/stack_overflow.rs277
-rw-r--r--src/libstd/sys/unix/sync.rs208
-rw-r--r--src/libstd/sys/unix/tcp.rs17
-rw-r--r--src/libstd/sys/unix/thread.rs271
-rw-r--r--src/libstd/sys/unix/thread_local.rs52
-rw-r--r--src/libstd/sys/unix/timer.rs4
-rw-r--r--src/libstd/sys/windows/backtrace.rs371
-rw-r--r--src/libstd/sys/windows/c.rs14
-rw-r--r--src/libstd/sys/windows/condvar.rs62
-rw-r--r--src/libstd/sys/windows/ext.rs100
-rw-r--r--src/libstd/sys/windows/fs.rs26
-rw-r--r--src/libstd/sys/windows/mod.rs25
-rw-r--r--src/libstd/sys/windows/mutex.rs78
-rw-r--r--src/libstd/sys/windows/os.rs238
-rw-r--r--src/libstd/sys/windows/pipe.rs17
-rw-r--r--src/libstd/sys/windows/process.rs70
-rw-r--r--src/libstd/sys/windows/rwlock.rs53
-rw-r--r--src/libstd/sys/windows/stack_overflow.rs115
-rw-r--r--src/libstd/sys/windows/sync.rs58
-rw-r--r--src/libstd/sys/windows/tcp.rs45
-rw-r--r--src/libstd/sys/windows/thread.rs96
-rw-r--r--src/libstd/sys/windows/thread_local.rs259
-rw-r--r--src/libstd/sys/windows/timer.rs4
-rw-r--r--src/libstd/sys/windows/tty.rs4
45 files changed, 4507 insertions, 213 deletions
diff --git a/src/libstd/sys/common/backtrace.rs b/src/libstd/sys/common/backtrace.rs
new file mode 100644
index 00000000000..1d646eb06b1
--- /dev/null
+++ b/src/libstd/sys/common/backtrace.rs
@@ -0,0 +1,136 @@
+// Copyright 2014 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 prelude::*;
+
+use io::IoResult;
+
+#[cfg(target_word_size = "64")] pub const HEX_WIDTH: uint = 18;
+#[cfg(target_word_size = "32")] pub const HEX_WIDTH: uint = 10;
+
+// All rust symbols are in theory lists of "::"-separated identifiers. Some
+// assemblers, however, can't handle these characters in symbol names. To get
+// around this, we use C++-style mangling. The mangling method is:
+//
+// 1. Prefix the symbol with "_ZN"
+// 2. For each element of the path, emit the length plus the element
+// 3. End the path with "E"
+//
+// For example, "_ZN4testE" => "test" and "_ZN3foo3bar" => "foo::bar".
+//
+// We're the ones printing our backtraces, so we can't rely on anything else to
+// demangle our symbols. It's *much* nicer to look at demangled symbols, so
+// this function is implemented to give us nice pretty output.
+//
+// Note that this demangler isn't quite as fancy as it could be. We have lots
+// of other information in our symbols like hashes, version, type information,
+// etc. Additionally, this doesn't handle glue symbols at all.
+pub fn demangle(writer: &mut Writer, s: &str) -> IoResult<()> {
+    // First validate the symbol. If it doesn't look like anything we're
+    // expecting, we just print it literally. Note that we must handle non-rust
+    // symbols because we could have any function in the backtrace.
+    let mut valid = true;
+    let mut inner = s;
+    if s.len() > 4 && s.starts_with("_ZN") && s.ends_with("E") {
+        inner = s.slice(3, s.len() - 1);
+    // On Windows, dbghelp strips leading underscores, so we accept "ZN...E" form too.
+    } else if s.len() > 3 && s.starts_with("ZN") && s.ends_with("E") {
+        inner = s.slice(2, s.len() - 1);
+    } else {
+        valid = false;
+    }
+
+    if valid {
+        let mut chars = inner.chars();
+        while valid {
+            let mut i = 0;
+            for c in chars {
+                if c.is_numeric() {
+                    i = i * 10 + c as uint - '0' as uint;
+                } else {
+                    break
+                }
+            }
+            if i == 0 {
+                valid = chars.next().is_none();
+                break
+            } else if chars.by_ref().take(i - 1).count() != i - 1 {
+                valid = false;
+            }
+        }
+    }
+
+    // Alright, let's do this.
+    if !valid {
+        try!(writer.write_str(s));
+    } else {
+        let mut first = true;
+        while inner.len() > 0 {
+            if !first {
+                try!(writer.write_str("::"));
+            } else {
+                first = false;
+            }
+            let mut rest = inner;
+            while rest.char_at(0).is_numeric() {
+                rest = rest.slice_from(1);
+            }
+            let i: uint = inner.slice_to(inner.len() - rest.len()).parse().unwrap();
+            inner = rest.slice_from(i);
+            rest = rest.slice_to(i);
+            while rest.len() > 0 {
+                if rest.starts_with("$") {
+                    macro_rules! demangle {
+                        ($($pat:expr => $demangled:expr),*) => ({
+                            $(if rest.starts_with($pat) {
+                                try!(writer.write_str($demangled));
+                                rest = rest.slice_from($pat.len());
+                              } else)*
+                            {
+                                try!(writer.write_str(rest));
+                                break;
+                            }
+
+                        })
+                    }
+
+                    // see src/librustc/back/link.rs for these mappings
+                    demangle! (
+                        "$SP$" => "@",
+                        "$UP$" => "Box",
+                        "$RP$" => "*",
+                        "$BP$" => "&",
+                        "$LT$" => "<",
+                        "$GT$" => ">",
+                        "$LP$" => "(",
+                        "$RP$" => ")",
+                        "$C$"  => ",",
+
+                        // in theory we can demangle any Unicode code point, but
+                        // for simplicity we just catch the common ones.
+                        "$x20" => " ",
+                        "$x27" => "'",
+                        "$x5b" => "[",
+                        "$x5d" => "]"
+                    )
+                } else {
+                    let idx = match rest.find('$') {
+                        None => rest.len(),
+                        Some(i) => i,
+                    };
+                    try!(writer.write_str(rest.slice_to(idx)));
+                    rest = rest.slice_from(idx);
+                }
+            }
+        }
+    }
+
+    Ok(())
+}
diff --git a/src/libstd/sys/common/condvar.rs b/src/libstd/sys/common/condvar.rs
new file mode 100644
index 00000000000..e09d9704029
--- /dev/null
+++ b/src/libstd/sys/common/condvar.rs
@@ -0,0 +1,67 @@
+// Copyright 2014 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 time::Duration;
+use sys_common::mutex::{mod, Mutex};
+use sys::condvar as imp;
+
+/// An OS-based condition variable.
+///
+/// This structure is the lowest layer possible on top of the OS-provided
+/// condition variables. It is consequently entirely unsafe to use. It is
+/// recommended to use the safer types at the top level of this crate instead of
+/// this type.
+pub struct Condvar(imp::Condvar);
+
+/// Static initializer for condition variables.
+pub const CONDVAR_INIT: Condvar = Condvar(imp::CONDVAR_INIT);
+
+impl Condvar {
+    /// Creates a new condition variable for use.
+    ///
+    /// Behavior is undefined if the condition variable is moved after it is
+    /// first used with any of the functions below.
+    #[inline]
+    pub unsafe fn new() -> Condvar { Condvar(imp::Condvar::new()) }
+
+    /// Signal one waiter on this condition variable to wake up.
+    #[inline]
+    pub unsafe fn notify_one(&self) { self.0.notify_one() }
+
+    /// Awaken all current waiters on this condition variable.
+    #[inline]
+    pub unsafe fn notify_all(&self) { self.0.notify_all() }
+
+    /// Wait for a signal on the specified mutex.
+    ///
+    /// Behavior is undefined if the mutex is not locked by the current thread.
+    /// Behavior is also undefined if more than one mutex is used concurrently
+    /// on this condition variable.
+    #[inline]
+    pub unsafe fn wait(&self, mutex: &Mutex) { self.0.wait(mutex::raw(mutex)) }
+
+    /// Wait for a signal on the specified mutex with a timeout duration
+    /// specified by `dur` (a relative time into the future).
+    ///
+    /// Behavior is undefined if the mutex is not locked by the current thread.
+    /// Behavior is also undefined if more than one mutex is used concurrently
+    /// on this condition variable.
+    #[inline]
+    pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
+        self.0.wait_timeout(mutex::raw(mutex), dur)
+    }
+
+    /// Deallocate all resources associated with this condition variable.
+    ///
+    /// Behavior is undefined if there are current or will be future users of
+    /// this condition variable.
+    #[inline]
+    pub unsafe fn destroy(&self) { self.0.destroy() }
+}
diff --git a/src/libstd/sys/common/helper_thread.rs b/src/libstd/sys/common/helper_thread.rs
index 9508d8d9232..421778e2012 100644
--- a/src/libstd/sys/common/helper_thread.rs
+++ b/src/libstd/sys/common/helper_thread.rs
@@ -20,15 +20,15 @@
 //! can be created in the future and there must be no active timers at that
 //! time.
 
-use mem;
-use rustrt::bookkeeping;
-use rustrt::mutex::StaticNativeMutex;
-use rustrt;
+use prelude::*;
+
 use cell::UnsafeCell;
+use mem;
+use sync::{StaticMutex, StaticCondvar};
+use rt;
 use sys::helper_signal;
-use prelude::*;
 
-use task;
+use thread::Thread;
 
 /// A structure for management of a helper thread.
 ///
@@ -39,7 +39,8 @@ use task;
 /// is for static initialization.
 pub struct Helper<M> {
     /// Internal lock which protects the remaining fields
-    pub lock: StaticNativeMutex,
+    pub lock: StaticMutex,
+    pub cond: StaticCondvar,
 
     // You'll notice that the remaining fields are UnsafeCell<T>, and this is
     // because all helper thread operations are done through &self, but we need
@@ -53,6 +54,9 @@ pub struct Helper<M> {
 
     /// Flag if this helper thread has booted and been initialized yet.
     pub initialized: UnsafeCell<bool>,
+
+    /// Flag if this helper thread has shut down
+    pub shutdown: UnsafeCell<bool>,
 }
 
 impl<M: Send> Helper<M> {
@@ -65,9 +69,10 @@ impl<M: Send> Helper<M> {
     /// passed to the helper thread in a separate task.
     ///
     /// This function is safe to be called many times.
-    pub fn boot<T: Send>(&'static self,
-                         f: || -> T,
-                         helper: fn(helper_signal::signal, Receiver<M>, T)) {
+    pub fn boot<T, F>(&'static self, f: F, helper: fn(helper_signal::signal, Receiver<M>, T)) where
+        T: Send,
+        F: FnOnce() -> T,
+    {
         unsafe {
             let _guard = self.lock.lock();
             if !*self.initialized.get() {
@@ -77,13 +82,14 @@ impl<M: Send> Helper<M> {
                 *self.signal.get() = send as uint;
 
                 let t = f();
-                task::spawn(proc() {
-                    bookkeeping::decrement();
+                Thread::spawn(move |:| {
                     helper(receive, rx, t);
-                    self.lock.lock().signal()
-                });
+                    let _g = self.lock.lock();
+                    *self.shutdown.get() = true;
+                    self.cond.notify_one()
+                }).detach();
 
-                rustrt::at_exit(proc() { self.shutdown() });
+                rt::at_exit(move|:| { self.shutdown() });
                 *self.initialized.get() = true;
             }
         }
@@ -119,7 +125,9 @@ impl<M: Send> Helper<M> {
             helper_signal::signal(*self.signal.get() as helper_signal::signal);
 
             // Wait for the child to exit
-            guard.wait();
+            while !*self.shutdown.get() {
+                self.cond.wait(&guard);
+            }
             drop(guard);
 
             // Clean up after ourselves
diff --git a/src/libstd/sys/common/mod.rs b/src/libstd/sys/common/mod.rs
index cacb128faa5..dc0ad08cdbe 100644
--- a/src/libstd/sys/common/mod.rs
+++ b/src/libstd/sys/common/mod.rs
@@ -13,14 +13,22 @@
 
 use io::{mod, IoError, IoResult};
 use prelude::*;
-use sys::{last_error, retry, fs};
+use sys::{last_error, retry};
 use c_str::CString;
 use num::Int;
 use path::BytesContainer;
 use collections;
 
-pub mod net;
+pub mod backtrace;
+pub mod condvar;
 pub mod helper_thread;
+pub mod mutex;
+pub mod net;
+pub mod rwlock;
+pub mod stack;
+pub mod thread;
+pub mod thread_info;
+pub mod thread_local;
 
 // common error constructors
 
@@ -65,7 +73,9 @@ pub fn mkerr_libc<T: Int>(ret: T) -> IoResult<()> {
     }
 }
 
-pub fn keep_going(data: &[u8], f: |*const u8, uint| -> i64) -> i64 {
+pub fn keep_going<F>(data: &[u8], mut f: F) -> i64 where
+    F: FnMut(*const u8, uint) -> i64,
+{
     let origamt = data.len();
     let mut data = data.as_ptr();
     let mut amt = origamt;
@@ -83,10 +93,9 @@ pub fn keep_going(data: &[u8], f: |*const u8, uint| -> i64) -> i64 {
     return (origamt - amt) as i64;
 }
 
-// traits for extracting representations from
-
-pub trait AsFileDesc {
-    fn as_fd(&self) -> &fs::FileDesc;
+// A trait for extracting representations from std::io types
+pub trait AsInner<Inner> {
+    fn as_inner(&self) -> &Inner;
 }
 
 pub trait ProcessConfig<K: BytesContainer, V: BytesContainer> {
diff --git a/src/libstd/sys/common/mutex.rs b/src/libstd/sys/common/mutex.rs
new file mode 100644
index 00000000000..1a8a92a105a
--- /dev/null
+++ b/src/libstd/sys/common/mutex.rs
@@ -0,0 +1,62 @@
+// Copyright 2014 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 sys::mutex as imp;
+
+/// An OS-based mutual exclusion lock.
+///
+/// This is the thinnest cross-platform wrapper around OS mutexes. All usage of
+/// this mutex is unsafe and it is recommended to instead use the safe wrapper
+/// at the top level of the crate instead of this type.
+pub struct Mutex(imp::Mutex);
+
+/// Constant initializer for statically allocated mutexes.
+pub const MUTEX_INIT: Mutex = Mutex(imp::MUTEX_INIT);
+
+impl Mutex {
+    /// Creates a newly initialized mutex.
+    ///
+    /// Behavior is undefined if the mutex is moved after the first method is
+    /// called on the mutex.
+    #[inline]
+    pub unsafe fn new() -> Mutex { Mutex(imp::Mutex::new()) }
+
+    /// Lock the mutex blocking the current thread until it is available.
+    ///
+    /// Behavior is undefined if the mutex has been moved between this and any
+    /// previous function call.
+    #[inline]
+    pub unsafe fn lock(&self) { self.0.lock() }
+
+    /// Attempt to lock the mutex without blocking, returning whether it was
+    /// successfully acquired or not.
+    ///
+    /// Behavior is undefined if the mutex has been moved between this and any
+    /// previous function call.
+    #[inline]
+    pub unsafe fn try_lock(&self) -> bool { self.0.try_lock() }
+
+    /// Unlock the mutex.
+    ///
+    /// Behavior is undefined if the current thread does not actually hold the
+    /// mutex.
+    #[inline]
+    pub unsafe fn unlock(&self) { self.0.unlock() }
+
+    /// Deallocate all resources associated with this mutex.
+    ///
+    /// Behavior is undefined if there are current or will be future users of
+    /// this mutex.
+    #[inline]
+    pub unsafe fn destroy(&self) { self.0.destroy() }
+}
+
+// not meant to be exported to the outside world, just the containing module
+pub fn raw(mutex: &Mutex) -> &imp::Mutex { &mutex.0 }
diff --git a/src/libstd/sys/common/net.rs b/src/libstd/sys/common/net.rs
index 029fc852742..382f6875b28 100644
--- a/src/libstd/sys/common/net.rs
+++ b/src/libstd/sys/common/net.rs
@@ -8,21 +8,21 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-pub use self::SocketStatus::*;
-pub use self::InAddr::*;
+use self::SocketStatus::*;
+use self::InAddr::*;
 
 use alloc::arc::Arc;
 use libc::{mod, c_char, c_int};
 use mem;
 use num::Int;
 use ptr::{mod, null, null_mut};
-use rustrt::mutex;
 use io::net::ip::{SocketAddr, IpAddr, Ipv4Addr, Ipv6Addr};
 use io::net::addrinfo;
 use io::{IoResult, IoError};
 use sys::{mod, retry, c, sock_t, last_error, last_net_error, last_gai_error, close_sock,
           wrlen, msglen_t, os, wouldblock, set_nonblocking, timer, ms_to_timeval,
           decode_error_detailed};
+use sync::{Mutex, MutexGuard};
 use sys_common::{mod, keep_going, short_write, timeout};
 use prelude::*;
 use cmp;
@@ -344,10 +344,10 @@ pub fn get_host_addresses(host: Option<&str>, servname: Option<&str>,
 // [1] http://twistedmatrix.com/pipermail/twisted-commits/2012-April/034692.html
 // [2] http://stackoverflow.com/questions/19819198/does-send-msg-dontwait
 
-pub fn read<T>(fd: sock_t,
-               deadline: u64,
-               lock: || -> T,
-               read: |bool| -> libc::c_int) -> IoResult<uint> {
+pub fn read<T, L, R>(fd: sock_t, deadline: u64, mut lock: L, mut read: R) -> IoResult<uint> where
+    L: FnMut() -> T,
+    R: FnMut(bool) -> libc::c_int,
+{
     let mut ret = -1;
     if deadline == 0 {
         ret = retry(|| read(false));
@@ -386,12 +386,15 @@ pub fn read<T>(fd: sock_t,
     }
 }
 
-pub fn write<T>(fd: sock_t,
-                deadline: u64,
-                buf: &[u8],
-                write_everything: bool,
-                lock: || -> T,
-                write: |bool, *const u8, uint| -> i64) -> IoResult<uint> {
+pub fn write<T, L, W>(fd: sock_t,
+                      deadline: u64,
+                      buf: &[u8],
+                      write_everything: bool,
+                      mut lock: L,
+                      mut write: W) -> IoResult<uint> where
+    L: FnMut() -> T,
+    W: FnMut(bool, *const u8, uint) -> i64,
+{
     let mut ret = -1;
     let mut written = 0;
     if deadline == 0 {
@@ -557,12 +560,12 @@ struct Inner {
 
     // Unused on Linux, where this lock is not necessary.
     #[allow(dead_code)]
-    lock: mutex::NativeMutex
+    lock: Mutex<()>,
 }
 
 impl Inner {
     fn new(fd: sock_t) -> Inner {
-        Inner { fd: fd, lock: unsafe { mutex::NativeMutex::new() } }
+        Inner { fd: fd, lock: Mutex::new(()) }
     }
 }
 
@@ -572,7 +575,7 @@ impl Drop for Inner {
 
 pub struct Guard<'a> {
     pub fd: sock_t,
-    pub guard: mutex::LockGuard<'a>,
+    pub guard: MutexGuard<'a, ()>,
 }
 
 #[unsafe_destructor]
@@ -666,7 +669,7 @@ impl TcpStream {
     fn lock_nonblocking<'a>(&'a self) -> Guard<'a> {
         let ret = Guard {
             fd: self.fd(),
-            guard: unsafe { self.inner.lock.lock() },
+            guard: self.inner.lock.lock(),
         };
         assert!(set_nonblocking(self.fd(), true).is_ok());
         ret
@@ -674,8 +677,8 @@ impl TcpStream {
 
     pub fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
         let fd = self.fd();
-        let dolock = || self.lock_nonblocking();
-        let doread = |nb| unsafe {
+        let dolock = |&:| self.lock_nonblocking();
+        let doread = |&mut: nb| unsafe {
             let flags = if nb {c::MSG_DONTWAIT} else {0};
             libc::recv(fd,
                        buf.as_mut_ptr() as *mut libc::c_void,
@@ -687,8 +690,8 @@ impl TcpStream {
 
     pub fn write(&mut self, buf: &[u8]) -> IoResult<()> {
         let fd = self.fd();
-        let dolock = || self.lock_nonblocking();
-        let dowrite = |nb: bool, buf: *const u8, len: uint| unsafe {
+        let dolock = |&:| self.lock_nonblocking();
+        let dowrite = |&: nb: bool, buf: *const u8, len: uint| unsafe {
             let flags = if nb {c::MSG_DONTWAIT} else {0};
             libc::send(fd,
                        buf as *const _,
@@ -805,7 +808,7 @@ impl UdpSocket {
     fn lock_nonblocking<'a>(&'a self) -> Guard<'a> {
         let ret = Guard {
             fd: self.fd(),
-            guard: unsafe { self.inner.lock.lock() },
+            guard: self.inner.lock.lock(),
         };
         assert!(set_nonblocking(self.fd(), true).is_ok());
         ret
@@ -822,7 +825,7 @@ impl UdpSocket {
         let mut addrlen: libc::socklen_t =
                 mem::size_of::<libc::sockaddr_storage>() as libc::socklen_t;
 
-        let dolock = || self.lock_nonblocking();
+        let dolock = |&:| self.lock_nonblocking();
         let n = try!(read(fd, self.read_deadline, dolock, |nb| unsafe {
             let flags = if nb {c::MSG_DONTWAIT} else {0};
             libc::recvfrom(fd,
@@ -843,8 +846,8 @@ impl UdpSocket {
         let dstp = &storage as *const _ as *const libc::sockaddr;
 
         let fd = self.fd();
-        let dolock = || self.lock_nonblocking();
-        let dowrite = |nb, buf: *const u8, len: uint| unsafe {
+        let dolock = |&: | self.lock_nonblocking();
+        let dowrite = |&mut: nb, buf: *const u8, len: uint| unsafe {
             let flags = if nb {c::MSG_DONTWAIT} else {0};
             libc::sendto(fd,
                          buf as *const libc::c_void,
diff --git a/src/libstd/sys/common/rwlock.rs b/src/libstd/sys/common/rwlock.rs
new file mode 100644
index 00000000000..df016b9e293
--- /dev/null
+++ b/src/libstd/sys/common/rwlock.rs
@@ -0,0 +1,86 @@
+// Copyright 2014 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 sys::rwlock as imp;
+
+/// An OS-based reader-writer lock.
+///
+/// This structure is entirely unsafe and serves as the lowest layer of a
+/// cross-platform binding of system rwlocks. It is recommended to use the
+/// safer types at the top level of this crate instead of this type.
+pub struct RWLock(imp::RWLock);
+
+/// Constant initializer for static RWLocks.
+pub const RWLOCK_INIT: RWLock = RWLock(imp::RWLOCK_INIT);
+
+impl RWLock {
+    /// Creates a new instance of an RWLock.
+    ///
+    /// Usage of an RWLock is undefined if it is moved after its first use (any
+    /// function calls below).
+    #[inline]
+    pub unsafe fn new() -> RWLock { RWLock(imp::RWLock::new()) }
+
+    /// Acquire shared access to the underlying lock, blocking the current
+    /// thread to do so.
+    ///
+    /// Behavior is undefined if the rwlock has been moved between this and any
+    /// previous methodo call.
+    #[inline]
+    pub unsafe fn read(&self) { self.0.read() }
+
+    /// Attempt to acquire shared access to this lock, returning whether it
+    /// succeeded or not.
+    ///
+    /// This function does not block the current thread.
+    ///
+    /// Behavior is undefined if the rwlock has been moved between this and any
+    /// previous methodo call.
+    #[inline]
+    pub unsafe fn try_read(&self) -> bool { self.0.try_read() }
+
+    /// Acquire write access to the underlying lock, blocking the current thread
+    /// to do so.
+    ///
+    /// Behavior is undefined if the rwlock has been moved between this and any
+    /// previous methodo call.
+    #[inline]
+    pub unsafe fn write(&self) { self.0.write() }
+
+    /// Attempt to acquire exclusive access to this lock, returning whether it
+    /// succeeded or not.
+    ///
+    /// This function does not block the current thread.
+    ///
+    /// Behavior is undefined if the rwlock has been moved between this and any
+    /// previous methodo call.
+    #[inline]
+    pub unsafe fn try_write(&self) -> bool { self.0.try_write() }
+
+    /// Unlock previously acquired shared access to this lock.
+    ///
+    /// Behavior is undefined if the current thread does not have shared access.
+    #[inline]
+    pub unsafe fn read_unlock(&self) { self.0.read_unlock() }
+
+    /// Unlock previously acquired exclusive access to this lock.
+    ///
+    /// Behavior is undefined if the current thread does not currently have
+    /// exclusive access.
+    #[inline]
+    pub unsafe fn write_unlock(&self) { self.0.write_unlock() }
+
+    /// Destroy OS-related resources with this RWLock.
+    ///
+    /// Behavior is undefined if there are any currently active users of this
+    /// lock.
+    #[inline]
+    pub unsafe fn destroy(&self) { self.0.destroy() }
+}
diff --git a/src/libstd/sys/common/stack.rs b/src/libstd/sys/common/stack.rs
new file mode 100644
index 00000000000..2a88e20c8fa
--- /dev/null
+++ b/src/libstd/sys/common/stack.rs
@@ -0,0 +1,325 @@
+// Copyright 2013 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.
+
+//! Rust stack-limit management
+//!
+//! Currently Rust uses a segmented-stack-like scheme in order to detect stack
+//! overflow for rust tasks. In this scheme, the prologue of all functions are
+//! preceded with a check to see whether the current stack limits are being
+//! exceeded.
+//!
+//! This module provides the functionality necessary in order to manage these
+//! stack limits (which are stored in platform-specific locations). The
+//! functions here are used at the borders of the task lifetime in order to
+//! manage these limits.
+//!
+//! This function is an unstable module because this scheme for stack overflow
+//! detection is not guaranteed to continue in the future. Usage of this module
+//! is discouraged unless absolutely necessary.
+
+// iOS related notes
+//
+// It is possible to implement it using idea from
+// http://www.opensource.apple.com/source/Libc/Libc-825.40.1/pthreads/pthread_machdep.h
+//
+// In short: _pthread_{get,set}_specific_direct allows extremely fast
+// access, exactly what is required for segmented stack
+// There is a pool of reserved slots for Apple internal use (0..119)
+// First dynamic allocated pthread key starts with 257 (on iOS7)
+// So using slot 149 should be pretty safe ASSUMING space is reserved
+// for every key < first dynamic key
+//
+// There is also an opportunity to steal keys reserved for Garbage Collection
+// ranges 80..89 and 110..119, especially considering the fact Garbage Collection
+// never supposed to work on iOS. But as everybody knows it - there is a chance
+// that those slots will be re-used, like it happened with key 95 (moved from
+// JavaScriptCore to CoreText)
+//
+// Unfortunately Apple rejected patch to LLVM which generated
+// corresponding prolog, decision was taken to disable segmented
+// stack support on iOS.
+
+pub const RED_ZONE: uint = 20 * 1024;
+
+/// This function is invoked from rust's current __morestack function. Segmented
+/// stacks are currently not enabled as segmented stacks, but rather one giant
+/// stack segment. This means that whenever we run out of stack, we want to
+/// truly consider it to be stack overflow rather than allocating a new stack.
+#[cfg(not(test))] // in testing, use the original libstd's version
+#[lang = "stack_exhausted"]
+extern fn stack_exhausted() {
+    use intrinsics;
+
+    unsafe {
+        // We're calling this function because the stack just ran out. We need
+        // to call some other rust functions, but if we invoke the functions
+        // right now it'll just trigger this handler being called again. In
+        // order to alleviate this, we move the stack limit to be inside of the
+        // red zone that was allocated for exactly this reason.
+        let limit = get_sp_limit();
+        record_sp_limit(limit - RED_ZONE / 2);
+
+        // This probably isn't the best course of action. Ideally one would want
+        // to unwind the stack here instead of just aborting the entire process.
+        // This is a tricky problem, however. There's a few things which need to
+        // be considered:
+        //
+        //  1. We're here because of a stack overflow, yet unwinding will run
+        //     destructors and hence arbitrary code. What if that code overflows
+        //     the stack? One possibility is to use the above allocation of an
+        //     extra 10k to hope that we don't hit the limit, and if we do then
+        //     abort the whole program. Not the best, but kind of hard to deal
+        //     with unless we want to switch stacks.
+        //
+        //  2. LLVM will optimize functions based on whether they can unwind or
+        //     not. It will flag functions with 'nounwind' if it believes that
+        //     the function cannot trigger unwinding, but if we do unwind on
+        //     stack overflow then it means that we could unwind in any function
+        //     anywhere. We would have to make sure that LLVM only places the
+        //     nounwind flag on functions which don't call any other functions.
+        //
+        //  3. The function that overflowed may have owned arguments. These
+        //     arguments need to have their destructors run, but we haven't even
+        //     begun executing the function yet, so unwinding will not run the
+        //     any landing pads for these functions. If this is ignored, then
+        //     the arguments will just be leaked.
+        //
+        // Exactly what to do here is a very delicate topic, and is possibly
+        // still up in the air for what exactly to do. Some relevant issues:
+        //
+        //  #3555 - out-of-stack failure leaks arguments
+        //  #3695 - should there be a stack limit?
+        //  #9855 - possible strategies which could be taken
+        //  #9854 - unwinding on windows through __morestack has never worked
+        //  #2361 - possible implementation of not using landing pads
+
+        ::rt::util::report_overflow();
+
+        intrinsics::abort();
+    }
+}
+
+// Windows maintains a record of upper and lower stack bounds in the Thread Information
+// Block (TIB), and some syscalls do check that addresses which are supposed to be in
+// the stack, indeed lie between these two values.
+// (See https://github.com/rust-lang/rust/issues/3445#issuecomment-26114839)
+//
+// When using Rust-managed stacks (libgreen), we must maintain these values accordingly.
+// For OS-managed stacks (libnative), we let the OS manage them for us.
+//
+// On all other platforms both variants behave identically.
+
+#[inline(always)]
+pub unsafe fn record_os_managed_stack_bounds(stack_lo: uint, _stack_hi: uint) {
+    record_sp_limit(stack_lo + RED_ZONE);
+}
+
+#[inline(always)]
+pub unsafe fn record_rust_managed_stack_bounds(stack_lo: uint, stack_hi: uint) {
+    // When the old runtime had segmented stacks, it used a calculation that was
+    // "limit + RED_ZONE + FUDGE". The red zone was for things like dynamic
+    // symbol resolution, llvm function calls, etc. In theory this red zone
+    // value is 0, but it matters far less when we have gigantic stacks because
+    // we don't need to be so exact about our stack budget. The "fudge factor"
+    // was because LLVM doesn't emit a stack check for functions < 256 bytes in
+    // size. Again though, we have giant stacks, so we round all these
+    // calculations up to the nice round number of 20k.
+    record_sp_limit(stack_lo + RED_ZONE);
+
+    return target_record_stack_bounds(stack_lo, stack_hi);
+
+    #[cfg(not(windows))] #[inline(always)]
+    unsafe fn target_record_stack_bounds(_stack_lo: uint, _stack_hi: uint) {}
+
+    #[cfg(all(windows, target_arch = "x86"))] #[inline(always)]
+    unsafe fn target_record_stack_bounds(stack_lo: uint, stack_hi: uint) {
+        // stack range is at TIB: %fs:0x04 (top) and %fs:0x08 (bottom)
+        asm!("mov $0, %fs:0x04" :: "r"(stack_hi) :: "volatile");
+        asm!("mov $0, %fs:0x08" :: "r"(stack_lo) :: "volatile");
+    }
+    #[cfg(all(windows, target_arch = "x86_64"))] #[inline(always)]
+    unsafe fn target_record_stack_bounds(stack_lo: uint, stack_hi: uint) {
+        // stack range is at TIB: %gs:0x08 (top) and %gs:0x10 (bottom)
+        asm!("mov $0, %gs:0x08" :: "r"(stack_hi) :: "volatile");
+        asm!("mov $0, %gs:0x10" :: "r"(stack_lo) :: "volatile");
+    }
+}
+
+/// Records the current limit of the stack as specified by `end`.
+///
+/// This is stored in an OS-dependent location, likely inside of the thread
+/// local storage. The location that the limit is stored is a pre-ordained
+/// location because it's where LLVM has emitted code to check.
+///
+/// Note that this cannot be called under normal circumstances. This function is
+/// changing the stack limit, so upon returning any further function calls will
+/// possibly be triggering the morestack logic if you're not careful.
+///
+/// Also note that this and all of the inside functions are all flagged as
+/// "inline(always)" because they're messing around with the stack limits.  This
+/// would be unfortunate for the functions themselves to trigger a morestack
+/// invocation (if they were an actual function call).
+#[inline(always)]
+pub unsafe fn record_sp_limit(limit: uint) {
+    return target_record_sp_limit(limit);
+
+    // x86-64
+    #[cfg(all(target_arch = "x86_64",
+              any(target_os = "macos", target_os = "ios")))]
+    #[inline(always)]
+    unsafe fn target_record_sp_limit(limit: uint) {
+        asm!("movq $$0x60+90*8, %rsi
+              movq $0, %gs:(%rsi)" :: "r"(limit) : "rsi" : "volatile")
+    }
+    #[cfg(all(target_arch = "x86_64", target_os = "linux"))] #[inline(always)]
+    unsafe fn target_record_sp_limit(limit: uint) {
+        asm!("movq $0, %fs:112" :: "r"(limit) :: "volatile")
+    }
+    #[cfg(all(target_arch = "x86_64", target_os = "windows"))] #[inline(always)]
+    unsafe fn target_record_sp_limit(_: uint) {
+    }
+    #[cfg(all(target_arch = "x86_64", target_os = "freebsd"))] #[inline(always)]
+    unsafe fn target_record_sp_limit(limit: uint) {
+        asm!("movq $0, %fs:24" :: "r"(limit) :: "volatile")
+    }
+    #[cfg(all(target_arch = "x86_64", target_os = "dragonfly"))] #[inline(always)]
+    unsafe fn target_record_sp_limit(limit: uint) {
+        asm!("movq $0, %fs:32" :: "r"(limit) :: "volatile")
+    }
+
+    // x86
+    #[cfg(all(target_arch = "x86",
+              any(target_os = "macos", target_os = "ios")))]
+    #[inline(always)]
+    unsafe fn target_record_sp_limit(limit: uint) {
+        asm!("movl $$0x48+90*4, %eax
+              movl $0, %gs:(%eax)" :: "r"(limit) : "eax" : "volatile")
+    }
+    #[cfg(all(target_arch = "x86",
+              any(target_os = "linux", target_os = "freebsd")))]
+    #[inline(always)]
+    unsafe fn target_record_sp_limit(limit: uint) {
+        asm!("movl $0, %gs:48" :: "r"(limit) :: "volatile")
+    }
+    #[cfg(all(target_arch = "x86", target_os = "windows"))] #[inline(always)]
+    unsafe fn target_record_sp_limit(_: uint) {
+    }
+
+    // mips, arm - Some brave soul can port these to inline asm, but it's over
+    //             my head personally
+    #[cfg(any(target_arch = "mips",
+              target_arch = "mipsel",
+              all(target_arch = "arm", not(target_os = "ios"))))]
+    #[inline(always)]
+    unsafe fn target_record_sp_limit(limit: uint) {
+        use libc::c_void;
+        return record_sp_limit(limit as *const c_void);
+        extern {
+            fn record_sp_limit(limit: *const c_void);
+        }
+    }
+
+    // iOS segmented stack is disabled for now, see related notes
+    #[cfg(all(target_arch = "arm", target_os = "ios"))] #[inline(always)]
+    unsafe fn target_record_sp_limit(_: uint) {
+    }
+}
+
+/// The counterpart of the function above, this function will fetch the current
+/// stack limit stored in TLS.
+///
+/// Note that all of these functions are meant to be exact counterparts of their
+/// brethren above, except that the operands are reversed.
+///
+/// As with the setter, this function does not have a __morestack header and can
+/// therefore be called in a "we're out of stack" situation.
+#[inline(always)]
+pub unsafe fn get_sp_limit() -> uint {
+    return target_get_sp_limit();
+
+    // x86-64
+    #[cfg(all(target_arch = "x86_64",
+              any(target_os = "macos", target_os = "ios")))]
+    #[inline(always)]
+    unsafe fn target_get_sp_limit() -> uint {
+        let limit;
+        asm!("movq $$0x60+90*8, %rsi
+              movq %gs:(%rsi), $0" : "=r"(limit) :: "rsi" : "volatile");
+        return limit;
+    }
+    #[cfg(all(target_arch = "x86_64", target_os = "linux"))] #[inline(always)]
+    unsafe fn target_get_sp_limit() -> uint {
+        let limit;
+        asm!("movq %fs:112, $0" : "=r"(limit) ::: "volatile");
+        return limit;
+    }
+    #[cfg(all(target_arch = "x86_64", target_os = "windows"))] #[inline(always)]
+    unsafe fn target_get_sp_limit() -> uint {
+        return 1024;
+    }
+    #[cfg(all(target_arch = "x86_64", target_os = "freebsd"))] #[inline(always)]
+    unsafe fn target_get_sp_limit() -> uint {
+        let limit;
+        asm!("movq %fs:24, $0" : "=r"(limit) ::: "volatile");
+        return limit;
+    }
+    #[cfg(all(target_arch = "x86_64", target_os = "dragonfly"))] #[inline(always)]
+    unsafe fn target_get_sp_limit() -> uint {
+        let limit;
+        asm!("movq %fs:32, $0" : "=r"(limit) ::: "volatile");
+        return limit;
+    }
+
+
+    // x86
+    #[cfg(all(target_arch = "x86",
+              any(target_os = "macos", target_os = "ios")))]
+    #[inline(always)]
+    unsafe fn target_get_sp_limit() -> uint {
+        let limit;
+        asm!("movl $$0x48+90*4, %eax
+              movl %gs:(%eax), $0" : "=r"(limit) :: "eax" : "volatile");
+        return limit;
+    }
+    #[cfg(all(target_arch = "x86",
+              any(target_os = "linux", target_os = "freebsd")))]
+    #[inline(always)]
+    unsafe fn target_get_sp_limit() -> uint {
+        let limit;
+        asm!("movl %gs:48, $0" : "=r"(limit) ::: "volatile");
+        return limit;
+    }
+    #[cfg(all(target_arch = "x86", target_os = "windows"))] #[inline(always)]
+    unsafe fn target_get_sp_limit() -> uint {
+        return 1024;
+    }
+
+    // mips, arm - Some brave soul can port these to inline asm, but it's over
+    //             my head personally
+    #[cfg(any(target_arch = "mips",
+              target_arch = "mipsel",
+              all(target_arch = "arm", not(target_os = "ios"))))]
+    #[inline(always)]
+    unsafe fn target_get_sp_limit() -> uint {
+        use libc::c_void;
+        return get_sp_limit() as uint;
+        extern {
+            fn get_sp_limit() -> *const c_void;
+        }
+    }
+
+    // iOS doesn't support segmented stacks yet. This function might
+    // be called by runtime though so it is unsafe to mark it as
+    // unreachable, let's return a fixed constant.
+    #[cfg(all(target_arch = "arm", target_os = "ios"))] #[inline(always)]
+    unsafe fn target_get_sp_limit() -> uint {
+        1024
+    }
+}
diff --git a/src/libstd/sys/common/thread.rs b/src/libstd/sys/common/thread.rs
new file mode 100644
index 00000000000..048e33399a3
--- /dev/null
+++ b/src/libstd/sys/common/thread.rs
@@ -0,0 +1,35 @@
+// Copyright 2014 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::prelude::*;
+
+use boxed::Box;
+use mem;
+use uint;
+use libc;
+use thunk::Thunk;
+use sys_common::stack;
+use sys::{thread, stack_overflow};
+
+// This is the starting point of rust os threads. The first thing we do
+// is make sure that we don't trigger __morestack (also why this has a
+// no_stack_check annotation), and then we extract the main function
+// and invoke it.
+#[no_stack_check]
+pub fn start_thread(main: *mut libc::c_void) -> thread::rust_thread_return {
+    unsafe {
+        stack::record_os_managed_stack_bounds(0, uint::MAX);
+        let handler = stack_overflow::Handler::new();
+        let f: Box<Thunk> = mem::transmute(main);
+        f.invoke(());
+        drop(handler);
+        mem::transmute(0 as thread::rust_thread_return)
+    }
+}
diff --git a/src/libstd/sys/common/thread_info.rs b/src/libstd/sys/common/thread_info.rs
new file mode 100644
index 00000000000..dc21feb17a8
--- /dev/null
+++ b/src/libstd/sys/common/thread_info.rs
@@ -0,0 +1,68 @@
+// Copyright 2014 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::prelude::*;
+
+use thread::Thread;
+use cell::RefCell;
+use string::String;
+
+struct ThreadInfo {
+    // This field holds the known bounds of the stack in (lo, hi)
+    // form. Not all threads necessarily know their precise bounds,
+    // hence this is optional.
+    stack_bounds: (uint, uint),
+    stack_guard: uint,
+    thread: Thread,
+}
+
+thread_local! { static THREAD_INFO: RefCell<Option<ThreadInfo>> = RefCell::new(None) }
+
+impl ThreadInfo {
+    fn with<R>(f: |&mut ThreadInfo| -> R) -> R {
+        if THREAD_INFO.destroyed() {
+            panic!("Use of std::thread::Thread::current() is not possible after \
+                    the thread's local data has been destroyed");
+        }
+
+        THREAD_INFO.with(|c| {
+            if c.borrow().is_none() {
+                *c.borrow_mut() = Some(ThreadInfo {
+                    stack_bounds: (0, 0),
+                    stack_guard: 0,
+                    thread: NewThread::new(None),
+                })
+            }
+            f(c.borrow_mut().as_mut().unwrap())
+        })
+    }
+}
+
+pub fn current_thread() -> Thread {
+    ThreadInfo::with(|info| info.thread.clone())
+}
+
+pub fn stack_guard() -> uint {
+    ThreadInfo::with(|info| info.stack_guard)
+}
+
+pub fn set(stack_bounds: (uint, uint), stack_guard: uint, thread: Thread) {
+    THREAD_INFO.with(|c| assert!(c.borrow().is_none()));
+    THREAD_INFO.with(move |c| *c.borrow_mut() = Some(ThreadInfo{
+        stack_bounds: stack_bounds,
+        stack_guard: stack_guard,
+        thread: thread,
+    }));
+}
+
+// a hack to get around privacy restrictions; implemented by `std::thread::Thread`
+pub trait NewThread {
+    fn new(name: Option<String>) -> Self;
+}
diff --git a/src/libstd/sys/common/thread_local.rs b/src/libstd/sys/common/thread_local.rs
new file mode 100644
index 00000000000..fe7a7d8d037
--- /dev/null
+++ b/src/libstd/sys/common/thread_local.rs
@@ -0,0 +1,284 @@
+// Copyright 2014 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.
+
+//! OS-based thread local storage
+//!
+//! This module provides an implementation of OS-based thread local storage,
+//! using the native OS-provided facilities (think `TlsAlloc` or
+//! `pthread_setspecific`). The interface of this differs from the other types
+//! of thread-local-storage provided in this crate in that OS-based TLS can only
+//! get/set pointers,
+//!
+//! This module also provides two flavors of TLS. One is intended for static
+//! initialization, and does not contain a `Drop` implementation to deallocate
+//! the OS-TLS key. The other is a type which does implement `Drop` and hence
+//! has a safe interface.
+//!
+//! # Usage
+//!
+//! This module should likely not be used directly unless other primitives are
+//! being built on. types such as `thread_local::scoped::Key` are likely much
+//! more useful in practice than this OS-based version which likely requires
+//! unsafe code to interoperate with.
+//!
+//! # Example
+//!
+//! Using a dynamically allocated TLS key. Note that this key can be shared
+//! among many threads via an `Arc`.
+//!
+//! ```rust,ignore
+//! let key = Key::new(None);
+//! assert!(key.get().is_null());
+//! key.set(1 as *mut u8);
+//! assert!(!key.get().is_null());
+//!
+//! drop(key); // deallocate this TLS slot.
+//! ```
+//!
+//! Sometimes a statically allocated key is either required or easier to work
+//! with, however.
+//!
+//! ```rust,ignore
+//! static KEY: StaticKey = INIT;
+//!
+//! unsafe {
+//!     assert!(KEY.get().is_null());
+//!     KEY.set(1 as *mut u8);
+//! }
+//! ```
+
+#![allow(non_camel_case_types)]
+
+use prelude::*;
+
+use sync::atomic::{mod, AtomicUint};
+use sync::{Mutex, Once, ONCE_INIT};
+
+use sys::thread_local as imp;
+
+/// A type for TLS keys that are statically allocated.
+///
+/// This type is entirely `unsafe` to use as it does not protect against
+/// use-after-deallocation or use-during-deallocation.
+///
+/// The actual OS-TLS key is lazily allocated when this is used for the first
+/// time. The key is also deallocated when the Rust runtime exits or `destroy`
+/// is called, whichever comes first.
+///
+/// # Example
+///
+/// ```ignore
+/// use tls::os::{StaticKey, INIT};
+///
+/// static KEY: StaticKey = INIT;
+///
+/// unsafe {
+///     assert!(KEY.get().is_null());
+///     KEY.set(1 as *mut u8);
+/// }
+/// ```
+pub struct StaticKey {
+    /// Inner static TLS key (internals), created with by `INIT_INNER` in this
+    /// module.
+    pub inner: StaticKeyInner,
+    /// Destructor for the TLS value.
+    ///
+    /// See `Key::new` for information about when the destructor runs and how
+    /// it runs.
+    pub dtor: Option<unsafe extern fn(*mut u8)>,
+}
+
+/// Inner contents of `StaticKey`, created by the `INIT_INNER` constant.
+pub struct StaticKeyInner {
+    key: AtomicUint,
+}
+
+/// A type for a safely managed OS-based TLS slot.
+///
+/// This type allocates an OS TLS key when it is initialized and will deallocate
+/// the key when it falls out of scope. When compared with `StaticKey`, this
+/// type is entirely safe to use.
+///
+/// Implementations will likely, however, contain unsafe code as this type only
+/// operates on `*mut u8`, an unsafe pointer.
+///
+/// # Example
+///
+/// ```rust,ignore
+/// use tls::os::Key;
+///
+/// let key = Key::new(None);
+/// assert!(key.get().is_null());
+/// key.set(1 as *mut u8);
+/// assert!(!key.get().is_null());
+///
+/// drop(key); // deallocate this TLS slot.
+/// ```
+pub struct Key {
+    key: imp::Key,
+}
+
+/// Constant initialization value for static TLS keys.
+///
+/// This value specifies no destructor by default.
+pub const INIT: StaticKey = StaticKey {
+    inner: INIT_INNER,
+    dtor: None,
+};
+
+/// Constant initialization value for the inner part of static TLS keys.
+///
+/// This value allows specific configuration of the destructor for a TLS key.
+pub const INIT_INNER: StaticKeyInner = StaticKeyInner {
+    key: atomic::INIT_ATOMIC_UINT,
+};
+
+static INIT_KEYS: Once = ONCE_INIT;
+static mut KEYS: *mut Mutex<Vec<imp::Key>> = 0 as *mut _;
+
+impl StaticKey {
+    /// Gets the value associated with this TLS key
+    ///
+    /// This will lazily allocate a TLS key from the OS if one has not already
+    /// been allocated.
+    #[inline]
+    pub unsafe fn get(&self) -> *mut u8 { imp::get(self.key()) }
+
+    /// Sets this TLS key to a new value.
+    ///
+    /// This will lazily allocate a TLS key from the OS if one has not already
+    /// been allocated.
+    #[inline]
+    pub unsafe fn set(&self, val: *mut u8) { imp::set(self.key(), val) }
+
+    /// Deallocates this OS TLS key.
+    ///
+    /// This function is unsafe as there is no guarantee that the key is not
+    /// currently in use by other threads or will not ever be used again.
+    ///
+    /// Note that this does *not* run the user-provided destructor if one was
+    /// specified at definition time. Doing so must be done manually.
+    pub unsafe fn destroy(&self) {
+        match self.inner.key.swap(0, atomic::SeqCst) {
+            0 => {}
+            n => { imp::destroy(n as imp::Key) }
+        }
+    }
+
+    #[inline]
+    unsafe fn key(&self) -> imp::Key {
+        match self.inner.key.load(atomic::Relaxed) {
+            0 => self.lazy_init() as imp::Key,
+            n => n as imp::Key
+        }
+    }
+
+    unsafe fn lazy_init(&self) -> uint {
+        // POSIX allows the key created here to be 0, but the compare_and_swap
+        // below relies on using 0 as a sentinel value to check who won the
+        // race to set the shared TLS key. As far as I know, there is no
+        // guaranteed value that cannot be returned as a posix_key_create key,
+        // so there is no value we can initialize the inner key with to
+        // prove that it has not yet been set. As such, we'll continue using a
+        // value of 0, but with some gyrations to make sure we have a non-0
+        // value returned from the creation routine.
+        // FIXME: this is clearly a hack, and should be cleaned up.
+        let key1 = imp::create(self.dtor);
+        let key = if key1 != 0 {
+            key1
+        } else {
+            let key2 = imp::create(self.dtor);
+            imp::destroy(key1);
+            key2
+        };
+        assert!(key != 0);
+        match self.inner.key.compare_and_swap(0, key as uint, atomic::SeqCst) {
+            // The CAS succeeded, so we've created the actual key
+            0 => key as uint,
+            // If someone beat us to the punch, use their key instead
+            n => { imp::destroy(key); n }
+        }
+    }
+}
+
+impl Key {
+    /// Create a new managed OS TLS key.
+    ///
+    /// This key will be deallocated when the key falls out of scope.
+    ///
+    /// The argument provided is an optionally-specified destructor for the
+    /// value of this TLS key. When a thread exits and the value for this key
+    /// is non-null the destructor will be invoked. The TLS value will be reset
+    /// to null before the destructor is invoked.
+    ///
+    /// Note that the destructor will not be run when the `Key` goes out of
+    /// scope.
+    #[inline]
+    pub fn new(dtor: Option<unsafe extern fn(*mut u8)>) -> Key {
+        Key { key: unsafe { imp::create(dtor) } }
+    }
+
+    /// See StaticKey::get
+    #[inline]
+    pub fn get(&self) -> *mut u8 {
+        unsafe { imp::get(self.key) }
+    }
+
+    /// See StaticKey::set
+    #[inline]
+    pub fn set(&self, val: *mut u8) {
+        unsafe { imp::set(self.key, val) }
+    }
+}
+
+impl Drop for Key {
+    fn drop(&mut self) {
+        unsafe { imp::destroy(self.key) }
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use prelude::*;
+    use super::{Key, StaticKey, INIT_INNER};
+
+    fn assert_sync<T: Sync>() {}
+    fn assert_send<T: Send>() {}
+
+    #[test]
+    fn smoke() {
+        assert_sync::<Key>();
+        assert_send::<Key>();
+
+        let k1 = Key::new(None);
+        let k2 = Key::new(None);
+        assert!(k1.get().is_null());
+        assert!(k2.get().is_null());
+        k1.set(1 as *mut _);
+        k2.set(2 as *mut _);
+        assert_eq!(k1.get() as uint, 1);
+        assert_eq!(k2.get() as uint, 2);
+    }
+
+    #[test]
+    fn statik() {
+        static K1: StaticKey = StaticKey { inner: INIT_INNER, dtor: None };
+        static K2: StaticKey = StaticKey { inner: INIT_INNER, dtor: None };
+
+        unsafe {
+            assert!(K1.get().is_null());
+            assert!(K2.get().is_null());
+            K1.set(1 as *mut _);
+            K2.set(2 as *mut _);
+            assert_eq!(K1.get() as uint, 1);
+            assert_eq!(K2.get() as uint, 2);
+        }
+    }
+}
diff --git a/src/libstd/sys/unix/backtrace.rs b/src/libstd/sys/unix/backtrace.rs
new file mode 100644
index 00000000000..983d0e5fa14
--- /dev/null
+++ b/src/libstd/sys/unix/backtrace.rs
@@ -0,0 +1,493 @@
+// Copyright 2014 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.
+
+/// Backtrace support built on libgcc with some extra OS-specific support
+///
+/// Some methods of getting a backtrace:
+///
+/// * The backtrace() functions on unix. It turns out this doesn't work very
+///   well for green threads on OSX, and the address to symbol portion of it
+///   suffers problems that are described below.
+///
+/// * Using libunwind. This is more difficult than it sounds because libunwind
+///   isn't installed everywhere by default. It's also a bit of a hefty library,
+///   so possibly not the best option. When testing, libunwind was excellent at
+///   getting both accurate backtraces and accurate symbols across platforms.
+///   This route was not chosen in favor of the next option, however.
+///
+/// * We're already using libgcc_s for exceptions in rust (triggering task
+///   unwinding and running destructors on the stack), and it turns out that it
+///   conveniently comes with a function that also gives us a backtrace. All of
+///   these functions look like _Unwind_*, but it's not quite the full
+///   repertoire of the libunwind API. Due to it already being in use, this was
+///   the chosen route of getting a backtrace.
+///
+/// After choosing libgcc_s for backtraces, the sad part is that it will only
+/// give us a stack trace of instruction pointers. Thankfully these instruction
+/// pointers are accurate (they work for green and native threads), but it's
+/// then up to us again to figure out how to translate these addresses to
+/// symbols. As with before, we have a few options. Before, that, a little bit
+/// of an interlude about symbols. This is my very limited knowledge about
+/// symbol tables, and this information is likely slightly wrong, but the
+/// general idea should be correct.
+///
+/// When talking about symbols, it's helpful to know a few things about where
+/// symbols are located. Some symbols are located in the dynamic symbol table
+/// of the executable which in theory means that they're available for dynamic
+/// linking and lookup. Other symbols end up only in the local symbol table of
+/// the file. This loosely corresponds to pub and priv functions in Rust.
+///
+/// Armed with this knowledge, we know that our solution for address to symbol
+/// translation will need to consult both the local and dynamic symbol tables.
+/// With that in mind, here's our options of translating an address to
+/// a symbol.
+///
+/// * Use dladdr(). The original backtrace()-based idea actually uses dladdr()
+///   behind the scenes to translate, and this is why backtrace() was not used.
+///   Conveniently, this method works fantastically on OSX. It appears dladdr()
+///   uses magic to consult the local symbol table, or we're putting everything
+///   in the dynamic symbol table anyway. Regardless, for OSX, this is the
+///   method used for translation. It's provided by the system and easy to do.o
+///
+///   Sadly, all other systems have a dladdr() implementation that does not
+///   consult the local symbol table. This means that most functions are blank
+///   because they don't have symbols. This means that we need another solution.
+///
+/// * Use unw_get_proc_name(). This is part of the libunwind api (not the
+///   libgcc_s version of the libunwind api), but involves taking a dependency
+///   to libunwind. We may pursue this route in the future if we bundle
+///   libunwind, but libunwind was unwieldy enough that it was not chosen at
+///   this time to provide this functionality.
+///
+/// * Shell out to a utility like `readelf`. Crazy though it may sound, it's a
+///   semi-reasonable solution. The stdlib already knows how to spawn processes,
+///   so in theory it could invoke readelf, parse the output, and consult the
+///   local/dynamic symbol tables from there. This ended up not getting chosen
+///   due to the craziness of the idea plus the advent of the next option.
+///
+/// * Use `libbacktrace`. It turns out that this is a small library bundled in
+///   the gcc repository which provides backtrace and symbol translation
+///   functionality. All we really need from it is the backtrace functionality,
+///   and we only really need this on everything that's not OSX, so this is the
+///   chosen route for now.
+///
+/// In summary, the current situation uses libgcc_s to get a trace of stack
+/// pointers, and we use dladdr() or libbacktrace to translate these addresses
+/// to symbols. This is a bit of a hokey implementation as-is, but it works for
+/// all unix platforms we support right now, so it at least gets the job done.
+
+use c_str::CString;
+use io::{IoResult, Writer};
+use libc;
+use mem;
+use option::Option::{mod, Some, None};
+use result::Result::{Ok, Err};
+use sync::{StaticMutex, MUTEX_INIT};
+
+use sys_common::backtrace::*;
+
+/// As always - iOS on arm uses SjLj exceptions and
+/// _Unwind_Backtrace is even not available there. Still,
+/// backtraces could be extracted using a backtrace function,
+/// which thanks god is public
+///
+/// As mentioned in a huge comment block above, backtrace doesn't
+/// play well with green threads, so while it is extremely nice
+/// and simple to use it should be used only on iOS devices as the
+/// only viable option.
+#[cfg(all(target_os = "ios", target_arch = "arm"))]
+#[inline(never)]
+pub fn write(w: &mut Writer) -> IoResult<()> {
+    use iter::{IteratorExt, range};
+    use result;
+    use slice::SliceExt;
+
+    extern {
+        fn backtrace(buf: *mut *mut libc::c_void,
+                     sz: libc::c_int) -> libc::c_int;
+    }
+
+    // while it doesn't requires lock for work as everything is
+    // local, it still displays much nicer backtraces when a
+    // couple of tasks panic simultaneously
+    static LOCK: StaticMutex = MUTEX_INIT;
+    let _g = unsafe { LOCK.lock() };
+
+    try!(writeln!(w, "stack backtrace:"));
+    // 100 lines should be enough
+    const SIZE: uint = 100;
+    let mut buf: [*mut libc::c_void, ..SIZE] = unsafe {mem::zeroed()};
+    let cnt = unsafe { backtrace(buf.as_mut_ptr(), SIZE as libc::c_int) as uint};
+
+    // skipping the first one as it is write itself
+    let iter = range(1, cnt).map(|i| {
+        print(w, i as int, buf[i])
+    });
+    result::fold(iter, (), |_, _| ())
+}
+
+#[cfg(not(all(target_os = "ios", target_arch = "arm")))]
+#[inline(never)] // if we know this is a function call, we can skip it when
+                 // tracing
+pub fn write(w: &mut Writer) -> IoResult<()> {
+    use io::IoError;
+
+    struct Context<'a> {
+        idx: int,
+        writer: &'a mut (Writer+'a),
+        last_error: Option<IoError>,
+    }
+
+    // When using libbacktrace, we use some necessary global state, so we
+    // need to prevent more than one thread from entering this block. This
+    // is semi-reasonable in terms of printing anyway, and we know that all
+    // I/O done here is blocking I/O, not green I/O, so we don't have to
+    // worry about this being a native vs green mutex.
+    static LOCK: StaticMutex = MUTEX_INIT;
+    let _g = unsafe { LOCK.lock() };
+
+    try!(writeln!(w, "stack backtrace:"));
+
+    let mut cx = Context { writer: w, last_error: None, idx: 0 };
+    return match unsafe {
+        uw::_Unwind_Backtrace(trace_fn,
+                              &mut cx as *mut Context as *mut libc::c_void)
+    } {
+        uw::_URC_NO_REASON => {
+            match cx.last_error {
+                Some(err) => Err(err),
+                None => Ok(())
+            }
+        }
+        _ => Ok(()),
+    };
+
+    extern fn trace_fn(ctx: *mut uw::_Unwind_Context,
+                       arg: *mut libc::c_void) -> uw::_Unwind_Reason_Code {
+        let cx: &mut Context = unsafe { mem::transmute(arg) };
+        let ip = unsafe { uw::_Unwind_GetIP(ctx) as *mut libc::c_void };
+        // dladdr() on osx gets whiny when we use FindEnclosingFunction, and
+        // it appears to work fine without it, so we only use
+        // FindEnclosingFunction on non-osx platforms. In doing so, we get a
+        // slightly more accurate stack trace in the process.
+        //
+        // This is often because panic involves the last instruction of a
+        // function being "call std::rt::begin_unwind", with no ret
+        // instructions after it. This means that the return instruction
+        // pointer points *outside* of the calling function, and by
+        // unwinding it we go back to the original function.
+        let ip = if cfg!(target_os = "macos") || cfg!(target_os = "ios") {
+            ip
+        } else {
+            unsafe { uw::_Unwind_FindEnclosingFunction(ip) }
+        };
+
+        // Don't print out the first few frames (they're not user frames)
+        cx.idx += 1;
+        if cx.idx <= 0 { return uw::_URC_NO_REASON }
+        // Don't print ginormous backtraces
+        if cx.idx > 100 {
+            match write!(cx.writer, " ... <frames omitted>\n") {
+                Ok(()) => {}
+                Err(e) => { cx.last_error = Some(e); }
+            }
+            return uw::_URC_FAILURE
+        }
+
+        // Once we hit an error, stop trying to print more frames
+        if cx.last_error.is_some() { return uw::_URC_FAILURE }
+
+        match print(cx.writer, cx.idx, ip) {
+            Ok(()) => {}
+            Err(e) => { cx.last_error = Some(e); }
+        }
+
+        // keep going
+        return uw::_URC_NO_REASON
+    }
+}
+
+#[cfg(any(target_os = "macos", target_os = "ios"))]
+fn print(w: &mut Writer, idx: int, addr: *mut libc::c_void) -> IoResult<()> {
+    use intrinsics;
+    #[repr(C)]
+    struct Dl_info {
+        dli_fname: *const libc::c_char,
+        dli_fbase: *mut libc::c_void,
+        dli_sname: *const libc::c_char,
+        dli_saddr: *mut libc::c_void,
+    }
+    extern {
+        fn dladdr(addr: *const libc::c_void,
+                  info: *mut Dl_info) -> libc::c_int;
+    }
+
+    let mut info: Dl_info = unsafe { intrinsics::init() };
+    if unsafe { dladdr(addr as *const libc::c_void, &mut info) == 0 } {
+        output(w, idx,addr, None)
+    } else {
+        output(w, idx, addr, Some(unsafe {
+            CString::new(info.dli_sname, false)
+        }))
+    }
+}
+
+#[cfg(not(any(target_os = "macos", target_os = "ios")))]
+fn print(w: &mut Writer, idx: int, addr: *mut libc::c_void) -> IoResult<()> {
+    use iter::{Iterator, IteratorExt};
+    use os;
+    use path::GenericPath;
+    use ptr::RawPtr;
+    use ptr;
+    use slice::SliceExt;
+
+    ////////////////////////////////////////////////////////////////////////
+    // libbacktrace.h API
+    ////////////////////////////////////////////////////////////////////////
+    type backtrace_syminfo_callback =
+        extern "C" fn(data: *mut libc::c_void,
+                      pc: libc::uintptr_t,
+                      symname: *const libc::c_char,
+                      symval: libc::uintptr_t,
+                      symsize: libc::uintptr_t);
+    type backtrace_error_callback =
+        extern "C" fn(data: *mut libc::c_void,
+                      msg: *const libc::c_char,
+                      errnum: libc::c_int);
+    enum backtrace_state {}
+    #[link(name = "backtrace", kind = "static")]
+    #[cfg(not(test))]
+    extern {}
+
+    extern {
+        fn backtrace_create_state(filename: *const libc::c_char,
+                                  threaded: libc::c_int,
+                                  error: backtrace_error_callback,
+                                  data: *mut libc::c_void)
+                                        -> *mut backtrace_state;
+        fn backtrace_syminfo(state: *mut backtrace_state,
+                             addr: libc::uintptr_t,
+                             cb: backtrace_syminfo_callback,
+                             error: backtrace_error_callback,
+                             data: *mut libc::c_void) -> libc::c_int;
+    }
+
+    ////////////////////////////////////////////////////////////////////////
+    // helper callbacks
+    ////////////////////////////////////////////////////////////////////////
+
+    extern fn error_cb(_data: *mut libc::c_void, _msg: *const libc::c_char,
+                       _errnum: libc::c_int) {
+        // do nothing for now
+    }
+    extern fn syminfo_cb(data: *mut libc::c_void,
+                         _pc: libc::uintptr_t,
+                         symname: *const libc::c_char,
+                         _symval: libc::uintptr_t,
+                         _symsize: libc::uintptr_t) {
+        let slot = data as *mut *const libc::c_char;
+        unsafe { *slot = symname; }
+    }
+
+    // The libbacktrace API supports creating a state, but it does not
+    // support destroying a state. I personally take this to mean that a
+    // state is meant to be created and then live forever.
+    //
+    // I would love to register an at_exit() handler which cleans up this
+    // state, but libbacktrace provides no way to do so.
+    //
+    // With these constraints, this function has a statically cached state
+    // that is calculated the first time this is requested. Remember that
+    // backtracing all happens serially (one global lock).
+    //
+    // An additionally oddity in this function is that we initialize the
+    // filename via self_exe_name() to pass to libbacktrace. It turns out
+    // that on Linux libbacktrace seamlessly gets the filename of the
+    // current executable, but this fails on freebsd. by always providing
+    // it, we make sure that libbacktrace never has a reason to not look up
+    // the symbols. The libbacktrace API also states that the filename must
+    // be in "permanent memory", so we copy it to a static and then use the
+    // static as the pointer.
+    //
+    // FIXME: We also call self_exe_name() on DragonFly BSD. I haven't
+    //        tested if this is required or not.
+    unsafe fn init_state() -> *mut backtrace_state {
+        static mut STATE: *mut backtrace_state = 0 as *mut backtrace_state;
+        static mut LAST_FILENAME: [libc::c_char, ..256] = [0, ..256];
+        if !STATE.is_null() { return STATE }
+        let selfname = if cfg!(target_os = "freebsd") ||
+                          cfg!(target_os = "dragonfly") {
+            os::self_exe_name()
+        } else {
+            None
+        };
+        let filename = match selfname {
+            Some(path) => {
+                let bytes = path.as_vec();
+                if bytes.len() < LAST_FILENAME.len() {
+                    let i = bytes.iter();
+                    for (slot, val) in LAST_FILENAME.iter_mut().zip(i) {
+                        *slot = *val as libc::c_char;
+                    }
+                    LAST_FILENAME.as_ptr()
+                } else {
+                    ptr::null()
+                }
+            }
+            None => ptr::null(),
+        };
+        STATE = backtrace_create_state(filename, 0, error_cb,
+                                       ptr::null_mut());
+        return STATE
+    }
+
+    ////////////////////////////////////////////////////////////////////////
+    // translation
+    ////////////////////////////////////////////////////////////////////////
+
+    // backtrace errors are currently swept under the rug, only I/O
+    // errors are reported
+    let state = unsafe { init_state() };
+    if state.is_null() {
+        return output(w, idx, addr, None)
+    }
+    let mut data = 0 as *const libc::c_char;
+    let data_addr = &mut data as *mut *const libc::c_char;
+    let ret = unsafe {
+        backtrace_syminfo(state, addr as libc::uintptr_t,
+                          syminfo_cb, error_cb,
+                          data_addr as *mut libc::c_void)
+    };
+    if ret == 0 || data.is_null() {
+        output(w, idx, addr, None)
+    } else {
+        output(w, idx, addr, Some(unsafe { CString::new(data, false) }))
+    }
+}
+
+// Finally, after all that work above, we can emit a symbol.
+fn output(w: &mut Writer, idx: int, addr: *mut libc::c_void,
+          s: Option<CString>) -> IoResult<()> {
+    try!(write!(w, "  {:2}: {:2$} - ", idx, addr, HEX_WIDTH));
+    match s.as_ref().and_then(|c| c.as_str()) {
+        Some(string) => try!(demangle(w, string)),
+        None => try!(write!(w, "<unknown>")),
+    }
+    w.write(&['\n' as u8])
+}
+
+/// Unwind library interface used for backtraces
+///
+/// Note that dead code is allowed as here are just bindings
+/// iOS doesn't use all of them it but adding more
+/// platform-specific configs pollutes the code too much
+#[allow(non_camel_case_types)]
+#[allow(non_snake_case)]
+#[allow(dead_code)]
+mod uw {
+    pub use self::_Unwind_Reason_Code::*;
+
+    use libc;
+
+    #[repr(C)]
+    pub enum _Unwind_Reason_Code {
+        _URC_NO_REASON = 0,
+        _URC_FOREIGN_EXCEPTION_CAUGHT = 1,
+        _URC_FATAL_PHASE2_ERROR = 2,
+        _URC_FATAL_PHASE1_ERROR = 3,
+        _URC_NORMAL_STOP = 4,
+        _URC_END_OF_STACK = 5,
+        _URC_HANDLER_FOUND = 6,
+        _URC_INSTALL_CONTEXT = 7,
+        _URC_CONTINUE_UNWIND = 8,
+        _URC_FAILURE = 9, // used only by ARM EABI
+    }
+
+    pub enum _Unwind_Context {}
+
+    pub type _Unwind_Trace_Fn =
+            extern fn(ctx: *mut _Unwind_Context,
+                      arg: *mut libc::c_void) -> _Unwind_Reason_Code;
+
+    extern {
+        // No native _Unwind_Backtrace on iOS
+        #[cfg(not(all(target_os = "ios", target_arch = "arm")))]
+        pub fn _Unwind_Backtrace(trace: _Unwind_Trace_Fn,
+                                 trace_argument: *mut libc::c_void)
+                    -> _Unwind_Reason_Code;
+
+        #[cfg(all(not(target_os = "android"),
+                  not(all(target_os = "linux", target_arch = "arm"))))]
+        pub fn _Unwind_GetIP(ctx: *mut _Unwind_Context) -> libc::uintptr_t;
+
+        #[cfg(all(not(target_os = "android"),
+                  not(all(target_os = "linux", target_arch = "arm"))))]
+        pub fn _Unwind_FindEnclosingFunction(pc: *mut libc::c_void)
+            -> *mut libc::c_void;
+    }
+
+    // On android, the function _Unwind_GetIP is a macro, and this is the
+    // expansion of the macro. This is all copy/pasted directly from the
+    // header file with the definition of _Unwind_GetIP.
+    #[cfg(any(target_os = "android",
+              all(target_os = "linux", target_arch = "arm")))]
+    pub unsafe fn _Unwind_GetIP(ctx: *mut _Unwind_Context) -> libc::uintptr_t {
+        #[repr(C)]
+        enum _Unwind_VRS_Result {
+            _UVRSR_OK = 0,
+            _UVRSR_NOT_IMPLEMENTED = 1,
+            _UVRSR_FAILED = 2,
+        }
+        #[repr(C)]
+        enum _Unwind_VRS_RegClass {
+            _UVRSC_CORE = 0,
+            _UVRSC_VFP = 1,
+            _UVRSC_FPA = 2,
+            _UVRSC_WMMXD = 3,
+            _UVRSC_WMMXC = 4,
+        }
+        #[repr(C)]
+        enum _Unwind_VRS_DataRepresentation {
+            _UVRSD_UINT32 = 0,
+            _UVRSD_VFPX = 1,
+            _UVRSD_FPAX = 2,
+            _UVRSD_UINT64 = 3,
+            _UVRSD_FLOAT = 4,
+            _UVRSD_DOUBLE = 5,
+        }
+
+        type _Unwind_Word = libc::c_uint;
+        extern {
+            fn _Unwind_VRS_Get(ctx: *mut _Unwind_Context,
+                               klass: _Unwind_VRS_RegClass,
+                               word: _Unwind_Word,
+                               repr: _Unwind_VRS_DataRepresentation,
+                               data: *mut libc::c_void)
+                -> _Unwind_VRS_Result;
+        }
+
+        let mut val: _Unwind_Word = 0;
+        let ptr = &mut val as *mut _Unwind_Word;
+        let _ = _Unwind_VRS_Get(ctx, _Unwind_VRS_RegClass::_UVRSC_CORE, 15,
+                                _Unwind_VRS_DataRepresentation::_UVRSD_UINT32,
+                                ptr as *mut libc::c_void);
+        (val & !1) as libc::uintptr_t
+    }
+
+    // This function also doesn't exist on Android or ARM/Linux, so make it
+    // a no-op
+    #[cfg(any(target_os = "android",
+              all(target_os = "linux", target_arch = "arm")))]
+    pub unsafe fn _Unwind_FindEnclosingFunction(pc: *mut libc::c_void)
+        -> *mut libc::c_void
+    {
+        pc
+    }
+}
diff --git a/src/libstd/sys/unix/condvar.rs b/src/libstd/sys/unix/condvar.rs
new file mode 100644
index 00000000000..f64718539ef
--- /dev/null
+++ b/src/libstd/sys/unix/condvar.rs
@@ -0,0 +1,83 @@
+// Copyright 2014 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 libc;
+use sys::mutex::{mod, Mutex};
+use sys::sync as ffi;
+use time::Duration;
+
+pub struct Condvar { inner: UnsafeCell<ffi::pthread_cond_t> }
+
+pub const CONDVAR_INIT: Condvar = Condvar {
+    inner: UnsafeCell { value: ffi::PTHREAD_COND_INITIALIZER },
+};
+
+impl Condvar {
+    #[inline]
+    pub unsafe fn new() -> Condvar {
+        // Might be moved and address is changing it is better to avoid
+        // initialization of potentially opaque OS data before it landed
+        Condvar { inner: UnsafeCell::new(ffi::PTHREAD_COND_INITIALIZER) }
+    }
+
+    #[inline]
+    pub unsafe fn notify_one(&self) {
+        let r = ffi::pthread_cond_signal(self.inner.get());
+        debug_assert_eq!(r, 0);
+    }
+
+    #[inline]
+    pub unsafe fn notify_all(&self) {
+        let r = ffi::pthread_cond_broadcast(self.inner.get());
+        debug_assert_eq!(r, 0);
+    }
+
+    #[inline]
+    pub unsafe fn wait(&self, mutex: &Mutex) {
+        let r = ffi::pthread_cond_wait(self.inner.get(), mutex::raw(mutex));
+        debug_assert_eq!(r, 0);
+    }
+
+    pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
+        assert!(dur >= Duration::nanoseconds(0));
+
+        // First, figure out what time it currently is
+        let mut tv = libc::timeval { tv_sec: 0, tv_usec: 0 };
+        let r = ffi::gettimeofday(&mut tv, 0 as *mut _);
+        debug_assert_eq!(r, 0);
+
+        // Offset that time with the specified duration
+        let abs = Duration::seconds(tv.tv_sec as i64) +
+                  Duration::microseconds(tv.tv_usec as i64) +
+                  dur;
+        let ns = abs.num_nanoseconds().unwrap() as u64;
+        let timeout = libc::timespec {
+            tv_sec: (ns / 1000000000) as libc::time_t,
+            tv_nsec: (ns % 1000000000) as libc::c_long,
+        };
+
+        // And wait!
+        let r = ffi::pthread_cond_timedwait(self.inner.get(), mutex::raw(mutex),
+                                            &timeout);
+        if r != 0 {
+            debug_assert_eq!(r as int, libc::ETIMEDOUT as int);
+            false
+        } else {
+            true
+        }
+    }
+
+    #[inline]
+    pub unsafe fn destroy(&self) {
+        let r = ffi::pthread_cond_destroy(self.inner.get());
+        debug_assert_eq!(r, 0);
+    }
+}
diff --git a/src/libstd/sys/unix/ext.rs b/src/libstd/sys/unix/ext.rs
new file mode 100644
index 00000000000..ae3c939bf78
--- /dev/null
+++ b/src/libstd/sys/unix/ext.rs
@@ -0,0 +1,107 @@
+// Copyright 2014 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
+//!
+//! ```rust,ignore
+//! #![feature(globs)]
+//!
+//! use std::io::fs::File;
+//! use std::os::unix::prelude::*;
+//!
+//! fn main() {
+//!     let f = File::create(&Path::new("foo.txt")).unwrap();
+//!     let fd = f.as_raw_fd();
+//!
+//!     // use fd with native unix bindings
+//! }
+//! ```
+
+#![experimental]
+
+use sys_common::AsInner;
+use libc;
+
+use io;
+
+/// Raw file descriptors.
+pub type Fd = libc::c_int;
+
+/// Extract raw file descriptor
+pub trait AsRawFd {
+    /// Extract the raw file descriptor, without taking any ownership.
+    fn as_raw_fd(&self) -> Fd;
+}
+
+impl AsRawFd for io::fs::File {
+    fn as_raw_fd(&self) -> Fd {
+        self.as_inner().fd()
+    }
+}
+
+impl AsRawFd for io::pipe::PipeStream {
+    fn as_raw_fd(&self) -> Fd {
+        self.as_inner().fd()
+    }
+}
+
+impl AsRawFd for io::net::pipe::UnixStream {
+    fn as_raw_fd(&self) -> Fd {
+        self.as_inner().fd()
+    }
+}
+
+impl AsRawFd for io::net::pipe::UnixListener {
+    fn as_raw_fd(&self) -> Fd {
+        self.as_inner().fd()
+    }
+}
+
+impl AsRawFd for io::net::pipe::UnixAcceptor {
+    fn as_raw_fd(&self) -> Fd {
+        self.as_inner().fd()
+    }
+}
+
+impl AsRawFd for io::net::tcp::TcpStream {
+    fn as_raw_fd(&self) -> Fd {
+        self.as_inner().fd()
+    }
+}
+
+impl AsRawFd for io::net::tcp::TcpListener {
+    fn as_raw_fd(&self) -> Fd {
+        self.as_inner().fd()
+    }
+}
+
+impl AsRawFd for io::net::tcp::TcpAcceptor {
+    fn as_raw_fd(&self) -> Fd {
+        self.as_inner().fd()
+    }
+}
+
+impl AsRawFd for io::net::udp::UdpSocket {
+    fn as_raw_fd(&self) -> Fd {
+        self.as_inner().fd()
+    }
+}
+
+/// A prelude for conveniently writing platform-specific code.
+///
+/// Includes all extension traits, and some important type definitions.
+pub mod prelude {
+    pub use super::{Fd, AsRawFd};
+}
diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs
index 816876b5e4a..98d860f9646 100644
--- a/src/libstd/sys/unix/fs.rs
+++ b/src/libstd/sys/unix/fs.rs
@@ -18,14 +18,11 @@ use io;
 use prelude::*;
 
 use io::{FilePermission, Write, UnstableFileStat, Open, FileAccess, FileMode};
-use io::{IoResult, FileStat, SeekStyle, Reader};
+use io::{IoResult, FileStat, SeekStyle};
 use io::{Read, Truncate, SeekCur, SeekSet, ReadWrite, SeekEnd, Append};
-use result::{Ok, Err};
 use sys::retry;
 use sys_common::{keep_going, eof, mkerr_libc};
 
-pub use path::PosixPath as Path;
-
 pub type fd_t = libc::c_int;
 
 pub struct FileDesc {
@@ -201,7 +198,7 @@ pub fn readdir(p: &Path) -> IoResult<Vec<Path>> {
 
     let size = unsafe { rust_dirent_t_size() };
     let mut buf = Vec::<u8>::with_capacity(size as uint);
-    let ptr = buf.as_mut_slice().as_mut_ptr() as *mut dirent_t;
+    let ptr = buf.as_mut_ptr() as *mut dirent_t;
 
     let p = p.to_c_str();
     let dir_ptr = unsafe {opendir(p.as_ptr())};
@@ -305,12 +302,12 @@ fn mkstat(stat: &libc::stat) -> FileStat {
     FileStat {
         size: stat.st_size as u64,
         kind: match (stat.st_mode as libc::mode_t) & libc::S_IFMT {
-            libc::S_IFREG => io::TypeFile,
-            libc::S_IFDIR => io::TypeDirectory,
-            libc::S_IFIFO => io::TypeNamedPipe,
-            libc::S_IFBLK => io::TypeBlockSpecial,
-            libc::S_IFLNK => io::TypeSymlink,
-            _ => io::TypeUnknown,
+            libc::S_IFREG => io::FileType::RegularFile,
+            libc::S_IFDIR => io::FileType::Directory,
+            libc::S_IFIFO => io::FileType::NamedPipe,
+            libc::S_IFBLK => io::FileType::BlockSpecial,
+            libc::S_IFLNK => io::FileType::Symlink,
+            _ => io::FileType::Unknown,
         },
         perm: FilePermission::from_bits_truncate(stat.st_mode as u32),
         created: mktime(stat.st_ctime as u64, stat.st_ctime_nsec as u64),
diff --git a/src/libstd/sys/unix/mod.rs b/src/libstd/sys/unix/mod.rs
index 664a6a1e70c..f3babca3287 100644
--- a/src/libstd/sys/unix/mod.rs
+++ b/src/libstd/sys/unix/mod.rs
@@ -23,25 +23,36 @@ use prelude::*;
 use io::{mod, IoResult, IoError};
 use sys_common::mkerr_libc;
 
-macro_rules! helper_init( (static $name:ident: Helper<$m:ty>) => (
+macro_rules! helper_init { (static $name:ident: Helper<$m:ty>) => (
     static $name: Helper<$m> = Helper {
-        lock: ::rustrt::mutex::NATIVE_MUTEX_INIT,
+        lock: ::sync::MUTEX_INIT,
+        cond: ::sync::CONDVAR_INIT,
         chan: ::cell::UnsafeCell { value: 0 as *mut Sender<$m> },
         signal: ::cell::UnsafeCell { value: 0 },
         initialized: ::cell::UnsafeCell { value: false },
+        shutdown: ::cell::UnsafeCell { value: false },
     };
-) )
+) }
 
+pub mod backtrace;
 pub mod c;
+pub mod ext;
+pub mod condvar;
 pub mod fs;
+pub mod helper_signal;
+pub mod mutex;
 pub mod os;
-pub mod tcp;
-pub mod udp;
 pub mod pipe;
-pub mod helper_signal;
 pub mod process;
+pub mod rwlock;
+pub mod stack_overflow;
+pub mod sync;
+pub mod tcp;
+pub mod thread;
+pub mod thread_local;
 pub mod timer;
 pub mod tty;
+pub mod udp;
 
 pub mod addrinfo {
     pub use sys_common::net::get_host_addresses;
@@ -117,7 +128,10 @@ pub fn decode_error_detailed(errno: i32) -> IoError {
 }
 
 #[inline]
-pub fn retry<T: SignedInt> (f: || -> T) -> T {
+pub fn retry<T, F> (mut f: F) -> T where
+    T: SignedInt,
+    F: FnMut() -> T,
+{
     let one: T = Int::one();
     loop {
         let n = f();
diff --git a/src/libstd/sys/unix/mutex.rs b/src/libstd/sys/unix/mutex.rs
new file mode 100644
index 00000000000..2f01c53cb2c
--- /dev/null
+++ b/src/libstd/sys/unix/mutex.rs
@@ -0,0 +1,52 @@
+// Copyright 2014 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 sys::sync as ffi;
+use sys_common::mutex;
+
+pub struct Mutex { inner: UnsafeCell<ffi::pthread_mutex_t> }
+
+#[inline]
+pub unsafe fn raw(m: &Mutex) -> *mut ffi::pthread_mutex_t {
+    m.inner.get()
+}
+
+pub const MUTEX_INIT: Mutex = Mutex {
+    inner: UnsafeCell { value: ffi::PTHREAD_MUTEX_INITIALIZER },
+};
+
+impl Mutex {
+    #[inline]
+    pub unsafe fn new() -> Mutex {
+        // Might be moved and address is changing it is better to avoid
+        // initialization of potentially opaque OS data before it landed
+        MUTEX_INIT
+    }
+    #[inline]
+    pub unsafe fn lock(&self) {
+        let r = ffi::pthread_mutex_lock(self.inner.get());
+        debug_assert_eq!(r, 0);
+    }
+    #[inline]
+    pub unsafe fn unlock(&self) {
+        let r = ffi::pthread_mutex_unlock(self.inner.get());
+        debug_assert_eq!(r, 0);
+    }
+    #[inline]
+    pub unsafe fn try_lock(&self) -> bool {
+        ffi::pthread_mutex_trylock(self.inner.get()) == 0
+    }
+    #[inline]
+    pub unsafe fn destroy(&self) {
+        let r = ffi::pthread_mutex_destroy(self.inner.get());
+        debug_assert_eq!(r, 0);
+    }
+}
diff --git a/src/libstd/sys/unix/os.rs b/src/libstd/sys/unix/os.rs
index 4e495f043bc..316d97064ee 100644
--- a/src/libstd/sys/unix/os.rs
+++ b/src/libstd/sys/unix/os.rs
@@ -8,14 +8,24 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use libc;
-use libc::{c_int, c_char};
+//! Implementation of `std::os` functionality for unix systems
+
 use prelude::*;
-use io::IoResult;
+
+use error::{FromError, Error};
+use fmt;
+use io::{IoError, IoResult};
+use libc::{mod, c_int, c_char, c_void};
+use path::BytesContainer;
+use ptr;
+use sync::atomic::{AtomicInt, INIT_ATOMIC_INT, SeqCst};
 use sys::fs::FileDesc;
+use os;
 
 use os::TMPBUF_SZ;
 
+const BUF_BYTES : uint = 2048u;
+
 /// Returns the platform-specific value of errno
 pub fn errno() -> int {
     #[cfg(any(target_os = "macos",
@@ -98,7 +108,7 @@ pub fn error_string(errno: i32) -> String {
             panic!("strerror_r failure");
         }
 
-        ::string::raw::from_buf(p as *const u8)
+        String::from_raw_buf(p as *const u8)
     }
 }
 
@@ -110,3 +120,122 @@ pub unsafe fn pipe() -> IoResult<(FileDesc, FileDesc)> {
         Err(super::last_error())
     }
 }
+
+pub fn getcwd() -> IoResult<Path> {
+    use c_str::CString;
+
+    let mut buf = [0 as c_char, ..BUF_BYTES];
+    unsafe {
+        if libc::getcwd(buf.as_mut_ptr(), buf.len() as libc::size_t).is_null() {
+            Err(IoError::last_error())
+        } else {
+            Ok(Path::new(CString::new(buf.as_ptr(), false)))
+        }
+    }
+}
+
+pub unsafe fn get_env_pairs() -> Vec<Vec<u8>> {
+    use c_str::CString;
+
+    extern {
+        fn rust_env_pairs() -> *const *const c_char;
+    }
+    let mut environ = rust_env_pairs();
+    if environ as uint == 0 {
+        panic!("os::env() failure getting env string from OS: {}",
+               os::last_os_error());
+    }
+    let mut result = Vec::new();
+    while *environ != 0 as *const _ {
+        let env_pair =
+            CString::new(*environ, false).as_bytes_no_nul().to_vec();
+        result.push(env_pair);
+        environ = environ.offset(1);
+    }
+    result
+}
+
+pub fn split_paths(unparsed: &[u8]) -> Vec<Path> {
+    unparsed.split(|b| *b == b':').map(Path::new).collect()
+}
+
+pub fn join_paths<T: BytesContainer>(paths: &[T]) -> Result<Vec<u8>, &'static str> {
+    let mut joined = Vec::new();
+    let sep = b':';
+
+    for (i, path) in paths.iter().map(|p| p.container_as_bytes()).enumerate() {
+        if i > 0 { joined.push(sep) }
+        if path.contains(&sep) { return Err("path segment contains separator `:`") }
+        joined.push_all(path);
+    }
+
+    Ok(joined)
+}
+
+#[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
+pub fn load_self() -> Option<Vec<u8>> {
+    unsafe {
+        use libc::funcs::bsd44::*;
+        use libc::consts::os::extra::*;
+        let mut mib = vec![CTL_KERN as c_int,
+                           KERN_PROC as c_int,
+                           KERN_PROC_PATHNAME as c_int,
+                           -1 as c_int];
+        let mut sz: libc::size_t = 0;
+        let err = sysctl(mib.as_mut_ptr(), mib.len() as ::libc::c_uint,
+                         ptr::null_mut(), &mut sz, ptr::null_mut(),
+                         0u as libc::size_t);
+        if err != 0 { return None; }
+        if sz == 0 { return None; }
+        let mut v: Vec<u8> = Vec::with_capacity(sz as uint);
+        let err = sysctl(mib.as_mut_ptr(), mib.len() as ::libc::c_uint,
+                         v.as_mut_ptr() as *mut libc::c_void, &mut sz,
+                         ptr::null_mut(), 0u as libc::size_t);
+        if err != 0 { return None; }
+        if sz == 0 { return None; }
+        v.set_len(sz as uint - 1); // chop off trailing NUL
+        Some(v)
+    }
+}
+
+#[cfg(any(target_os = "linux", target_os = "android"))]
+pub fn load_self() -> Option<Vec<u8>> {
+    use std::io;
+
+    match io::fs::readlink(&Path::new("/proc/self/exe")) {
+        Ok(path) => Some(path.into_vec()),
+        Err(..) => None
+    }
+}
+
+#[cfg(any(target_os = "macos", target_os = "ios"))]
+pub fn load_self() -> Option<Vec<u8>> {
+    unsafe {
+        use libc::funcs::extra::_NSGetExecutablePath;
+        let mut sz: u32 = 0;
+        _NSGetExecutablePath(ptr::null_mut(), &mut sz);
+        if sz == 0 { return None; }
+        let mut v: Vec<u8> = Vec::with_capacity(sz as uint);
+        let err = _NSGetExecutablePath(v.as_mut_ptr() as *mut i8, &mut sz);
+        if err != 0 { return None; }
+        v.set_len(sz as uint - 1); // chop off trailing NUL
+        Some(v)
+    }
+}
+
+pub fn chdir(p: &Path) -> IoResult<()> {
+    p.with_c_str(|buf| {
+        unsafe {
+            match libc::chdir(buf) == (0 as c_int) {
+                true => Ok(()),
+                false => Err(IoError::last_error()),
+            }
+        }
+    })
+}
+
+pub fn page_size() -> uint {
+    unsafe {
+        libc::sysconf(libc::_SC_PAGESIZE) as uint
+    }
+}
diff --git a/src/libstd/sys/unix/pipe.rs b/src/libstd/sys/unix/pipe.rs
index 4d3469a9c24..348b7cfad33 100644
--- a/src/libstd/sys/unix/pipe.rs
+++ b/src/libstd/sys/unix/pipe.rs
@@ -12,14 +12,14 @@ use alloc::arc::Arc;
 use libc;
 use c_str::CString;
 use mem;
-use rustrt::mutex;
-use sync::atomic;
+use sync::{atomic, Mutex};
 use io::{mod, IoResult, IoError};
 use prelude::*;
 
 use sys::{mod, timer, retry, c, set_nonblocking, wouldblock};
 use sys::fs::{fd_t, FileDesc};
 use sys_common::net::*;
+use sys_common::net::SocketStatus::*;
 use sys_common::{eof, mkerr_libc};
 
 fn unix_socket(ty: libc::c_int) -> IoResult<fd_t> {
@@ -60,12 +60,12 @@ struct Inner {
 
     // Unused on Linux, where this lock is not necessary.
     #[allow(dead_code)]
-    lock: mutex::NativeMutex
+    lock: Mutex<()>,
 }
 
 impl Inner {
     fn new(fd: fd_t) -> Inner {
-        Inner { fd: fd, lock: unsafe { mutex::NativeMutex::new() } }
+        Inner { fd: fd, lock: Mutex::new(()) }
     }
 }
 
@@ -133,7 +133,7 @@ impl UnixStream {
         }
     }
 
-    fn fd(&self) -> fd_t { self.inner.fd }
+    pub fn fd(&self) -> fd_t { self.inner.fd }
 
     #[cfg(target_os = "linux")]
     fn lock_nonblocking(&self) {}
@@ -150,8 +150,8 @@ impl UnixStream {
 
     pub fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
         let fd = self.fd();
-        let dolock = || self.lock_nonblocking();
-        let doread = |nb| unsafe {
+        let dolock = |&:| self.lock_nonblocking();
+        let doread = |&mut: nb| unsafe {
             let flags = if nb {c::MSG_DONTWAIT} else {0};
             libc::recv(fd,
                        buf.as_mut_ptr() as *mut libc::c_void,
@@ -163,8 +163,8 @@ impl UnixStream {
 
     pub fn write(&mut self, buf: &[u8]) -> IoResult<()> {
         let fd = self.fd();
-        let dolock = || self.lock_nonblocking();
-        let dowrite = |nb: bool, buf: *const u8, len: uint| unsafe {
+        let dolock = |&: | self.lock_nonblocking();
+        let dowrite = |&: nb: bool, buf: *const u8, len: uint| unsafe {
             let flags = if nb {c::MSG_DONTWAIT} else {0};
             libc::send(fd,
                        buf as *const _,
@@ -222,7 +222,7 @@ impl UnixListener {
         })
     }
 
-    fn fd(&self) -> fd_t { self.inner.fd }
+    pub fn fd(&self) -> fd_t { self.inner.fd }
 
     pub fn listen(self) -> IoResult<UnixAcceptor> {
         match unsafe { libc::listen(self.fd(), 128) } {
@@ -260,7 +260,7 @@ struct AcceptorInner {
 }
 
 impl UnixAcceptor {
-    fn fd(&self) -> fd_t { self.inner.listener.fd() }
+    pub fn fd(&self) -> fd_t { self.inner.listener.fd() }
 
     pub fn accept(&mut self) -> IoResult<UnixStream> {
         let deadline = if self.deadline == 0 {None} else {Some(self.deadline)};
diff --git a/src/libstd/sys/unix/process.rs b/src/libstd/sys/unix/process.rs
index 81bc138ca91..835f4279d9b 100644
--- a/src/libstd/sys/unix/process.rs
+++ b/src/libstd/sys/unix/process.rs
@@ -11,7 +11,7 @@ use self::Req::*;
 
 use libc::{mod, pid_t, c_void, c_int};
 use c_str::CString;
-use io::{mod, IoResult, IoError};
+use io::{mod, IoResult, IoError, EndOfFile};
 use mem;
 use os;
 use ptr;
@@ -24,11 +24,11 @@ use hash::Hash;
 use sys::{mod, retry, c, wouldblock, set_nonblocking, ms_to_timeval};
 use sys::fs::FileDesc;
 use sys_common::helper_thread::Helper;
-use sys_common::{AsFileDesc, mkerr_libc, timeout};
+use sys_common::{AsInner, mkerr_libc, timeout};
 
 pub use sys_common::ProcessConfig;
 
-helper_init!(static HELPER: Helper<Req>)
+helper_init! { static HELPER: Helper<Req> }
 
 /// The unique id of the process (this should never be negative).
 pub struct Process {
@@ -39,6 +39,8 @@ enum Req {
     NewChild(libc::pid_t, Sender<ProcessExit>, u64),
 }
 
+const CLOEXEC_MSG_FOOTER: &'static [u8] = b"NOEX";
+
 impl Process {
     pub fn id(&self) -> pid_t {
         self.pid
@@ -56,7 +58,7 @@ impl Process {
     pub fn spawn<K, V, C, P>(cfg: &C, in_fd: Option<P>,
                               out_fd: Option<P>, err_fd: Option<P>)
                               -> IoResult<Process>
-        where C: ProcessConfig<K, V>, P: AsFileDesc,
+        where C: ProcessConfig<K, V>, P: AsInner<FileDesc>,
               K: BytesContainer + Eq + Hash, V: BytesContainer
     {
         use libc::funcs::posix88::unistd::{fork, dup2, close, chdir, execvp};
@@ -92,8 +94,8 @@ impl Process {
             mem::transmute::<&ProcessConfig<K,V>,&'static ProcessConfig<K,V>>(cfg)
         };
 
-        with_envp(cfg.env(), proc(envp) {
-            with_argv(cfg.program(), cfg.args(), proc(argv) unsafe {
+        with_envp(cfg.env(), move|: envp: *const c_void| {
+            with_argv(cfg.program(), cfg.args(), move|: argv: *const *const libc::c_char| unsafe {
                 let (input, mut output) = try!(sys::os::pipe());
 
                 // We may use this in the child, so perform allocations before the
@@ -106,18 +108,36 @@ impl Process {
                 if pid < 0 {
                     return Err(super::last_error())
                 } else if pid > 0 {
+                    #[inline]
+                    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
+                    }
+
+                    let p = Process{ pid: pid };
                     drop(output);
-                    let mut bytes = [0, ..4];
+                    let mut bytes = [0, ..8];
                     return match input.read(&mut bytes) {
-                        Ok(4) => {
-                            let errno = (bytes[0] as i32 << 24) |
-                                        (bytes[1] as i32 << 16) |
-                                        (bytes[2] as i32 <<  8) |
-                                        (bytes[3] as i32 <<  0);
+                        Ok(8) => {
+                            assert!(combine(CLOEXEC_MSG_FOOTER) == combine(bytes.slice(4, 8)),
+                                "Validation on the CLOEXEC pipe failed: {}", bytes);
+                            let errno = combine(bytes.slice(0, 4));
+                            assert!(p.wait(0).is_ok(), "wait(0) should either return Ok or panic");
                             Err(super::decode_error(errno))
                         }
-                        Err(..) => Ok(Process { pid: pid }),
-                        Ok(..) => panic!("short read on the cloexec pipe"),
+                        Err(ref e) if e.kind == EndOfFile => Ok(p),
+                        Err(e) => {
+                            assert!(p.wait(0).is_ok(), "wait(0) 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(0).is_ok(), "wait(0) should either return Ok or panic");
+                            panic!("short read on the CLOEXEC pipe")
+                        }
                     };
                 }
 
@@ -154,13 +174,16 @@ impl Process {
                 let _ = libc::close(input.fd());
 
                 fn fail(output: &mut FileDesc) -> ! {
-                    let errno = sys::os::errno();
+                    let errno = sys::os::errno() 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
                     assert!(output.write(&bytes).is_ok());
                     unsafe { libc::_exit(1) }
                 }
@@ -183,7 +206,7 @@ impl Process {
                             libc::open(devnull.as_ptr(), flags, 0)
                         }
                         Some(obj) => {
-                            let fd = obj.as_fd().fd();
+                            let fd = obj.as_inner().fd();
                             // Leak the memory and the file descriptor. We're in the
                             // child now an all our resources are going to be
                             // cleaned up very soon
@@ -356,8 +379,8 @@ impl Process {
                 // wait indefinitely for a message to arrive.
                 //
                 // FIXME: sure would be nice to not have to scan the entire array
-                let min = active.iter().map(|a| *a.ref2()).enumerate().min_by(|p| {
-                    p.val1()
+                let min = active.iter().map(|a| a.2).enumerate().min_by(|p| {
+                    p.1
                 });
                 let (p, idx) = match min {
                     Some((idx, deadline)) => {
@@ -508,8 +531,11 @@ impl Process {
     }
 }
 
-fn with_argv<T>(prog: &CString, args: &[CString],
-                cb: proc(*const *const libc::c_char) -> T) -> T {
+fn with_argv<T,F>(prog: &CString, args: &[CString],
+                  cb: F)
+                  -> T
+    where F : FnOnce(*const *const libc::c_char) -> T
+{
     let mut ptrs: Vec<*const libc::c_char> = Vec::with_capacity(args.len()+1);
 
     // Convert the CStrings into an array of pointers. Note: the
@@ -526,9 +552,12 @@ fn with_argv<T>(prog: &CString, args: &[CString],
     cb(ptrs.as_ptr())
 }
 
-fn with_envp<K, V, T>(env: Option<&collections::HashMap<K, V>>,
-                      cb: proc(*const c_void) -> T) -> T
-    where K: BytesContainer + Eq + Hash, V: BytesContainer
+fn with_envp<K,V,T,F>(env: Option<&collections::HashMap<K, V>>,
+                      cb: F)
+                      -> T
+    where F : FnOnce(*const c_void) -> T,
+          K : BytesContainer + Eq + Hash,
+          V : BytesContainer
 {
     // On posixy systems we can pass a char** for envp, which is a
     // null-terminated array of "k=v\0" strings. Since we must create
@@ -541,9 +570,9 @@ fn with_envp<K, V, T>(env: Option<&collections::HashMap<K, V>>,
 
             for pair in env.iter() {
                 let mut kv = Vec::new();
-                kv.push_all(pair.ref0().container_as_bytes());
+                kv.push_all(pair.0.container_as_bytes());
                 kv.push('=' as u8);
-                kv.push_all(pair.ref1().container_as_bytes());
+                kv.push_all(pair.1.container_as_bytes());
                 kv.push(0); // terminating null
                 tmps.push(kv);
             }
diff --git a/src/libstd/sys/unix/rwlock.rs b/src/libstd/sys/unix/rwlock.rs
new file mode 100644
index 00000000000..0d63ff14ff2
--- /dev/null
+++ b/src/libstd/sys/unix/rwlock.rs
@@ -0,0 +1,57 @@
+// Copyright 2014 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 sys::sync as ffi;
+
+pub struct RWLock { inner: UnsafeCell<ffi::pthread_rwlock_t> }
+
+pub const RWLOCK_INIT: RWLock = RWLock {
+    inner: UnsafeCell { value: ffi::PTHREAD_RWLOCK_INITIALIZER },
+};
+
+impl RWLock {
+    #[inline]
+    pub unsafe fn new() -> RWLock {
+        // Might be moved and address is changing it is better to avoid
+        // initialization of potentially opaque OS data before it landed
+        RWLOCK_INIT
+    }
+    #[inline]
+    pub unsafe fn read(&self) {
+        let r = ffi::pthread_rwlock_rdlock(self.inner.get());
+        debug_assert_eq!(r, 0);
+    }
+    #[inline]
+    pub unsafe fn try_read(&self) -> bool {
+        ffi::pthread_rwlock_tryrdlock(self.inner.get()) == 0
+    }
+    #[inline]
+    pub unsafe fn write(&self) {
+        let r = ffi::pthread_rwlock_wrlock(self.inner.get());
+        debug_assert_eq!(r, 0);
+    }
+    #[inline]
+    pub unsafe fn try_write(&self) -> bool {
+        ffi::pthread_rwlock_trywrlock(self.inner.get()) == 0
+    }
+    #[inline]
+    pub unsafe fn read_unlock(&self) {
+        let r = ffi::pthread_rwlock_unlock(self.inner.get());
+        debug_assert_eq!(r, 0);
+    }
+    #[inline]
+    pub unsafe fn write_unlock(&self) { self.read_unlock() }
+    #[inline]
+    pub unsafe fn destroy(&self) {
+        let r = ffi::pthread_rwlock_destroy(self.inner.get());
+        debug_assert_eq!(r, 0);
+    }
+}
diff --git a/src/libstd/sys/unix/stack_overflow.rs b/src/libstd/sys/unix/stack_overflow.rs
new file mode 100644
index 00000000000..340f9514241
--- /dev/null
+++ b/src/libstd/sys/unix/stack_overflow.rs
@@ -0,0 +1,277 @@
+// Copyright 2014 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 core::prelude::*;
+use self::imp::{make_handler, drop_handler};
+
+pub use self::imp::{init, cleanup};
+
+pub struct Handler {
+    _data: *mut libc::c_void
+}
+
+impl Handler {
+    pub unsafe fn new() -> Handler {
+        make_handler()
+    }
+}
+
+impl Drop for Handler {
+    fn drop(&mut self) {
+        unsafe {
+            drop_handler(self);
+        }
+    }
+}
+
+#[cfg(any(target_os = "linux", target_os = "macos"))]
+mod imp {
+    use core::prelude::*;
+    use sys_common::stack;
+
+    use super::Handler;
+    use rt::util::report_overflow;
+    use mem;
+    use ptr;
+    use intrinsics;
+    use self::signal::{siginfo, sigaction, SIGBUS, SIG_DFL,
+                       SA_SIGINFO, SA_ONSTACK, sigaltstack,
+                       SIGSTKSZ};
+    use libc;
+    use libc::funcs::posix88::mman::{mmap, munmap};
+    use libc::consts::os::posix88::{SIGSEGV,
+                                    PROT_READ,
+                                    PROT_WRITE,
+                                    MAP_PRIVATE,
+                                    MAP_ANON,
+                                    MAP_FAILED};
+
+    use sys_common::thread_info;
+
+
+    // This is initialized in init() and only read from after
+    static mut PAGE_SIZE: uint = 0;
+
+    #[no_stack_check]
+    unsafe extern fn signal_handler(signum: libc::c_int,
+                                     info: *mut siginfo,
+                                     _data: *mut libc::c_void) {
+
+        // We can not return from a SIGSEGV or SIGBUS signal.
+        // See: https://www.gnu.org/software/libc/manual/html_node/Handler-Returns.html
+
+        unsafe fn term(signum: libc::c_int) -> ! {
+            use core::mem::transmute;
+
+            signal(signum, transmute(SIG_DFL));
+            raise(signum);
+            intrinsics::abort();
+        }
+
+        // We're calling into functions with stack checks
+        stack::record_sp_limit(0);
+
+        let guard = thread_info::stack_guard();
+        let addr = (*info).si_addr as uint;
+
+        if guard == 0 || addr < guard - PAGE_SIZE || addr >= guard {
+            term(signum);
+        }
+
+        report_overflow();
+
+        intrinsics::abort()
+    }
+
+    static mut MAIN_ALTSTACK: *mut libc::c_void = 0 as *mut libc::c_void;
+
+    pub unsafe fn init() {
+        let psize = libc::sysconf(libc::consts::os::sysconf::_SC_PAGESIZE);
+        if psize == -1 {
+            panic!("failed to get page size");
+        }
+
+        PAGE_SIZE = psize as uint;
+
+        let mut action: sigaction = mem::zeroed();
+        action.sa_flags = SA_SIGINFO | SA_ONSTACK;
+        action.sa_sigaction = signal_handler as sighandler_t;
+        sigaction(SIGSEGV, &action, ptr::null_mut());
+        sigaction(SIGBUS, &action, ptr::null_mut());
+
+        let handler = make_handler();
+        MAIN_ALTSTACK = handler._data;
+        mem::forget(handler);
+    }
+
+    pub unsafe fn cleanup() {
+        Handler { _data: MAIN_ALTSTACK };
+    }
+
+    pub unsafe fn make_handler() -> Handler {
+        let alt_stack = mmap(ptr::null_mut(),
+                             signal::SIGSTKSZ,
+                             PROT_READ | PROT_WRITE,
+                             MAP_PRIVATE | MAP_ANON,
+                             -1,
+                             0);
+        if alt_stack == MAP_FAILED {
+            panic!("failed to allocate an alternative stack");
+        }
+
+        let mut stack: sigaltstack = mem::zeroed();
+
+        stack.ss_sp = alt_stack;
+        stack.ss_flags = 0;
+        stack.ss_size = SIGSTKSZ;
+
+        sigaltstack(&stack, ptr::null_mut());
+
+        Handler { _data: alt_stack }
+    }
+
+    pub unsafe fn drop_handler(handler: &mut Handler) {
+        munmap(handler._data, SIGSTKSZ);
+    }
+
+    type sighandler_t = *mut libc::c_void;
+
+    #[cfg(any(all(target_os = "linux", target_arch = "x86"), // may not match
+              all(target_os = "linux", target_arch = "x86_64"),
+              all(target_os = "linux", target_arch = "arm"), // may not match
+              all(target_os = "linux", target_arch = "mips"), // may not match
+              all(target_os = "linux", target_arch = "mipsel"), // may not match
+              target_os = "android"))] // may not match
+    mod signal {
+        use libc;
+        use super::sighandler_t;
+
+        pub static SA_ONSTACK: libc::c_int = 0x08000000;
+        pub static SA_SIGINFO: libc::c_int = 0x00000004;
+        pub static SIGBUS: libc::c_int = 7;
+
+        pub static SIGSTKSZ: libc::size_t = 8192;
+
+        pub static SIG_DFL: sighandler_t = 0i as sighandler_t;
+
+        // This definition is not as accurate as it could be, {si_addr} is
+        // actually a giant union. Currently we're only interested in that field,
+        // however.
+        #[repr(C)]
+        pub struct siginfo {
+            si_signo: libc::c_int,
+            si_errno: libc::c_int,
+            si_code: libc::c_int,
+            pub si_addr: *mut libc::c_void
+        }
+
+        #[repr(C)]
+        pub struct sigaction {
+            pub sa_sigaction: sighandler_t,
+            pub sa_mask: sigset_t,
+            pub sa_flags: libc::c_int,
+            sa_restorer: *mut libc::c_void,
+        }
+
+        #[cfg(target_word_size = "32")]
+        #[repr(C)]
+        pub struct sigset_t {
+            __val: [libc::c_ulong, ..32],
+        }
+        #[cfg(target_word_size = "64")]
+        #[repr(C)]
+        pub struct sigset_t {
+            __val: [libc::c_ulong, ..16],
+        }
+
+        #[repr(C)]
+        pub struct sigaltstack {
+            pub ss_sp: *mut libc::c_void,
+            pub ss_flags: libc::c_int,
+            pub ss_size: libc::size_t
+        }
+
+    }
+
+    #[cfg(target_os = "macos")]
+    mod signal {
+        use libc;
+        use super::sighandler_t;
+
+        pub const SA_ONSTACK: libc::c_int = 0x0001;
+        pub const SA_SIGINFO: libc::c_int = 0x0040;
+        pub const SIGBUS: libc::c_int = 10;
+
+        pub const SIGSTKSZ: libc::size_t = 131072;
+
+        pub const SIG_DFL: sighandler_t = 0i as sighandler_t;
+
+        pub type sigset_t = u32;
+
+        // This structure has more fields, but we're not all that interested in
+        // them.
+        #[repr(C)]
+        pub struct siginfo {
+            pub si_signo: libc::c_int,
+            pub si_errno: libc::c_int,
+            pub si_code: libc::c_int,
+            pub pid: libc::pid_t,
+            pub uid: libc::uid_t,
+            pub status: libc::c_int,
+            pub si_addr: *mut libc::c_void
+        }
+
+        #[repr(C)]
+        pub struct sigaltstack {
+            pub ss_sp: *mut libc::c_void,
+            pub ss_size: libc::size_t,
+            pub ss_flags: libc::c_int
+        }
+
+        #[repr(C)]
+        pub struct sigaction {
+            pub sa_sigaction: sighandler_t,
+            pub sa_mask: sigset_t,
+            pub sa_flags: libc::c_int,
+        }
+    }
+
+    extern {
+        pub fn signal(signum: libc::c_int, handler: sighandler_t) -> sighandler_t;
+        pub fn raise(signum: libc::c_int) -> libc::c_int;
+
+        pub fn sigaction(signum: libc::c_int,
+                         act: *const sigaction,
+                         oldact: *mut sigaction) -> libc::c_int;
+
+        pub fn sigaltstack(ss: *const sigaltstack,
+                           oss: *mut sigaltstack) -> libc::c_int;
+    }
+}
+
+#[cfg(not(any(target_os = "linux",
+              target_os = "macos")))]
+mod imp {
+    use libc;
+
+    pub unsafe fn init() {
+    }
+
+    pub unsafe fn cleanup() {
+    }
+
+    pub unsafe fn make_handler() -> super::Handler {
+        super::Handler { _data: 0i as *mut libc::c_void }
+    }
+
+    pub unsafe fn drop_handler(_handler: &mut super::Handler) {
+    }
+}
diff --git a/src/libstd/sys/unix/sync.rs b/src/libstd/sys/unix/sync.rs
new file mode 100644
index 00000000000..007826b4b9d
--- /dev/null
+++ b/src/libstd/sys/unix/sync.rs
@@ -0,0 +1,208 @@
+// Copyright 2014 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(bad_style)]
+
+use libc;
+
+pub use self::os::{PTHREAD_MUTEX_INITIALIZER, pthread_mutex_t};
+pub use self::os::{PTHREAD_COND_INITIALIZER, pthread_cond_t};
+pub use self::os::{PTHREAD_RWLOCK_INITIALIZER, pthread_rwlock_t};
+
+extern {
+    // mutexes
+    pub fn pthread_mutex_destroy(lock: *mut pthread_mutex_t) -> libc::c_int;
+    pub fn pthread_mutex_lock(lock: *mut pthread_mutex_t) -> libc::c_int;
+    pub fn pthread_mutex_trylock(lock: *mut pthread_mutex_t) -> libc::c_int;
+    pub fn pthread_mutex_unlock(lock: *mut pthread_mutex_t) -> libc::c_int;
+
+    // cvars
+    pub fn pthread_cond_wait(cond: *mut pthread_cond_t,
+                             lock: *mut pthread_mutex_t) -> libc::c_int;
+    pub fn pthread_cond_timedwait(cond: *mut pthread_cond_t,
+                              lock: *mut pthread_mutex_t,
+                              abstime: *const libc::timespec) -> libc::c_int;
+    pub fn pthread_cond_signal(cond: *mut pthread_cond_t) -> libc::c_int;
+    pub fn pthread_cond_broadcast(cond: *mut pthread_cond_t) -> libc::c_int;
+    pub fn pthread_cond_destroy(cond: *mut pthread_cond_t) -> libc::c_int;
+    pub fn gettimeofday(tp: *mut libc::timeval,
+                        tz: *mut libc::c_void) -> libc::c_int;
+
+    // rwlocks
+    pub fn pthread_rwlock_destroy(lock: *mut pthread_rwlock_t) -> libc::c_int;
+    pub fn pthread_rwlock_rdlock(lock: *mut pthread_rwlock_t) -> libc::c_int;
+    pub fn pthread_rwlock_tryrdlock(lock: *mut pthread_rwlock_t) -> libc::c_int;
+    pub fn pthread_rwlock_wrlock(lock: *mut pthread_rwlock_t) -> libc::c_int;
+    pub fn pthread_rwlock_trywrlock(lock: *mut pthread_rwlock_t) -> libc::c_int;
+    pub fn pthread_rwlock_unlock(lock: *mut pthread_rwlock_t) -> libc::c_int;
+}
+
+#[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
+mod os {
+    use libc;
+
+    pub type pthread_mutex_t = *mut libc::c_void;
+    pub type pthread_cond_t = *mut libc::c_void;
+    pub type pthread_rwlock_t = *mut libc::c_void;
+
+    pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = 0 as *mut _;
+    pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = 0 as *mut _;
+    pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = 0 as *mut _;
+}
+
+#[cfg(any(target_os = "macos", target_os = "ios"))]
+mod os {
+    use libc;
+
+    #[cfg(target_arch = "x86_64")]
+    const __PTHREAD_MUTEX_SIZE__: uint = 56;
+    #[cfg(any(target_arch = "x86",
+              target_arch = "arm"))]
+    const __PTHREAD_MUTEX_SIZE__: uint = 40;
+
+    #[cfg(target_arch = "x86_64")]
+    const __PTHREAD_COND_SIZE__: uint = 40;
+    #[cfg(any(target_arch = "x86",
+              target_arch = "arm"))]
+    const __PTHREAD_COND_SIZE__: uint = 24;
+
+    #[cfg(target_arch = "x86_64")]
+    const __PTHREAD_RWLOCK_SIZE__: uint = 192;
+    #[cfg(any(target_arch = "x86",
+              target_arch = "arm"))]
+    const __PTHREAD_RWLOCK_SIZE__: uint = 124;
+
+    const _PTHREAD_MUTEX_SIG_INIT: libc::c_long = 0x32AAABA7;
+    const _PTHREAD_COND_SIG_INIT: libc::c_long = 0x3CB0B1BB;
+    const _PTHREAD_RWLOCK_SIG_INIT: libc::c_long = 0x2DA8B3B4;
+
+    #[repr(C)]
+    pub struct pthread_mutex_t {
+        __sig: libc::c_long,
+        __opaque: [u8, ..__PTHREAD_MUTEX_SIZE__],
+    }
+    #[repr(C)]
+    pub struct pthread_cond_t {
+        __sig: libc::c_long,
+        __opaque: [u8, ..__PTHREAD_COND_SIZE__],
+    }
+    #[repr(C)]
+    pub struct pthread_rwlock_t {
+        __sig: libc::c_long,
+        __opaque: [u8, ..__PTHREAD_RWLOCK_SIZE__],
+    }
+
+    pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t {
+        __sig: _PTHREAD_MUTEX_SIG_INIT,
+        __opaque: [0, ..__PTHREAD_MUTEX_SIZE__],
+    };
+    pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = pthread_cond_t {
+        __sig: _PTHREAD_COND_SIG_INIT,
+        __opaque: [0, ..__PTHREAD_COND_SIZE__],
+    };
+    pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = pthread_rwlock_t {
+        __sig: _PTHREAD_RWLOCK_SIG_INIT,
+        __opaque: [0, ..__PTHREAD_RWLOCK_SIZE__],
+    };
+}
+
+#[cfg(target_os = "linux")]
+mod os {
+    use libc;
+
+    // minus 8 because we have an 'align' field
+    #[cfg(target_arch = "x86_64")]
+    const __SIZEOF_PTHREAD_MUTEX_T: uint = 40 - 8;
+    #[cfg(any(target_arch = "x86",
+              target_arch = "arm",
+              target_arch = "mips",
+              target_arch = "mipsel"))]
+    const __SIZEOF_PTHREAD_MUTEX_T: uint = 24 - 8;
+
+    #[cfg(any(target_arch = "x86_64",
+              target_arch = "x86",
+              target_arch = "arm",
+              target_arch = "mips",
+              target_arch = "mipsel"))]
+    const __SIZEOF_PTHREAD_COND_T: uint = 48 - 8;
+
+    #[cfg(target_arch = "x86_64")]
+    const __SIZEOF_PTHREAD_RWLOCK_T: uint = 56 - 8;
+
+    #[cfg(any(target_arch = "x86",
+              target_arch = "arm",
+              target_arch = "mips",
+              target_arch = "mipsel"))]
+    const __SIZEOF_PTHREAD_RWLOCK_T: uint = 32 - 8;
+
+    #[repr(C)]
+    pub struct pthread_mutex_t {
+        __align: libc::c_longlong,
+        size: [u8, ..__SIZEOF_PTHREAD_MUTEX_T],
+    }
+    #[repr(C)]
+    pub struct pthread_cond_t {
+        __align: libc::c_longlong,
+        size: [u8, ..__SIZEOF_PTHREAD_COND_T],
+    }
+    #[repr(C)]
+    pub struct pthread_rwlock_t {
+        __align: libc::c_longlong,
+        size: [u8, ..__SIZEOF_PTHREAD_RWLOCK_T],
+    }
+
+    pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t {
+        __align: 0,
+        size: [0, ..__SIZEOF_PTHREAD_MUTEX_T],
+    };
+    pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = pthread_cond_t {
+        __align: 0,
+        size: [0, ..__SIZEOF_PTHREAD_COND_T],
+    };
+    pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = pthread_rwlock_t {
+        __align: 0,
+        size: [0, ..__SIZEOF_PTHREAD_RWLOCK_T],
+    };
+}
+#[cfg(target_os = "android")]
+mod os {
+    use libc;
+
+    #[repr(C)]
+    pub struct pthread_mutex_t { value: libc::c_int }
+    #[repr(C)]
+    pub struct pthread_cond_t { value: libc::c_int }
+    #[repr(C)]
+    pub struct pthread_rwlock_t {
+        lock: pthread_mutex_t,
+        cond: pthread_cond_t,
+        numLocks: libc::c_int,
+        writerThreadId: libc::c_int,
+        pendingReaders: libc::c_int,
+        pendingWriters: libc::c_int,
+        reserved: [*mut libc::c_void, ..4],
+    }
+
+    pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t {
+        value: 0,
+    };
+    pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = pthread_cond_t {
+        value: 0,
+    };
+    pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = pthread_rwlock_t {
+        lock: PTHREAD_MUTEX_INITIALIZER,
+        cond: PTHREAD_COND_INITIALIZER,
+        numLocks: 0,
+        writerThreadId: 0,
+        pendingReaders: 0,
+        pendingWriters: 0,
+        reserved: [0 as *mut _, ..4],
+    };
+}
diff --git a/src/libstd/sys/unix/tcp.rs b/src/libstd/sys/unix/tcp.rs
index 00643ac0a79..5c99ad1e0ce 100644
--- a/src/libstd/sys/unix/tcp.rs
+++ b/src/libstd/sys/unix/tcp.rs
@@ -20,7 +20,8 @@ use sys::fs::FileDesc;
 use sys::{set_nonblocking, wouldblock};
 use sys;
 use sys_common;
-use sys_common::net::*;
+use sys_common::net;
+use sys_common::net::SocketStatus::Readable;
 
 pub use sys_common::net::TcpStream;
 
@@ -34,17 +35,19 @@ pub struct TcpListener {
 
 impl TcpListener {
     pub fn bind(addr: ip::SocketAddr) -> IoResult<TcpListener> {
-        let fd = try!(socket(addr, libc::SOCK_STREAM));
+        let fd = try!(net::socket(addr, libc::SOCK_STREAM));
         let ret = TcpListener { inner: FileDesc::new(fd, true) };
 
         let mut storage = unsafe { mem::zeroed() };
-        let len = addr_to_sockaddr(addr, &mut storage);
+        let len = net::addr_to_sockaddr(addr, &mut storage);
         let addrp = &storage as *const _ as *const libc::sockaddr;
 
         // On platforms with Berkeley-derived sockets, this allows
         // to quickly rebind a socket, without needing to wait for
         // the OS to clean up the previous one.
-        try!(setsockopt(fd, libc::SOL_SOCKET, libc::SO_REUSEADDR, 1 as libc::c_int));
+        try!(net::setsockopt(fd, libc::SOL_SOCKET,
+                             libc::SO_REUSEADDR,
+                             1 as libc::c_int));
 
 
         match unsafe { libc::bind(fd, addrp, len) } {
@@ -77,7 +80,7 @@ impl TcpListener {
     }
 
     pub fn socket_name(&mut self) -> IoResult<ip::SocketAddr> {
-        sockname(self.fd(), libc::getsockname)
+        net::sockname(self.fd(), libc::getsockname)
     }
 }
 
@@ -121,7 +124,7 @@ impl TcpAcceptor {
                 -1 => return Err(last_net_error()),
                 fd => return Ok(TcpStream::new(fd as sock_t)),
             }
-            try!(await(&[self.fd(), self.inner.reader.fd()],
+            try!(net::await(&[self.fd(), self.inner.reader.fd()],
                        deadline, Readable));
         }
 
@@ -129,7 +132,7 @@ impl TcpAcceptor {
     }
 
     pub fn socket_name(&mut self) -> IoResult<ip::SocketAddr> {
-        sockname(self.fd(), libc::getsockname)
+        net::sockname(self.fd(), libc::getsockname)
     }
 
     pub fn set_timeout(&mut self, timeout: Option<u64>) {
diff --git a/src/libstd/sys/unix/thread.rs b/src/libstd/sys/unix/thread.rs
new file mode 100644
index 00000000000..2416b64f98f
--- /dev/null
+++ b/src/libstd/sys/unix/thread.rs
@@ -0,0 +1,271 @@
+// Copyright 2014 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::prelude::*;
+
+use boxed::Box;
+use cmp;
+use mem;
+use ptr;
+use libc::consts::os::posix01::{PTHREAD_CREATE_JOINABLE, PTHREAD_STACK_MIN};
+use libc;
+use thunk::Thunk;
+
+use sys_common::stack::RED_ZONE;
+use sys_common::thread::*;
+
+pub type rust_thread = libc::pthread_t;
+pub type rust_thread_return = *mut u8;
+pub type StartFn = extern "C" fn(*mut libc::c_void) -> rust_thread_return;
+
+#[no_stack_check]
+pub extern fn thread_start(main: *mut libc::c_void) -> rust_thread_return {
+    return start_thread(main);
+}
+
+#[cfg(all(not(target_os = "linux"), not(target_os = "macos")))]
+pub mod guard {
+    pub unsafe fn current() -> uint {
+        0
+    }
+
+    pub unsafe fn main() -> uint {
+        0
+    }
+
+    pub unsafe fn init() {
+    }
+}
+
+#[cfg(any(target_os = "linux", target_os = "macos"))]
+pub mod guard {
+    use super::*;
+    #[cfg(any(target_os = "linux", target_os = "android"))]
+    use mem;
+    #[cfg(any(target_os = "linux", target_os = "android"))]
+    use ptr;
+    use libc;
+    use libc::funcs::posix88::mman::{mmap};
+    use libc::consts::os::posix88::{PROT_NONE,
+                                    MAP_PRIVATE,
+                                    MAP_ANON,
+                                    MAP_FAILED,
+                                    MAP_FIXED};
+
+    // These are initialized in init() and only read from after
+    static mut PAGE_SIZE: uint = 0;
+    static mut GUARD_PAGE: uint = 0;
+
+    #[cfg(target_os = "macos")]
+    unsafe fn get_stack_start() -> *mut libc::c_void {
+        current() as *mut libc::c_void
+    }
+
+    #[cfg(any(target_os = "linux", target_os = "android"))]
+    unsafe fn get_stack_start() -> *mut libc::c_void {
+        let mut attr: libc::pthread_attr_t = mem::zeroed();
+        if pthread_getattr_np(pthread_self(), &mut attr) != 0 {
+            panic!("failed to get thread attributes");
+        }
+        let mut stackaddr = ptr::null_mut();
+        let mut stacksize = 0;
+        if pthread_attr_getstack(&attr, &mut stackaddr, &mut stacksize) != 0 {
+            panic!("failed to get stack information");
+        }
+        if pthread_attr_destroy(&mut attr) != 0 {
+            panic!("failed to destroy thread attributes");
+        }
+        stackaddr
+    }
+
+    pub unsafe fn init() {
+        let psize = libc::sysconf(libc::consts::os::sysconf::_SC_PAGESIZE);
+        if psize == -1 {
+            panic!("failed to get page size");
+        }
+
+        PAGE_SIZE = psize as uint;
+
+        let stackaddr = get_stack_start();
+
+        // Rellocate the last page of the stack.
+        // This ensures SIGBUS will be raised on
+        // stack overflow.
+        let result = mmap(stackaddr,
+                          PAGE_SIZE as libc::size_t,
+                          PROT_NONE,
+                          MAP_PRIVATE | MAP_ANON | MAP_FIXED,
+                          -1,
+                          0);
+
+        if result != stackaddr || result == MAP_FAILED {
+            panic!("failed to allocate a guard page");
+        }
+
+        let offset = if cfg!(target_os = "linux") {
+            2
+        } else {
+            1
+        };
+
+        GUARD_PAGE = stackaddr as uint + offset * PAGE_SIZE;
+    }
+
+    pub unsafe fn main() -> uint {
+        GUARD_PAGE
+    }
+
+    #[cfg(target_os = "macos")]
+    pub unsafe fn current() -> uint {
+        (pthread_get_stackaddr_np(pthread_self()) as libc::size_t -
+         pthread_get_stacksize_np(pthread_self())) as uint
+    }
+
+    #[cfg(any(target_os = "linux", target_os = "android"))]
+    pub unsafe fn current() -> uint {
+        let mut attr: libc::pthread_attr_t = mem::zeroed();
+        if pthread_getattr_np(pthread_self(), &mut attr) != 0 {
+            panic!("failed to get thread attributes");
+        }
+        let mut guardsize = 0;
+        if pthread_attr_getguardsize(&attr, &mut guardsize) != 0 {
+            panic!("failed to get stack guard page");
+        }
+        if guardsize == 0 {
+            panic!("there is no guard page");
+        }
+        let mut stackaddr = ptr::null_mut();
+        let mut stacksize = 0;
+        if pthread_attr_getstack(&attr, &mut stackaddr, &mut stacksize) != 0 {
+            panic!("failed to get stack information");
+        }
+        if pthread_attr_destroy(&mut attr) != 0 {
+            panic!("failed to destroy thread attributes");
+        }
+
+        stackaddr as uint + guardsize as uint
+    }
+}
+
+pub unsafe fn create(stack: uint, p: Thunk) -> rust_thread {
+    let mut native: libc::pthread_t = mem::zeroed();
+    let mut attr: libc::pthread_attr_t = mem::zeroed();
+    assert_eq!(pthread_attr_init(&mut attr), 0);
+    assert_eq!(pthread_attr_setdetachstate(&mut attr,
+                                           PTHREAD_CREATE_JOINABLE), 0);
+
+    // Reserve room for the red zone, the runtime's stack of last resort.
+    let stack_size = cmp::max(stack, RED_ZONE + min_stack_size(&attr) as uint);
+    match pthread_attr_setstacksize(&mut attr, stack_size as libc::size_t) {
+        0 => {
+        },
+        libc::EINVAL => {
+            // EINVAL means |stack_size| is either too small or not a
+            // multiple of the system page size.  Because it's definitely
+            // >= PTHREAD_STACK_MIN, it must be an alignment issue.
+            // Round up to the nearest page and try again.
+            let page_size = libc::sysconf(libc::_SC_PAGESIZE) as uint;
+            let stack_size = (stack_size + page_size - 1) &
+                             (-(page_size as int - 1) as uint - 1);
+            assert_eq!(pthread_attr_setstacksize(&mut attr, stack_size as libc::size_t), 0);
+        },
+        errno => {
+            // This cannot really happen.
+            panic!("pthread_attr_setstacksize() error: {}", errno);
+        },
+    };
+
+    let arg: *mut libc::c_void = mem::transmute(box p); // must box since sizeof(p)=2*uint
+    let ret = pthread_create(&mut native, &attr, thread_start, arg);
+    assert_eq!(pthread_attr_destroy(&mut attr), 0);
+
+    if ret != 0 {
+        // be sure to not leak the closure
+        let _p: Box<Box<FnOnce()+Send>> = mem::transmute(arg);
+        panic!("failed to spawn native thread: {}", ret);
+    }
+    native
+}
+
+pub unsafe fn join(native: rust_thread) {
+    assert_eq!(pthread_join(native, ptr::null_mut()), 0);
+}
+
+pub unsafe fn detach(native: rust_thread) {
+    assert_eq!(pthread_detach(native), 0);
+}
+
+pub unsafe fn yield_now() { assert_eq!(sched_yield(), 0); }
+// glibc >= 2.15 has a __pthread_get_minstack() function that returns
+// PTHREAD_STACK_MIN plus however many bytes are needed for thread-local
+// storage.  We need that information to avoid blowing up when a small stack
+// is created in an application with big thread-local storage requirements.
+// See #6233 for rationale and details.
+//
+// Link weakly to the symbol for compatibility with older versions of glibc.
+// Assumes that we've been dynamically linked to libpthread but that is
+// currently always the case.  Note that you need to check that the symbol
+// is non-null before calling it!
+#[cfg(target_os = "linux")]
+fn min_stack_size(attr: *const libc::pthread_attr_t) -> libc::size_t {
+    type F = unsafe extern "C" fn(*const libc::pthread_attr_t) -> libc::size_t;
+    extern {
+        #[linkage = "extern_weak"]
+        static __pthread_get_minstack: *const ();
+    }
+    if __pthread_get_minstack.is_null() {
+        PTHREAD_STACK_MIN
+    } else {
+        unsafe { mem::transmute::<*const (), F>(__pthread_get_minstack)(attr) }
+    }
+}
+
+// __pthread_get_minstack() is marked as weak but extern_weak linkage is
+// not supported on OS X, hence this kludge...
+#[cfg(not(target_os = "linux"))]
+fn min_stack_size(_: *const libc::pthread_attr_t) -> libc::size_t {
+    PTHREAD_STACK_MIN
+}
+
+#[cfg(any(target_os = "linux"))]
+extern {
+    pub fn pthread_self() -> libc::pthread_t;
+    pub fn pthread_getattr_np(native: libc::pthread_t,
+                              attr: *mut libc::pthread_attr_t) -> libc::c_int;
+    pub fn pthread_attr_getguardsize(attr: *const libc::pthread_attr_t,
+                                     guardsize: *mut libc::size_t) -> libc::c_int;
+    pub fn pthread_attr_getstack(attr: *const libc::pthread_attr_t,
+                                 stackaddr: *mut *mut libc::c_void,
+                                 stacksize: *mut libc::size_t) -> libc::c_int;
+}
+
+#[cfg(target_os = "macos")]
+extern {
+    pub fn pthread_self() -> libc::pthread_t;
+    pub fn pthread_get_stackaddr_np(thread: libc::pthread_t) -> *mut libc::c_void;
+    pub fn pthread_get_stacksize_np(thread: libc::pthread_t) -> libc::size_t;
+}
+
+extern {
+    fn pthread_create(native: *mut libc::pthread_t,
+                      attr: *const libc::pthread_attr_t,
+                      f: StartFn,
+                      value: *mut libc::c_void) -> libc::c_int;
+    fn pthread_join(native: libc::pthread_t,
+                    value: *mut *mut libc::c_void) -> libc::c_int;
+    fn pthread_attr_init(attr: *mut libc::pthread_attr_t) -> libc::c_int;
+    pub fn pthread_attr_destroy(attr: *mut libc::pthread_attr_t) -> libc::c_int;
+    fn pthread_attr_setstacksize(attr: *mut libc::pthread_attr_t,
+                                 stack_size: libc::size_t) -> libc::c_int;
+    fn pthread_attr_setdetachstate(attr: *mut libc::pthread_attr_t,
+                                   state: libc::c_int) -> libc::c_int;
+    fn pthread_detach(thread: libc::pthread_t) -> libc::c_int;
+    fn sched_yield() -> libc::c_int;
+}
diff --git a/src/libstd/sys/unix/thread_local.rs b/src/libstd/sys/unix/thread_local.rs
new file mode 100644
index 00000000000..b300e93eeb6
--- /dev/null
+++ b/src/libstd/sys/unix/thread_local.rs
@@ -0,0 +1,52 @@
+// Copyright 2014 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 prelude::*;
+use libc::c_int;
+
+pub type Key = pthread_key_t;
+
+#[inline]
+pub unsafe fn create(dtor: Option<unsafe extern fn(*mut u8)>) -> Key {
+    let mut key = 0;
+    assert_eq!(pthread_key_create(&mut key, dtor), 0);
+    return key;
+}
+
+#[inline]
+pub unsafe fn set(key: Key, value: *mut u8) {
+    let r = pthread_setspecific(key, value);
+    debug_assert_eq!(r, 0);
+}
+
+#[inline]
+pub unsafe fn get(key: Key) -> *mut u8 {
+    pthread_getspecific(key)
+}
+
+#[inline]
+pub unsafe fn destroy(key: Key) {
+    let r = pthread_key_delete(key);
+    debug_assert_eq!(r, 0);
+}
+
+#[cfg(target_os = "macos")]
+type pthread_key_t = ::libc::c_ulong;
+
+#[cfg(not(target_os = "macos"))]
+type pthread_key_t = ::libc::c_uint;
+
+extern {
+    fn pthread_key_create(key: *mut pthread_key_t,
+                          dtor: Option<unsafe extern fn(*mut u8)>) -> c_int;
+    fn pthread_key_delete(key: pthread_key_t) -> c_int;
+    fn pthread_getspecific(key: pthread_key_t) -> *mut u8;
+    fn pthread_setspecific(key: pthread_key_t, value: *mut u8) -> c_int;
+}
diff --git a/src/libstd/sys/unix/timer.rs b/src/libstd/sys/unix/timer.rs
index 6ebbedb8e90..fe393b81e3d 100644
--- a/src/libstd/sys/unix/timer.rs
+++ b/src/libstd/sys/unix/timer.rs
@@ -46,7 +46,7 @@
 //!
 //! Note that all time units in this file are in *milliseconds*.
 
-pub use self::Req::*;
+use self::Req::*;
 
 use libc;
 use mem;
@@ -60,7 +60,7 @@ use sys_common::helper_thread::Helper;
 use prelude::*;
 use io::IoResult;
 
-helper_init!(static HELPER: Helper<Req>)
+helper_init! { static HELPER: Helper<Req> }
 
 pub trait Callback {
     fn call(&mut self);
diff --git a/src/libstd/sys/windows/backtrace.rs b/src/libstd/sys/windows/backtrace.rs
new file mode 100644
index 00000000000..42c8f7705e1
--- /dev/null
+++ b/src/libstd/sys/windows/backtrace.rs
@@ -0,0 +1,371 @@
+// Copyright 2014 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.
+/// As always, windows has something very different than unix, we mainly want
+/// to avoid having to depend too much on libunwind for windows.
+///
+/// If you google around, you'll find a fair bit of references to built-in
+/// functions to get backtraces on windows. It turns out that most of these are
+/// in an external library called dbghelp. I was unable to find this library
+/// via `-ldbghelp`, but it is apparently normal to do the `dlopen` equivalent
+/// of it.
+///
+/// You'll also find that there's a function called CaptureStackBackTrace
+/// mentioned frequently (which is also easy to use), but sadly I didn't have a
+/// copy of that function in my mingw install (maybe it was broken?). Instead,
+/// this takes the route of using StackWalk64 in order to walk the stack.
+
+use c_str::CString;
+use intrinsics;
+use io::{IoResult, Writer};
+use libc;
+use mem;
+use ops::Drop;
+use option::Option::{Some, None};
+use path::Path;
+use result::Result::{Ok, Err};
+use sync::{StaticMutex, MUTEX_INIT};
+use slice::SliceExt;
+use str::StrExt;
+use dynamic_lib::DynamicLibrary;
+
+use sys_common::backtrace::*;
+
+#[allow(non_snake_case)]
+extern "system" {
+    fn GetCurrentProcess() -> libc::HANDLE;
+    fn GetCurrentThread() -> libc::HANDLE;
+    fn RtlCaptureContext(ctx: *mut arch::CONTEXT);
+}
+
+type SymFromAddrFn =
+    extern "system" fn(libc::HANDLE, u64, *mut u64,
+                       *mut SYMBOL_INFO) -> libc::BOOL;
+type SymInitializeFn =
+    extern "system" fn(libc::HANDLE, *mut libc::c_void,
+                       libc::BOOL) -> libc::BOOL;
+type SymCleanupFn =
+    extern "system" fn(libc::HANDLE) -> libc::BOOL;
+
+type StackWalk64Fn =
+    extern "system" fn(libc::DWORD, libc::HANDLE, libc::HANDLE,
+                       *mut STACKFRAME64, *mut arch::CONTEXT,
+                       *mut libc::c_void, *mut libc::c_void,
+                       *mut libc::c_void, *mut libc::c_void) -> libc::BOOL;
+
+const MAX_SYM_NAME: uint = 2000;
+const IMAGE_FILE_MACHINE_I386: libc::DWORD = 0x014c;
+const IMAGE_FILE_MACHINE_IA64: libc::DWORD = 0x0200;
+const IMAGE_FILE_MACHINE_AMD64: libc::DWORD = 0x8664;
+
+#[repr(C)]
+struct SYMBOL_INFO {
+    SizeOfStruct: libc::c_ulong,
+    TypeIndex: libc::c_ulong,
+    Reserved: [u64, ..2],
+    Index: libc::c_ulong,
+    Size: libc::c_ulong,
+    ModBase: u64,
+    Flags: libc::c_ulong,
+    Value: u64,
+    Address: u64,
+    Register: libc::c_ulong,
+    Scope: libc::c_ulong,
+    Tag: libc::c_ulong,
+    NameLen: libc::c_ulong,
+    MaxNameLen: libc::c_ulong,
+    // note that windows has this as 1, but it basically just means that
+    // the name is inline at the end of the struct. For us, we just bump
+    // the struct size up to MAX_SYM_NAME.
+    Name: [libc::c_char, ..MAX_SYM_NAME],
+}
+
+
+#[repr(C)]
+enum ADDRESS_MODE {
+    AddrMode1616,
+    AddrMode1632,
+    AddrModeReal,
+    AddrModeFlat,
+}
+
+struct ADDRESS64 {
+    Offset: u64,
+    Segment: u16,
+    Mode: ADDRESS_MODE,
+}
+
+struct STACKFRAME64 {
+    AddrPC: ADDRESS64,
+    AddrReturn: ADDRESS64,
+    AddrFrame: ADDRESS64,
+    AddrStack: ADDRESS64,
+    AddrBStore: ADDRESS64,
+    FuncTableEntry: *mut libc::c_void,
+    Params: [u64, ..4],
+    Far: libc::BOOL,
+    Virtual: libc::BOOL,
+    Reserved: [u64, ..3],
+    KdHelp: KDHELP64,
+}
+
+struct KDHELP64 {
+    Thread: u64,
+    ThCallbackStack: libc::DWORD,
+    ThCallbackBStore: libc::DWORD,
+    NextCallback: libc::DWORD,
+    FramePointer: libc::DWORD,
+    KiCallUserMode: u64,
+    KeUserCallbackDispatcher: u64,
+    SystemRangeStart: u64,
+    KiUserExceptionDispatcher: u64,
+    StackBase: u64,
+    StackLimit: u64,
+    Reserved: [u64, ..5],
+}
+
+#[cfg(target_arch = "x86")]
+mod arch {
+    use libc;
+
+    const MAXIMUM_SUPPORTED_EXTENSION: uint = 512;
+
+    #[repr(C)]
+    pub struct CONTEXT {
+        ContextFlags: libc::DWORD,
+        Dr0: libc::DWORD,
+        Dr1: libc::DWORD,
+        Dr2: libc::DWORD,
+        Dr3: libc::DWORD,
+        Dr6: libc::DWORD,
+        Dr7: libc::DWORD,
+        FloatSave: FLOATING_SAVE_AREA,
+        SegGs: libc::DWORD,
+        SegFs: libc::DWORD,
+        SegEs: libc::DWORD,
+        SegDs: libc::DWORD,
+        Edi: libc::DWORD,
+        Esi: libc::DWORD,
+        Ebx: libc::DWORD,
+        Edx: libc::DWORD,
+        Ecx: libc::DWORD,
+        Eax: libc::DWORD,
+        Ebp: libc::DWORD,
+        Eip: libc::DWORD,
+        SegCs: libc::DWORD,
+        EFlags: libc::DWORD,
+        Esp: libc::DWORD,
+        SegSs: libc::DWORD,
+        ExtendedRegisters: [u8, ..MAXIMUM_SUPPORTED_EXTENSION],
+    }
+
+    #[repr(C)]
+    pub struct FLOATING_SAVE_AREA {
+        ControlWord: libc::DWORD,
+        StatusWord: libc::DWORD,
+        TagWord: libc::DWORD,
+        ErrorOffset: libc::DWORD,
+        ErrorSelector: libc::DWORD,
+        DataOffset: libc::DWORD,
+        DataSelector: libc::DWORD,
+        RegisterArea: [u8, ..80],
+        Cr0NpxState: libc::DWORD,
+    }
+
+    pub fn init_frame(frame: &mut super::STACKFRAME64,
+                      ctx: &CONTEXT) -> libc::DWORD {
+        frame.AddrPC.Offset = ctx.Eip as u64;
+        frame.AddrPC.Mode = super::ADDRESS_MODE::AddrModeFlat;
+        frame.AddrStack.Offset = ctx.Esp as u64;
+        frame.AddrStack.Mode = super::ADDRESS_MODE::AddrModeFlat;
+        frame.AddrFrame.Offset = ctx.Ebp as u64;
+        frame.AddrFrame.Mode = super::ADDRESS_MODE::AddrModeFlat;
+        super::IMAGE_FILE_MACHINE_I386
+    }
+}
+
+#[cfg(target_arch = "x86_64")]
+mod arch {
+    use libc::{c_longlong, c_ulonglong};
+    use libc::types::os::arch::extra::{WORD, DWORD, DWORDLONG};
+    use simd;
+
+    #[repr(C)]
+    pub struct CONTEXT {
+        _align_hack: [simd::u64x2, ..0], // FIXME align on 16-byte
+        P1Home: DWORDLONG,
+        P2Home: DWORDLONG,
+        P3Home: DWORDLONG,
+        P4Home: DWORDLONG,
+        P5Home: DWORDLONG,
+        P6Home: DWORDLONG,
+
+        ContextFlags: DWORD,
+        MxCsr: DWORD,
+
+        SegCs: WORD,
+        SegDs: WORD,
+        SegEs: WORD,
+        SegFs: WORD,
+        SegGs: WORD,
+        SegSs: WORD,
+        EFlags: DWORD,
+
+        Dr0: DWORDLONG,
+        Dr1: DWORDLONG,
+        Dr2: DWORDLONG,
+        Dr3: DWORDLONG,
+        Dr6: DWORDLONG,
+        Dr7: DWORDLONG,
+
+        Rax: DWORDLONG,
+        Rcx: DWORDLONG,
+        Rdx: DWORDLONG,
+        Rbx: DWORDLONG,
+        Rsp: DWORDLONG,
+        Rbp: DWORDLONG,
+        Rsi: DWORDLONG,
+        Rdi: DWORDLONG,
+        R8:  DWORDLONG,
+        R9:  DWORDLONG,
+        R10: DWORDLONG,
+        R11: DWORDLONG,
+        R12: DWORDLONG,
+        R13: DWORDLONG,
+        R14: DWORDLONG,
+        R15: DWORDLONG,
+
+        Rip: DWORDLONG,
+
+        FltSave: FLOATING_SAVE_AREA,
+
+        VectorRegister: [M128A, .. 26],
+        VectorControl: DWORDLONG,
+
+        DebugControl: DWORDLONG,
+        LastBranchToRip: DWORDLONG,
+        LastBranchFromRip: DWORDLONG,
+        LastExceptionToRip: DWORDLONG,
+        LastExceptionFromRip: DWORDLONG,
+    }
+
+    #[repr(C)]
+    pub struct M128A {
+        _align_hack: [simd::u64x2, ..0], // FIXME align on 16-byte
+        Low:  c_ulonglong,
+        High: c_longlong
+    }
+
+    #[repr(C)]
+    pub struct FLOATING_SAVE_AREA {
+        _align_hack: [simd::u64x2, ..0], // FIXME align on 16-byte
+        _Dummy: [u8, ..512] // FIXME: Fill this out
+    }
+
+    pub fn init_frame(frame: &mut super::STACKFRAME64,
+                      ctx: &CONTEXT) -> DWORD {
+        frame.AddrPC.Offset = ctx.Rip as u64;
+        frame.AddrPC.Mode = super::ADDRESS_MODE::AddrModeFlat;
+        frame.AddrStack.Offset = ctx.Rsp as u64;
+        frame.AddrStack.Mode = super::ADDRESS_MODE::AddrModeFlat;
+        frame.AddrFrame.Offset = ctx.Rbp as u64;
+        frame.AddrFrame.Mode = super::ADDRESS_MODE::AddrModeFlat;
+        super::IMAGE_FILE_MACHINE_AMD64
+    }
+}
+
+#[repr(C)]
+struct Cleanup {
+    handle: libc::HANDLE,
+    SymCleanup: SymCleanupFn,
+}
+
+impl Drop for Cleanup {
+    fn drop(&mut self) { (self.SymCleanup)(self.handle); }
+}
+
+pub fn write(w: &mut Writer) -> IoResult<()> {
+    // According to windows documentation, all dbghelp functions are
+    // single-threaded.
+    static LOCK: StaticMutex = MUTEX_INIT;
+    let _g = unsafe { LOCK.lock() };
+
+    // Open up dbghelp.dll, we don't link to it explicitly because it can't
+    // always be found. Additionally, it's nice having fewer dependencies.
+    let path = Path::new("dbghelp.dll");
+    let lib = match DynamicLibrary::open(Some(&path)) {
+        Ok(lib) => lib,
+        Err(..) => return Ok(()),
+    };
+
+    macro_rules! sym{ ($e:expr, $t:ident) => (unsafe {
+        match lib.symbol($e) {
+            Ok(f) => mem::transmute::<*mut u8, $t>(f),
+            Err(..) => return Ok(())
+        }
+    }) }
+
+    // Fetch the symbols necessary from dbghelp.dll
+    let SymFromAddr = sym!("SymFromAddr", SymFromAddrFn);
+    let SymInitialize = sym!("SymInitialize", SymInitializeFn);
+    let SymCleanup = sym!("SymCleanup", SymCleanupFn);
+    let StackWalk64 = sym!("StackWalk64", StackWalk64Fn);
+
+    // Allocate necessary structures for doing the stack walk
+    let process = unsafe { GetCurrentProcess() };
+    let thread = unsafe { GetCurrentThread() };
+    let mut context: arch::CONTEXT = unsafe { intrinsics::init() };
+    unsafe { RtlCaptureContext(&mut context); }
+    let mut frame: STACKFRAME64 = unsafe { intrinsics::init() };
+    let image = arch::init_frame(&mut frame, &context);
+
+    // Initialize this process's symbols
+    let ret = SymInitialize(process, 0 as *mut libc::c_void, libc::TRUE);
+    if ret != libc::TRUE { return Ok(()) }
+    let _c = Cleanup { handle: process, SymCleanup: SymCleanup };
+
+    // And now that we're done with all the setup, do the stack walking!
+    let mut i = 0i;
+    try!(write!(w, "stack backtrace:\n"));
+    while StackWalk64(image, process, thread, &mut frame, &mut context,
+                      0 as *mut libc::c_void,
+                      0 as *mut libc::c_void,
+                      0 as *mut libc::c_void,
+                      0 as *mut libc::c_void) == libc::TRUE{
+        let addr = frame.AddrPC.Offset;
+        if addr == frame.AddrReturn.Offset || addr == 0 ||
+           frame.AddrReturn.Offset == 0 { break }
+
+        i += 1;
+        try!(write!(w, "  {:2}: {:#2$x}", i, addr, HEX_WIDTH));
+        let mut info: SYMBOL_INFO = unsafe { intrinsics::init() };
+        info.MaxNameLen = MAX_SYM_NAME as libc::c_ulong;
+        // the struct size in C.  the value is different to
+        // `size_of::<SYMBOL_INFO>() - MAX_SYM_NAME + 1` (== 81)
+        // due to struct alignment.
+        info.SizeOfStruct = 88;
+
+        let mut displacement = 0u64;
+        let ret = SymFromAddr(process, addr as u64, &mut displacement,
+                              &mut info);
+
+        if ret == libc::TRUE {
+            try!(write!(w, " - "));
+            let cstr = unsafe { CString::new(info.Name.as_ptr(), false) };
+            let bytes = cstr.as_bytes();
+            match cstr.as_str() {
+                Some(s) => try!(demangle(w, s)),
+                None => try!(w.write(bytes[..bytes.len()-1])),
+            }
+        }
+        try!(w.write(&['\n' as u8]));
+    }
+
+    Ok(())
+}
diff --git a/src/libstd/sys/windows/c.rs b/src/libstd/sys/windows/c.rs
index b8e9b1dca3a..d1cb91bcdb3 100644
--- a/src/libstd/sys/windows/c.rs
+++ b/src/libstd/sys/windows/c.rs
@@ -131,7 +131,7 @@ extern "system" {
 
 pub mod compat {
     use intrinsics::{atomic_store_relaxed, transmute};
-    use iter::Iterator;
+    use iter::IteratorExt;
     use libc::types::os::arch::extra::{LPCWSTR, HMODULE, LPCSTR, LPVOID};
     use prelude::*;
 
@@ -169,7 +169,7 @@ pub mod compat {
     ///
     /// Note that arguments unused by the fallback implementation should not be called `_` as
     /// they are used to be passed to the real function if available.
-    macro_rules! compat_fn(
+    macro_rules! compat_fn {
         ($module:ident::$symbol:ident($($argname:ident: $argtype:ty),*)
                                       -> $rettype:ty $fallback:block) => (
             #[inline(always)]
@@ -195,7 +195,7 @@ pub mod compat {
         ($module:ident::$symbol:ident($($argname:ident: $argtype:ty),*) $fallback:block) => (
             compat_fn!($module::$symbol($($argname: $argtype),*) -> () $fallback)
         )
-    )
+    }
 
     /// Compatibility layer for functions in `kernel32.dll`
     ///
@@ -211,20 +211,20 @@ pub mod compat {
             fn SetLastError(dwErrCode: DWORD);
         }
 
-        compat_fn!(kernel32::CreateSymbolicLinkW(_lpSymlinkFileName: LPCWSTR,
+        compat_fn! { kernel32::CreateSymbolicLinkW(_lpSymlinkFileName: LPCWSTR,
                                                  _lpTargetFileName: LPCWSTR,
                                                  _dwFlags: DWORD) -> BOOLEAN {
             unsafe { SetLastError(ERROR_CALL_NOT_IMPLEMENTED as DWORD); }
             0
-        })
+        } }
 
-        compat_fn!(kernel32::GetFinalPathNameByHandleW(_hFile: HANDLE,
+        compat_fn! { kernel32::GetFinalPathNameByHandleW(_hFile: HANDLE,
                                                        _lpszFilePath: LPCWSTR,
                                                        _cchFilePath: DWORD,
                                                        _dwFlags: DWORD) -> DWORD {
             unsafe { SetLastError(ERROR_CALL_NOT_IMPLEMENTED as DWORD); }
             0
-        })
+        } }
     }
 }
 
diff --git a/src/libstd/sys/windows/condvar.rs b/src/libstd/sys/windows/condvar.rs
new file mode 100644
index 00000000000..7f9d669c447
--- /dev/null
+++ b/src/libstd/sys/windows/condvar.rs
@@ -0,0 +1,62 @@
+// Copyright 2014 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 libc::{mod, DWORD};
+use os;
+use sys::mutex::{mod, Mutex};
+use sys::sync as ffi;
+use time::Duration;
+
+pub struct Condvar { inner: UnsafeCell<ffi::CONDITION_VARIABLE> }
+
+pub const CONDVAR_INIT: Condvar = Condvar {
+    inner: UnsafeCell { value: ffi::CONDITION_VARIABLE_INIT }
+};
+
+impl Condvar {
+    #[inline]
+    pub unsafe fn new() -> Condvar { CONDVAR_INIT }
+
+    #[inline]
+    pub unsafe fn wait(&self, mutex: &Mutex) {
+        let r = ffi::SleepConditionVariableCS(self.inner.get(),
+                                              mutex::raw(mutex),
+                                              libc::INFINITE);
+        debug_assert!(r != 0);
+    }
+
+    pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
+        let r = ffi::SleepConditionVariableCS(self.inner.get(),
+                                              mutex::raw(mutex),
+                                              dur.num_milliseconds() as DWORD);
+        if r == 0 {
+            const ERROR_TIMEOUT: DWORD = 0x5B4;
+            debug_assert_eq!(os::errno() as uint, ERROR_TIMEOUT as uint);
+            false
+        } else {
+            true
+        }
+    }
+
+    #[inline]
+    pub unsafe fn notify_one(&self) {
+        ffi::WakeConditionVariable(self.inner.get())
+    }
+
+    #[inline]
+    pub unsafe fn notify_all(&self) {
+        ffi::WakeAllConditionVariable(self.inner.get())
+    }
+
+    pub unsafe fn destroy(&self) {
+        // ...
+    }
+}
diff --git a/src/libstd/sys/windows/ext.rs b/src/libstd/sys/windows/ext.rs
new file mode 100644
index 00000000000..049aca3f590
--- /dev/null
+++ b/src/libstd/sys/windows/ext.rs
@@ -0,0 +1,100 @@
+// Copyright 2014 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 Windows.
+//!
+//! For now, this module is limited to extracting handles, file
+//! descriptors, and sockets, but its functionality will grow over
+//! time.
+
+#![experimental]
+
+use sys_common::AsInner;
+use libc;
+
+use io;
+
+/// Raw HANDLEs.
+pub type Handle = libc::HANDLE;
+
+/// Raw SOCKETs.
+pub type Socket = libc::SOCKET;
+
+/// Extract raw handles.
+pub trait AsRawHandle {
+    /// Extract the raw handle, without taking any ownership.
+    fn as_raw_handle(&self) -> Handle;
+}
+
+impl AsRawHandle for io::fs::File {
+    fn as_raw_handle(&self) -> Handle {
+        self.as_inner().handle()
+    }
+}
+
+impl AsRawHandle for io::pipe::PipeStream {
+    fn as_raw_handle(&self) -> Handle {
+        self.as_inner().handle()
+    }
+}
+
+impl AsRawHandle for io::net::pipe::UnixStream {
+    fn as_raw_handle(&self) -> Handle {
+        self.as_inner().handle()
+    }
+}
+
+impl AsRawHandle for io::net::pipe::UnixListener {
+    fn as_raw_handle(&self) -> Handle {
+        self.as_inner().handle()
+    }
+}
+
+impl AsRawHandle for io::net::pipe::UnixAcceptor {
+    fn as_raw_handle(&self) -> Handle {
+        self.as_inner().handle()
+    }
+}
+
+/// Extract raw sockets.
+pub trait AsRawSocket {
+    fn as_raw_socket(&self) -> Socket;
+}
+
+impl AsRawSocket for io::net::tcp::TcpStream {
+    fn as_raw_socket(&self) -> Socket {
+        self.as_inner().fd()
+    }
+}
+
+impl AsRawSocket for io::net::tcp::TcpListener {
+    fn as_raw_socket(&self) -> Socket {
+        self.as_inner().socket()
+    }
+}
+
+impl AsRawSocket for io::net::tcp::TcpAcceptor {
+    fn as_raw_socket(&self) -> Socket {
+        self.as_inner().socket()
+    }
+}
+
+impl AsRawSocket for io::net::udp::UdpSocket {
+    fn as_raw_socket(&self) -> Socket {
+        self.as_inner().fd()
+    }
+}
+
+/// A prelude for conveniently writing platform-specific code.
+///
+/// Includes all extension traits, and some important type definitions.
+pub mod prelude {
+    pub use super::{Socket, Handle, AsRawSocket, AsRawHandle};
+}
diff --git a/src/libstd/sys/windows/fs.rs b/src/libstd/sys/windows/fs.rs
index b881eb2d495..15eddd569be 100644
--- a/src/libstd/sys/windows/fs.rs
+++ b/src/libstd/sys/windows/fs.rs
@@ -15,7 +15,7 @@ use libc::{mod, c_int};
 
 use c_str::CString;
 use mem;
-use os::windows::fill_utf16_buf_and_decode;
+use sys::os::fill_utf16_buf_and_decode;
 use path;
 use ptr;
 use str;
@@ -23,13 +23,13 @@ use io;
 
 use prelude::*;
 use sys;
+use sys::os;
 use sys_common::{keep_going, eof, mkerr_libc};
 
 use io::{FilePermission, Write, UnstableFileStat, Open, FileAccess, FileMode};
-use io::{IoResult, IoError, FileStat, SeekStyle, Seek, Writer, Reader};
+use io::{IoResult, IoError, FileStat, SeekStyle};
 use io::{Read, Truncate, SeekCur, SeekSet, ReadWrite, SeekEnd, Append};
 
-pub use path::WindowsPath as Path;
 pub type fd_t = libc::c_int;
 
 pub struct FileDesc {
@@ -131,7 +131,7 @@ impl FileDesc {
         return ret;
     }
 
-    pub fn fstat(&mut self) -> IoResult<io::FileStat> {
+    pub fn fstat(&self) -> IoResult<io::FileStat> {
         let mut stat: libc::stat = unsafe { mem::zeroed() };
         match unsafe { libc::fstat(self.fd(), &mut stat) } {
             0 => Ok(mkstat(&stat)),
@@ -263,7 +263,7 @@ pub fn readdir(p: &Path) -> IoResult<Vec<Path>> {
             let mut more_files = 1 as libc::BOOL;
             while more_files != 0 {
                 {
-                    let filename = str::truncate_utf16_at_nul(&wfd.cFileName);
+                    let filename = os::truncate_utf16_at_nul(&wfd.cFileName);
                     match String::from_utf16(filename) {
                         Some(filename) => paths.push(Path::new(filename)),
                         None => {
@@ -376,8 +376,8 @@ pub fn readlink(p: &Path) -> IoResult<Path> {
                                   libc::VOLUME_NAME_DOS)
     });
     let ret = match ret {
-        Some(ref s) if s.as_slice().starts_with(r"\\?\") => { // "
-            Ok(Path::new(s.as_slice().slice_from(4)))
+        Some(ref s) if s.starts_with(r"\\?\") => { // "
+            Ok(Path::new(s.slice_from(4)))
         }
         Some(s) => Ok(Path::new(s)),
         None => Err(super::last_error()),
@@ -407,12 +407,12 @@ fn mkstat(stat: &libc::stat) -> FileStat {
     FileStat {
         size: stat.st_size as u64,
         kind: match (stat.st_mode as libc::c_int) & libc::S_IFMT {
-            libc::S_IFREG => io::TypeFile,
-            libc::S_IFDIR => io::TypeDirectory,
-            libc::S_IFIFO => io::TypeNamedPipe,
-            libc::S_IFBLK => io::TypeBlockSpecial,
-            libc::S_IFLNK => io::TypeSymlink,
-            _ => io::TypeUnknown,
+            libc::S_IFREG => io::FileType::RegularFile,
+            libc::S_IFDIR => io::FileType::Directory,
+            libc::S_IFIFO => io::FileType::NamedPipe,
+            libc::S_IFBLK => io::FileType::BlockSpecial,
+            libc::S_IFLNK => io::FileType::Symlink,
+            _ => io::FileType::Unknown,
         },
         perm: FilePermission::from_bits_truncate(stat.st_mode as u32),
         created: stat.st_ctime as u64,
diff --git a/src/libstd/sys/windows/mod.rs b/src/libstd/sys/windows/mod.rs
index 815ace21f87..6924687d8c4 100644
--- a/src/libstd/sys/windows/mod.rs
+++ b/src/libstd/sys/windows/mod.rs
@@ -24,25 +24,36 @@ use prelude::*;
 use io::{mod, IoResult, IoError};
 use sync::{Once, ONCE_INIT};
 
-macro_rules! helper_init( (static $name:ident: Helper<$m:ty>) => (
+macro_rules! helper_init { (static $name:ident: Helper<$m:ty>) => (
     static $name: Helper<$m> = Helper {
-        lock: ::rustrt::mutex::NATIVE_MUTEX_INIT,
+        lock: ::sync::MUTEX_INIT,
+        cond: ::sync::CONDVAR_INIT,
         chan: ::cell::UnsafeCell { value: 0 as *mut Sender<$m> },
         signal: ::cell::UnsafeCell { value: 0 },
         initialized: ::cell::UnsafeCell { value: false },
+        shutdown: ::cell::UnsafeCell { value: false },
     };
-) )
+) }
 
+pub mod backtrace;
 pub mod c;
+pub mod ext;
+pub mod condvar;
 pub mod fs;
+pub mod helper_signal;
+pub mod mutex;
 pub mod os;
-pub mod tcp;
-pub mod udp;
 pub mod pipe;
-pub mod helper_signal;
 pub mod process;
+pub mod rwlock;
+pub mod sync;
+pub mod stack_overflow;
+pub mod tcp;
+pub mod thread;
+pub mod thread_local;
 pub mod timer;
 pub mod tty;
+pub mod udp;
 
 pub mod addrinfo {
     pub use sys_common::net::get_host_addresses;
@@ -130,7 +141,7 @@ pub fn decode_error_detailed(errno: i32) -> IoError {
 }
 
 #[inline]
-pub fn retry<I> (f: || -> I) -> I { f() } // PR rust-lang/rust/#17020
+pub fn retry<I, F>(f: F) -> I where F: FnOnce() -> I { f() } // PR rust-lang/rust/#17020
 
 pub fn ms_to_timeval(ms: u64) -> libc::timeval {
     libc::timeval {
diff --git a/src/libstd/sys/windows/mutex.rs b/src/libstd/sys/windows/mutex.rs
new file mode 100644
index 00000000000..ddd89070ed5
--- /dev/null
+++ b/src/libstd/sys/windows/mutex.rs
@@ -0,0 +1,78 @@
+// Copyright 2014 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 prelude::*;
+
+use sync::atomic;
+use alloc::{mod, heap};
+
+use libc::DWORD;
+use sys::sync as ffi;
+
+const SPIN_COUNT: DWORD = 4000;
+
+pub struct Mutex { inner: atomic::AtomicUint }
+
+pub const MUTEX_INIT: Mutex = Mutex { inner: atomic::INIT_ATOMIC_UINT };
+
+#[inline]
+pub unsafe fn raw(m: &Mutex) -> ffi::LPCRITICAL_SECTION {
+    m.get()
+}
+
+impl Mutex {
+    #[inline]
+    pub unsafe fn new() -> Mutex {
+        Mutex { inner: atomic::AtomicUint::new(init_lock() as uint) }
+    }
+    #[inline]
+    pub unsafe fn lock(&self) {
+        ffi::EnterCriticalSection(self.get())
+    }
+    #[inline]
+    pub unsafe fn try_lock(&self) -> bool {
+        ffi::TryEnterCriticalSection(self.get()) != 0
+    }
+    #[inline]
+    pub unsafe fn unlock(&self) {
+        ffi::LeaveCriticalSection(self.get())
+    }
+    pub unsafe fn destroy(&self) {
+        let lock = self.inner.swap(0, atomic::SeqCst);
+        if lock != 0 { free_lock(lock as ffi::LPCRITICAL_SECTION) }
+    }
+
+    unsafe fn get(&self) -> ffi::LPCRITICAL_SECTION {
+        match self.inner.load(atomic::SeqCst) {
+            0 => {}
+            n => return n as ffi::LPCRITICAL_SECTION
+        }
+        let lock = init_lock();
+        match self.inner.compare_and_swap(0, lock as uint, atomic::SeqCst) {
+            0 => return lock as ffi::LPCRITICAL_SECTION,
+            _ => {}
+        }
+        free_lock(lock);
+        return self.inner.load(atomic::SeqCst) as ffi::LPCRITICAL_SECTION;
+    }
+}
+
+unsafe fn init_lock() -> ffi::LPCRITICAL_SECTION {
+    let block = heap::allocate(ffi::CRITICAL_SECTION_SIZE, 8)
+                        as ffi::LPCRITICAL_SECTION;
+    if block.is_null() { alloc::oom() }
+    ffi::InitializeCriticalSectionAndSpinCount(block, SPIN_COUNT);
+    return block;
+}
+
+unsafe fn free_lock(h: ffi::LPCRITICAL_SECTION) {
+    ffi::DeleteCriticalSection(h);
+    heap::deallocate(h as *mut _, ffi::CRITICAL_SECTION_SIZE, 8);
+}
diff --git a/src/libstd/sys/windows/os.rs b/src/libstd/sys/windows/os.rs
index aa43b42e746..e007b46b261 100644
--- a/src/libstd/sys/windows/os.rs
+++ b/src/libstd/sys/windows/os.rs
@@ -8,17 +8,38 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+//! Implementation of `std::os` functionality for Windows
+
 // FIXME: move various extern bindings from here into liblibc or
 // something similar
 
-use libc;
-use libc::{c_int, c_char, c_void};
 use prelude::*;
+
+use fmt;
 use io::{IoResult, IoError};
-use sys::fs::FileDesc;
+use libc::{c_int, c_char, c_void};
+use libc;
+use os;
+use path::BytesContainer;
 use ptr;
+use sync::atomic::{AtomicInt, INIT_ATOMIC_INT, SeqCst};
+use sys::fs::FileDesc;
+use slice;
 
 use os::TMPBUF_SZ;
+use libc::types::os::arch::extra::DWORD;
+
+const BUF_BYTES : uint = 2048u;
+
+/// Return a slice of `v` ending at (and not including) the first NUL
+/// (0).
+pub fn truncate_utf16_at_nul<'a>(v: &'a [u16]) -> &'a [u16] {
+    match v.iter().position(|c| *c == 0) {
+        // don't include the 0
+        Some(i) => v[..i],
+        None => v
+    }
+}
 
 pub fn errno() -> uint {
     use libc::types::os::arch::extra::DWORD;
@@ -76,7 +97,7 @@ pub fn error_string(errnum: i32) -> String {
             return format!("OS Error {} (FormatMessageW() returned error {})", errnum, fm_err);
         }
 
-        let msg = String::from_utf16(::str::truncate_utf16_at_nul(&buf));
+        let msg = String::from_utf16(truncate_utf16_at_nul(&buf));
         match msg {
             Some(msg) => format!("OS Error {}: {}", errnum, msg),
             None => format!("OS Error {} (FormatMessageW() returned invalid UTF-16)", errnum),
@@ -101,3 +122,212 @@ pub unsafe fn pipe() -> IoResult<(FileDesc, FileDesc)> {
         _ => Err(IoError::last_error()),
     }
 }
+
+pub fn fill_utf16_buf_and_decode(f: |*mut u16, DWORD| -> DWORD) -> Option<String> {
+    unsafe {
+        let mut n = TMPBUF_SZ as DWORD;
+        let mut res = None;
+        let mut done = false;
+        while !done {
+            let mut buf = Vec::from_elem(n as uint, 0u16);
+            let k = f(buf.as_mut_ptr(), n);
+            if k == (0 as DWORD) {
+                done = true;
+            } else if k == n &&
+                      libc::GetLastError() ==
+                      libc::ERROR_INSUFFICIENT_BUFFER as DWORD {
+                n *= 2 as DWORD;
+            } else if k >= n {
+                n = k;
+            } else {
+                done = true;
+            }
+            if k != 0 && done {
+                let sub = buf.slice(0, k as uint);
+                // We want to explicitly catch the case when the
+                // closure returned invalid UTF-16, rather than
+                // set `res` to None and continue.
+                let s = String::from_utf16(sub)
+                    .expect("fill_utf16_buf_and_decode: closure created invalid UTF-16");
+                res = Some(s)
+            }
+        }
+        return res;
+    }
+}
+
+pub fn getcwd() -> IoResult<Path> {
+    use libc::DWORD;
+    use libc::GetCurrentDirectoryW;
+    use io::OtherIoError;
+
+    let mut buf = [0 as u16, ..BUF_BYTES];
+    unsafe {
+        if libc::GetCurrentDirectoryW(buf.len() as DWORD, buf.as_mut_ptr()) == 0 as DWORD {
+            return Err(IoError::last_error());
+        }
+    }
+
+    match String::from_utf16(truncate_utf16_at_nul(&buf)) {
+        Some(ref cwd) => Ok(Path::new(cwd)),
+        None => Err(IoError {
+            kind: OtherIoError,
+            desc: "GetCurrentDirectoryW returned invalid UTF-16",
+            detail: None,
+        }),
+    }
+}
+
+pub unsafe fn get_env_pairs() -> Vec<Vec<u8>> {
+    use libc::funcs::extra::kernel32::{
+        GetEnvironmentStringsW,
+        FreeEnvironmentStringsW
+    };
+    let ch = GetEnvironmentStringsW();
+    if ch as uint == 0 {
+        panic!("os::env() failure getting env string from OS: {}",
+               os::last_os_error());
+    }
+    // Here, we lossily decode the string as UTF16.
+    //
+    // The docs suggest that the result should be in Unicode, but
+    // Windows doesn't guarantee it's actually UTF16 -- it doesn't
+    // validate the environment string passed to CreateProcess nor
+    // SetEnvironmentVariable.  Yet, it's unlikely that returning a
+    // raw u16 buffer would be of practical use since the result would
+    // be inherently platform-dependent and introduce additional
+    // complexity to this code.
+    //
+    // Using the non-Unicode version of GetEnvironmentStrings is even
+    // worse since the result is in an OEM code page.  Characters that
+    // can't be encoded in the code page would be turned into question
+    // marks.
+    let mut result = Vec::new();
+    let mut i = 0;
+    while *ch.offset(i) != 0 {
+        let p = &*ch.offset(i);
+        let mut len = 0;
+        while *(p as *const _).offset(len) != 0 {
+            len += 1;
+        }
+        let p = p as *const u16;
+        let s = slice::from_raw_buf(&p, len as uint);
+        result.push(String::from_utf16_lossy(s).into_bytes());
+        i += len as int + 1;
+    }
+    FreeEnvironmentStringsW(ch);
+    result
+}
+
+pub fn split_paths(unparsed: &[u8]) -> Vec<Path> {
+    // On Windows, the PATH environment variable is semicolon separated.  Double
+    // quotes are used as a way of introducing literal semicolons (since
+    // c:\some;dir is a valid Windows path). Double quotes are not themselves
+    // permitted in path names, so there is no way to escape a double quote.
+    // Quoted regions can appear in arbitrary locations, so
+    //
+    //   c:\foo;c:\som"e;di"r;c:\bar
+    //
+    // Should parse as [c:\foo, c:\some;dir, c:\bar].
+    //
+    // (The above is based on testing; there is no clear reference available
+    // for the grammar.)
+
+    let mut parsed = Vec::new();
+    let mut in_progress = Vec::new();
+    let mut in_quote = false;
+
+    for b in unparsed.iter() {
+        match *b {
+            b';' if !in_quote => {
+                parsed.push(Path::new(in_progress.as_slice()));
+                in_progress.truncate(0)
+            }
+            b'"' => {
+                in_quote = !in_quote;
+            }
+            _  => {
+                in_progress.push(*b);
+            }
+        }
+    }
+    parsed.push(Path::new(in_progress));
+    parsed
+}
+
+pub fn join_paths<T: BytesContainer>(paths: &[T]) -> Result<Vec<u8>, &'static str> {
+    let mut joined = Vec::new();
+    let sep = b';';
+
+    for (i, path) in paths.iter().map(|p| p.container_as_bytes()).enumerate() {
+        if i > 0 { joined.push(sep) }
+        if path.contains(&b'"') {
+            return Err("path segment contains `\"`");
+        } else if path.contains(&sep) {
+            joined.push(b'"');
+            joined.push_all(path);
+            joined.push(b'"');
+        } else {
+            joined.push_all(path);
+        }
+    }
+
+    Ok(joined)
+}
+
+pub fn load_self() -> Option<Vec<u8>> {
+    unsafe {
+        fill_utf16_buf_and_decode(|buf, sz| {
+            libc::GetModuleFileNameW(0u as libc::DWORD, buf, sz)
+        }).map(|s| s.to_string().into_bytes())
+    }
+}
+
+pub fn chdir(p: &Path) -> IoResult<()> {
+    let mut p = p.as_str().unwrap().utf16_units().collect::<Vec<u16>>();
+    p.push(0);
+
+    unsafe {
+        match libc::SetCurrentDirectoryW(p.as_ptr()) != (0 as libc::BOOL) {
+            true => Ok(()),
+            false => Err(IoError::last_error()),
+        }
+    }
+}
+
+pub fn page_size() -> uint {
+    use mem;
+    unsafe {
+        let mut info = mem::zeroed();
+        libc::GetSystemInfo(&mut info);
+
+        return info.dwPageSize as uint;
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::truncate_utf16_at_nul;
+
+    #[test]
+    fn test_truncate_utf16_at_nul() {
+        let v = [];
+        let b: &[u16] = &[];
+        assert_eq!(truncate_utf16_at_nul(&v), b);
+
+        let v = [0, 2, 3];
+        assert_eq!(truncate_utf16_at_nul(&v), b);
+
+        let v = [1, 0, 3];
+        let b: &[u16] = &[1];
+        assert_eq!(truncate_utf16_at_nul(&v), b);
+
+        let v = [1, 2, 0];
+        let b: &[u16] = &[1, 2];
+        assert_eq!(truncate_utf16_at_nul(&v), b);
+
+        let v = [1, 2, 3];
+        let b: &[u16] = &[1, 2, 3];
+        assert_eq!(truncate_utf16_at_nul(&v), b);
+    }
+}
diff --git a/src/libstd/sys/windows/pipe.rs b/src/libstd/sys/windows/pipe.rs
index a623c2cd8e2..bf658d0efd0 100644
--- a/src/libstd/sys/windows/pipe.rs
+++ b/src/libstd/sys/windows/pipe.rs
@@ -89,8 +89,7 @@ use libc;
 use c_str::CString;
 use mem;
 use ptr;
-use sync::atomic;
-use rustrt::mutex;
+use sync::{atomic, Mutex};
 use io::{mod, IoError, IoResult};
 use prelude::*;
 
@@ -126,7 +125,7 @@ impl Drop for Event {
 
 struct Inner {
     handle: libc::HANDLE,
-    lock: mutex::NativeMutex,
+    lock: Mutex<()>,
     read_closed: atomic::AtomicBool,
     write_closed: atomic::AtomicBool,
 }
@@ -135,7 +134,7 @@ impl Inner {
     fn new(handle: libc::HANDLE) -> Inner {
         Inner {
             handle: handle,
-            lock: unsafe { mutex::NativeMutex::new() },
+            lock: Mutex::new(()),
             read_closed: atomic::AtomicBool::new(false),
             write_closed: atomic::AtomicBool::new(false),
         }
@@ -329,7 +328,7 @@ impl UnixStream {
         }
     }
 
-    fn handle(&self) -> libc::HANDLE { self.inner.handle }
+    pub fn handle(&self) -> libc::HANDLE { self.inner.handle }
 
     fn read_closed(&self) -> bool {
         self.inner.read_closed.load(atomic::SeqCst)
@@ -585,6 +584,10 @@ impl UnixListener {
             }),
         })
     }
+
+    pub fn handle(&self) -> libc::HANDLE {
+        self.handle
+    }
 }
 
 impl Drop for UnixListener {
@@ -729,6 +732,10 @@ impl UnixAcceptor {
             Ok(())
         }
     }
+
+    pub fn handle(&self) -> libc::HANDLE {
+        self.listener.handle()
+    }
 }
 
 impl Clone for UnixAcceptor {
diff --git a/src/libstd/sys/windows/process.rs b/src/libstd/sys/windows/process.rs
index 3fb5ee34356..0c2c76077dd 100644
--- a/src/libstd/sys/windows/process.rs
+++ b/src/libstd/sys/windows/process.rs
@@ -26,20 +26,17 @@ use sys::fs;
 use sys::{mod, retry, c, wouldblock, set_nonblocking, ms_to_timeval, timer};
 use sys::fs::FileDesc;
 use sys_common::helper_thread::Helper;
-use sys_common::{AsFileDesc, mkerr_libc, timeout};
+use sys_common::{AsInner, mkerr_libc, timeout};
 
 use io::fs::PathExtensions;
-use string::String;
 
 pub use sys_common::ProcessConfig;
 
-/**
- * A value representing a child process.
- *
- * The lifetime of this value is linked to the lifetime of the actual
- * process - the Process destructor calls self.finish() which waits
- * for the process to terminate.
- */
+/// A value representing a child process.
+///
+/// The lifetime of this value is linked to the lifetime of the actual
+/// process - the Process destructor calls self.finish() which waits
+/// for the process to terminate.
 pub struct Process {
     /// The unique id of the process (this should never be negative).
     pid: pid_t,
@@ -105,7 +102,7 @@ impl Process {
     pub fn spawn<K, V, C, P>(cfg: &C, in_fd: Option<P>,
                               out_fd: Option<P>, err_fd: Option<P>)
                               -> IoResult<Process>
-        where C: ProcessConfig<K, V>, P: AsFileDesc,
+        where C: ProcessConfig<K, V>, P: AsInner<FileDesc>,
               K: BytesContainer + Eq + Hash, V: BytesContainer
     {
         use libc::types::os::arch::extra::{DWORD, HANDLE, STARTUPINFO};
@@ -124,8 +121,8 @@ impl Process {
         use libc::funcs::extra::msvcrt::get_osfhandle;
 
         use mem;
-        use iter::Iterator;
-        use str::StrPrelude;
+        use iter::{Iterator, IteratorExt};
+        use str::StrExt;
 
         if cfg.gid().is_some() || cfg.uid().is_some() {
             return Err(IoError {
@@ -195,7 +192,7 @@ impl Process {
                         }
                     }
                     Some(ref fd) => {
-                        let orig = get_osfhandle(fd.as_fd().fd()) as HANDLE;
+                        let orig = get_osfhandle(fd.as_inner().fd()) as HANDLE;
                         if orig == INVALID_HANDLE_VALUE {
                             return Err(super::last_error())
                         }
@@ -225,7 +222,7 @@ impl Process {
 
             with_envp(cfg.env(), |envp| {
                 with_dirp(cfg.cwd(), |dirp| {
-                    let mut cmd_str: Vec<u16> = cmd_str.as_slice().utf16_units().collect();
+                    let mut cmd_str: Vec<u16> = cmd_str.utf16_units().collect();
                     cmd_str.push(0);
                     let created = CreateProcessW(ptr::null(),
                                                  cmd_str.as_mut_ptr(),
@@ -263,16 +260,14 @@ impl Process {
         }
     }
 
-    /**
-     * Waits for a process to exit and returns the exit code, failing
-     * if there is no process with the specified id.
-     *
-     * Note that this is private to avoid race conditions on unix where if
-     * a user calls waitpid(some_process.get_id()) then some_process.finish()
-     * and some_process.destroy() and some_process.finalize() will then either
-     * operate on a none-existent process or, even worse, on a newer process
-     * with the same id.
-     */
+    /// Waits for a process to exit and returns the exit code, failing
+    /// if there is no process with the specified id.
+    ///
+    /// Note that this is private to avoid race conditions on unix where if
+    /// a user calls waitpid(some_process.get_id()) then some_process.finish()
+    /// and some_process.destroy() and some_process.finalize() will then either
+    /// operate on a none-existent process or, even worse, on a newer process
+    /// with the same id.
     pub fn wait(&self, deadline: u64) -> IoResult<ProcessExit> {
         use libc::types::os::arch::extra::DWORD;
         use libc::consts::os::extra::{
@@ -422,9 +417,8 @@ fn make_command_line(prog: &CString, args: &[CString]) -> String {
     }
 }
 
-fn with_envp<K, V, T>(env: Option<&collections::HashMap<K, V>>,
-                      cb: |*mut c_void| -> T) -> T
-    where K: BytesContainer + Eq + Hash, V: BytesContainer
+fn with_envp<K, V, T, F>(env: Option<&collections::HashMap<K, V>>, cb: F) -> T where
+    K: BytesContainer + Eq + Hash, V: BytesContainer, F: FnOnce(*mut c_void) -> T,
 {
     // On Windows we pass an "environment block" which is not a char**, but
     // rather a concatenation of null-terminated k=v\0 sequences, with a final
@@ -435,9 +429,9 @@ fn with_envp<K, V, T>(env: Option<&collections::HashMap<K, V>>,
 
             for pair in env.iter() {
                 let kv = format!("{}={}",
-                                 pair.ref0().container_as_str().unwrap(),
-                                 pair.ref1().container_as_str().unwrap());
-                blk.extend(kv.as_slice().utf16_units());
+                                 pair.0.container_as_str().unwrap(),
+                                 pair.1.container_as_str().unwrap());
+                blk.extend(kv.utf16_units());
                 blk.push(0);
             }
 
@@ -449,7 +443,9 @@ fn with_envp<K, V, T>(env: Option<&collections::HashMap<K, V>>,
     }
 }
 
-fn with_dirp<T>(d: Option<&CString>, cb: |*const u16| -> T) -> T {
+fn with_dirp<T, F>(d: Option<&CString>, cb: F) -> T where
+    F: FnOnce(*const u16) -> T,
+{
     match d {
       Some(dir) => {
           let dir_str = dir.as_str()
@@ -488,24 +484,24 @@ mod tests {
 
         assert_eq!(
             test_wrapper("prog", &["aaa", "bbb", "ccc"]),
-            "prog aaa bbb ccc".to_string()
+            "prog aaa bbb ccc"
         );
 
         assert_eq!(
             test_wrapper("C:\\Program Files\\blah\\blah.exe", &["aaa"]),
-            "\"C:\\Program Files\\blah\\blah.exe\" aaa".to_string()
+            "\"C:\\Program Files\\blah\\blah.exe\" aaa"
         );
         assert_eq!(
             test_wrapper("C:\\Program Files\\test", &["aa\"bb"]),
-            "\"C:\\Program Files\\test\" aa\\\"bb".to_string()
+            "\"C:\\Program Files\\test\" aa\\\"bb"
         );
         assert_eq!(
             test_wrapper("echo", &["a b c"]),
-            "echo \"a b c\"".to_string()
+            "echo \"a b c\""
         );
         assert_eq!(
-            test_wrapper("\u03c0\u042f\u97f3\u00e6\u221e", &[]),
-            "\u03c0\u042f\u97f3\u00e6\u221e".to_string()
+            test_wrapper("\u{03c0}\u{042f}\u{97f3}\u{00e6}\u{221e}", &[]),
+            "\u{03c0}\u{042f}\u{97f3}\u{00e6}\u{221e}"
         );
     }
 }
diff --git a/src/libstd/sys/windows/rwlock.rs b/src/libstd/sys/windows/rwlock.rs
new file mode 100644
index 00000000000..88ce85c39f6
--- /dev/null
+++ b/src/libstd/sys/windows/rwlock.rs
@@ -0,0 +1,53 @@
+// Copyright 2014 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 sys::sync as ffi;
+
+pub struct RWLock { inner: UnsafeCell<ffi::SRWLOCK> }
+
+pub const RWLOCK_INIT: RWLock = RWLock {
+    inner: UnsafeCell { value: ffi::SRWLOCK_INIT }
+};
+
+impl RWLock {
+    #[inline]
+    pub unsafe fn new() -> RWLock { RWLOCK_INIT }
+
+    #[inline]
+    pub unsafe fn read(&self) {
+        ffi::AcquireSRWLockShared(self.inner.get())
+    }
+    #[inline]
+    pub unsafe fn try_read(&self) -> bool {
+        ffi::TryAcquireSRWLockShared(self.inner.get()) != 0
+    }
+    #[inline]
+    pub unsafe fn write(&self) {
+        ffi::AcquireSRWLockExclusive(self.inner.get())
+    }
+    #[inline]
+    pub unsafe fn try_write(&self) -> bool {
+        ffi::TryAcquireSRWLockExclusive(self.inner.get()) != 0
+    }
+    #[inline]
+    pub unsafe fn read_unlock(&self) {
+        ffi::ReleaseSRWLockShared(self.inner.get())
+    }
+    #[inline]
+    pub unsafe fn write_unlock(&self) {
+        ffi::ReleaseSRWLockExclusive(self.inner.get())
+    }
+
+    #[inline]
+    pub unsafe fn destroy(&self) {
+        // ...
+    }
+}
diff --git a/src/libstd/sys/windows/stack_overflow.rs b/src/libstd/sys/windows/stack_overflow.rs
new file mode 100644
index 00000000000..bdf2e0bccb1
--- /dev/null
+++ b/src/libstd/sys/windows/stack_overflow.rs
@@ -0,0 +1,115 @@
+// Copyright 2014 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 rt::util::report_overflow;
+use core::prelude::*;
+use ptr;
+use mem;
+use libc;
+use libc::types::os::arch::extra::{LPVOID, DWORD, LONG, BOOL};
+use sys_common::{stack, thread_info};
+
+pub struct Handler {
+    _data: *mut libc::c_void
+}
+
+impl Handler {
+    pub unsafe fn new() -> Handler {
+        make_handler()
+    }
+}
+
+impl Drop for Handler {
+    fn drop(&mut self) {}
+}
+
+// get_task_info is called from an exception / signal handler.
+// It returns the guard page of the current task or 0 if that
+// guard page doesn't exist. None is returned if there's currently
+// no local task.
+unsafe fn get_task_guard_page() -> uint {
+    thread_info::stack_guard()
+}
+
+// This is initialized in init() and only read from after
+static mut PAGE_SIZE: uint = 0;
+
+#[no_stack_check]
+extern "system" fn vectored_handler(ExceptionInfo: *mut EXCEPTION_POINTERS) -> LONG {
+    unsafe {
+        let rec = &(*(*ExceptionInfo).ExceptionRecord);
+        let code = rec.ExceptionCode;
+
+        if code != EXCEPTION_STACK_OVERFLOW {
+            return EXCEPTION_CONTINUE_SEARCH;
+        }
+
+        // We're calling into functions with stack checks,
+        // however stack checks by limit should be disabled on Windows
+        stack::record_sp_limit(0);
+
+        report_overflow();
+
+        EXCEPTION_CONTINUE_SEARCH
+    }
+}
+
+pub unsafe fn init() {
+    let mut info = mem::zeroed();
+    libc::GetSystemInfo(&mut info);
+    PAGE_SIZE = info.dwPageSize as uint;
+
+    if AddVectoredExceptionHandler(0, vectored_handler) == ptr::null_mut() {
+        panic!("failed to install exception handler");
+    }
+
+    mem::forget(make_handler());
+}
+
+pub unsafe fn cleanup() {
+}
+
+pub unsafe fn make_handler() -> Handler {
+    if SetThreadStackGuarantee(&mut 0x5000) == 0 {
+        panic!("failed to reserve stack space for exception handling");
+    }
+
+    Handler { _data: 0i as *mut libc::c_void }
+}
+
+pub struct EXCEPTION_RECORD {
+    pub ExceptionCode: DWORD,
+    pub ExceptionFlags: DWORD,
+    pub ExceptionRecord: *mut EXCEPTION_RECORD,
+    pub ExceptionAddress: LPVOID,
+    pub NumberParameters: DWORD,
+    pub ExceptionInformation: [LPVOID, ..EXCEPTION_MAXIMUM_PARAMETERS]
+}
+
+pub struct EXCEPTION_POINTERS {
+    pub ExceptionRecord: *mut EXCEPTION_RECORD,
+    pub ContextRecord: LPVOID
+}
+
+pub type PVECTORED_EXCEPTION_HANDLER = extern "system"
+        fn(ExceptionInfo: *mut EXCEPTION_POINTERS) -> LONG;
+
+pub type ULONG = libc::c_ulong;
+
+const EXCEPTION_CONTINUE_SEARCH: LONG = 0;
+const EXCEPTION_MAXIMUM_PARAMETERS: uint = 15;
+const EXCEPTION_STACK_OVERFLOW: DWORD = 0xc00000fd;
+
+extern "system" {
+    fn AddVectoredExceptionHandler(FirstHandler: ULONG,
+                                   VectoredHandler: PVECTORED_EXCEPTION_HANDLER)
+                                  -> LPVOID;
+    fn SetThreadStackGuarantee(StackSizeInBytes: *mut ULONG) -> BOOL;
+}
diff --git a/src/libstd/sys/windows/sync.rs b/src/libstd/sys/windows/sync.rs
new file mode 100644
index 00000000000..cbca47912b5
--- /dev/null
+++ b/src/libstd/sys/windows/sync.rs
@@ -0,0 +1,58 @@
+// Copyright 2014 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::{BOOL, DWORD, c_void, LPVOID};
+use libc::types::os::arch::extra::BOOLEAN;
+
+pub type LPCRITICAL_SECTION = *mut c_void;
+pub type LPCONDITION_VARIABLE = *mut CONDITION_VARIABLE;
+pub type LPSRWLOCK = *mut SRWLOCK;
+
+#[cfg(target_arch = "x86")]
+pub const CRITICAL_SECTION_SIZE: uint = 24;
+#[cfg(target_arch = "x86_64")]
+pub const CRITICAL_SECTION_SIZE: uint = 40;
+
+#[repr(C)]
+pub struct CONDITION_VARIABLE { pub ptr: LPVOID }
+#[repr(C)]
+pub struct SRWLOCK { pub ptr: LPVOID }
+
+pub const CONDITION_VARIABLE_INIT: CONDITION_VARIABLE = CONDITION_VARIABLE {
+    ptr: 0 as *mut _,
+};
+pub const SRWLOCK_INIT: SRWLOCK = SRWLOCK { ptr: 0 as *mut _ };
+
+extern "system" {
+    // critical sections
+    pub fn InitializeCriticalSectionAndSpinCount(
+                    lpCriticalSection: LPCRITICAL_SECTION,
+                    dwSpinCount: DWORD) -> BOOL;
+    pub fn DeleteCriticalSection(lpCriticalSection: LPCRITICAL_SECTION);
+    pub fn EnterCriticalSection(lpCriticalSection: LPCRITICAL_SECTION);
+    pub fn LeaveCriticalSection(lpCriticalSection: LPCRITICAL_SECTION);
+    pub fn TryEnterCriticalSection(lpCriticalSection: LPCRITICAL_SECTION) -> BOOL;
+
+    // condition variables
+    pub fn SleepConditionVariableCS(ConditionVariable: LPCONDITION_VARIABLE,
+                                    CriticalSection: LPCRITICAL_SECTION,
+                                    dwMilliseconds: DWORD) -> BOOL;
+    pub fn WakeConditionVariable(ConditionVariable: LPCONDITION_VARIABLE);
+    pub fn WakeAllConditionVariable(ConditionVariable: LPCONDITION_VARIABLE);
+
+    // slim rwlocks
+    pub fn AcquireSRWLockExclusive(SRWLock: LPSRWLOCK);
+    pub fn AcquireSRWLockShared(SRWLock: LPSRWLOCK);
+    pub fn ReleaseSRWLockExclusive(SRWLock: LPSRWLOCK);
+    pub fn ReleaseSRWLockShared(SRWLock: LPSRWLOCK);
+    pub fn TryAcquireSRWLockExclusive(SRWLock: LPSRWLOCK) -> BOOLEAN;
+    pub fn TryAcquireSRWLockShared(SRWLock: LPSRWLOCK) -> BOOLEAN;
+}
+
diff --git a/src/libstd/sys/windows/tcp.rs b/src/libstd/sys/windows/tcp.rs
index 3baf2be08d2..505e6137bf9 100644
--- a/src/libstd/sys/windows/tcp.rs
+++ b/src/libstd/sys/windows/tcp.rs
@@ -18,8 +18,7 @@ use super::{last_error, last_net_error, retry, sock_t};
 use sync::{Arc, atomic};
 use sys::fs::FileDesc;
 use sys::{mod, c, set_nonblocking, wouldblock, timer};
-use sys_common::{mod, timeout, eof};
-use sys_common::net::*;
+use sys_common::{mod, timeout, eof, net};
 
 pub use sys_common::net::TcpStream;
 
@@ -48,37 +47,35 @@ impl Drop for Event {
 // TCP listeners
 ////////////////////////////////////////////////////////////////////////////////
 
-pub struct TcpListener {
-    inner: FileDesc,
-}
+pub struct TcpListener { sock: sock_t }
 
 impl TcpListener {
     pub fn bind(addr: ip::SocketAddr) -> IoResult<TcpListener> {
         sys::init_net();
 
-        let fd = try!(socket(addr, libc::SOCK_STREAM));
-        let ret = TcpListener { inner: FileDesc::new(fd as libc::c_int, true) };
+        let sock = try!(net::socket(addr, libc::SOCK_STREAM));
+        let ret = TcpListener { sock: sock };
 
         let mut storage = unsafe { mem::zeroed() };
-        let len = addr_to_sockaddr(addr, &mut storage);
+        let len = net::addr_to_sockaddr(addr, &mut storage);
         let addrp = &storage as *const _ as *const libc::sockaddr;
 
-        match unsafe { libc::bind(fd, addrp, len) } {
+        match unsafe { libc::bind(sock, addrp, len) } {
             -1 => Err(last_net_error()),
             _ => Ok(ret),
         }
     }
 
-    pub fn fd(&self) -> sock_t { self.inner.fd as sock_t }
+    pub fn socket(&self) -> sock_t { self.sock }
 
     pub fn listen(self, backlog: int) -> IoResult<TcpAcceptor> {
-        match unsafe { libc::listen(self.fd(), backlog as libc::c_int) } {
+        match unsafe { libc::listen(self.socket(), backlog as libc::c_int) } {
             -1 => Err(last_net_error()),
 
             _ => {
                 let accept = try!(Event::new());
                 let ret = unsafe {
-                    c::WSAEventSelect(self.fd(), accept.handle(), c::FD_ACCEPT)
+                    c::WSAEventSelect(self.socket(), accept.handle(), c::FD_ACCEPT)
                 };
                 if ret != 0 {
                     return Err(last_net_error())
@@ -97,7 +94,13 @@ impl TcpListener {
     }
 
     pub fn socket_name(&mut self) -> IoResult<ip::SocketAddr> {
-        sockname(self.fd(), libc::getsockname)
+        net::sockname(self.socket(), libc::getsockname)
+    }
+}
+
+impl Drop for TcpListener {
+    fn drop(&mut self) {
+        unsafe { super::close_sock(self.sock); }
     }
 }
 
@@ -114,7 +117,7 @@ struct AcceptorInner {
 }
 
 impl TcpAcceptor {
-    pub fn fd(&self) -> sock_t { self.inner.listener.fd() }
+    pub fn socket(&self) -> sock_t { self.inner.listener.socket() }
 
     pub fn accept(&mut self) -> IoResult<TcpStream> {
         // Unlink unix, windows cannot invoke `select` on arbitrary file
@@ -161,13 +164,13 @@ impl TcpAcceptor {
 
             let mut wsaevents: c::WSANETWORKEVENTS = unsafe { mem::zeroed() };
             let ret = unsafe {
-                c::WSAEnumNetworkEvents(self.fd(), events[1], &mut wsaevents)
+                c::WSAEnumNetworkEvents(self.socket(), events[1], &mut wsaevents)
             };
             if ret != 0 { return Err(last_net_error()) }
 
             if wsaevents.lNetworkEvents & c::FD_ACCEPT == 0 { continue }
             match unsafe {
-                libc::accept(self.fd(), ptr::null_mut(), ptr::null_mut())
+                libc::accept(self.socket(), ptr::null_mut(), ptr::null_mut())
             } {
                 -1 if wouldblock() => {}
                 -1 => return Err(last_net_error()),
@@ -175,13 +178,13 @@ impl TcpAcceptor {
                 // Accepted sockets inherit the same properties as the caller,
                 // so we need to deregister our event and switch the socket back
                 // to blocking mode
-                fd => {
-                    let stream = TcpStream::new(fd);
+                socket => {
+                    let stream = TcpStream::new(socket);
                     let ret = unsafe {
-                        c::WSAEventSelect(fd, events[1], 0)
+                        c::WSAEventSelect(socket, events[1], 0)
                     };
                     if ret != 0 { return Err(last_net_error()) }
-                    try!(set_nonblocking(fd, false));
+                    try!(set_nonblocking(socket, false));
                     return Ok(stream)
                 }
             }
@@ -191,7 +194,7 @@ impl TcpAcceptor {
     }
 
     pub fn socket_name(&mut self) -> IoResult<ip::SocketAddr> {
-        sockname(self.fd(), libc::getsockname)
+        net::sockname(self.socket(), libc::getsockname)
     }
 
     pub fn set_timeout(&mut self, timeout: Option<u64>) {
diff --git a/src/libstd/sys/windows/thread.rs b/src/libstd/sys/windows/thread.rs
new file mode 100644
index 00000000000..4498f56c00a
--- /dev/null
+++ b/src/libstd/sys/windows/thread.rs
@@ -0,0 +1,96 @@
+// Copyright 2014 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::prelude::*;
+
+use boxed::Box;
+use cmp;
+use mem;
+use ptr;
+use libc;
+use libc::types::os::arch::extra::{LPSECURITY_ATTRIBUTES, SIZE_T, BOOL,
+                                   LPVOID, DWORD, LPDWORD, HANDLE};
+use thunk::Thunk;
+use sys_common::stack::RED_ZONE;
+use sys_common::thread::*;
+
+pub type rust_thread = HANDLE;
+pub type rust_thread_return = DWORD;
+
+pub type StartFn = extern "system" fn(*mut libc::c_void) -> rust_thread_return;
+
+#[no_stack_check]
+pub extern "system" fn thread_start(main: *mut libc::c_void) -> rust_thread_return {
+    return start_thread(main);
+}
+
+pub mod guard {
+    pub unsafe fn main() -> uint {
+        0
+    }
+
+    pub unsafe fn current() -> uint {
+        0
+    }
+
+    pub unsafe fn init() {
+    }
+}
+
+pub unsafe fn create(stack: uint, p: Thunk) -> rust_thread {
+    let arg: *mut libc::c_void = mem::transmute(box p);
+    // FIXME On UNIX, we guard against stack sizes that are too small but
+    // that's because pthreads enforces that stacks are at least
+    // PTHREAD_STACK_MIN bytes big.  Windows has no such lower limit, it's
+    // just that below a certain threshold you can't do anything useful.
+    // That threshold is application and architecture-specific, however.
+    // For now, the only requirement is that it's big enough to hold the
+    // red zone.  Round up to the next 64 kB because that's what the NT
+    // kernel does, might as well make it explicit.  With the current
+    // 20 kB red zone, that makes for a 64 kB minimum stack.
+    let stack_size = (cmp::max(stack, RED_ZONE) + 0xfffe) & (-0xfffe - 1);
+    let ret = CreateThread(ptr::null_mut(), stack_size as libc::size_t,
+                           thread_start, arg, 0, ptr::null_mut());
+
+    if ret as uint == 0 {
+        // be sure to not leak the closure
+        let _p: Box<Thunk> = mem::transmute(arg);
+        panic!("failed to spawn native thread: {}", ret);
+    }
+    return ret;
+}
+
+pub unsafe fn join(native: rust_thread) {
+    use libc::consts::os::extra::INFINITE;
+    WaitForSingleObject(native, INFINITE);
+}
+
+pub unsafe fn detach(native: rust_thread) {
+    assert!(libc::CloseHandle(native) != 0);
+}
+
+pub unsafe fn yield_now() {
+    // This function will return 0 if there are no other threads to execute,
+    // but this also means that the yield was useless so this isn't really a
+    // case that needs to be worried about.
+    SwitchToThread();
+}
+
+#[allow(non_snake_case)]
+extern "system" {
+    fn CreateThread(lpThreadAttributes: LPSECURITY_ATTRIBUTES,
+                    dwStackSize: SIZE_T,
+                    lpStartAddress: StartFn,
+                    lpParameter: LPVOID,
+                    dwCreationFlags: DWORD,
+                    lpThreadId: LPDWORD) -> HANDLE;
+    fn WaitForSingleObject(hHandle: HANDLE, dwMilliseconds: DWORD) -> DWORD;
+    fn SwitchToThread() -> BOOL;
+}
diff --git a/src/libstd/sys/windows/thread_local.rs b/src/libstd/sys/windows/thread_local.rs
new file mode 100644
index 00000000000..60b0d584db3
--- /dev/null
+++ b/src/libstd/sys/windows/thread_local.rs
@@ -0,0 +1,259 @@
+// Copyright 2014 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 prelude::*;
+
+use libc::types::os::arch::extra::{DWORD, LPVOID, BOOL};
+
+use mem;
+use rt;
+use sys_common::mutex::{MUTEX_INIT, Mutex};
+
+pub type Key = DWORD;
+pub type Dtor = unsafe extern fn(*mut u8);
+
+// Turns out, like pretty much everything, Windows is pretty close the
+// functionality that Unix provides, but slightly different! In the case of
+// TLS, Windows does not provide an API to provide a destructor for a TLS
+// variable. This ends up being pretty crucial to this implementation, so we
+// need a way around this.
+//
+// The solution here ended up being a little obscure, but fear not, the
+// internet has informed me [1][2] that this solution is not unique (no way
+// I could have thought of it as well!). The key idea is to insert some hook
+// somewhere to run arbitrary code on thread termination. With this in place
+// we'll be able to run anything we like, including all TLS destructors!
+//
+// To accomplish this feat, we perform a number of tasks, all contained
+// within this module:
+//
+// * All TLS destructors are tracked by *us*, not the windows runtime. This
+//   means that we have a global list of destructors for each TLS key that
+//   we know about.
+// * When a TLS key is destroyed, we're sure to remove it from the dtor list
+//   if it's in there.
+// * When a thread exits, we run over the entire list and run dtors for all
+//   non-null keys. This attempts to match Unix semantics in this regard.
+//
+// This ends up having the overhead of using a global list, having some
+// locks here and there, and in general just adding some more code bloat. We
+// attempt to optimize runtime by forgetting keys that don't have
+// destructors, but this only gets us so far.
+//
+// For more details and nitty-gritty, see the code sections below!
+//
+// [1]: http://www.codeproject.com/Articles/8113/Thread-Local-Storage-The-C-Way
+// [2]: https://github.com/ChromiumWebApps/chromium/blob/master/base
+//                        /threading/thread_local_storage_win.cc#L42
+
+// NB these are specifically not types from `std::sync` as they currently rely
+// on poisoning and this module needs to operate at a lower level than requiring
+// the thread infrastructure to be in place (useful on the borders of
+// initialization/destruction).
+static DTOR_LOCK: Mutex = MUTEX_INIT;
+static mut DTORS: *mut Vec<(Key, Dtor)> = 0 as *mut _;
+
+// -------------------------------------------------------------------------
+// Native bindings
+//
+// This section is just raw bindings to the native functions that Windows
+// provides, There's a few extra calls to deal with destructors.
+
+#[inline]
+pub unsafe fn create(dtor: Option<Dtor>) -> Key {
+    const TLS_OUT_OF_INDEXES: DWORD = 0xFFFFFFFF;
+    let key = TlsAlloc();
+    assert!(key != TLS_OUT_OF_INDEXES);
+    match dtor {
+        Some(f) => register_dtor(key, f),
+        None => {}
+    }
+    return key;
+}
+
+#[inline]
+pub unsafe fn set(key: Key, value: *mut u8) {
+    let r = TlsSetValue(key, value as LPVOID);
+    debug_assert!(r != 0);
+}
+
+#[inline]
+pub unsafe fn get(key: Key) -> *mut u8 {
+    TlsGetValue(key) as *mut u8
+}
+
+#[inline]
+pub unsafe fn destroy(key: Key) {
+    if unregister_dtor(key) {
+        // FIXME: Currently if a key has a destructor associated with it we
+        // can't actually ever unregister it. If we were to
+        // unregister it, then any key destruction would have to be
+        // serialized with respect to actually running destructors.
+        //
+        // We want to avoid a race where right before run_dtors runs
+        // some destructors TlsFree is called. Allowing the call to
+        // TlsFree would imply that the caller understands that *all
+        // known threads* are not exiting, which is quite a difficult
+        // thing to know!
+        //
+        // For now we just leak all keys with dtors to "fix" this.
+        // Note that source [2] above shows precedent for this sort
+        // of strategy.
+    } else {
+        let r = TlsFree(key);
+        debug_assert!(r != 0);
+    }
+}
+
+extern "system" {
+    fn TlsAlloc() -> DWORD;
+    fn TlsFree(dwTlsIndex: DWORD) -> BOOL;
+    fn TlsGetValue(dwTlsIndex: DWORD) -> LPVOID;
+    fn TlsSetValue(dwTlsIndex: DWORD, lpTlsvalue: LPVOID) -> BOOL;
+}
+
+// -------------------------------------------------------------------------
+// Dtor registration
+//
+// These functions are associated with registering and unregistering
+// destructors. They're pretty simple, they just push onto a vector and scan
+// a vector currently.
+//
+// FIXME: This could probably be at least a little faster with a BTree.
+
+unsafe fn init_dtors() {
+    if !DTORS.is_null() { return }
+
+    let dtors = box Vec::<(Key, Dtor)>::new();
+    DTORS = mem::transmute(dtors);
+
+    rt::at_exit(move|| {
+        DTOR_LOCK.lock();
+        let dtors = DTORS;
+        DTORS = 0 as *mut _;
+        mem::transmute::<_, Box<Vec<(Key, Dtor)>>>(dtors);
+        assert!(DTORS.is_null()); // can't re-init after destructing
+        DTOR_LOCK.unlock();
+    });
+}
+
+unsafe fn register_dtor(key: Key, dtor: Dtor) {
+    DTOR_LOCK.lock();
+    init_dtors();
+    (*DTORS).push((key, dtor));
+    DTOR_LOCK.unlock();
+}
+
+unsafe fn unregister_dtor(key: Key) -> bool {
+    DTOR_LOCK.lock();
+    init_dtors();
+    let ret = {
+        let dtors = &mut *DTORS;
+        let before = dtors.len();
+        dtors.retain(|&(k, _)| k != key);
+        dtors.len() != before
+    };
+    DTOR_LOCK.unlock();
+    ret
+}
+
+// -------------------------------------------------------------------------
+// Where the Magic (TM) Happens
+//
+// If you're looking at this code, and wondering "what is this doing?",
+// you're not alone! I'll try to break this down step by step:
+//
+// # What's up with CRT$XLB?
+//
+// For anything about TLS destructors to work on Windows, we have to be able
+// to run *something* when a thread exits. To do so, we place a very special
+// static in a very special location. If this is encoded in just the right
+// way, the kernel's loader is apparently nice enough to run some function
+// of ours whenever a thread exits! How nice of the kernel!
+//
+// Lots of detailed information can be found in source [1] above, but the
+// gist of it is that this is leveraging a feature of Microsoft's PE format
+// (executable format) which is not actually used by any compilers today.
+// This apparently translates to any callbacks in the ".CRT$XLB" section
+// being run on certain events.
+//
+// So after all that, we use the compiler's #[link_section] feature to place
+// a callback pointer into the magic section so it ends up being called.
+//
+// # What's up with this callback?
+//
+// The callback specified receives a number of parameters from... someone!
+// (the kernel? the runtime? I'm not qute sure!) There are a few events that
+// this gets invoked for, but we're currentl only interested on when a
+// thread or a process "detaches" (exits). The process part happens for the
+// last thread and the thread part happens for any normal thread.
+//
+// # Ok, what's up with running all these destructors?
+//
+// This will likely need to be improved over time, but this function
+// attempts a "poor man's" destructor callback system. To do this we clone a
+// local copy of the dtor list to start out with. This is our fudgy attempt
+// to not hold the lock while destructors run and not worry about the list
+// changing while we're looking at it.
+//
+// Once we've got a list of what to run, we iterate over all keys, check
+// their values, and then run destructors if the values turn out to be non
+// null (setting them to null just beforehand). We do this a few times in a
+// loop to basically match Unix semantics. If we don't reach a fixed point
+// after a short while then we just inevitably leak something most likely.
+//
+// # The article mentions crazy stuff about "/INCLUDE"?
+//
+// It sure does! This seems to work for now, so maybe we'll just run into
+// that if we start linking with msvc?
+
+#[link_section = ".CRT$XLB"]
+#[linkage = "external"]
+#[allow(warnings)]
+pub static p_thread_callback: unsafe extern "system" fn(LPVOID, DWORD,
+                                                        LPVOID) =
+        on_tls_callback;
+
+#[allow(warnings)]
+unsafe extern "system" fn on_tls_callback(h: LPVOID,
+                                          dwReason: DWORD,
+                                          pv: LPVOID) {
+    const DLL_THREAD_DETACH: DWORD = 3;
+    const DLL_PROCESS_DETACH: DWORD = 0;
+    if dwReason == DLL_THREAD_DETACH || dwReason == DLL_PROCESS_DETACH {
+        run_dtors();
+    }
+}
+
+unsafe fn run_dtors() {
+    let mut any_run = true;
+    for _ in range(0, 5i) {
+        if !any_run { break }
+        any_run = false;
+        let dtors = {
+            DTOR_LOCK.lock();
+            let ret = if DTORS.is_null() {
+                Vec::new()
+            } else {
+                (*DTORS).iter().map(|s| *s).collect()
+            };
+            DTOR_LOCK.unlock();
+            ret
+        };
+        for &(key, dtor) in dtors.iter() {
+            let ptr = TlsGetValue(key);
+            if !ptr.is_null() {
+                TlsSetValue(key, 0 as *mut _);
+                dtor(ptr as *mut _);
+                any_run = true;
+            }
+        }
+    }
+}
diff --git a/src/libstd/sys/windows/timer.rs b/src/libstd/sys/windows/timer.rs
index 9af3a7c8b6e..7e4dd768aa9 100644
--- a/src/libstd/sys/windows/timer.rs
+++ b/src/libstd/sys/windows/timer.rs
@@ -20,7 +20,7 @@
 //! Other than that, the implementation is pretty straightforward in terms of
 //! the other two implementations of timers with nothing *that* new showing up.
 
-pub use self::Req::*;
+use self::Req::*;
 
 use libc;
 use ptr;
@@ -32,7 +32,7 @@ use sys_common::helper_thread::Helper;
 use prelude::*;
 use io::IoResult;
 
-helper_init!(static HELPER: Helper<Req>)
+helper_init! { static HELPER: Helper<Req> }
 
 pub trait Callback {
     fn call(&mut self);
diff --git a/src/libstd/sys/windows/tty.rs b/src/libstd/sys/windows/tty.rs
index 0e7b06cbb94..f793de5bb57 100644
--- a/src/libstd/sys/windows/tty.rs
+++ b/src/libstd/sys/windows/tty.rs
@@ -111,9 +111,9 @@ impl TTY {
     }
 
     pub fn write(&mut self, buf: &[u8]) -> IoResult<()> {
-        let utf16 = match from_utf8(buf) {
+        let utf16 = match from_utf8(buf).ok() {
             Some(utf8) => {
-                utf8.as_slice().utf16_units().collect::<Vec<u16>>()
+                utf8.utf16_units().collect::<Vec<u16>>()
             }
             None => return Err(invalid_encoding()),
         };