about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2014-06-04 00:01:40 -0700
committerAlex Crichton <alex@alexcrichton.com>2014-06-06 23:00:01 -0700
commit75014f7b1790e7ebdf13d38acc04dfdab6e450e9 (patch)
tree46fb046e002a37ba60f6e8b8ef5ee0675fbb7fd8
parentd743b8831e6dc5b390af112cc23159d667cf583b (diff)
downloadrust-75014f7b1790e7ebdf13d38acc04dfdab6e450e9.tar.gz
rust-75014f7b1790e7ebdf13d38acc04dfdab6e450e9.zip
libs: Fix miscellaneous fallout of librustrt
-rw-r--r--src/liballoc/lib.rs15
-rw-r--r--src/liballoc/util.rs17
-rw-r--r--src/libcollections/lib.rs4
-rw-r--r--src/libcollections/slice.rs8
-rw-r--r--src/libgreen/basic.rs53
-rw-r--r--src/libgreen/lib.rs6
-rw-r--r--src/libgreen/sched.rs6
-rw-r--r--src/libgreen/simple.rs5
-rw-r--r--src/libgreen/stack.rs20
-rw-r--r--src/libgreen/task.rs29
-rw-r--r--src/liblibc/lib.rs7
-rw-r--r--src/libnative/io/addrinfo.rs2
-rw-r--r--src/libnative/io/file_win32.rs158
-rw-r--r--src/libnative/io/net.rs6
-rw-r--r--src/libnative/io/pipe_win32.rs37
-rw-r--r--src/libnative/io/process.rs24
-rw-r--r--src/libnative/io/timer_win32.rs21
-rw-r--r--src/librustrt/c_str.rs8
-rw-r--r--src/librustrt/lib.rs1
-rw-r--r--src/librustrt/local_data.rs2
-rw-r--r--src/librustrt/task.rs29
-rw-r--r--src/librustrt/unwind.rs21
-rw-r--r--src/librustrt/util.rs4
-rw-r--r--src/librustuv/lib.rs21
-rw-r--r--src/librustuv/uvll.rs5
-rw-r--r--src/libstd/io/mod.rs5
-rw-r--r--src/libstd/io/net/tcp.rs3
-rw-r--r--src/libstd/lib.rs5
-rw-r--r--src/libstd/rt/backtrace.rs6
-rw-r--r--src/libstd/rt/mod.rs5
-rw-r--r--src/libstd/task.rs10
-rw-r--r--src/libsync/mutex.rs2
-rw-r--r--src/test/run-pass/running-with-no-runtime.rs4
-rw-r--r--src/test/run-pass/tcp-stress.rs2
34 files changed, 263 insertions, 288 deletions
diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs
index 511983da4f7..ca7ed6f4ba0 100644
--- a/src/liballoc/lib.rs
+++ b/src/liballoc/lib.rs
@@ -96,6 +96,21 @@ pub mod owned;
 pub mod arc;
 pub mod rc;
 
+// FIXME(#14344): When linking liballoc with libstd, this library will be linked
+//                as an rlib (it only exists as an rlib). It turns out that an
+//                optimized standard library doesn't actually use *any* symbols
+//                from this library. Everything is inlined and optimized away.
+//                This means that linkers will actually omit the object for this
+//                file, even though it may be needed in the future.
+//
+//                To get around this for now, we define a dummy symbol which
+//                will never get inlined so the stdlib can call it. The stdlib's
+//                reference to this symbol will cause this library's object file
+//                to get linked in to libstd successfully (the linker won't
+//                optimize it out).
+#[doc(hidden)]
+pub fn fixme_14344_be_sure_to_link_to_collections() {}
+
 #[cfg(not(test))]
 #[doc(hidden)]
 mod std {
diff --git a/src/liballoc/util.rs b/src/liballoc/util.rs
index 64d62035890..7e35af79eab 100644
--- a/src/liballoc/util.rs
+++ b/src/liballoc/util.rs
@@ -28,20 +28,3 @@ fn align_to(size: uint, align: uint) -> uint {
     assert!(align != 0);
     (size + align - 1) & !(align - 1)
 }
-
-// FIXME(#14344): When linking liballoc with libstd, this library will be linked
-//                as an rlib (it only exists as an rlib). It turns out that an
-//                optimized standard library doesn't actually use *any* symbols
-//                from this library. Everything is inlined and optimized away.
-//                This means that linkers will actually omit the object for this
-//                file, even though it may be needed in the future.
-//
-//                To get around this for now, we define a dummy symbol which
-//                will never get inlined so the stdlib can call it. The stdlib's
-//                reference to this symbol will cause this library's object file
-//                to get linked in to libstd successfully (the linker won't
-//                optimize it out).
-#[deprecated]
-#[doc(hidden)]
-pub fn make_stdlib_link_work() {}
-
diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs
index a65c06107ce..c46ea84a765 100644
--- a/src/libcollections/lib.rs
+++ b/src/libcollections/lib.rs
@@ -72,6 +72,10 @@ fn expect<T>(a: core::option::Option<T>, b: &str) -> T {
     }
 }
 
+// FIXME(#14344) this shouldn't be necessary
+#[doc(hidden)]
+pub fn fixme_14344_be_sure_to_link_to_collections() {}
+
 #[cfg(not(test))]
 mod std {
     pub use core::fmt;      // necessary for fail!()
diff --git a/src/libcollections/slice.rs b/src/libcollections/slice.rs
index e631b8b77cf..4798218e3ff 100644
--- a/src/libcollections/slice.rs
+++ b/src/libcollections/slice.rs
@@ -862,7 +862,7 @@ mod tests {
     use std::prelude::*;
     use std::rand::{Rng, task_rng};
     use std::rc::Rc;
-    use std::unstable;
+    use std::rt;
     use slice::*;
 
     use vec::Vec;
@@ -1104,9 +1104,9 @@ mod tests {
     #[test]
     fn test_swap_remove_noncopyable() {
         // Tests that we don't accidentally run destructors twice.
-        let mut v = vec![unstable::sync::Exclusive::new(()),
-                         unstable::sync::Exclusive::new(()),
-                         unstable::sync::Exclusive::new(())];
+        let mut v = vec![rt::exclusive::Exclusive::new(()),
+                         rt::exclusive::Exclusive::new(()),
+                         rt::exclusive::Exclusive::new(())];
         let mut _e = v.swap_remove(0);
         assert_eq!(v.len(), 2);
         _e = v.swap_remove(1);
diff --git a/src/libgreen/basic.rs b/src/libgreen/basic.rs
index 1ebebbe555e..7f033a1bc61 100644
--- a/src/libgreen/basic.rs
+++ b/src/libgreen/basic.rs
@@ -20,7 +20,7 @@ use std::sync::atomics;
 use std::mem;
 use std::rt::rtio::{EventLoop, IoFactory, RemoteCallback};
 use std::rt::rtio::{PausableIdleCallback, Callback};
-use std::unstable::sync::Exclusive;
+use std::rt::exclusive::Exclusive;
 
 /// This is the only exported function from this module.
 pub fn event_loop() -> Box<EventLoop:Send> {
@@ -31,7 +31,7 @@ struct BasicLoop {
     work: Vec<proc():Send>,             // pending work
     remotes: Vec<(uint, Box<Callback:Send>)>,
     next_remote: uint,
-    messages: Exclusive<Vec<Message>>,
+    messages: Arc<Exclusive<Vec<Message>>>,
     idle: Option<Box<Callback:Send>>,
     idle_active: Option<Arc<atomics::AtomicBool>>,
 }
@@ -46,7 +46,7 @@ impl BasicLoop {
             idle_active: None,
             next_remote: 0,
             remotes: vec![],
-            messages: Exclusive::new(vec![]),
+            messages: Arc::new(Exclusive::new(Vec::new())),
         }
     }
 
@@ -61,19 +61,10 @@ impl BasicLoop {
 
     fn remote_work(&mut self) {
         let messages = unsafe {
-            self.messages.with(|messages| {
-                if messages.len() > 0 {
-                    Some(mem::replace(messages, vec![]))
-                } else {
-                    None
-                }
-            })
-        };
-        let messages = match messages {
-            Some(m) => m, None => return
+            mem::replace(&mut *self.messages.lock(), Vec::new())
         };
-        for message in messages.iter() {
-            self.message(*message);
+        for message in messages.move_iter() {
+            self.message(message);
         }
     }
 
@@ -125,13 +116,13 @@ impl EventLoop for BasicLoop {
             }
 
             unsafe {
+                let mut messages = self.messages.lock();
                 // We block here if we have no messages to process and we may
                 // receive a message at a later date
-                self.messages.hold_and_wait(|messages| {
-                    self.remotes.len() > 0 &&
-                        messages.len() == 0 &&
-                        self.work.len() == 0
-                })
+                if self.remotes.len() > 0 && messages.len() == 0 &&
+                   self.work.len() == 0 {
+                    messages.wait()
+                }
             }
         }
     }
@@ -165,33 +156,29 @@ impl EventLoop for BasicLoop {
 }
 
 struct BasicRemote {
-    queue: Exclusive<Vec<Message>>,
+    queue: Arc<Exclusive<Vec<Message>>>,
     id: uint,
 }
 
 impl BasicRemote {
-    fn new(queue: Exclusive<Vec<Message>>, id: uint) -> BasicRemote {
+    fn new(queue: Arc<Exclusive<Vec<Message>>>, id: uint) -> BasicRemote {
         BasicRemote { queue: queue, id: id }
     }
 }
 
 impl RemoteCallback for BasicRemote {
     fn fire(&mut self) {
-        unsafe {
-            self.queue.hold_and_signal(|queue| {
-                queue.push(RunRemote(self.id));
-            })
-        }
+        let mut queue = unsafe { self.queue.lock() };
+        queue.push(RunRemote(self.id));
+        queue.signal();
     }
 }
 
 impl Drop for BasicRemote {
     fn drop(&mut self) {
-        unsafe {
-            self.queue.hold_and_signal(|queue| {
-                queue.push(RemoveRemote(self.id));
-            })
-        }
+        let mut queue = unsafe { self.queue.lock() };
+        queue.push(RemoveRemote(self.id));
+        queue.signal();
     }
 }
 
@@ -216,7 +203,7 @@ impl Drop for BasicPausable {
 
 #[cfg(test)]
 mod test {
-    use std::task::TaskOpts;
+    use std::rt::task::TaskOpts;
 
     use basic;
     use PoolConfig;
diff --git a/src/libgreen/lib.rs b/src/libgreen/lib.rs
index c75d69480ce..333ac80907f 100644
--- a/src/libgreen/lib.rs
+++ b/src/libgreen/lib.rs
@@ -160,7 +160,7 @@
 //! # Using a scheduler pool
 //!
 //! ```rust
-//! use std::task::TaskOpts;
+//! use std::rt::task::TaskOpts;
 //! use green::{SchedPool, PoolConfig};
 //! use green::sched::{PinnedTask, TaskFromFriend};
 //!
@@ -221,10 +221,10 @@ use std::mem::replace;
 use std::os;
 use std::rt::rtio;
 use std::rt::thread::Thread;
+use std::rt::task::TaskOpts;
 use std::rt;
 use std::sync::atomics::{SeqCst, AtomicUint, INIT_ATOMIC_UINT};
 use std::sync::deque;
-use std::task::TaskOpts;
 
 use sched::{Shutdown, Scheduler, SchedHandle, TaskFromFriend, NewNeighbor};
 use sleeper_list::SleeperList;
@@ -319,7 +319,7 @@ pub fn run(event_loop_factory: fn() -> Box<rtio::EventLoop:Send>,
     let mut pool = SchedPool::new(cfg);
     let (tx, rx) = channel();
     let mut opts = TaskOpts::new();
-    opts.notify_chan = Some(tx);
+    opts.on_exit = Some(proc(r) tx.send(r));
     opts.name = Some("<main>".into_maybe_owned());
     pool.spawn(opts, main);
 
diff --git a/src/libgreen/sched.rs b/src/libgreen/sched.rs
index e410d2719b1..f55dc92eac6 100644
--- a/src/libgreen/sched.rs
+++ b/src/libgreen/sched.rs
@@ -10,11 +10,11 @@
 
 use std::mem;
 use std::rt::local::Local;
+use std::rt::mutex::NativeMutex;
 use std::rt::rtio::{RemoteCallback, PausableIdleCallback, Callback, EventLoop};
 use std::rt::task::BlockedTask;
 use std::rt::task::Task;
 use std::sync::deque;
-use std::unstable::mutex::NativeMutex;
 use std::raw;
 
 use std::rand::{XorShiftRng, Rng, Rand};
@@ -1022,7 +1022,7 @@ fn new_sched_rng() -> XorShiftRng {
 mod test {
     use rustuv;
 
-    use std::task::TaskOpts;
+    use std::rt::task::TaskOpts;
     use std::rt::task::Task;
     use std::rt::local::Local;
 
@@ -1475,7 +1475,7 @@ mod test {
 
     #[test]
     fn test_spawn_sched_blocking() {
-        use std::unstable::mutex::{StaticNativeMutex, NATIVE_MUTEX_INIT};
+        use std::rt::mutex::{StaticNativeMutex, NATIVE_MUTEX_INIT};
         static mut LOCK: StaticNativeMutex = NATIVE_MUTEX_INIT;
 
         // Testing that a task in one scheduler can block in foreign code
diff --git a/src/libgreen/simple.rs b/src/libgreen/simple.rs
index 49aef15f93b..7b738ed9c7c 100644
--- a/src/libgreen/simple.rs
+++ b/src/libgreen/simple.rs
@@ -15,10 +15,9 @@ use std::any::Any;
 use std::mem;
 use std::rt::Runtime;
 use std::rt::local::Local;
+use std::rt::mutex::NativeMutex;
 use std::rt::rtio;
-use std::rt::task::{Task, BlockedTask};
-use std::task::TaskOpts;
-use std::unstable::mutex::NativeMutex;
+use std::rt::task::{Task, BlockedTask, TaskOpts};
 
 struct SimpleTask {
     lock: NativeMutex,
diff --git a/src/libgreen/stack.rs b/src/libgreen/stack.rs
index f42d636cafb..2e385f75e1d 100644
--- a/src/libgreen/stack.rs
+++ b/src/libgreen/stack.rs
@@ -8,9 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::rt::env::max_cached_stacks;
+use std::sync::atomics;
 use std::os::{errno, page_size, MemoryMap, MapReadable, MapWritable,
-              MapNonStandardFlags, MapVirtual};
+              MapNonStandardFlags, MapVirtual, getenv};
 use libc;
 
 /// A task's stack. The name "Stack" is a vestige of segmented stacks.
@@ -151,6 +151,22 @@ impl StackPool {
     }
 }
 
+fn max_cached_stacks() -> uint {
+    static mut AMT: atomics::AtomicUint = atomics::INIT_ATOMIC_UINT;
+    match unsafe { AMT.load(atomics::SeqCst) } {
+        0 => {}
+        n => return n - 1,
+    }
+    let amt = getenv("RUST_MAX_CACHED_STACKS").and_then(|s| from_str(s.as_slice()));
+    // This default corresponds to 20M of cache per scheduler (at the
+    // default size).
+    let amt = amt.unwrap_or(10);
+    // 0 is our sentinel value, so ensure that we'll never see 0 after
+    // initialization has run
+    unsafe { AMT.store(amt + 1, atomics::SeqCst); }
+    return amt;
+}
+
 extern {
     fn rust_valgrind_stack_register(start: *libc::uintptr_t,
                                     end: *libc::uintptr_t) -> libc::c_uint;
diff --git a/src/libgreen/task.rs b/src/libgreen/task.rs
index f50f65af6f9..91ebad3b3f8 100644
--- a/src/libgreen/task.rs
+++ b/src/libgreen/task.rs
@@ -22,13 +22,12 @@ use std::any::Any;
 use std::mem;
 use std::raw;
 use std::rt::Runtime;
-use std::rt::env;
 use std::rt::local::Local;
+use std::rt::mutex::NativeMutex;
 use std::rt::rtio;
 use std::rt::stack;
-use std::rt::task::{Task, BlockedTask, SendMessage};
-use std::task::TaskOpts;
-use std::unstable::mutex::NativeMutex;
+use std::rt::task::{Task, BlockedTask, TaskOpts};
+use std::rt;
 
 use context::Context;
 use coroutine::Coroutine;
@@ -142,7 +141,7 @@ impl GreenTask {
         let mut ops = GreenTask::new_typed(None, TypeGreen(Some(home)));
 
         // Allocate a stack for us to run on
-        let stack_size = stack_size.unwrap_or_else(|| env::min_stack());
+        let stack_size = stack_size.unwrap_or_else(|| rt::min_stack());
         let mut stack = stack_pool.take_stack(stack_size);
         let context = Context::new(bootstrap_green_task, ops.as_uint(), start,
                                    &mut stack);
@@ -176,23 +175,13 @@ impl GreenTask {
     pub fn configure(pool: &mut StackPool,
                      opts: TaskOpts,
                      f: proc():Send) -> Box<GreenTask> {
-        let TaskOpts {
-            notify_chan, name, stack_size,
-            stderr, stdout,
-        } = opts;
+        let TaskOpts { name, stack_size, on_exit } = opts;
 
         let mut green = GreenTask::new(pool, stack_size, f);
         {
             let task = green.task.get_mut_ref();
             task.name = name;
-            task.stderr = stderr;
-            task.stdout = stdout;
-            match notify_chan {
-                Some(chan) => {
-                    task.death.on_exit = Some(SendMessage(chan));
-                }
-                None => {}
-            }
+            task.death.on_exit = on_exit;
         }
         return green;
     }
@@ -490,7 +479,7 @@ mod tests {
     use std::rt::local::Local;
     use std::rt::task::Task;
     use std::task;
-    use std::task::TaskOpts;
+    use std::rt::task::TaskOpts;
 
     use super::super::{PoolConfig, SchedPool};
     use super::GreenTask;
@@ -529,7 +518,7 @@ mod tests {
         opts.name = Some("test".into_maybe_owned());
         opts.stack_size = Some(20 * 4096);
         let (tx, rx) = channel();
-        opts.notify_chan = Some(tx);
+        opts.on_exit = Some(proc(r) tx.send(r));
         spawn_opts(opts, proc() {});
         assert!(rx.recv().is_ok());
     }
@@ -538,7 +527,7 @@ mod tests {
     fn smoke_opts_fail() {
         let mut opts = TaskOpts::new();
         let (tx, rx) = channel();
-        opts.notify_chan = Some(tx);
+        opts.on_exit = Some(proc(r) tx.send(r));
         spawn_opts(opts, proc() { fail!() });
         assert!(rx.recv().is_err());
     }
diff --git a/src/liblibc/lib.rs b/src/liblibc/lib.rs
index 5b7f58fcb81..b833b2a6515 100644
--- a/src/liblibc/lib.rs
+++ b/src/liblibc/lib.rs
@@ -172,6 +172,7 @@ pub use funcs::bsd43::{shutdown};
 #[cfg(unix)] pub use consts::os::posix88::{ENOTCONN, ECONNABORTED, EADDRNOTAVAIL, EINTR};
 #[cfg(unix)] pub use consts::os::posix88::{EADDRINUSE, ENOENT, EISDIR, EAGAIN, EWOULDBLOCK};
 #[cfg(unix)] pub use consts::os::posix88::{ECANCELED, SIGINT, EINPROGRESS};
+#[cfg(unix)] pub use consts::os::posix88::{ENOSYS, ENOTTY, ETIMEDOUT};
 #[cfg(unix)] pub use consts::os::posix88::{SIGTERM, SIGKILL, SIGPIPE, PROT_NONE};
 #[cfg(unix)] pub use consts::os::posix01::{SIG_IGN};
 #[cfg(unix)] pub use consts::os::bsd44::{AF_UNIX};
@@ -195,7 +196,7 @@ pub use funcs::bsd43::{shutdown};
 #[cfg(windows)] pub use consts::os::c95::{WSAECONNREFUSED, WSAECONNRESET, WSAEACCES};
 #[cfg(windows)] pub use consts::os::c95::{WSAEWOULDBLOCK, WSAENOTCONN, WSAECONNABORTED};
 #[cfg(windows)] pub use consts::os::c95::{WSAEADDRNOTAVAIL, WSAEADDRINUSE, WSAEINTR};
-#[cfg(windows)] pub use consts::os::c95::{WSAEINPROGRESS};
+#[cfg(windows)] pub use consts::os::c95::{WSAEINPROGRESS, WSAEINVAL};
 #[cfg(windows)] pub use consts::os::extra::{ERROR_INSUFFICIENT_BUFFER};
 #[cfg(windows)] pub use consts::os::extra::{O_BINARY, O_NOINHERIT, PAGE_NOACCESS};
 #[cfg(windows)] pub use consts::os::extra::{PAGE_READONLY, PAGE_READWRITE, PAGE_EXECUTE};
@@ -205,6 +206,9 @@ pub use funcs::bsd43::{shutdown};
 #[cfg(windows)] pub use consts::os::extra::{ERROR_ALREADY_EXISTS, ERROR_NO_DATA};
 #[cfg(windows)] pub use consts::os::extra::{ERROR_FILE_NOT_FOUND, ERROR_INVALID_NAME};
 #[cfg(windows)] pub use consts::os::extra::{ERROR_BROKEN_PIPE, ERROR_INVALID_FUNCTION};
+#[cfg(windows)] pub use consts::os::extra::{ERROR_CALL_NOT_IMPLEMENTED};
+#[cfg(windows)] pub use consts::os::extra::{ERROR_NOTHING_TO_TERMINATE};
+#[cfg(windows)] pub use consts::os::extra::{ERROR_INVALID_HANDLE};
 #[cfg(windows)] pub use consts::os::extra::{TRUE, FALSE, INFINITE};
 #[cfg(windows)] pub use consts::os::extra::{PROCESS_TERMINATE, PROCESS_QUERY_INFORMATION};
 #[cfg(windows)] pub use consts::os::extra::{STILL_ACTIVE, DETACHED_PROCESS};
@@ -1758,6 +1762,7 @@ pub mod consts {
             pub static ERROR_NO_DATA: c_int = 232;
             pub static ERROR_INVALID_ADDRESS : c_int = 487;
             pub static ERROR_PIPE_CONNECTED: c_int = 535;
+            pub static ERROR_NOTHING_TO_TERMINATE: c_int = 758;
             pub static ERROR_OPERATION_ABORTED: c_int = 995;
             pub static ERROR_IO_PENDING: c_int = 997;
             pub static ERROR_FILE_INVALID : c_int = 1006;
diff --git a/src/libnative/io/addrinfo.rs b/src/libnative/io/addrinfo.rs
index b79061dd9d6..255c3f4bd21 100644
--- a/src/libnative/io/addrinfo.rs
+++ b/src/libnative/io/addrinfo.rs
@@ -92,8 +92,6 @@ extern "system" {
     fn freeaddrinfo(res: *mut libc::addrinfo);
     #[cfg(not(windows))]
     fn gai_strerror(errcode: c_int) -> *c_char;
-    #[cfg(windows)]
-    fn WSAGetLastError() -> c_int;
 }
 
 #[cfg(windows)]
diff --git a/src/libnative/io/file_win32.rs b/src/libnative/io/file_win32.rs
index 2cf54ab4007..2a5b78e5506 100644
--- a/src/libnative/io/file_win32.rs
+++ b/src/libnative/io/file_win32.rs
@@ -14,17 +14,14 @@ use alloc::arc::Arc;
 use libc::{c_int, c_void};
 use libc;
 use std::c_str::CString;
-use std::io::IoError;
-use std::io;
 use std::mem;
 use std::os::win32::{as_utf16_p, fill_utf16_buf_and_decode};
 use std::ptr;
 use std::rt::rtio;
+use std::rt::rtio::IoResult;
 use std::str;
 use std::vec;
 
-use io::IoResult;
-
 pub type fd_t = libc::c_int;
 
 struct Inner {
@@ -52,7 +49,7 @@ impl FileDesc {
         }) }
     }
 
-    pub fn inner_read(&mut self, buf: &mut [u8]) -> Result<uint, IoError> {
+    pub fn inner_read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
         let mut read = 0;
         let ret = unsafe {
             libc::ReadFile(self.handle(), buf.as_ptr() as libc::LPVOID,
@@ -65,7 +62,7 @@ impl FileDesc {
             Err(super::last_error())
         }
     }
-    pub fn inner_write(&mut self, buf: &[u8]) -> Result<(), IoError> {
+    pub fn inner_write(&mut self, buf: &[u8]) -> IoResult<()> {
         let mut cur = buf.as_ptr();
         let mut remaining = buf.len();
         while remaining > 0 {
@@ -93,11 +90,11 @@ impl FileDesc {
 
     // A version of seek that takes &self so that tell can call it
     //   - the private seek should of course take &mut self.
-    fn seek_common(&self, pos: i64, style: io::SeekStyle) -> Result<u64, IoError> {
+    fn seek_common(&self, pos: i64, style: rtio::SeekStyle) -> IoResult<u64> {
         let whence = match style {
-            io::SeekSet => libc::FILE_BEGIN,
-            io::SeekEnd => libc::FILE_END,
-            io::SeekCur => libc::FILE_CURRENT,
+            rtio::SeekSet => libc::FILE_BEGIN,
+            rtio::SeekEnd => libc::FILE_END,
+            rtio::SeekCur => libc::FILE_CURRENT,
         };
         unsafe {
             let mut newpos = 0;
@@ -111,27 +108,15 @@ impl FileDesc {
 
 }
 
-impl io::Reader for FileDesc {
-    fn read(&mut self, buf: &mut [u8]) -> io::IoResult<uint> {
-        self.inner_read(buf)
-    }
-}
-
-impl io::Writer for FileDesc {
-    fn write(&mut self, buf: &[u8]) -> io::IoResult<()> {
-        self.inner_write(buf)
-    }
-}
-
 impl rtio::RtioFileStream for FileDesc {
-    fn read(&mut self, buf: &mut [u8]) -> Result<int, IoError> {
+    fn read(&mut self, buf: &mut [u8]) -> IoResult<int> {
         self.inner_read(buf).map(|i| i as int)
     }
-    fn write(&mut self, buf: &[u8]) -> Result<(), IoError> {
+    fn write(&mut self, buf: &[u8]) -> IoResult<()> {
         self.inner_write(buf)
     }
 
-    fn pread(&mut self, buf: &mut [u8], offset: u64) -> Result<int, IoError> {
+    fn pread(&mut self, buf: &mut [u8], offset: u64) -> IoResult<int> {
         let mut read = 0;
         let mut overlap: libc::OVERLAPPED = unsafe { mem::zeroed() };
         overlap.Offset = offset as libc::DWORD;
@@ -147,7 +132,7 @@ impl rtio::RtioFileStream for FileDesc {
             Err(super::last_error())
         }
     }
-    fn pwrite(&mut self, buf: &[u8], mut offset: u64) -> Result<(), IoError> {
+    fn pwrite(&mut self, buf: &[u8], mut offset: u64) -> IoResult<()> {
         let mut cur = buf.as_ptr();
         let mut remaining = buf.len();
         let mut overlap: libc::OVERLAPPED = unsafe { mem::zeroed() };
@@ -171,36 +156,36 @@ impl rtio::RtioFileStream for FileDesc {
         Ok(())
     }
 
-    fn seek(&mut self, pos: i64, style: io::SeekStyle) -> Result<u64, IoError> {
+    fn seek(&mut self, pos: i64, style: rtio::SeekStyle) -> IoResult<u64> {
         self.seek_common(pos, style)
     }
 
-    fn tell(&self) -> Result<u64, IoError> {
-        self.seek_common(0, io::SeekCur)
+    fn tell(&self) -> IoResult<u64> {
+        self.seek_common(0, rtio::SeekCur)
     }
 
-    fn fsync(&mut self) -> Result<(), IoError> {
+    fn fsync(&mut self) -> IoResult<()> {
         super::mkerr_winbool(unsafe {
             libc::FlushFileBuffers(self.handle())
         })
     }
 
-    fn datasync(&mut self) -> Result<(), IoError> { return self.fsync(); }
+    fn datasync(&mut self) -> IoResult<()> { return self.fsync(); }
 
-    fn truncate(&mut self, offset: i64) -> Result<(), IoError> {
+    fn truncate(&mut self, offset: i64) -> IoResult<()> {
         let orig_pos = try!(self.tell());
-        let _ = try!(self.seek(offset, io::SeekSet));
+        let _ = try!(self.seek(offset, rtio::SeekSet));
         let ret = unsafe {
             match libc::SetEndOfFile(self.handle()) {
                 0 => Err(super::last_error()),
                 _ => Ok(())
             }
         };
-        let _ = self.seek(orig_pos as i64, io::SeekSet);
+        let _ = self.seek(orig_pos as i64, rtio::SeekSet);
         return ret;
     }
 
-    fn fstat(&mut self) -> IoResult<io::FileStat> {
+    fn fstat(&mut self) -> IoResult<rtio::FileStat> {
         let mut stat: libc::stat = unsafe { mem::zeroed() };
         match unsafe { libc::fstat(self.fd(), &mut stat) } {
             0 => Ok(mkstat(&stat)),
@@ -210,10 +195,10 @@ impl rtio::RtioFileStream for FileDesc {
 }
 
 impl rtio::RtioPipe for FileDesc {
-    fn read(&mut self, buf: &mut [u8]) -> Result<uint, IoError> {
+    fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
         self.inner_read(buf)
     }
-    fn write(&mut self, buf: &[u8]) -> Result<(), IoError> {
+    fn write(&mut self, buf: &[u8]) -> IoResult<()> {
         self.inner_write(buf)
     }
     fn clone(&self) -> Box<rtio::RtioPipe:Send> {
@@ -225,10 +210,10 @@ impl rtio::RtioPipe for FileDesc {
     // std::io::PipeStream. If the functionality is exposed in the future, then
     // these methods will need to be implemented.
     fn close_read(&mut self) -> IoResult<()> {
-        Err(io::standard_error(io::InvalidInput))
+        Err(super::unimpl())
     }
     fn close_write(&mut self) -> IoResult<()> {
-        Err(io::standard_error(io::InvalidInput))
+        Err(super::unimpl())
     }
     fn set_timeout(&mut self, _t: Option<u64>) {}
     fn set_read_timeout(&mut self, _t: Option<u64>) {}
@@ -236,16 +221,16 @@ impl rtio::RtioPipe for FileDesc {
 }
 
 impl rtio::RtioTTY for FileDesc {
-    fn read(&mut self, buf: &mut [u8]) -> Result<uint, IoError> {
+    fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
         self.inner_read(buf)
     }
-    fn write(&mut self, buf: &[u8]) -> Result<(), IoError> {
+    fn write(&mut self, buf: &[u8]) -> IoResult<()> {
         self.inner_write(buf)
     }
-    fn set_raw(&mut self, _raw: bool) -> Result<(), IoError> {
+    fn set_raw(&mut self, _raw: bool) -> IoResult<()> {
         Err(super::unimpl())
     }
-    fn get_winsize(&mut self) -> Result<(int, int), IoError> {
+    fn get_winsize(&mut self) -> IoResult<(int, int)> {
         Err(super::unimpl())
     }
     fn isatty(&self) -> bool { false }
@@ -268,24 +253,24 @@ impl Drop for Inner {
     }
 }
 
-pub fn open(path: &CString, fm: io::FileMode, fa: io::FileAccess)
+pub fn open(path: &CString, fm: rtio::FileMode, fa: rtio::FileAccess)
         -> IoResult<FileDesc> {
     // Flags passed to open_osfhandle
     let flags = match fm {
-        io::Open => 0,
-        io::Append => libc::O_APPEND,
-        io::Truncate => libc::O_TRUNC,
+        rtio::Open => 0,
+        rtio::Append => libc::O_APPEND,
+        rtio::Truncate => libc::O_TRUNC,
     };
     let flags = match fa {
-        io::Read => flags | libc::O_RDONLY,
-        io::Write => flags | libc::O_WRONLY | libc::O_CREAT,
-        io::ReadWrite => flags | libc::O_RDWR | libc::O_CREAT,
+        rtio::Read => flags | libc::O_RDONLY,
+        rtio::Write => flags | libc::O_WRONLY | libc::O_CREAT,
+        rtio::ReadWrite => flags | libc::O_RDWR | libc::O_CREAT,
     };
 
     let mut dwDesiredAccess = match fa {
-        io::Read => libc::FILE_GENERIC_READ,
-        io::Write => libc::FILE_GENERIC_WRITE,
-        io::ReadWrite => libc::FILE_GENERIC_READ | libc::FILE_GENERIC_WRITE
+        rtio::Read => libc::FILE_GENERIC_READ,
+        rtio::Write => libc::FILE_GENERIC_WRITE,
+        rtio::ReadWrite => libc::FILE_GENERIC_READ | libc::FILE_GENERIC_WRITE
     };
 
     // libuv has a good comment about this, but the basic idea is what we try to
@@ -295,15 +280,15 @@ pub fn open(path: &CString, fm: io::FileMode, fa: io::FileAccess)
                       libc::FILE_SHARE_DELETE;
 
     let dwCreationDisposition = match (fm, fa) {
-        (io::Truncate, io::Read) => libc::TRUNCATE_EXISTING,
-        (io::Truncate, _) => libc::CREATE_ALWAYS,
-        (io::Open, io::Read) => libc::OPEN_EXISTING,
-        (io::Open, _) => libc::OPEN_ALWAYS,
-        (io::Append, io::Read) => {
+        (rtio::Truncate, rtio::Read) => libc::TRUNCATE_EXISTING,
+        (rtio::Truncate, _) => libc::CREATE_ALWAYS,
+        (rtio::Open, rtio::Read) => libc::OPEN_EXISTING,
+        (rtio::Open, _) => libc::OPEN_ALWAYS,
+        (rtio::Append, rtio::Read) => {
             dwDesiredAccess |= libc::FILE_APPEND_DATA;
             libc::OPEN_EXISTING
         }
-        (io::Append, _) => {
+        (rtio::Append, _) => {
             dwDesiredAccess &= !libc::FILE_WRITE_DATA;
             dwDesiredAccess |= libc::FILE_APPEND_DATA;
             libc::OPEN_ALWAYS
@@ -338,7 +323,7 @@ pub fn open(path: &CString, fm: io::FileMode, fa: io::FileAccess)
     }
 }
 
-pub fn mkdir(p: &CString, _mode: io::FilePermission) -> IoResult<()> {
+pub fn mkdir(p: &CString, _mode: uint) -> IoResult<()> {
     super::mkerr_winbool(unsafe {
         // FIXME: turn mode into something useful? #2623
         as_utf16_p(p.as_str().unwrap(), |buf| {
@@ -413,9 +398,9 @@ pub fn rename(old: &CString, new: &CString) -> IoResult<()> {
     })
 }
 
-pub fn chmod(p: &CString, mode: io::FilePermission) -> IoResult<()> {
+pub fn chmod(p: &CString, mode: uint) -> IoResult<()> {
     super::mkerr_libc(as_utf16_p(p.as_str().unwrap(), |p| unsafe {
-        libc::wchmod(p, mode.bits() as libc::c_int)
+        libc::wchmod(p, mode as libc::c_int)
     }))
 }
 
@@ -430,7 +415,7 @@ pub fn chown(_p: &CString, _uid: int, _gid: int) -> IoResult<()> {
     Ok(())
 }
 
-pub fn readlink(p: &CString) -> IoResult<Path> {
+pub fn readlink(p: &CString) -> IoResult<CString> {
     // FIXME: I have a feeling that this reads intermediate symlinks as well.
     use io::c::compat::kernel32::GetFinalPathNameByHandleW;
     let handle = unsafe {
@@ -457,9 +442,9 @@ pub fn readlink(p: &CString) -> IoResult<Path> {
     });
     let ret = match ret {
         Some(ref s) if s.as_slice().starts_with(r"\\?\") => {
-            Ok(Path::new(s.as_slice().slice_from(4)))
+            Ok(Path::new(s.as_slice().slice_from(4)).to_c_str())
         }
-        Some(s) => Ok(Path::new(s)),
+        Some(s) => Ok(Path::new(s).to_c_str()),
         None => Err(super::last_error()),
     };
     assert!(unsafe { libc::CloseHandle(handle) } != 0);
@@ -483,39 +468,28 @@ pub fn link(src: &CString, dst: &CString) -> IoResult<()> {
     }))
 }
 
-fn mkstat(stat: &libc::stat) -> io::FileStat {
-    let kind = match (stat.st_mode as 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,
-    };
-
-    io::FileStat {
+fn mkstat(stat: &libc::stat) -> rtio::FileStat {
+    rtio::FileStat {
         size: stat.st_size as u64,
-        kind: kind,
-        perm: io::FilePermission::from_bits_truncate(stat.st_mode as u32),
+        kind: stat.st_mode as u64,
+        perm: stat.st_mode as u64,
         created: stat.st_ctime as u64,
         modified: stat.st_mtime as u64,
         accessed: stat.st_atime as u64,
-        unstable: io::UnstableFileStat {
-            device: stat.st_dev as u64,
-            inode: stat.st_ino as u64,
-            rdev: stat.st_rdev as u64,
-            nlink: stat.st_nlink as u64,
-            uid: stat.st_uid as u64,
-            gid: stat.st_gid as u64,
-            blksize: 0,
-            blocks: 0,
-            flags: 0,
-            gen: 0,
-        }
+        device: stat.st_dev as u64,
+        inode: stat.st_ino as u64,
+        rdev: stat.st_rdev as u64,
+        nlink: stat.st_nlink as u64,
+        uid: stat.st_uid as u64,
+        gid: stat.st_gid as u64,
+        blksize: 0,
+        blocks: 0,
+        flags: 0,
+        gen: 0,
     }
 }
 
-pub fn stat(p: &CString) -> IoResult<io::FileStat> {
+pub fn stat(p: &CString) -> IoResult<rtio::FileStat> {
     let mut stat: libc::stat = unsafe { mem::zeroed() };
     as_utf16_p(p.as_str().unwrap(), |up| {
         match unsafe { libc::wstat(up, &mut stat) } {
@@ -525,7 +499,7 @@ pub fn stat(p: &CString) -> IoResult<io::FileStat> {
     })
 }
 
-pub fn lstat(_p: &CString) -> IoResult<io::FileStat> {
+pub fn lstat(_p: &CString) -> IoResult<rtio::FileStat> {
     // FIXME: implementation is missing
     Err(super::unimpl())
 }
diff --git a/src/libnative/io/net.rs b/src/libnative/io/net.rs
index 68cc5273b5e..24956e514ec 100644
--- a/src/libnative/io/net.rs
+++ b/src/libnative/io/net.rs
@@ -135,10 +135,12 @@ pub fn getsockopt<T: Copy>(fd: sock_t, opt: libc::c_int,
 }
 
 #[cfg(windows)]
-fn last_error() -> IoError {
+pub fn last_error() -> IoError {
+    use std::os;
     let code = unsafe { c::WSAGetLastError() as uint };
     IoError {
         code: code,
+        extra: 0,
         detail: Some(os::error_string(code)),
     }
 }
@@ -225,7 +227,7 @@ pub fn init() {}
 pub fn init() {
 
     unsafe {
-        use std::unstable::mutex::{StaticNativeMutex, NATIVE_MUTEX_INIT};
+        use std::rt::mutex::{StaticNativeMutex, NATIVE_MUTEX_INIT};
         static mut INITIALIZED: bool = false;
         static mut LOCK: StaticNativeMutex = NATIVE_MUTEX_INIT;
 
diff --git a/src/libnative/io/pipe_win32.rs b/src/libnative/io/pipe_win32.rs
index cd4cbf2c90f..a5694436b97 100644
--- a/src/libnative/io/pipe_win32.rs
+++ b/src/libnative/io/pipe_win32.rs
@@ -87,16 +87,15 @@
 use alloc::arc::Arc;
 use libc;
 use std::c_str::CString;
-use std::io;
 use std::mem;
 use std::os::win32::as_utf16_p;
 use std::os;
 use std::ptr;
 use std::rt::rtio;
+use std::rt::rtio::{IoResult, IoError};
 use std::sync::atomics;
-use std::unstable::mutex;
+use std::rt::mutex;
 
-use super::IoResult;
 use super::c;
 use super::util;
 
@@ -190,6 +189,14 @@ pub fn await(handle: libc::HANDLE, deadline: u64,
     }
 }
 
+fn epipe() -> IoError {
+    IoError {
+        code: libc::ERROR_BROKEN_PIPE as uint,
+        extra: 0,
+        detail: None,
+    }
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // Unix Streams
 ////////////////////////////////////////////////////////////////////////////////
@@ -355,7 +362,7 @@ impl rtio::RtioPipe for UnixStream {
         // See comments in close_read() about why this lock is necessary.
         let guard = unsafe { self.inner.lock.lock() };
         if self.read_closed() {
-            return Err(io::standard_error(io::EndOfFile))
+            return Err(util::eof())
         }
 
         // Issue a nonblocking requests, succeeding quickly if it happened to
@@ -403,10 +410,10 @@ impl rtio::RtioPipe for UnixStream {
             // If the reading half is now closed, then we're done. If we woke up
             // because the writing half was closed, keep trying.
             if !succeeded {
-                return Err(io::standard_error(io::TimedOut))
+                return Err(util::timeout("read timed out"))
             }
             if self.read_closed() {
-                return Err(io::standard_error(io::EndOfFile))
+                return Err(util::eof())
             }
         }
     }
@@ -431,7 +438,7 @@ impl rtio::RtioPipe for UnixStream {
             // See comments in close_read() about why this lock is necessary.
             let guard = unsafe { self.inner.lock.lock() };
             if self.write_closed() {
-                return Err(io::standard_error(io::BrokenPipe))
+                return Err(epipe())
             }
             let ret = unsafe {
                 libc::WriteFile(self.handle(),
@@ -445,7 +452,11 @@ impl rtio::RtioPipe for UnixStream {
 
             if ret == 0 {
                 if err != libc::ERROR_IO_PENDING as uint {
-                    return Err(io::IoError::from_errno(err, true));
+                    return Err(IoError {
+                        code: err as uint,
+                        extra: 0,
+                        detail: Some(os::error_string(err as uint)),
+                    })
                 }
                 // Process a timeout if one is pending
                 let succeeded = await(self.handle(), self.write_deadline,
@@ -466,17 +477,17 @@ impl rtio::RtioPipe for UnixStream {
                     if !succeeded {
                         let amt = offset + bytes_written as uint;
                         return if amt > 0 {
-                            Err(io::IoError {
-                                kind: io::ShortWrite(amt),
-                                desc: "short write during write",
-                                detail: None,
+                            Err(IoError {
+                                code: libc::ERROR_OPERATION_ABORTED as uint,
+                                extra: amt,
+                                detail: Some("short write during write".to_str()),
                             })
                         } else {
                             Err(util::timeout("write timed out"))
                         }
                     }
                     if self.write_closed() {
-                        return Err(io::standard_error(io::BrokenPipe))
+                        return Err(epipe())
                     }
                     continue // retry
                 }
diff --git a/src/libnative/io/process.rs b/src/libnative/io/process.rs
index 8b3f4debe5d..2c2b7cec1de 100644
--- a/src/libnative/io/process.rs
+++ b/src/libnative/io/process.rs
@@ -210,23 +210,23 @@ unsafe fn killpid(pid: pid_t, signal: int) -> IoResult<()> {
             if ret == 0 {
                 Err(super::last_error())
             } else if status != libc::STILL_ACTIVE {
-                Err(io::IoError {
-                    kind: io::OtherIoError,
-                    desc: "process no longer alive",
+                Err(IoError {
+                    code: libc::ERROR_NOTHING_TO_TERMINATE as uint,
+                    extra: 0,
                     detail: None,
                 })
             } else {
                 Ok(())
             }
         }
-        io::process::PleaseExitSignal | io::process::MustDieSignal => {
+        15 | 9 => { // sigterm or sigkill
             let ret = libc::TerminateProcess(handle, 1);
             super::mkerr_winbool(ret)
         }
-        _ => Err(io::IoError {
-            kind: io::OtherIoError,
-            desc: "unsupported signal on windows",
-            detail: None,
+        _ => Err(IoError {
+            code: libc::ERROR_CALL_NOT_IMPLEMENTED as uint,
+            extra: 0,
+            detail: Some("unsupported signal on windows".to_string()),
         })
     };
     let _ = libc::CloseHandle(handle);
@@ -266,10 +266,10 @@ fn spawn_process_os(cfg: ProcessConfig,
     use std::mem;
 
     if cfg.gid.is_some() || cfg.uid.is_some() {
-        return Err(io::IoError {
-            kind: io::OtherIoError,
-            desc: "unsupported gid/uid requested on windows",
-            detail: None,
+        return Err(IoError {
+            code: libc::ERROR_CALL_NOT_IMPLEMENTED as uint,
+            extra: 0,
+            detail: Some("unsupported gid/uid requested on windows".to_str()),
         })
     }
 
diff --git a/src/libnative/io/timer_win32.rs b/src/libnative/io/timer_win32.rs
index e7130de05c2..d175060dd98 100644
--- a/src/libnative/io/timer_win32.rs
+++ b/src/libnative/io/timer_win32.rs
@@ -23,10 +23,10 @@
 use libc;
 use std::ptr;
 use std::rt::rtio;
+use std::rt::rtio::{IoResult, Callback};
 use std::comm;
 
 use io::helper_thread::Helper;
-use io::IoResult;
 
 helper_init!(static mut HELPER: Helper<Req>)
 
@@ -36,7 +36,7 @@ pub struct Timer {
 }
 
 pub enum Req {
-    NewTimer(libc::HANDLE, Sender<()>, bool),
+    NewTimer(libc::HANDLE, Box<Callback:Send>, bool),
     RemoveTimer(libc::HANDLE, Sender<()>),
 }
 
@@ -79,8 +79,8 @@ fn helper(input: libc::HANDLE, messages: Receiver<Req>, _: ()) {
             }
         } else {
             let remove = {
-                match chans.get(idx as uint - 1) {
-                    &(ref c, oneshot) => c.send_opt(()).is_err() || oneshot
+                match chans.get_mut(idx as uint - 1) {
+                    &(ref mut c, oneshot) => { c.call(); oneshot }
                 }
             };
             if remove {
@@ -148,9 +148,8 @@ impl rtio::RtioTimer for Timer {
         let _ = unsafe { imp::WaitForSingleObject(self.obj, libc::INFINITE) };
     }
 
-    fn oneshot(&mut self, msecs: u64) -> Receiver<()> {
+    fn oneshot(&mut self, msecs: u64, cb: Box<Callback:Send>) {
         self.remove();
-        let (tx, rx) = channel();
 
         // see above for the calculation
         let due = -(msecs as i64 * 10000) as libc::LARGE_INTEGER;
@@ -159,14 +158,12 @@ impl rtio::RtioTimer for Timer {
                                   ptr::mut_null(), 0)
         }, 1);
 
-        unsafe { HELPER.send(NewTimer(self.obj, tx, true)) }
+        unsafe { HELPER.send(NewTimer(self.obj, cb, true)) }
         self.on_worker = true;
-        return rx;
     }
 
-    fn period(&mut self, msecs: u64) -> Receiver<()> {
+    fn period(&mut self, msecs: u64, cb: Box<Callback:Send>) {
         self.remove();
-        let (tx, rx) = channel();
 
         // see above for the calculation
         let due = -(msecs as i64 * 10000) as libc::LARGE_INTEGER;
@@ -175,10 +172,8 @@ impl rtio::RtioTimer for Timer {
                                   ptr::null(), ptr::mut_null(), 0)
         }, 1);
 
-        unsafe { HELPER.send(NewTimer(self.obj, tx, false)) }
+        unsafe { HELPER.send(NewTimer(self.obj, cb, false)) }
         self.on_worker = true;
-
-        return rx;
     }
 }
 
diff --git a/src/librustrt/c_str.rs b/src/librustrt/c_str.rs
index 1690c54285c..4234c085148 100644
--- a/src/librustrt/c_str.rs
+++ b/src/librustrt/c_str.rs
@@ -238,9 +238,15 @@ impl Container for CString {
     #[inline]
     fn len(&self) -> uint {
         if self.buf.is_null() { fail!("CString is null!"); }
+        let mut cur = self.buf;
+        let mut len = 0;
         unsafe {
-            ptr::position(self.buf, |c| *c == 0)
+            while *cur != 0 {
+                len += 1;
+                cur = cur.offset(1);
+            }
         }
+        return len;
     }
 }
 
diff --git a/src/librustrt/lib.rs b/src/librustrt/lib.rs
index 506df10aab2..3158687c6ab 100644
--- a/src/librustrt/lib.rs
+++ b/src/librustrt/lib.rs
@@ -113,6 +113,7 @@ pub fn init(argc: int, argv: **u8) {
     // FIXME(#14344) this shouldn't be necessary
     collections::fixme_14344_be_sure_to_link_to_collections();
     alloc::fixme_14344_be_sure_to_link_to_collections();
+    libc::issue_14344_workaround();
 }
 
 /// Enqueues a procedure to run when the runtime is cleaned up
diff --git a/src/librustrt/local_data.rs b/src/librustrt/local_data.rs
index 88c154045c6..6b468bd0827 100644
--- a/src/librustrt/local_data.rs
+++ b/src/librustrt/local_data.rs
@@ -95,8 +95,6 @@ type TLSValue = Box<LocalData:Send>;
 
 // Gets the map from the runtime. Lazily initialises if not done so already.
 unsafe fn get_local_map() -> Option<&mut Map> {
-    use rt::local::Local;
-
     if !Local::exists(None::<Task>) { return None }
 
     let task: *mut Task = Local::unsafe_borrow();
diff --git a/src/librustrt/task.rs b/src/librustrt/task.rs
index f56b891ed9f..0640b2b9c77 100644
--- a/src/librustrt/task.rs
+++ b/src/librustrt/task.rs
@@ -18,10 +18,11 @@ use core::prelude::*;
 use alloc::arc::Arc;
 use alloc::owned::{AnyOwnExt, Box};
 use core::any::Any;
+use core::atomics::{AtomicUint, SeqCst};
+use core::finally::Finally;
 use core::iter::Take;
 use core::mem;
-use core::finally::Finally;
-use core::atomics::{AtomicUint, SeqCst};
+use core::raw;
 
 use local_data;
 use Runtime;
@@ -142,18 +143,17 @@ impl Task {
                 // TLS, or possibly some destructors for those objects being
                 // annihilated invoke TLS. Sadly these two operations seemed to
                 // be intertwined, and miraculously work for now...
-                let mut task = Local::borrow(None::<Task>);
-                let storage_map = {
+                drop({
+                    let mut task = Local::borrow(None::<Task>);
                     let &LocalStorage(ref mut optmap) = &mut task.storage;
                     optmap.take()
-                };
-                drop(task);
-                drop(storage_map);
+                });
 
                 // Destroy remaining boxes. Also may run user dtors.
-                let mut task = Local::borrow(None::<Task>);
-                let mut heap = mem::replace(&mut task.heap, LocalHeap::new());
-                drop(task);
+                let mut heap = {
+                    let mut task = Local::borrow(None::<Task>);
+                    mem::replace(&mut task.heap, LocalHeap::new())
+                };
                 unsafe { heap.annihilate() }
                 drop(heap);
             })
@@ -202,13 +202,16 @@ impl Task {
         //      crops up.
         unsafe {
             let imp = self.imp.take_unwrap();
-            let &(vtable, _): &(uint, uint) = mem::transmute(&imp);
+            let vtable = mem::transmute::<_, &raw::TraitObject>(&imp).vtable;
             match imp.wrap().move::<T>() {
                 Ok(t) => Some(t),
                 Err(t) => {
-                    let (_, obj): (uint, uint) = mem::transmute(t);
+                    let data = mem::transmute::<_, raw::TraitObject>(t).data;
                     let obj: Box<Runtime:Send> =
-                        mem::transmute((vtable, obj));
+                        mem::transmute(raw::TraitObject {
+                            vtable: vtable,
+                            data: data,
+                        });
                     self.put_runtime(obj);
                     None
                 }
diff --git a/src/librustrt/unwind.rs b/src/librustrt/unwind.rs
index da6fd3644ce..2fd9f4ef1f1 100644
--- a/src/librustrt/unwind.rs
+++ b/src/librustrt/unwind.rs
@@ -121,7 +121,7 @@ impl Unwinder {
         self.cause = unsafe { try(f) }.err();
     }
 
-    pub fn result(&mut self) -> TaskResult {
+    pub fn result(&mut self) -> Result {
         if self.unwinding {
             Err(self.cause.take().unwrap())
         } else {
@@ -150,10 +150,7 @@ impl Unwinder {
 ///   guaranteed that a rust task is in place when invoking this function.
 ///   Unwinding twice can lead to resource leaks where some destructors are not
 ///   run.
-pub unsafe fn try(f: ||) -> Result<(), Box<Any:Send>> {
-    use raw::Closure;
-    use libc::{c_void};
-
+pub unsafe fn try(f: ||) -> ::core::result::Result<(), Box<Any:Send>> {
     let closure: Closure = mem::transmute(f);
     let ep = rust_try(try_fn, closure.code as *c_void,
                       closure.env as *c_void);
@@ -300,7 +297,7 @@ pub mod eabi {
 #[cfg(target_arch = "arm", not(test))]
 #[allow(visible_private_types)]
 pub mod eabi {
-    use uw = rt::libunwind;
+    use uw = libunwind;
     use libc::c_int;
 
     extern "C" {
@@ -432,9 +429,9 @@ fn begin_unwind_inner(msg: Box<Any:Send>,
     // Now that we've run all the necessary unwind callbacks, we actually
     // perform the unwinding. If we don't have a task, then it's time to die
     // (hopefully someone printed something about this).
-    let task: Box<Task> = match Local::try_take() {
+    let mut task: Box<Task> = match Local::try_take() {
         Some(task) => task,
-        None => unsafe { intrinsics::abort() }
+        None => rust_fail(msg),
     };
 
     if task.unwinder.unwinding {
@@ -445,17 +442,13 @@ fn begin_unwind_inner(msg: Box<Any:Send>,
         rterrln!("task failed during unwinding. aborting.");
         unsafe { intrinsics::abort() }
     }
+    task.unwinder.unwinding = true;
 
     // Put the task back in TLS because the unwinding process may run code which
     // requires the task. We need a handle to its unwinder, however, so after
     // this we unsafely extract it and continue along.
     Local::put(task);
-    unsafe {
-        let task: *mut Task = Local::unsafe_borrow();
-        (*task).unwinder.begin_unwind(msg);
-    }
-    task.name = name;
-    Local::put(task);
+    rust_fail(msg);
 }
 
 /// Register a callback to be invoked when a task unwinds.
diff --git a/src/librustrt/util.rs b/src/librustrt/util.rs
index 0b517bcc7fb..c08652cc08c 100644
--- a/src/librustrt/util.rs
+++ b/src/librustrt/util.rs
@@ -73,9 +73,7 @@ pub fn abort(args: &fmt::Arguments) -> ! {
     let mut w = BufWriter { buf: msg, pos: 0 };
     let _ = write!(&mut w, "{}", args);
     let msg = str::from_utf8(w.buf.slice_to(w.pos)).unwrap_or("aborted");
-    let msg = if msg.is_empty() {
-        "aborted"
-    } else { "aborted" };
+    let msg = if msg.is_empty() {"aborted"} else {msg};
 
     // Give some context to the message
     let hash = msg.bytes().fold(0, |accum, val| accum + (val as uint) );
diff --git a/src/librustuv/lib.rs b/src/librustuv/lib.rs
index cbbb961e048..e2122aea036 100644
--- a/src/librustuv/lib.rs
+++ b/src/librustuv/lib.rs
@@ -404,22 +404,23 @@ pub fn uv_error_to_io_error(uverr: UvError) -> IoError {
     let UvError(errcode) = uverr;
     IoError {
         code: match errcode {
-            uvll::EOF => io::EOF,
-            uvll::EACCES => io::ERROR_ACCESS_DENIED,
-            uvll::ECONNREFUSED => io::WSAECONNREFUSED,
-            uvll::ECONNRESET => io::WSAECONNRESET,
-            uvll::ENOTCONN => io::WSAENOTCONN,
-            uvll::ENOENT => io::ERROR_NOT_FOUND,
-            uvll::EPIPE => io::ERROR_BROKEN_PIPE,
-            uvll::ECONNABORTED => io::WSAECONNABORTED,
-            uvll::EADDRNOTAVAIL => io::WSAEADDRNOTAVAIL,
+            uvll::EOF => libc::EOF,
+            uvll::EACCES => libc::ERROR_ACCESS_DENIED,
+            uvll::ECONNREFUSED => libc::WSAECONNREFUSED,
+            uvll::ECONNRESET => libc::WSAECONNRESET,
+            uvll::ENOTCONN => libc::WSAENOTCONN,
+            uvll::ENOENT => libc::ERROR_FILE_NOT_FOUND,
+            uvll::EPIPE => libc::ERROR_NO_DATA,
+            uvll::ECONNABORTED => libc::WSAECONNABORTED,
+            uvll::EADDRNOTAVAIL => libc::WSAEADDRNOTAVAIL,
             uvll::ECANCELED => libc::ERROR_OPERATION_ABORTED,
+            uvll::EADDRINUSE => libc::WSAEADDRINUSE,
             err => {
                 uvdebug!("uverr.code {}", err as int);
                 // FIXME: Need to map remaining uv error types
                 -1
             }
-        },
+        } as uint,
         extra: 0,
         detail: Some(uverr.desc()),
     }
diff --git a/src/librustuv/uvll.rs b/src/librustuv/uvll.rs
index 91c68147251..f6c6d6c9068 100644
--- a/src/librustuv/uvll.rs
+++ b/src/librustuv/uvll.rs
@@ -38,7 +38,8 @@ use std::rt::libc_heap::malloc_raw;
 use libc::uintptr_t;
 
 pub use self::errors::{EACCES, ECONNREFUSED, ECONNRESET, EPIPE, ECONNABORTED,
-                       ECANCELED, EBADF, ENOTCONN, ENOENT, EADDRNOTAVAIL};
+                       ECANCELED, EBADF, ENOTCONN, ENOENT, EADDRNOTAVAIL,
+                       EADDRINUSE};
 
 pub static OK: c_int = 0;
 pub static EOF: c_int = -4095;
@@ -61,6 +62,7 @@ pub mod errors {
     pub static ECANCELED: c_int = -4081;
     pub static EBADF: c_int = -4083;
     pub static EADDRNOTAVAIL: c_int = -4090;
+    pub static EADDRINUSE: c_int = -4091;
 }
 #[cfg(not(windows))]
 pub mod errors {
@@ -77,6 +79,7 @@ pub mod errors {
     pub static ECANCELED : c_int = -libc::ECANCELED;
     pub static EBADF : c_int = -libc::EBADF;
     pub static EADDRNOTAVAIL : c_int = -libc::EADDRNOTAVAIL;
+    pub static EADDRINUSE : c_int = -libc::EADDRINUSE;
 }
 
 pub static PROCESS_SETUID: c_int = 1 << 0;
diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs
index 94d60cb3ce7..c72cc0ded9b 100644
--- a/src/libstd/io/mod.rs
+++ b/src/libstd/io/mod.rs
@@ -313,7 +313,8 @@ impl IoError {
                 libc::ERROR_INVALID_NAME => (InvalidInput, "invalid file name"),
                 libc::WSAECONNREFUSED => (ConnectionRefused, "connection refused"),
                 libc::WSAECONNRESET => (ConnectionReset, "connection reset"),
-                libc::WSAEACCES => (PermissionDenied, "permission denied"),
+                libc::ERROR_ACCESS_DENIED | libc::WSAEACCES =>
+                    (PermissionDenied, "permission denied"),
                 libc::WSAEWOULDBLOCK => {
                     (ResourceUnavailable, "resource temporarily unavailable")
                 }
@@ -327,7 +328,7 @@ impl IoError {
                 libc::WSAEINVAL => (InvalidInput, "invalid argument"),
                 libc::ERROR_CALL_NOT_IMPLEMENTED =>
                     (IoUnavailable, "function not implemented"),
-                libc::ERROR_CALL_NOT_IMPLEMENTED =>
+                libc::ERROR_INVALID_HANDLE =>
                     (MismatchedFileTypeForOperation,
                      "invalid handle provided to function"),
                 libc::ERROR_NOTHING_TO_TERMINATE =>
diff --git a/src/libstd/io/net/tcp.rs b/src/libstd/io/net/tcp.rs
index 8ce77faa296..6c773467553 100644
--- a/src/libstd/io/net/tcp.rs
+++ b/src/libstd/io/net/tcp.rs
@@ -982,7 +982,8 @@ mod test {
         match TcpListener::bind(ip_str.as_slice(), port).listen() {
             Ok(..) => fail!(),
             Err(e) => {
-                assert!(e.kind == ConnectionRefused || e.kind == OtherIoError);
+                assert!(e.kind == ConnectionRefused || e.kind == OtherIoError,
+                        "unknown error: {} {}", e, e.kind);
             }
         }
     })
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index fe5fabef9d9..bac4d26b4e4 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -256,11 +256,6 @@ pub mod unstable;
 pub mod rt;
 mod failure;
 
-#[doc(hidden)]
-pub fn issue_14344_workaround() { // FIXME #14344 force linkage to happen correctly
-    libc::issue_14344_workaround();
-}
-
 // A curious inner-module that's not exported that contains the binding
 // 'std' so that macro-expanded references to std::error and such
 // can be resolved within libstd.
diff --git a/src/libstd/rt/backtrace.rs b/src/libstd/rt/backtrace.rs
index 4229e9ad32c..766901fa04f 100644
--- a/src/libstd/rt/backtrace.rs
+++ b/src/libstd/rt/backtrace.rs
@@ -603,6 +603,7 @@ mod imp {
 mod imp {
     use c_str::CString;
     use container::Container;
+    use intrinsics;
     use io::{IoResult, Writer};
     use libc;
     use mem;
@@ -610,11 +611,10 @@ mod imp {
     use option::{Some, None};
     use path::Path;
     use result::{Ok, Err};
+    use rt::mutex::{StaticNativeMutex, NATIVE_MUTEX_INIT};
+    use slice::ImmutableVector;
     use str::StrSlice;
     use unstable::dynamic_lib::DynamicLibrary;
-    use intrinsics;
-    use unstable::mutex::{StaticNativeMutex, NATIVE_MUTEX_INIT};
-    use slice::ImmutableVector;
 
     #[allow(non_snake_case_functions)]
     extern "system" {
diff --git a/src/libstd/rt/mod.rs b/src/libstd/rt/mod.rs
index e8df7465a74..a68a632bc37 100644
--- a/src/libstd/rt/mod.rs
+++ b/src/libstd/rt/mod.rs
@@ -57,10 +57,11 @@ Several modules in `core` are clients of `rt`:
 use failure;
 use rustrt;
 
-// TODO: dox
+// Reexport some of our utilities which are expected by other crates.
 pub use self::util::{default_sched_threads, min_stack, running_on_valgrind};
 
-// TODO: dox
+// Reexport functionality from librustrt and other crates underneath the
+// standard library which work together to create the entire runtime.
 pub use alloc::{heap, libc_heap};
 pub use rustrt::{task, local, mutex, exclusive, stack, args, rtio};
 pub use rustrt::{Stdio, Stdout, Stderr, begin_unwind, begin_unwind_fmt};
diff --git a/src/libstd/task.rs b/src/libstd/task.rs
index 55ebba69d90..9ee62ee3d81 100644
--- a/src/libstd/task.rs
+++ b/src/libstd/task.rs
@@ -182,14 +182,8 @@ impl TaskBuilder {
         };
         if stdout.is_some() || stderr.is_some() {
             t.spawn_sibling(opts, proc() {
-                match stdout {
-                    Some(handle) => { let _ = stdio::set_stdout(handle); }
-                    None => {}
-                }
-                match stderr {
-                    Some(handle) => { let _ = stdio::set_stderr(handle); }
-                    None => {}
-                }
+                let _ = stdout.map(stdio::set_stdout);
+                let _ = stderr.map(stdio::set_stderr);
                 f();
             });
         } else {
diff --git a/src/libsync/mutex.rs b/src/libsync/mutex.rs
index ee7fa525e79..bcf5a43fb6b 100644
--- a/src/libsync/mutex.rs
+++ b/src/libsync/mutex.rs
@@ -64,7 +64,7 @@ use std::rt::task::{BlockedTask, Task};
 use std::rt::thread::Thread;
 use std::sync::atomics;
 use std::ty::Unsafe;
-use std::unstable::mutex;
+use std::rt::mutex;
 
 use q = mpsc_intrusive;
 
diff --git a/src/test/run-pass/running-with-no-runtime.rs b/src/test/run-pass/running-with-no-runtime.rs
index 1fe99336bc9..0ef48c99782 100644
--- a/src/test/run-pass/running-with-no-runtime.rs
+++ b/src/test/run-pass/running-with-no-runtime.rs
@@ -28,7 +28,7 @@ fn start(argc: int, argv: **u8) -> int {
                 4 => assert!(try(|| fail!()).is_err()),
                 5 => assert!(try(|| spawn(proc() {})).is_err()),
                 6 => assert!(Command::new("test").spawn().is_err()),
-                7 => assert!(foo.get().is_some()),
+                7 => assert!(foo.get().is_none()),
                 8 => assert!(try(|| { foo.replace(Some(3)); }).is_err()),
                 _ => fail!()
             }
@@ -49,6 +49,8 @@ fn main() {
     pass(Command::new(me).arg(&[4u8]).output().unwrap());
     pass(Command::new(me).arg(&[5u8]).output().unwrap());
     pass(Command::new(me).arg(&[6u8]).output().unwrap());
+    pass(Command::new(me).arg(&[7u8]).output().unwrap());
+    pass(Command::new(me).arg(&[8u8]).output().unwrap());
 }
 
 fn pass(output: ProcessOutput) {
diff --git a/src/test/run-pass/tcp-stress.rs b/src/test/run-pass/tcp-stress.rs
index 4034c2571cd..a9a6e25adf3 100644
--- a/src/test/run-pass/tcp-stress.rs
+++ b/src/test/run-pass/tcp-stress.rs
@@ -61,7 +61,7 @@ fn main() {
     for _ in range(0, 1000) {
         let tx = tx.clone();
         let mut builder = TaskBuilder::new();
-        builder.opts.stack_size = Some(32 * 1024);
+        builder.opts.stack_size = Some(64 * 1024);
         builder.spawn(proc() {
             let host = addr.ip.to_str();
             let port = addr.port;