about summary refs log tree commit diff
path: root/src/libcore
diff options
context:
space:
mode:
Diffstat (limited to 'src/libcore')
-rw-r--r--src/libcore/bool.rs2
-rw-r--r--src/libcore/cast.rs44
-rw-r--r--src/libcore/char.rs1
-rw-r--r--src/libcore/cleanup.rs1
-rw-r--r--src/libcore/condition.rs23
-rw-r--r--src/libcore/core.rc16
-rw-r--r--src/libcore/either.rs10
-rw-r--r--src/libcore/hashmap.rs4
-rw-r--r--src/libcore/io.rs10
-rw-r--r--src/libcore/iter.rs93
-rw-r--r--src/libcore/iterator.rs21
-rw-r--r--src/libcore/libc.rs248
-rw-r--r--src/libcore/logging.rs1
-rw-r--r--src/libcore/macros.rs39
-rw-r--r--src/libcore/num/cmath.rs11
-rw-r--r--src/libcore/num/f32.rs21
-rw-r--r--src/libcore/num/f64.rs20
-rw-r--r--src/libcore/num/float.rs21
-rw-r--r--src/libcore/num/int-template.rs119
-rw-r--r--src/libcore/num/num.rs26
-rw-r--r--src/libcore/num/strconv.rs12
-rw-r--r--src/libcore/num/uint-template.rs27
-rw-r--r--src/libcore/ops.rs6
-rw-r--r--src/libcore/option.rs8
-rw-r--r--src/libcore/os.rs155
-rw-r--r--src/libcore/owned.rs1
-rw-r--r--src/libcore/pipes.rs38
-rw-r--r--src/libcore/prelude.rs5
-rw-r--r--src/libcore/rand.rs15
-rw-r--r--src/libcore/rand/distributions.rs148
-rw-r--r--src/libcore/rand/ziggurat_tables.rs412
-rw-r--r--src/libcore/repr.rs2
-rw-r--r--src/libcore/rt/context.rs1
-rw-r--r--src/libcore/rt/io/comm_adapters.rs1
-rw-r--r--src/libcore/rt/io/extensions.rs (renamed from src/libcore/rt/io/util.rs)0
-rw-r--r--src/libcore/rt/io/file.rs10
-rw-r--r--src/libcore/rt/io/mem.rs69
-rw-r--r--src/libcore/rt/io/mod.rs246
-rw-r--r--src/libcore/rt/io/net/ip.rs1
-rw-r--r--src/libcore/rt/io/net/mod.rs31
-rw-r--r--src/libcore/rt/io/net/tcp.rs30
-rw-r--r--src/libcore/rt/io/net/udp.rs6
-rw-r--r--src/libcore/rt/io/net/unix.rs8
-rw-r--r--src/libcore/rt/io/option.rs153
-rw-r--r--src/libcore/rt/io/support.rs (renamed from src/libcore/rt/io/misc.rs)0
-rw-r--r--src/libcore/rt/local_heap.rs80
-rw-r--r--src/libcore/rt/local_services.rs223
-rw-r--r--src/libcore/rt/mod.rs51
-rw-r--r--src/libcore/rt/sched/local_sched.rs1
-rw-r--r--src/libcore/rt/sched/mod.rs21
-rw-r--r--src/libcore/rt/test.rs120
-rw-r--r--src/libcore/rt/uv/mod.rs6
-rw-r--r--src/libcore/rt/uv/net.rs64
-rw-r--r--src/libcore/rt/uvio.rs124
-rw-r--r--src/libcore/rt/uvll.rs6
-rw-r--r--src/libcore/run.rs413
-rw-r--r--src/libcore/stackwalk.rs4
-rw-r--r--src/libcore/str.rs147
-rw-r--r--src/libcore/str/ascii.rs2
-rw-r--r--src/libcore/sys.rs54
-rw-r--r--src/libcore/task/local_data.rs11
-rw-r--r--src/libcore/task/local_data_priv.rs88
-rw-r--r--src/libcore/task/mod.rs110
-rw-r--r--src/libcore/task/spawn.rs8
-rw-r--r--src/libcore/to_bytes.rs3
-rw-r--r--src/libcore/unicode.rs3
-rw-r--r--src/libcore/unstable/exchange_alloc.rs1
-rw-r--r--src/libcore/unstable/extfmt.rs8
-rw-r--r--src/libcore/unstable/intrinsics.rs4
-rw-r--r--src/libcore/unstable/lang.rs41
-rw-r--r--src/libcore/unstable/weak_task.rs1
-rw-r--r--src/libcore/vec.rs8
72 files changed, 2928 insertions, 790 deletions
diff --git a/src/libcore/bool.rs b/src/libcore/bool.rs
index 6c60cec2595..1b4b81dca26 100644
--- a/src/libcore/bool.rs
+++ b/src/libcore/bool.rs
@@ -108,8 +108,6 @@ mod tests {
 
     #[test]
     fn test_bool_from_str() {
-        use from_str::FromStr;
-
         do all_values |v| {
             assert!(Some(v) == FromStr::from_str(to_str(v)))
         }
diff --git a/src/libcore/cast.rs b/src/libcore/cast.rs
index 6fb737d3770..96e1c3bd124 100644
--- a/src/libcore/cast.rs
+++ b/src/libcore/cast.rs
@@ -19,35 +19,11 @@ pub mod rusti {
     pub extern "rust-intrinsic" {
         fn forget<T>(+x: T);
 
-        #[cfg(stage0)]
-        fn reinterpret_cast<T, U>(&&e: T) -> U;
-
-        #[cfg(stage1)]
-        #[cfg(stage2)]
-        #[cfg(stage3)]
         fn transmute<T,U>(e: T) -> U;
     }
 }
 
 /// Casts the value at `src` to U. The two types must have the same length.
-#[inline(always)]
-#[cfg(stage0)]
-pub unsafe fn reinterpret_cast<T, U>(src: &T) -> U {
-    rusti::reinterpret_cast(*src)
-}
-
-/// Unsafely copies and casts the value at `src` to U, even if the value is
-/// noncopyable. The two types must have the same length.
-#[inline(always)]
-#[cfg(stage0)]
-pub unsafe fn transmute_copy<T, U>(src: &T) -> U {
-    rusti::reinterpret_cast(*src)
-}
-
-#[inline(always)]
-#[cfg(stage1)]
-#[cfg(stage2)]
-#[cfg(stage3)]
 pub unsafe fn transmute_copy<T, U>(src: &T) -> U {
     let mut dest: U = unstable::intrinsics::init();
     {
@@ -88,17 +64,6 @@ pub unsafe fn bump_box_refcount<T>(t: @T) { forget(t); }
  *     assert!(transmute("L") == ~[76u8, 0u8]);
  */
 #[inline(always)]
-#[cfg(stage0)]
-pub unsafe fn transmute<L, G>(thing: L) -> G {
-    let newthing: G = reinterpret_cast(&thing);
-    forget(thing);
-    newthing
-}
-
-#[inline(always)]
-#[cfg(stage1)]
-#[cfg(stage2)]
-#[cfg(stage3)]
 pub unsafe fn transmute<L, G>(thing: L) -> G {
     rusti::transmute(thing)
 }
@@ -159,15 +124,6 @@ mod tests {
     use cast::{bump_box_refcount, transmute};
 
     #[test]
-    #[cfg(stage0)]
-    fn test_reinterpret_cast() {
-        assert!(1u == unsafe { ::cast::reinterpret_cast(&1) });
-    }
-
-    #[test]
-    #[cfg(stage1)]
-    #[cfg(stage2)]
-    #[cfg(stage3)]
     fn test_transmute_copy() {
         assert!(1u == unsafe { ::cast::transmute_copy(&1) });
     }
diff --git a/src/libcore/char.rs b/src/libcore/char.rs
index ef2bd91e973..7868b463807 100644
--- a/src/libcore/char.rs
+++ b/src/libcore/char.rs
@@ -10,6 +10,7 @@
 
 //! Utilities for manipulating the char type
 
+#[cfg(notest)]
 use cmp::Ord;
 use option::{None, Option, Some};
 use str;
diff --git a/src/libcore/cleanup.rs b/src/libcore/cleanup.rs
index 3f7366c6c45..435b1cb7f34 100644
--- a/src/libcore/cleanup.rs
+++ b/src/libcore/cleanup.rs
@@ -258,4 +258,3 @@ pub mod rustrt {
         pub unsafe fn rust_get_task() -> *c_void;
     }
 }
-
diff --git a/src/libcore/condition.rs b/src/libcore/condition.rs
index dc6c80228dd..1240fe03dd5 100644
--- a/src/libcore/condition.rs
+++ b/src/libcore/condition.rs
@@ -192,4 +192,27 @@ mod test {
 
         assert!(trapped);
     }
+
+    // Issue #6009
+    mod m {
+        condition! {
+            sadness: int -> int;
+        }
+
+        mod n {
+            use super::sadness;
+
+            #[test]
+            fn test_conditions_are_public() {
+                let mut trapped = false;
+                do sadness::cond.trap(|_| {
+                    trapped = true;
+                    0
+                }).in {
+                    sadness::cond.raise(0);
+                }
+                assert!(trapped);
+            }
+        }
+    }
 }
diff --git a/src/libcore/core.rc b/src/libcore/core.rc
index f6e4056f3d0..9672bf887ca 100644
--- a/src/libcore/core.rc
+++ b/src/libcore/core.rc
@@ -63,7 +63,6 @@ they contained the following prologue:
 #[warn(vecs_implicitly_copyable)];
 #[deny(non_camel_case_types)];
 #[allow(deprecated_mutable_fields)];
-#[allow(deprecated_drop)];
 
 // Make core testable by not duplicating lang items. See #2912
 #[cfg(test)] extern mod realcore(name = "core", vers = "0.7-pre");
@@ -75,7 +74,7 @@ they contained the following prologue:
 
 pub use kinds::{Const, Copy, Owned, Durable};
 pub use ops::{Drop};
-pub use ops::{Add, Sub, Mul, Quot, Rem, Neg, Not};
+pub use ops::{Add, Sub, Mul, Div, Rem, Neg, Not};
 pub use ops::{BitAnd, BitOr, BitXor};
 pub use ops::{Shl, Shr, Index};
 
@@ -109,6 +108,7 @@ pub use num::{Bitwise, BitCount, Bounded};
 pub use num::{Primitive, Int, Float};
 
 pub use ptr::Ptr;
+pub use from_str::FromStr;
 pub use to_str::ToStr;
 pub use clone::Clone;
 
@@ -122,6 +122,9 @@ pub mod linkhack {
     }
 }
 
+// Internal macros
+mod macros;
+
 /* The Prelude. */
 
 pub mod prelude;
@@ -261,12 +264,3 @@ mod core {
     pub use sys;
     pub use pipes;
 }
-
-
-// Local Variables:
-// mode: rust;
-// fill-column: 78;
-// indent-tabs-mode: nil
-// c-basic-offset: 4
-// buffer-file-coding-system: utf-8-unix
-// End:
diff --git a/src/libcore/either.rs b/src/libcore/either.rs
index 92f850cddd6..33b7e81ee85 100644
--- a/src/libcore/either.rs
+++ b/src/libcore/either.rs
@@ -263,13 +263,3 @@ fn test_partition_empty() {
     assert_eq!(vec::len(lefts), 0u);
     assert_eq!(vec::len(rights), 0u);
 }
-
-//
-// Local Variables:
-// mode: rust
-// fill-column: 78;
-// indent-tabs-mode: nil
-// c-basic-offset: 4
-// buffer-file-coding-system: utf-8-unix
-// End:
-//
diff --git a/src/libcore/hashmap.rs b/src/libcore/hashmap.rs
index 8ed54741f12..9b01c1dad06 100644
--- a/src/libcore/hashmap.rs
+++ b/src/libcore/hashmap.rs
@@ -678,7 +678,7 @@ pub impl <T:Hash + Eq> HashSet<T> {
     }
 }
 
-#[test]
+#[cfg(test)]
 mod test_map {
     use container::{Container, Map, Set};
     use option::{None, Some};
@@ -854,7 +854,7 @@ mod test_map {
     }
 }
 
-#[test]
+#[cfg(test)]
 mod test_set {
     use super::*;
     use container::{Container, Map, Set};
diff --git a/src/libcore/io.rs b/src/libcore/io.rs
index 217ea1a9982..460fd60d4c5 100644
--- a/src/libcore/io.rs
+++ b/src/libcore/io.rs
@@ -1954,13 +1954,3 @@ mod tests {
         }
     }
 }
-
-//
-// Local Variables:
-// mode: rust
-// fill-column: 78;
-// indent-tabs-mode: nil
-// c-basic-offset: 4
-// buffer-file-coding-system: utf-8-unix
-// End:
-//
diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs
index 7476531ef94..8fc2db6d6f1 100644
--- a/src/libcore/iter.rs
+++ b/src/libcore/iter.rs
@@ -41,6 +41,9 @@ much easier to implement.
 
 */
 
+use cmp::Ord;
+use option::{Option, Some, None};
+
 pub trait Times {
     fn times(&self, it: &fn() -> bool);
 }
@@ -104,6 +107,78 @@ pub fn all<T>(predicate: &fn(T) -> bool, iter: &fn(f: &fn(T) -> bool)) -> bool {
     true
 }
 
+/**
+ * Return the first element where `predicate` returns `true`. Return `None` if no element is found.
+ *
+ * # Example:
+ *
+ * ~~~~
+ * let xs = ~[1u, 2, 3, 4, 5, 6];
+ * assert_eq!(*find(|& &x: & &uint| x > 3, |f| xs.each(f)).unwrap(), 4);
+ * ~~~~
+ */
+#[inline(always)]
+pub fn find<T>(predicate: &fn(&T) -> bool, iter: &fn(f: &fn(T) -> bool)) -> Option<T> {
+    for iter |x| {
+        if predicate(&x) {
+            return Some(x);
+        }
+    }
+    None
+}
+
+/**
+ * Return the largest item yielded by an iterator. Return `None` if the iterator is empty.
+ *
+ * # Example:
+ *
+ * ~~~~
+ * let xs = ~[8, 2, 3, 1, -5, 9, 11, 15];
+ * assert_eq!(max(|f| xs.each(f)).unwrap(), &15);
+ * ~~~~
+ */
+#[inline]
+pub fn max<T: Ord>(iter: &fn(f: &fn(T) -> bool)) -> Option<T> {
+    let mut result = None;
+    for iter |x| {
+        match result {
+            Some(ref mut y) => {
+                if x > *y {
+                    *y = x;
+                }
+            }
+            None => result = Some(x)
+        }
+    }
+    result
+}
+
+/**
+ * Return the smallest item yielded by an iterator. Return `None` if the iterator is empty.
+ *
+ * # Example:
+ *
+ * ~~~~
+ * let xs = ~[8, 2, 3, 1, -5, 9, 11, 15];
+ * assert_eq!(max(|f| xs.each(f)).unwrap(), &-5);
+ * ~~~~
+ */
+#[inline]
+pub fn min<T: Ord>(iter: &fn(f: &fn(T) -> bool)) -> Option<T> {
+    let mut result = None;
+    for iter |x| {
+        match result {
+            Some(ref mut y) => {
+                if x < *y {
+                    *y = x;
+                }
+            }
+            None => result = Some(x)
+        }
+    }
+    result
+}
+
 #[cfg(test)]
 mod tests {
     use super::*;
@@ -128,4 +203,22 @@ mod tests {
         assert!(all(|x: uint| x < 6, |f| uint::range(1, 6, f)));
         assert!(!all(|x: uint| x < 5, |f| uint::range(1, 6, f)));
     }
+
+    #[test]
+    fn test_find() {
+        let xs = ~[1u, 2, 3, 4, 5, 6];
+        assert_eq!(*find(|& &x: & &uint| x > 3, |f| xs.each(f)).unwrap(), 4);
+    }
+
+    #[test]
+    fn test_max() {
+        let xs = ~[8, 2, 3, 1, -5, 9, 11, 15];
+        assert_eq!(max(|f| xs.each(f)).unwrap(), &15);
+    }
+
+    #[test]
+    fn test_min() {
+        let xs = ~[8, 2, 3, 1, -5, 9, 11, 15];
+        assert_eq!(min(|f| xs.each(f)).unwrap(), &-5);
+    }
 }
diff --git a/src/libcore/iterator.rs b/src/libcore/iterator.rs
index 8bbf8430858..5e95485b273 100644
--- a/src/libcore/iterator.rs
+++ b/src/libcore/iterator.rs
@@ -29,7 +29,7 @@ pub trait Iterator<A> {
 ///
 /// In the future these will be default methods instead of a utility trait.
 pub trait IteratorUtil<A> {
-    fn chain(self, other: Self) -> ChainIterator<Self>;
+    fn chain<U: Iterator<A>>(self, other: U) -> ChainIterator<Self, U>;
     fn zip<B, U: Iterator<B>>(self, other: U) -> ZipIterator<Self, U>;
     // FIXME: #5898: should be called map
     fn transform<'r, B>(self, f: &'r fn(A) -> B) -> MapIterator<'r, A, B, Self>;
@@ -50,7 +50,7 @@ pub trait IteratorUtil<A> {
 /// In the future these will be default methods instead of a utility trait.
 impl<A, T: Iterator<A>> IteratorUtil<A> for T {
     #[inline(always)]
-    fn chain(self, other: T) -> ChainIterator<T> {
+    fn chain<U: Iterator<A>>(self, other: U) -> ChainIterator<T, U> {
         ChainIterator{a: self, b: other, flag: false}
     }
 
@@ -115,13 +115,13 @@ impl<A, T: Iterator<A>> IteratorUtil<A> for T {
     }
 }
 
-pub struct ChainIterator<T> {
+pub struct ChainIterator<T, U> {
     priv a: T,
-    priv b: T,
+    priv b: U,
     priv flag: bool
 }
 
-impl<A, T: Iterator<A>> Iterator<A> for ChainIterator<T> {
+impl<A, T: Iterator<A>, U: Iterator<A>> Iterator<A> for ChainIterator<T, U> {
     #[inline]
     fn next(&mut self) -> Option<A> {
         if self.flag {
@@ -385,7 +385,7 @@ mod tests {
     #[test]
     fn test_iterator_chain() {
         let xs = [0u, 1, 2, 3, 4, 5];
-        let ys = [30, 40, 50, 60];
+        let ys = [30u, 40, 50, 60];
         let expected = [0, 1, 2, 3, 4, 5, 30, 40, 50, 60];
         let mut it = xs.iter().chain(ys.iter());
         let mut i = 0;
@@ -394,6 +394,15 @@ mod tests {
             i += 1;
         }
         assert_eq!(i, expected.len());
+
+        let ys = Counter::new(30u, 10).take(4);
+        let mut it = xs.iter().transform(|&x| x).chain(ys);
+        let mut i = 0;
+        for it.advance |x: uint| {
+            assert_eq!(x, expected[i]);
+            i += 1;
+        }
+        assert_eq!(i, expected.len());
     }
 
     #[test]
diff --git a/src/libcore/libc.rs b/src/libcore/libc.rs
index d7a9ab4d63b..6fb4572913d 100644
--- a/src/libcore/libc.rs
+++ b/src/libcore/libc.rs
@@ -104,6 +104,7 @@ pub use libc::funcs::posix88::unistd::*;
 
 pub use libc::funcs::posix01::stat_::*;
 pub use libc::funcs::posix01::unistd::*;
+pub use libc::funcs::posix01::glob::*;
 pub use libc::funcs::posix08::unistd::*;
 
 pub use libc::funcs::bsd44::*;
@@ -210,7 +211,21 @@ pub mod types {
     #[cfg(target_os = "android")]
     pub mod os {
         pub mod common {
-            pub mod posix01 {}
+            pub mod posix01 {
+                use libc::types::common::c95::{c_void};
+                use libc::types::os::arch::c95::{c_char, size_t};
+                pub struct glob_t {
+                    gl_pathc: size_t,
+                    gl_pathv: **c_char,
+                    gl_offs:  size_t,
+
+                    __unused1: *c_void,
+                    __unused2: *c_void,
+                    __unused3: *c_void,
+                    __unused4: *c_void,
+                    __unused5: *c_void,
+                }
+            }
         }
 
         #[cfg(target_arch = "x86")]
@@ -368,7 +383,25 @@ pub mod types {
     #[cfg(target_os = "freebsd")]
     pub mod os {
         pub mod common {
-            pub mod posix01 {}
+            pub mod posix01 {
+                use libc::types::common::c95::{c_void};
+                use libc::types::os::arch::c95::{c_char, c_int, size_t};
+                pub struct glob_t {
+                    gl_pathc:  size_t,
+                    __unused1: size_t,
+                    gl_offs:   size_t,
+                    __unused2: c_int,
+                    gl_pathv:  **c_char,
+
+                    __unused3: *c_void,
+
+                    __unused4: *c_void,
+                    __unused5: *c_void,
+                    __unused6: *c_void,
+                    __unused7: *c_void,
+                    __unused8: *c_void,
+                }
+            }
         }
 
         #[cfg(target_arch = "x86_64")]
@@ -548,12 +581,16 @@ pub mod types {
 
                 pub type LPWSTR = *mut WCHAR;
                 pub type LPSTR = *mut CHAR;
+                pub type LPTSTR = *mut CHAR;
 
                 // Not really, but opaque to us.
                 pub type LPSECURITY_ATTRIBUTES = LPVOID;
 
                 pub type LPVOID = *mut c_void;
+                pub type LPBYTE = *mut BYTE;
                 pub type LPWORD = *mut WORD;
+                pub type LPDWORD = *mut DWORD;
+                pub type LPHANDLE = *mut HANDLE;
 
                 pub type LRESULT = LONG_PTR;
                 pub type PBOOL = *mut BOOL;
@@ -562,6 +599,36 @@ pub mod types {
 
                 pub type time64_t = i64;
                 pub type int64 = i64;
+
+                pub struct STARTUPINFO {
+                    cb: DWORD,
+                    lpReserved: LPTSTR,
+                    lpDesktop: LPTSTR,
+                    lpTitle: LPTSTR,
+                    dwX: DWORD,
+                    dwY: DWORD,
+                    dwXSize: DWORD,
+                    dwYSize: DWORD,
+                    dwXCountChars: DWORD,
+                    dwYCountCharts: DWORD,
+                    dwFillAttribute: DWORD,
+                    dwFlags: DWORD,
+                    wShowWindow: WORD,
+                    cbReserved2: WORD,
+                    lpReserved2: LPBYTE,
+                    hStdInput: HANDLE,
+                    hStdOutput: HANDLE,
+                    hStdError: HANDLE
+                }
+                pub type LPSTARTUPINFO = *mut STARTUPINFO;
+
+                pub struct PROCESS_INFORMATION {
+                    hProcess: HANDLE,
+                    hThread: HANDLE,
+                    dwProcessId: DWORD,
+                    dwThreadId: DWORD
+                }
+                pub type LPPROCESS_INFORMATION = *mut PROCESS_INFORMATION;
             }
         }
     }
@@ -570,6 +637,23 @@ pub mod types {
     pub mod os {
         pub mod common {
             pub mod posix01 {
+                use libc::types::common::c95::{c_void};
+                use libc::types::os::arch::c95::{c_char, c_int, size_t};
+                pub struct glob_t {
+                    gl_pathc:  size_t,
+                    __unused1: c_int,
+                    gl_offs:   size_t,
+                    __unused2: c_int,
+                    gl_pathv:  **c_char,
+
+                    __unused3: *c_void,
+
+                    __unused4: *c_void,
+                    __unused5: *c_void,
+                    __unused6: *c_void,
+                    __unused7: *c_void,
+                    __unused8: *c_void,
+                }
             }
         }
 
@@ -797,6 +881,11 @@ pub mod consts {
         pub mod bsd44 {
         }
         pub mod extra {
+            use libc::types::os::arch::extra::{DWORD, BOOL};
+
+            pub static TRUE : BOOL = 1;
+            pub static FALSE : BOOL = 0;
+
             pub static O_TEXT : int = 16384;
             pub static O_BINARY : int = 32768;
             pub static O_NOINHERIT: int = 128;
@@ -804,6 +893,50 @@ pub mod consts {
             pub static ERROR_SUCCESS : int = 0;
             pub static ERROR_INSUFFICIENT_BUFFER : int = 122;
             pub static INVALID_HANDLE_VALUE: int = -1;
+
+            pub static DELETE : DWORD = 0x00010000;
+            pub static READ_CONTROL : DWORD = 0x00020000;
+            pub static SYNCHRONIZE : DWORD = 0x00100000;
+            pub static WRITE_DAC : DWORD = 0x00040000;
+            pub static WRITE_OWNER : DWORD = 0x00080000;
+
+            pub static PROCESS_CREATE_PROCESS : DWORD = 0x0080;
+            pub static PROCESS_CREATE_THREAD : DWORD = 0x0002;
+            pub static PROCESS_DUP_HANDLE : DWORD = 0x0040;
+            pub static PROCESS_QUERY_INFORMATION : DWORD = 0x0400;
+            pub static PROCESS_QUERY_LIMITED_INFORMATION : DWORD = 0x1000;
+            pub static PROCESS_SET_INFORMATION : DWORD = 0x0200;
+            pub static PROCESS_SET_QUOTA : DWORD = 0x0100;
+            pub static PROCESS_SUSPEND_RESUME : DWORD = 0x0800;
+            pub static PROCESS_TERMINATE : DWORD = 0x0001;
+            pub static PROCESS_VM_OPERATION : DWORD = 0x0008;
+            pub static PROCESS_VM_READ : DWORD = 0x0010;
+            pub static PROCESS_VM_WRITE : DWORD = 0x0020;
+
+            pub static STARTF_FORCEONFEEDBACK : DWORD = 0x00000040;
+            pub static STARTF_FORCEOFFFEEDBACK : DWORD = 0x00000080;
+            pub static STARTF_PREVENTPINNING : DWORD = 0x00002000;
+            pub static STARTF_RUNFULLSCREEN : DWORD = 0x00000020;
+            pub static STARTF_TITLEISAPPID : DWORD = 0x00001000;
+            pub static STARTF_TITLEISLINKNAME : DWORD = 0x00000800;
+            pub static STARTF_USECOUNTCHARS : DWORD = 0x00000008;
+            pub static STARTF_USEFILLATTRIBUTE : DWORD = 0x00000010;
+            pub static STARTF_USEHOTKEY : DWORD = 0x00000200;
+            pub static STARTF_USEPOSITION : DWORD = 0x00000004;
+            pub static STARTF_USESHOWWINDOW : DWORD = 0x00000001;
+            pub static STARTF_USESIZE : DWORD = 0x00000002;
+            pub static STARTF_USESTDHANDLES : DWORD = 0x00000100;
+
+            pub static WAIT_ABANDONED : DWORD = 0x00000080;
+            pub static WAIT_OBJECT_0 : DWORD = 0x00000000;
+            pub static WAIT_TIMEOUT : DWORD = 0x00000102;
+            pub static WAIT_FAILED : DWORD = -1;
+
+            pub static DUPLICATE_CLOSE_SOURCE : DWORD = 0x00000001;
+            pub static DUPLICATE_SAME_ACCESS : DWORD = 0x00000002;
+
+            pub static INFINITE : DWORD = -1;
+            pub static STILL_ACTIVE : DWORD = 259;
         }
     }
 
@@ -876,6 +1009,18 @@ pub mod consts {
         }
         pub mod posix01 {
             pub static SIGTRAP : int = 5;
+
+            pub static GLOB_ERR      : int = 1 << 0;
+            pub static GLOB_MARK     : int = 1 << 1;
+            pub static GLOB_NOSORT   : int = 1 << 2;
+            pub static GLOB_DOOFFS   : int = 1 << 3;
+            pub static GLOB_NOCHECK  : int = 1 << 4;
+            pub static GLOB_APPEND   : int = 1 << 5;
+            pub static GLOB_NOESCAPE : int = 1 << 6;
+
+            pub static GLOB_NOSPACE  : int = 1;
+            pub static GLOB_ABORTED  : int = 2;
+            pub static GLOB_NOMATCH  : int = 3;
         }
         pub mod posix08 {
         }
@@ -955,6 +1100,18 @@ pub mod consts {
         }
         pub mod posix01 {
             pub static SIGTRAP : int = 5;
+
+            pub static GLOB_APPEND   : int = 0x0001;
+            pub static GLOB_DOOFFS   : int = 0x0002;
+            pub static GLOB_ERR      : int = 0x0004;
+            pub static GLOB_MARK     : int = 0x0008;
+            pub static GLOB_NOCHECK  : int = 0x0010;
+            pub static GLOB_NOSORT   : int = 0x0020;
+            pub static GLOB_NOESCAPE : int = 0x2000;
+
+            pub static GLOB_NOSPACE  : int = -1;
+            pub static GLOB_ABORTED  : int = -2;
+            pub static GLOB_NOMATCH  : int = -3;
         }
         pub mod posix08 {
         }
@@ -1035,6 +1192,18 @@ pub mod consts {
         }
         pub mod posix01 {
             pub static SIGTRAP : int = 5;
+
+            pub static GLOB_APPEND   : int = 0x0001;
+            pub static GLOB_DOOFFS   : int = 0x0002;
+            pub static GLOB_ERR      : int = 0x0004;
+            pub static GLOB_MARK     : int = 0x0008;
+            pub static GLOB_NOCHECK  : int = 0x0010;
+            pub static GLOB_NOSORT   : int = 0x0020;
+            pub static GLOB_NOESCAPE : int = 0x2000;
+
+            pub static GLOB_NOSPACE  : int = -1;
+            pub static GLOB_ABORTED  : int = -2;
+            pub static GLOB_NOMATCH  : int = -3;
         }
         pub mod posix08 {
         }
@@ -1605,6 +1774,21 @@ pub mod funcs {
                                -> pid_t;
             }
         }
+
+        #[nolink]
+        #[abi = "cdecl"]
+        pub mod glob {
+            use libc::types::common::c95::{c_void};
+            use libc::types::os::arch::c95::{c_char, c_int};
+            use libc::types::os::common::posix01::{glob_t};
+
+            pub extern {
+                unsafe fn glob(pattern: *c_char, flags: c_int,
+                               errfunc: *c_void, // XXX callback
+                               pglob: *mut glob_t);
+                unsafe fn globfree(pglob: *mut glob_t);
+            }
+        }
     }
 
     #[cfg(target_os = "win32")]
@@ -1614,6 +1798,9 @@ pub mod funcs {
 
         pub mod unistd {
         }
+
+        pub mod glob {
+        }
     }
 
 
@@ -1646,12 +1833,24 @@ pub mod funcs {
 
             unsafe fn sysctlnametomib(name: *c_char, mibp: *mut c_int,
                                sizep: *mut size_t) -> c_int;
+
+            unsafe fn getdtablesize() -> c_int;
         }
     }
 
 
     #[cfg(target_os = "linux")]
     #[cfg(target_os = "android")]
+    pub mod bsd44 {
+        use libc::types::os::arch::c95::{c_int};
+
+        #[abi = "cdecl"]
+        pub extern {
+            unsafe fn getdtablesize() -> c_int;
+        }
+    }
+
+
     #[cfg(target_os = "win32")]
     pub mod bsd44 {
     }
@@ -1685,9 +1884,11 @@ pub mod funcs {
         pub mod kernel32 {
             use libc::types::os::arch::c95::{c_uint};
             use libc::types::os::arch::extra::{BOOL, DWORD, HMODULE};
-            use libc::types::os::arch::extra::{LPCWSTR, LPWSTR, LPTCH};
-            use libc::types::os::arch::extra::{LPSECURITY_ATTRIBUTES};
-            use libc::types::os::arch::extra::{HANDLE};
+            use libc::types::os::arch::extra::{LPCWSTR, LPWSTR, LPCTSTR,
+                                               LPTSTR, LPTCH, LPDWORD, LPVOID};
+            use libc::types::os::arch::extra::{LPSECURITY_ATTRIBUTES, LPSTARTUPINFO,
+                                               LPPROCESS_INFORMATION};
+            use libc::types::os::arch::extra::{HANDLE, LPHANDLE};
 
             #[abi = "stdcall"]
             pub extern "stdcall" {
@@ -1724,29 +1925,46 @@ pub mod funcs {
                                        findFileData: HANDLE)
                     -> BOOL;
                 unsafe fn FindClose(findFile: HANDLE) -> BOOL;
+                unsafe fn DuplicateHandle(hSourceProcessHandle: HANDLE,
+                                          hSourceHandle: HANDLE,
+                                          hTargetProcessHandle: HANDLE,
+                                          lpTargetHandle: LPHANDLE,
+                                          dwDesiredAccess: DWORD,
+                                          bInheritHandle: BOOL,
+                                          dwOptions: DWORD) -> BOOL;
                 unsafe fn CloseHandle(hObject: HANDLE) -> BOOL;
+                unsafe fn OpenProcess(dwDesiredAccess: DWORD,
+                                      bInheritHandle: BOOL,
+                                      dwProcessId: DWORD) -> HANDLE;
+                unsafe fn GetCurrentProcess() -> HANDLE;
+                unsafe fn CreateProcessA(lpApplicationName: LPCTSTR,
+                                         lpCommandLine: LPTSTR,
+                                         lpProcessAttributes: LPSECURITY_ATTRIBUTES,
+                                         lpThreadAttributes: LPSECURITY_ATTRIBUTES,
+                                         bInheritHandles: BOOL,
+                                         dwCreationFlags: DWORD,
+                                         lpEnvironment: LPVOID,
+                                         lpCurrentDirectory: LPCTSTR,
+                                         lpStartupInfo: LPSTARTUPINFO,
+                                         lpProcessInformation: LPPROCESS_INFORMATION) -> BOOL;
+                unsafe fn WaitForSingleObject(hHandle: HANDLE, dwMilliseconds: DWORD) -> DWORD;
                 unsafe fn TerminateProcess(hProcess: HANDLE, uExitCode: c_uint) -> BOOL;
+                unsafe fn GetExitCodeProcess(hProcess: HANDLE, lpExitCode: LPDWORD) -> BOOL;
             }
         }
 
         pub mod msvcrt {
-            use libc::types::os::arch::c95::c_int;
+            use libc::types::os::arch::c95::{c_int, c_long};
 
             #[abi = "cdecl"]
             #[nolink]
             pub extern {
                 #[link_name = "_commit"]
                 unsafe fn commit(fd: c_int) -> c_int;
+
+                #[link_name = "_get_osfhandle"]
+                unsafe fn get_osfhandle(fd: c_int) -> c_long;
             }
         }
     }
 }
-
-
-// Local Variables:
-// mode: rust;
-// fill-column: 78;
-// indent-tabs-mode: nil
-// c-basic-offset: 4
-// buffer-file-coding-system: utf-8-unix
-// End:
diff --git a/src/libcore/logging.rs b/src/libcore/logging.rs
index ba976de50ab..afe8338f2ce 100644
--- a/src/libcore/logging.rs
+++ b/src/libcore/logging.rs
@@ -59,4 +59,3 @@ pub fn log_type<T>(level: u32, object: &T) {
         rustrt::rust_log_str(level, transmute(vec::raw::to_ptr(bytes)), len);
     }
 }
-
diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs
new file mode 100644
index 00000000000..b19a753b715
--- /dev/null
+++ b/src/libcore/macros.rs
@@ -0,0 +1,39 @@
+// Copyright 2012 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.
+
+#[macro_escape];
+
+// Some basic logging
+macro_rules! rtdebug_ (
+    ($( $arg:expr),+) => ( {
+        dumb_println(fmt!( $($arg),+ ));
+
+        fn dumb_println(s: &str) {
+            use io::WriterUtil;
+            let dbg = ::libc::STDERR_FILENO as ::io::fd_t;
+            dbg.write_str(s);
+            dbg.write_str("\n");
+        }
+
+    } )
+)
+
+// An alternate version with no output, for turning off logging
+macro_rules! rtdebug (
+    ($( $arg:expr),+) => ( $(let _ = $arg)*; )
+)
+
+macro_rules! abort(
+    ($( $msg:expr),+) => ( {
+        rtdebug!($($msg),+);
+
+        unsafe { ::libc::abort(); }
+    } )
+)
diff --git a/src/libcore/num/cmath.rs b/src/libcore/num/cmath.rs
index 30b0c54dc2d..8a0a88235d2 100644
--- a/src/libcore/num/cmath.rs
+++ b/src/libcore/num/cmath.rs
@@ -267,14 +267,3 @@ pub mod c_double_targ_consts {
 }
 
 */
-
-//
-// Local Variables:
-// mode: rust
-// fill-column: 78;
-// indent-tabs-mode: nil
-// c-basic-offset: 4
-// buffer-file-coding-system: utf-8-unix
-// End:
-//
-
diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs
index 6398127a5fa..416ec2069b5 100644
--- a/src/libcore/num/f32.rs
+++ b/src/libcore/num/f32.rs
@@ -10,7 +10,6 @@
 
 //! Operations and constants for `f32`
 
-use from_str;
 use num::{Zero, One, strconv};
 use prelude::*;
 
@@ -123,7 +122,7 @@ pub fn sub(x: f32, y: f32) -> f32 { return x - y; }
 pub fn mul(x: f32, y: f32) -> f32 { return x * y; }
 
 #[inline(always)]
-pub fn quot(x: f32, y: f32) -> f32 { return x / y; }
+pub fn div(x: f32, y: f32) -> f32 { return x / y; }
 
 #[inline(always)]
 pub fn rem(x: f32, y: f32) -> f32 { return x % y; }
@@ -278,11 +277,13 @@ impl Mul<f32,f32> for f32 {
     #[inline(always)]
     fn mul(&self, other: &f32) -> f32 { *self * *other }
 }
+
 #[cfg(notest)]
-impl Quot<f32,f32> for f32 {
+impl Div<f32,f32> for f32 {
     #[inline(always)]
-    fn quot(&self, other: &f32) -> f32 { *self / *other }
+    fn div(&self, other: &f32) -> f32 { *self / *other }
 }
+
 #[cfg(notest)]
 impl Rem<f32,f32> for f32 {
     #[inline(always)]
@@ -791,7 +792,7 @@ pub fn from_str_radix(num: &str, rdx: uint) -> Option<f32> {
                              strconv::ExpNone, false, false)
 }
 
-impl from_str::FromStr for f32 {
+impl FromStr for f32 {
     #[inline(always)]
     fn from_str(val: &str) -> Option<f32> { from_str(val) }
 }
@@ -979,13 +980,3 @@ mod tests {
         assert_eq!(Primitive::bytes::<f32>(), sys::size_of::<f32>());
     }
 }
-
-//
-// Local Variables:
-// mode: rust
-// fill-column: 78;
-// indent-tabs-mode: nil
-// c-basic-offset: 4
-// buffer-file-coding-system: utf-8-unix
-// End:
-//
diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs
index 013f3c5095e..6e09ca61a7d 100644
--- a/src/libcore/num/f64.rs
+++ b/src/libcore/num/f64.rs
@@ -10,7 +10,6 @@
 
 //! Operations and constants for `f64`
 
-use from_str;
 use libc::c_int;
 use num::{Zero, One, strconv};
 use prelude::*;
@@ -149,7 +148,7 @@ pub fn sub(x: f64, y: f64) -> f64 { return x - y; }
 pub fn mul(x: f64, y: f64) -> f64 { return x * y; }
 
 #[inline(always)]
-pub fn quot(x: f64, y: f64) -> f64 { return x / y; }
+pub fn div(x: f64, y: f64) -> f64 { return x / y; }
 
 #[inline(always)]
 pub fn rem(x: f64, y: f64) -> f64 { return x % y; }
@@ -297,9 +296,8 @@ impl Mul<f64,f64> for f64 {
     fn mul(&self, other: &f64) -> f64 { *self * *other }
 }
 #[cfg(notest)]
-impl Quot<f64,f64> for f64 {
-    #[inline(always)]
-    fn quot(&self, other: &f64) -> f64 { *self / *other }
+impl Div<f64,f64> for f64 {
+    fn div(&self, other: &f64) -> f64 { *self / *other }
 }
 #[cfg(notest)]
 impl Rem<f64,f64> for f64 {
@@ -837,7 +835,7 @@ pub fn from_str_radix(num: &str, rdx: uint) -> Option<f64> {
                              strconv::ExpNone, false, false)
 }
 
-impl from_str::FromStr for f64 {
+impl FromStr for f64 {
     #[inline(always)]
     fn from_str(val: &str) -> Option<f64> { from_str(val) }
 }
@@ -1030,13 +1028,3 @@ mod tests {
         assert_eq!(Primitive::bytes::<f64>(), sys::size_of::<f64>());
     }
 }
-
-//
-// Local Variables:
-// mode: rust
-// fill-column: 78;
-// indent-tabs-mode: nil
-// c-basic-offset: 4
-// buffer-file-coding-system: utf-8-unix
-// End:
-//
diff --git a/src/libcore/num/float.rs b/src/libcore/num/float.rs
index 496ad4ec176..da9d03f6a7b 100644
--- a/src/libcore/num/float.rs
+++ b/src/libcore/num/float.rs
@@ -20,12 +20,11 @@
 
 // PORT this must match in width according to architecture
 
-use from_str;
 use libc::c_int;
 use num::{Zero, One, strconv};
 use prelude::*;
 
-pub use f64::{add, sub, mul, quot, rem, lt, le, eq, ne, ge, gt};
+pub use f64::{add, sub, mul, div, rem, lt, le, eq, ne, ge, gt};
 pub use f64::logarithm;
 pub use f64::{acos, asin, atan2, cbrt, ceil, copysign, cosh, floor};
 pub use f64::{erf, erfc, exp, expm1, exp2, abs_sub};
@@ -289,7 +288,7 @@ pub fn from_str_radix(num: &str, radix: uint) -> Option<float> {
                              strconv::ExpNone, false, false)
 }
 
-impl from_str::FromStr for float {
+impl FromStr for float {
     #[inline(always)]
     fn from_str(val: &str) -> Option<float> { from_str(val) }
 }
@@ -691,11 +690,13 @@ impl Mul<float,float> for float {
     #[inline(always)]
     fn mul(&self, other: &float) -> float { *self * *other }
 }
+
 #[cfg(notest)]
-impl Quot<float,float> for float {
+impl Div<float,float> for float {
     #[inline(always)]
-    fn quot(&self, other: &float) -> float { *self / *other }
+    fn div(&self, other: &float) -> float { *self / *other }
 }
+
 #[cfg(notest)]
 impl Rem<float,float> for float {
     #[inline(always)]
@@ -1132,13 +1133,3 @@ mod tests {
         assert_eq!(to_str_digits(-infinity, 10u), ~"-inf");
     }
 }
-
-//
-// Local Variables:
-// mode: rust
-// fill-column: 78;
-// indent-tabs-mode: nil
-// c-basic-offset: 4
-// buffer-file-coding-system: utf-8-unix
-// End:
-//
diff --git a/src/libcore/num/int-template.rs b/src/libcore/num/int-template.rs
index 77b4eab1338..95c187a7be2 100644
--- a/src/libcore/num/int-template.rs
+++ b/src/libcore/num/int-template.rs
@@ -10,7 +10,6 @@
 
 use T = self::inst::T;
 
-use from_str::FromStr;
 use num::{ToStrRadix, FromStrRadix};
 use num::{Zero, One, strconv};
 use prelude::*;
@@ -30,7 +29,7 @@ pub fn sub(x: T, y: T) -> T { x - y }
 #[inline(always)]
 pub fn mul(x: T, y: T) -> T { x * y }
 #[inline(always)]
-pub fn quot(x: T, y: T) -> T { x / y }
+pub fn div(x: T, y: T) -> T { x / y }
 
 ///
 /// Returns the remainder of y / x.
@@ -202,10 +201,10 @@ impl Mul<T,T> for T {
 }
 
 #[cfg(notest)]
-impl Quot<T,T> for T {
+impl Div<T,T> for T {
     ///
-    /// Returns the integer quotient, truncated towards 0. As this behaviour reflects
-    /// the underlying machine implementation it is more efficient than `Natural::div`.
+    /// Integer division, truncated towards 0. As this behaviour reflects the underlying
+    /// machine implementation it is more efficient than `Integer::div_floor`.
     ///
     /// # Examples
     ///
@@ -222,7 +221,7 @@ impl Quot<T,T> for T {
     /// ~~~
     ///
     #[inline(always)]
-    fn quot(&self, other: &T) -> T { *self / *other }
+    fn div(&self, other: &T) -> T { *self / *other }
 }
 
 #[cfg(notest)]
@@ -297,25 +296,25 @@ impl Integer for T {
     /// # Examples
     ///
     /// ~~~
-    /// assert!(( 8).div( 3) ==  2);
-    /// assert!(( 8).div(-3) == -3);
-    /// assert!((-8).div( 3) == -3);
-    /// assert!((-8).div(-3) ==  2);
+    /// assert!(( 8).div_floor( 3) ==  2);
+    /// assert!(( 8).div_floor(-3) == -3);
+    /// assert!((-8).div_floor( 3) == -3);
+    /// assert!((-8).div_floor(-3) ==  2);
     ///
-    /// assert!(( 1).div( 2) ==  0);
-    /// assert!(( 1).div(-2) == -1);
-    /// assert!((-1).div( 2) == -1);
-    /// assert!((-1).div(-2) ==  0);
+    /// assert!(( 1).div_floor( 2) ==  0);
+    /// assert!(( 1).div_floor(-2) == -1);
+    /// assert!((-1).div_floor( 2) == -1);
+    /// assert!((-1).div_floor(-2) ==  0);
     /// ~~~
     ///
     #[inline(always)]
-    fn div(&self, other: &T) -> T {
+    fn div_floor(&self, other: &T) -> T {
         // Algorithm from [Daan Leijen. _Division and Modulus for Computer Scientists_,
         // December 2001](http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf)
-        match self.quot_rem(other) {
-            (q, r) if (r > 0 && *other < 0)
-                   || (r < 0 && *other > 0) => q - 1,
-            (q, _)                          => q,
+        match self.div_rem(other) {
+            (d, r) if (r > 0 && *other < 0)
+                   || (r < 0 && *other > 0) => d - 1,
+            (d, _)                          => d,
         }
     }
 
@@ -323,25 +322,25 @@ impl Integer for T {
     /// Integer modulo, satisfying:
     ///
     /// ~~~
-    /// assert!(n.div(d) * d + n.modulo(d) == n)
+    /// assert!(n.div_floor(d) * d + n.mod_floor(d) == n)
     /// ~~~
     ///
     /// # Examples
     ///
     /// ~~~
-    /// assert!(( 8).modulo( 3) ==  2);
-    /// assert!(( 8).modulo(-3) == -1);
-    /// assert!((-8).modulo( 3) ==  1);
-    /// assert!((-8).modulo(-3) == -2);
+    /// assert!(( 8).mod_floor( 3) ==  2);
+    /// assert!(( 8).mod_floor(-3) == -1);
+    /// assert!((-8).mod_floor( 3) ==  1);
+    /// assert!((-8).mod_floor(-3) == -2);
     ///
-    /// assert!(( 1).modulo( 2) ==  1);
-    /// assert!(( 1).modulo(-2) == -1);
-    /// assert!((-1).modulo( 2) ==  1);
-    /// assert!((-1).modulo(-2) == -1);
+    /// assert!(( 1).mod_floor( 2) ==  1);
+    /// assert!(( 1).mod_floor(-2) == -1);
+    /// assert!((-1).mod_floor( 2) ==  1);
+    /// assert!((-1).mod_floor(-2) == -1);
     /// ~~~
     ///
     #[inline(always)]
-    fn modulo(&self, other: &T) -> T {
+    fn mod_floor(&self, other: &T) -> T {
         // Algorithm from [Daan Leijen. _Division and Modulus for Computer Scientists_,
         // December 2001](http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf)
         match *self % *other {
@@ -351,21 +350,21 @@ impl Integer for T {
         }
     }
 
-    /// Calculates `div` and `modulo` simultaneously
+    /// Calculates `div_floor` and `mod_floor` simultaneously
     #[inline(always)]
-    fn div_mod(&self, other: &T) -> (T,T) {
+    fn div_mod_floor(&self, other: &T) -> (T,T) {
         // Algorithm from [Daan Leijen. _Division and Modulus for Computer Scientists_,
         // December 2001](http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf)
-        match self.quot_rem(other) {
-            (q, r) if (r > 0 && *other < 0)
-                   || (r < 0 && *other > 0) => (q - 1, r + *other),
-            (q, r)                          => (q, r),
+        match self.div_rem(other) {
+            (d, r) if (r > 0 && *other < 0)
+                   || (r < 0 && *other > 0) => (d - 1, r + *other),
+            (d, r)                          => (d, r),
         }
     }
 
-    /// Calculates `quot` (`\`) and `rem` (`%`) simultaneously
+    /// Calculates `div` (`\`) and `rem` (`%`) simultaneously
     #[inline(always)]
-    fn quot_rem(&self, other: &T) -> (T,T) {
+    fn div_rem(&self, other: &T) -> (T,T) {
         (*self / *other, *self % *other)
     }
 
@@ -589,42 +588,42 @@ mod tests {
     }
 
     #[test]
-    fn test_quot_rem() {
-        fn test_nd_qr(nd: (T,T), qr: (T,T)) {
+    fn test_div_rem() {
+        fn test_nd_dr(nd: (T,T), qr: (T,T)) {
             let (n,d) = nd;
-            let separate_quot_rem = (n / d, n % d);
-            let combined_quot_rem = n.quot_rem(&d);
+            let separate_div_rem = (n / d, n % d);
+            let combined_div_rem = n.div_rem(&d);
 
-            assert_eq!(separate_quot_rem, qr);
-            assert_eq!(combined_quot_rem, qr);
+            assert_eq!(separate_div_rem, qr);
+            assert_eq!(combined_div_rem, qr);
 
-            test_division_rule(nd, separate_quot_rem);
-            test_division_rule(nd, combined_quot_rem);
+            test_division_rule(nd, separate_div_rem);
+            test_division_rule(nd, combined_div_rem);
         }
 
-        test_nd_qr(( 8,  3), ( 2,  2));
-        test_nd_qr(( 8, -3), (-2,  2));
-        test_nd_qr((-8,  3), (-2, -2));
-        test_nd_qr((-8, -3), ( 2, -2));
+        test_nd_dr(( 8,  3), ( 2,  2));
+        test_nd_dr(( 8, -3), (-2,  2));
+        test_nd_dr((-8,  3), (-2, -2));
+        test_nd_dr((-8, -3), ( 2, -2));
 
-        test_nd_qr(( 1,  2), ( 0,  1));
-        test_nd_qr(( 1, -2), ( 0,  1));
-        test_nd_qr((-1,  2), ( 0, -1));
-        test_nd_qr((-1, -2), ( 0, -1));
+        test_nd_dr(( 1,  2), ( 0,  1));
+        test_nd_dr(( 1, -2), ( 0,  1));
+        test_nd_dr((-1,  2), ( 0, -1));
+        test_nd_dr((-1, -2), ( 0, -1));
     }
 
     #[test]
-    fn test_div_mod() {
+    fn test_div_mod_floor() {
         fn test_nd_dm(nd: (T,T), dm: (T,T)) {
             let (n,d) = nd;
-            let separate_div_mod = (n.div(&d), n.modulo(&d));
-            let combined_div_mod = n.div_mod(&d);
+            let separate_div_mod_floor = (n.div_floor(&d), n.mod_floor(&d));
+            let combined_div_mod_floor = n.div_mod_floor(&d);
 
-            assert_eq!(separate_div_mod, dm);
-            assert_eq!(combined_div_mod, dm);
+            assert_eq!(separate_div_mod_floor, dm);
+            assert_eq!(combined_div_mod_floor, dm);
 
-            test_division_rule(nd, separate_div_mod);
-            test_division_rule(nd, combined_div_mod);
+            test_division_rule(nd, separate_div_mod_floor);
+            test_division_rule(nd, combined_div_mod_floor);
         }
 
         test_nd_dm(( 8,  3), ( 2,  2));
diff --git a/src/libcore/num/num.rs b/src/libcore/num/num.rs
index 96fed51309e..1a59a069df7 100644
--- a/src/libcore/num/num.rs
+++ b/src/libcore/num/num.rs
@@ -10,7 +10,7 @@
 
 //! An interface for numeric types
 use cmp::{Eq, Ord};
-use ops::{Add, Sub, Mul, Quot, Rem, Neg};
+use ops::{Add, Sub, Mul, Div, Rem, Neg};
 use ops::{Not, BitAnd, BitOr, BitXor, Shl, Shr};
 use option::Option;
 use kinds::Copy;
@@ -25,7 +25,7 @@ pub trait Num: Eq + Zero + One
              + Add<Self,Self>
              + Sub<Self,Self>
              + Mul<Self,Self>
-             + Quot<Self,Self>
+             + Div<Self,Self>
              + Rem<Self,Self> {}
 
 pub trait IntConvertible {
@@ -69,12 +69,13 @@ pub fn abs<T:Ord + Zero + Neg<T>>(v: T) -> T {
 
 pub trait Integer: Num
                  + Orderable
-                 + Quot<Self,Self>
+                 + Div<Self,Self>
                  + Rem<Self,Self> {
-    fn div(&self, other: &Self) -> Self;
-    fn modulo(&self, other: &Self) -> Self;
-    fn div_mod(&self, other: &Self) -> (Self,Self);
-    fn quot_rem(&self, other: &Self) -> (Self,Self);
+    fn div_rem(&self, other: &Self) -> (Self,Self);
+
+    fn div_floor(&self, other: &Self) -> Self;
+    fn mod_floor(&self, other: &Self) -> Self;
+    fn div_mod_floor(&self, other: &Self) -> (Self,Self);
 
     fn gcd(&self, other: &Self) -> Self;
     fn lcm(&self, other: &Self) -> Self;
@@ -95,7 +96,7 @@ pub trait Round {
 pub trait Fractional: Num
                     + Orderable
                     + Round
-                    + Quot<Self,Self> {
+                    + Div<Self,Self> {
     fn recip(&self) -> Self;
 }
 
@@ -219,7 +220,7 @@ pub trait Primitive: Num
                    + Add<Self,Self>
                    + Sub<Self,Self>
                    + Mul<Self,Self>
-                   + Quot<Self,Self>
+                   + Div<Self,Self>
                    + Rem<Self,Self> {
     // FIXME (#5527): These should be associated constants
     fn bits() -> uint;
@@ -364,7 +365,7 @@ pub trait FromStrRadix {
 /// - If code written to use this function doesn't care about it, it's
 ///   probably assuming that `x^0` always equals `1`.
 ///
-pub fn pow_with_uint<T:NumCast+One+Zero+Copy+Quot<T,T>+Mul<T,T>>(
+pub fn pow_with_uint<T:NumCast+One+Zero+Copy+Div<T,T>+Mul<T,T>>(
     radix: uint, pow: uint) -> T {
     let _0: T = Zero::zero();
     let _1: T = One::one();
@@ -384,18 +385,19 @@ pub fn pow_with_uint<T:NumCast+One+Zero+Copy+Quot<T,T>+Mul<T,T>>(
     total
 }
 
+/// Helper function for testing numeric operations
 #[cfg(test)]
 pub fn test_num<T:Num + NumCast>(ten: T, two: T) {
     assert_eq!(ten.add(&two),  cast(12));
     assert_eq!(ten.sub(&two),  cast(8));
     assert_eq!(ten.mul(&two),  cast(20));
-    assert_eq!(ten.quot(&two), cast(5));
+    assert_eq!(ten.div(&two), cast(5));
     assert_eq!(ten.rem(&two),  cast(0));
 
     assert_eq!(ten.add(&two),  ten + two);
     assert_eq!(ten.sub(&two),  ten - two);
     assert_eq!(ten.mul(&two),  ten * two);
-    assert_eq!(ten.quot(&two), ten / two);
+    assert_eq!(ten.div(&two), ten / two);
     assert_eq!(ten.rem(&two),  ten % two);
 }
 
diff --git a/src/libcore/num/strconv.rs b/src/libcore/num/strconv.rs
index 004789e7fc1..c16a29f8295 100644
--- a/src/libcore/num/strconv.rs
+++ b/src/libcore/num/strconv.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 use core::cmp::{Ord, Eq};
-use ops::{Add, Sub, Mul, Quot, Rem, Neg};
+use ops::{Add, Sub, Mul, Div, Rem, Neg};
 use option::{None, Option, Some};
 use char;
 use str;
@@ -58,7 +58,7 @@ fn is_neg_inf<T:Eq+NumStrConv>(num: &T) -> bool {
 }
 
 #[inline(always)]
-fn is_neg_zero<T:Eq+One+Zero+NumStrConv+Quot<T,T>>(num: &T) -> bool {
+fn is_neg_zero<T:Eq+One+Zero+NumStrConv+Div<T,T>>(num: &T) -> bool {
     let _0: T = Zero::zero();
     let _1: T = One::one();
 
@@ -171,7 +171,7 @@ static nan_buf:          [u8, ..3] = ['N' as u8, 'a' as u8, 'N' as u8];
  * - Fails if `radix` < 2 or `radix` > 36.
  */
 pub fn to_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+NumStrConv+Copy+
-                                  Quot<T,T>+Neg<T>+Rem<T,T>+Mul<T,T>>(
+                                  Div<T,T>+Neg<T>+Rem<T,T>+Mul<T,T>>(
         num: &T, radix: uint, negative_zero: bool,
         sign: SignFormat, digits: SignificantDigits) -> (~[u8], bool) {
     if (radix as int) < 2 {
@@ -379,7 +379,7 @@ pub fn to_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+NumStrConv+Copy+
  */
 #[inline(always)]
 pub fn to_str_common<T:NumCast+Zero+One+Eq+Ord+NumStrConv+Copy+
-                            Quot<T,T>+Neg<T>+Rem<T,T>+Mul<T,T>>(
+                            Div<T,T>+Neg<T>+Rem<T,T>+Mul<T,T>>(
         num: &T, radix: uint, negative_zero: bool,
         sign: SignFormat, digits: SignificantDigits) -> (~str, bool) {
     let (bytes, special) = to_str_bytes_common(num, radix,
@@ -432,7 +432,7 @@ priv static DIGIT_E_RADIX: uint = ('e' as uint) - ('a' as uint) + 11u;
  * - Fails if `radix` > 18 and `special == true` due to conflict
  *   between digit and lowest first character in `inf` and `NaN`, the `'i'`.
  */
-pub fn from_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+Copy+Quot<T,T>+
+pub fn from_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+Copy+Div<T,T>+
                                     Mul<T,T>+Sub<T,T>+Neg<T>+Add<T,T>+
                                     NumStrConv>(
         buf: &[u8], radix: uint, negative: bool, fractional: bool,
@@ -629,7 +629,7 @@ pub fn from_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+Copy+Quot<T,T>+
  * `from_str_bytes_common()`, for details see there.
  */
 #[inline(always)]
-pub fn from_str_common<T:NumCast+Zero+One+Eq+Ord+Copy+Quot<T,T>+Mul<T,T>+
+pub fn from_str_common<T:NumCast+Zero+One+Eq+Ord+Copy+Div<T,T>+Mul<T,T>+
                               Sub<T,T>+Neg<T>+Add<T,T>+NumStrConv>(
         buf: &str, radix: uint, negative: bool, fractional: bool,
         special: bool, exponent: ExponentFormat, empty_zero: bool,
diff --git a/src/libcore/num/uint-template.rs b/src/libcore/num/uint-template.rs
index 2d204449468..6d0f1fe1fc7 100644
--- a/src/libcore/num/uint-template.rs
+++ b/src/libcore/num/uint-template.rs
@@ -11,7 +11,6 @@
 use T = self::inst::T;
 use T_SIGNED = self::inst::T_SIGNED;
 
-use from_str::FromStr;
 use num::{ToStrRadix, FromStrRadix};
 use num::{Zero, One, strconv};
 use prelude::*;
@@ -31,7 +30,7 @@ pub fn sub(x: T, y: T) -> T { x - y }
 #[inline(always)]
 pub fn mul(x: T, y: T) -> T { x * y }
 #[inline(always)]
-pub fn quot(x: T, y: T) -> T { x / y }
+pub fn div(x: T, y: T) -> T { x / y }
 #[inline(always)]
 pub fn rem(x: T, y: T) -> T { x % y }
 
@@ -167,9 +166,9 @@ impl Mul<T,T> for T {
 }
 
 #[cfg(notest)]
-impl Quot<T,T> for T {
+impl Div<T,T> for T {
     #[inline(always)]
-    fn quot(&self, other: &T) -> T { *self / *other }
+    fn div(&self, other: &T) -> T { *self / *other }
 }
 
 #[cfg(notest)]
@@ -187,23 +186,23 @@ impl Neg<T> for T {
 impl Unsigned for T {}
 
 impl Integer for T {
-    /// Unsigned integer division. Returns the same result as `quot` (`/`).
+    /// Calculates `div` (`\`) and `rem` (`%`) simultaneously
     #[inline(always)]
-    fn div(&self, other: &T) -> T { *self / *other }
+    fn div_rem(&self, other: &T) -> (T,T) {
+        (*self / *other, *self % *other)
+    }
 
-    /// Unsigned integer modulo operation. Returns the same result as `rem` (`%`).
+    /// Unsigned integer division. Returns the same result as `div` (`/`).
     #[inline(always)]
-    fn modulo(&self, other: &T) -> T { *self / *other }
+    fn div_floor(&self, other: &T) -> T { *self / *other }
 
-    /// Calculates `div` and `modulo` simultaneously
+    /// Unsigned integer modulo operation. Returns the same result as `rem` (`%`).
     #[inline(always)]
-    fn div_mod(&self, other: &T) -> (T,T) {
-        (*self / *other, *self % *other)
-    }
+    fn mod_floor(&self, other: &T) -> T { *self / *other }
 
-    /// Calculates `quot` (`\`) and `rem` (`%`) simultaneously
+    /// Calculates `div_floor` and `modulo_floor` simultaneously
     #[inline(always)]
-    fn quot_rem(&self, other: &T) -> (T,T) {
+    fn div_mod_floor(&self, other: &T) -> (T,T) {
         (*self / *other, *self % *other)
     }
 
diff --git a/src/libcore/ops.rs b/src/libcore/ops.rs
index 18dcf34e49b..47ff45be687 100644
--- a/src/libcore/ops.rs
+++ b/src/libcore/ops.rs
@@ -30,9 +30,9 @@ pub trait Mul<RHS,Result> {
     fn mul(&self, rhs: &RHS) -> Result;
 }
 
-#[lang="quot"]
-pub trait Quot<RHS,Result> {
-    fn quot(&self, rhs: &RHS) -> Result;
+#[lang="div"]
+pub trait Div<RHS,Result> {
+    fn div(&self, rhs: &RHS) -> Result;
 }
 
 #[lang="rem"]
diff --git a/src/libcore/option.rs b/src/libcore/option.rs
index 5abf376ddde..b7c51147fba 100644
--- a/src/libcore/option.rs
+++ b/src/libcore/option.rs
@@ -461,11 +461,3 @@ fn test_get_or_zero() {
     let no_stuff: Option<int> = None;
     assert!(no_stuff.get_or_zero() == 0);
 }
-
-// Local Variables:
-// mode: rust;
-// fill-column: 78;
-// indent-tabs-mode: nil
-// c-basic-offset: 4
-// buffer-file-coding-system: utf-8-unix
-// End:
diff --git a/src/libcore/os.rs b/src/libcore/os.rs
index d5271ec228b..42c77a687e5 100644
--- a/src/libcore/os.rs
+++ b/src/libcore/os.rs
@@ -38,6 +38,7 @@ use ptr;
 use str;
 use task;
 use uint;
+use unstable::finally::Finally;
 use vec;
 
 pub use libc::fclose;
@@ -372,8 +373,9 @@ pub fn pipe() -> Pipe {
         // inheritance has to be handled in a different way that I do not
         // fully understand. Here we explicitly make the pipe non-inheritable,
         // which means to pass it to a subprocess they need to be duplicated
-        // first, as in rust_run_program.
-        let mut fds = Pipe {in: 0 as c_int, out: 0 as c_int};
+        // first, as in core::run.
+        let mut fds = Pipe {in: 0 as c_int,
+                    out: 0 as c_int };
         let res = libc::pipe(&mut fds.in, 1024 as ::libc::c_uint,
                              (libc::O_BINARY | libc::O_NOINHERIT) as c_int);
         assert!((res == 0 as c_int));
@@ -770,6 +772,28 @@ pub fn list_dir_path(p: &Path) -> ~[~Path] {
     list_dir(p).map(|f| ~p.push(*f))
 }
 
+/// Removes a directory at the specified path, after removing
+/// all its contents. Use carefully!
+pub fn remove_dir_recursive(p: &Path) -> bool {
+    let mut error_happened = false;
+    for walk_dir(p) |inner| {
+        if !error_happened {
+            if path_is_dir(inner) {
+                if !remove_dir_recursive(inner) {
+                    error_happened = true;
+                }
+            }
+            else {
+                if !remove_file(inner) {
+                    error_happened = true;
+                }
+            }
+        }
+    };
+    // Directory should now be empty
+    !error_happened && remove_dir(p)
+}
+
 /// Removes a directory at the specified path
 pub fn remove_dir(p: &Path) -> bool {
    return rmdir(p);
@@ -817,6 +841,36 @@ pub fn change_dir(p: &Path) -> bool {
     }
 }
 
+/// Changes the current working directory to the specified
+/// path while acquiring a global lock, then calls `action`.
+/// If the change is successful, releases the lock and restores the
+/// CWD to what it was before, returning true.
+/// Returns false if the directory doesn't exist or if the directory change
+/// is otherwise unsuccessful.
+pub fn change_dir_locked(p: &Path, action: &fn()) -> bool {
+    use unstable::global::global_data_clone_create;
+    use unstable::{Exclusive, exclusive};
+
+    fn key(_: Exclusive<()>) { }
+
+    let result = unsafe {
+        global_data_clone_create(key, || {
+            ~exclusive(())
+        })
+    };
+
+    do result.with_imm() |_| {
+        let old_dir = os::getcwd();
+        if change_dir(p) {
+            action();
+            change_dir(&old_dir)
+        }
+        else {
+            false
+        }
+    }
+}
+
 /// Copies a file from one location to another
 pub fn copy_file(from: &Path, to: &Path) -> bool {
     return do_copy_file(from, to);
@@ -845,6 +899,10 @@ pub fn copy_file(from: &Path, to: &Path) -> bool {
             if istream as uint == 0u {
                 return false;
             }
+            // Preserve permissions
+            let from_mode = from.get_mode().expect("copy_file: couldn't get permissions \
+                                                    for source file");
+
             let ostream = do as_c_charp(to.to_str()) |top| {
                 do as_c_charp("w+b") |modebuf| {
                     libc::fopen(top, modebuf)
@@ -876,6 +934,15 @@ pub fn copy_file(from: &Path, to: &Path) -> bool {
             }
             fclose(istream);
             fclose(ostream);
+
+            // Give the new file the old file's permissions
+            unsafe {
+                if do str::as_c_str(to.to_str()) |to_buf| {
+                    libc::chmod(to_buf, from_mode as mode_t)
+                } != 0 {
+                    return false; // should be a condition...
+                }
+            }
             return ok;
         }
     }
@@ -1152,6 +1219,88 @@ pub fn set_args(new_args: ~[~str]) {
     }
 }
 
+// FIXME #6100 we should really use an internal implementation of this - using
+// the POSIX glob functions isn't portable to windows, probably has slight
+// inconsistencies even where it is implemented, and makes extending
+// functionality a lot more difficult
+// FIXME #6101 also provide a non-allocating version - each_glob or so?
+/// Returns a vector of Path objects that match the given glob pattern
+#[cfg(target_os = "linux")]
+#[cfg(target_os = "android")]
+#[cfg(target_os = "freebsd")]
+#[cfg(target_os = "macos")]
+pub fn glob(pattern: &str) -> ~[Path] {
+    #[cfg(target_os = "linux")]
+    #[cfg(target_os = "android")]
+    fn default_glob_t () -> libc::glob_t {
+        libc::glob_t {
+            gl_pathc: 0,
+            gl_pathv: ptr::null(),
+            gl_offs: 0,
+            __unused1: ptr::null(),
+            __unused2: ptr::null(),
+            __unused3: ptr::null(),
+            __unused4: ptr::null(),
+            __unused5: ptr::null(),
+        }
+    }
+
+    #[cfg(target_os = "freebsd")]
+    fn default_glob_t () -> libc::glob_t {
+        libc::glob_t {
+            gl_pathc: 0,
+            __unused1: 0,
+            gl_offs: 0,
+            __unused2: 0,
+            gl_pathv: ptr::null(),
+            __unused3: ptr::null(),
+            __unused4: ptr::null(),
+            __unused5: ptr::null(),
+            __unused6: ptr::null(),
+            __unused7: ptr::null(),
+            __unused8: ptr::null(),
+        }
+    }
+
+    #[cfg(target_os = "macos")]
+    fn default_glob_t () -> libc::glob_t {
+        libc::glob_t {
+            gl_pathc: 0,
+            __unused1: 0,
+            gl_offs: 0,
+            __unused2: 0,
+            gl_pathv: ptr::null(),
+            __unused3: ptr::null(),
+            __unused4: ptr::null(),
+            __unused5: ptr::null(),
+            __unused6: ptr::null(),
+            __unused7: ptr::null(),
+            __unused8: ptr::null(),
+        }
+    }
+
+    let mut g = default_glob_t();
+    do str::as_c_str(pattern) |c_pattern| {
+        unsafe { libc::glob(c_pattern, 0, ptr::null(), &mut g) }
+    };
+    do(|| {
+        let paths = unsafe {
+            vec::raw::from_buf_raw(g.gl_pathv, g.gl_pathc as uint)
+        };
+        do paths.map |&c_str| {
+            Path(unsafe { str::raw::from_c_str(c_str) })
+        }
+    }).finally {
+        unsafe { libc::globfree(&mut g) };
+    }
+}
+
+/// Returns a vector of Path objects that match the given glob pattern
+#[cfg(target_os = "win32")]
+pub fn glob(pattern: &str) -> ~[Path] {
+    fail!(~"glob() is unimplemented on Windows")
+}
+
 #[cfg(target_os = "macos")]
 extern {
     // These functions are in crt_externs.h.
@@ -1480,6 +1629,7 @@ mod tests {
                       == buf.len() as size_t))
           }
           assert!((libc::fclose(ostream) == (0u as c_int)));
+          let in_mode = in.get_mode();
           let rs = os::copy_file(&in, &out);
           if (!os::path_exists(&in)) {
             fail!(fmt!("%s doesn't exist", in.to_str()));
@@ -1487,6 +1637,7 @@ mod tests {
           assert!((rs));
           let rslt = run::run_program(~"diff", ~[in.to_str(), out.to_str()]);
           assert!((rslt == 0));
+          assert!(out.get_mode() == in_mode);
           assert!((remove_file(&in)));
           assert!((remove_file(&out)));
         }
diff --git a/src/libcore/owned.rs b/src/libcore/owned.rs
index c483ec79e21..599591e2f6d 100644
--- a/src/libcore/owned.rs
+++ b/src/libcore/owned.rs
@@ -31,4 +31,3 @@ impl<T:Ord> Ord for ~T {
     #[inline(always)]
     fn gt(&self, other: &~T) -> bool { *(*self) > *(*other) }
 }
-
diff --git a/src/libcore/pipes.rs b/src/libcore/pipes.rs
index 95b24d20a4b..19674900f90 100644
--- a/src/libcore/pipes.rs
+++ b/src/libcore/pipes.rs
@@ -86,7 +86,9 @@ use cast::{forget, transmute, transmute_copy};
 use either::{Either, Left, Right};
 use kinds::Owned;
 use libc;
+use ops::Drop;
 use option::{None, Option, Some};
+use unstable::finally::Finally;
 use unstable::intrinsics;
 use ptr;
 use task;
@@ -301,7 +303,7 @@ struct BufferResource<T> {
 }
 
 #[unsafe_destructor]
-impl<T> ::ops::Drop for BufferResource<T> {
+impl<T> Drop for BufferResource<T> {
     fn finalize(&self) {
         unsafe {
             let b = move_it!(self.buffer);
@@ -395,26 +397,22 @@ pub fn try_recv<T:Owned,Tbuffer:Owned>(p: RecvPacketBuffered<T, Tbuffer>)
     let p_ = p.unwrap();
     let p = unsafe { &*p_ };
 
-    #[unsafe_destructor]
-    struct DropState<'self> {
-        p: &'self PacketHeader,
-
-        drop {
-            unsafe {
-                if task::failing() {
-                    self.p.state = Terminated;
-                    let old_task = swap_task(&mut self.p.blocked_task,
-                                             ptr::null());
-                    if !old_task.is_null() {
-                        rustrt::rust_task_deref(old_task);
-                    }
+    do (|| {
+        try_recv_(p)
+    }).finally {
+        unsafe {
+            if task::failing() {
+                p.header.state = Terminated;
+                let old_task = swap_task(&mut p.header.blocked_task, ptr::null());
+                if !old_task.is_null() {
+                    rustrt::rust_task_deref(old_task);
                 }
             }
         }
-    };
-
-    let _drop_state = DropState { p: &p.header };
+    }
+}
 
+fn try_recv_<T:Owned>(p: &Packet<T>) -> Option<T> {
     // optimistic path
     match p.header.state {
       Full => {
@@ -451,7 +449,7 @@ pub fn try_recv<T:Owned,Tbuffer:Owned>(p: RecvPacketBuffered<T, Tbuffer>)
                                        Blocked);
         match old_state {
           Empty => {
-            debug!("no data available on %?, going to sleep.", p_);
+            debug!("no data available on %?, going to sleep.", p);
             if count == 0 {
                 wait_event(this);
             }
@@ -641,7 +639,7 @@ pub struct SendPacketBuffered<T, Tbuffer> {
 }
 
 #[unsafe_destructor]
-impl<T:Owned,Tbuffer:Owned> ::ops::Drop for SendPacketBuffered<T,Tbuffer> {
+impl<T:Owned,Tbuffer:Owned> Drop for SendPacketBuffered<T,Tbuffer> {
     fn finalize(&self) {
         //if self.p != none {
         //    debug!("drop send %?", option::get(self.p));
@@ -710,7 +708,7 @@ pub struct RecvPacketBuffered<T, Tbuffer> {
 }
 
 #[unsafe_destructor]
-impl<T:Owned,Tbuffer:Owned> ::ops::Drop for RecvPacketBuffered<T,Tbuffer> {
+impl<T:Owned,Tbuffer:Owned> Drop for RecvPacketBuffered<T,Tbuffer> {
     fn finalize(&self) {
         //if self.p != none {
         //    debug!("drop recv %?", option::get(self.p));
diff --git a/src/libcore/prelude.rs b/src/libcore/prelude.rs
index 318725d2822..42401ae5a1f 100644
--- a/src/libcore/prelude.rs
+++ b/src/libcore/prelude.rs
@@ -14,7 +14,7 @@
 
 pub use either::{Either, Left, Right};
 pub use kinds::{Const, Copy, Owned, Durable};
-pub use ops::{Add, Sub, Mul, Quot, Rem, Neg, Not};
+pub use ops::{Add, Sub, Mul, Div, Rem, Neg, Not};
 pub use ops::{BitAnd, BitOr, BitXor};
 pub use ops::{Drop};
 pub use ops::{Shl, Shr, Index};
@@ -28,7 +28,7 @@ pub use io::{print, println};
 /* Reexported types and traits */
 
 pub use clone::Clone;
-pub use cmp::{Eq, Ord, TotalEq, TotalOrd, Ordering, Less, Equal, Greater};
+pub use cmp::{Eq, Ord, TotalEq, TotalOrd, Ordering, Less, Equal, Greater, Equiv};
 pub use container::{Container, Mutable, Map, Set};
 pub use hash::Hash;
 pub use old_iter::{BaseIter, ReverseIter, MutableIter, ExtendedIter, EqIter};
@@ -48,6 +48,7 @@ pub use path::WindowsPath;
 pub use ptr::Ptr;
 pub use ascii::{Ascii, AsciiCast, OwnedAsciiCast, AsciiStr};
 pub use str::{StrSlice, OwnedStr};
+pub use from_str::{FromStr};
 pub use to_bytes::IterBytes;
 pub use to_str::{ToStr, ToStrConsume};
 pub use tuple::{CopyableTuple, ImmutableTuple, ExtendedTupleOps};
diff --git a/src/libcore/rand.rs b/src/libcore/rand.rs
index 9fa099cabbf..80f69f067eb 100644
--- a/src/libcore/rand.rs
+++ b/src/libcore/rand.rs
@@ -16,6 +16,9 @@ and so can be used to generate any type that implements `Rand`. Type inference
 means that often a simple call to `rand::random()` or `rng.gen()` will
 suffice, but sometimes an annotation is required, e.g. `rand::random::<float>()`.
 
+See the `distributions` submodule for sampling random numbers from
+distributions like normal and exponential.
+
 # Examples
 ~~~
 use core::rand::RngUtil;
@@ -47,6 +50,9 @@ use util;
 use vec;
 use libc::size_t;
 
+#[path="rand/distributions.rs"]
+pub mod distributions;
+
 /// A type that can be randomly generated using an Rng
 pub trait Rand {
     fn rand<R: Rng>(rng: &R) -> Self;
@@ -1067,12 +1073,3 @@ mod tests {
         }
     }
 }
-
-
-// Local Variables:
-// mode: rust;
-// fill-column: 78;
-// indent-tabs-mode: nil
-// c-basic-offset: 4
-// buffer-file-coding-system: utf-8-unix
-// End:
diff --git a/src/libcore/rand/distributions.rs b/src/libcore/rand/distributions.rs
new file mode 100644
index 00000000000..a644f60db69
--- /dev/null
+++ b/src/libcore/rand/distributions.rs
@@ -0,0 +1,148 @@
+// 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.
+
+//! Sampling from random distributions
+
+// Some implementations use the Ziggurat method
+// https://en.wikipedia.org/wiki/Ziggurat_algorithm
+//
+// The version used here is ZIGNOR [Doornik 2005, "An Improved
+// Ziggurat Method to Generate Normal Random Samples"] which is slower
+// (about double, it generates an extra random number) than the
+// canonical version [Marsaglia & Tsang 2000, "The Ziggurat Method for
+// Generating Random Variables"], but more robust. If one wanted, one
+// could implement VIZIGNOR the ZIGNOR paper for more speed.
+
+use prelude::*;
+use rand::{Rng,Rand};
+
+mod ziggurat_tables;
+
+// inlining should mean there is no performance penalty for this
+#[inline(always)]
+fn ziggurat<R:Rng>(rng: &R,
+                   center_u: bool,
+                   X: ziggurat_tables::ZigTable,
+                   F: ziggurat_tables::ZigTable,
+                   F_DIFF: ziggurat_tables::ZigTable,
+                   pdf: &'static fn(f64) -> f64, // probability density function
+                   zero_case: &'static fn(&R, f64) -> f64) -> f64 {
+    loop {
+        let u = if center_u {2.0 * rng.gen() - 1.0} else {rng.gen()};
+        let i: uint = rng.gen::<uint>() & 0xff;
+        let x = u * X[i];
+
+        let test_x = if center_u {f64::abs(x)} else {x};
+
+        // algebraically equivalent to |u| < X[i+1]/X[i] (or u < X[i+1]/X[i])
+        if test_x < X[i + 1] {
+            return x;
+        }
+        if i == 0 {
+            return zero_case(rng, u);
+        }
+        // algebraically equivalent to f1 + DRanU()*(f0 - f1) < 1
+        if F[i+1] + F_DIFF[i+1] * rng.gen() < pdf(x) {
+            return x;
+        }
+    }
+}
+
+/// A wrapper around an `f64` to generate N(0, 1) random numbers (a.k.a.  a
+/// standard normal, or Gaussian). Multiplying the generated values by the
+/// desired standard deviation `sigma` then adding the desired mean `mu` will
+/// give N(mu, sigma^2) distributed random numbers.
+///
+/// Note that this has to be unwrapped before use as an `f64` (using either
+/// `*` or `cast::transmute` is safe).
+///
+/// # Example
+///
+/// ~~~
+/// use core::rand::distributions::StandardNormal;
+///
+/// fn main() {
+///     let normal = 2.0 + (*rand::random::<StandardNormal>()) * 3.0;
+///     println(fmt!("%f is from a N(2, 9) distribution", normal))
+/// }
+/// ~~~
+pub struct StandardNormal(f64);
+
+impl Rand for StandardNormal {
+    fn rand<R:Rng>(rng: &R) -> StandardNormal {
+        #[inline(always)]
+        fn pdf(x: f64) -> f64 {
+            f64::exp((-x*x/2.0) as f64) as f64
+        }
+        #[inline(always)]
+        fn zero_case<R:Rng>(rng: &R, u: f64) -> f64 {
+            // compute a random number in the tail by hand
+
+            // strange initial conditions, because the loop is not
+            // do-while, so the condition should be true on the first
+            // run, they get overwritten anyway (0 < 1, so these are
+            // good).
+            let mut x = 1.0, y = 0.0;
+
+            // XXX infinities?
+            while -2.0*y < x * x {
+                x = f64::ln(rng.gen()) / ziggurat_tables::ZIG_NORM_R;
+                y = f64::ln(rng.gen());
+            }
+            if u < 0.0 {x-ziggurat_tables::ZIG_NORM_R} else {ziggurat_tables::ZIG_NORM_R-x}
+        }
+
+        StandardNormal(ziggurat(
+            rng,
+            true, // this is symmetric
+            &ziggurat_tables::ZIG_NORM_X,
+            &ziggurat_tables::ZIG_NORM_F, &ziggurat_tables::ZIG_NORM_F_DIFF,
+            pdf, zero_case))
+    }
+}
+
+/// A wrapper around an `f64` to generate Exp(1) random numbers. Dividing by
+/// the desired rate `lambda` will give Exp(lambda) distributed random
+/// numbers.
+///
+/// Note that this has to be unwrapped before use as an `f64` (using either
+/// `*` or `cast::transmute` is safe).
+///
+/// # Example
+///
+/// ~~~
+/// use core::rand::distributions::Exp1;
+///
+/// fn main() {
+///     let exp2 = (*rand::random::<Exp1>()) * 0.5;
+///     println(fmt!("%f is from a Exp(2) distribution", exp2));
+/// }
+/// ~~~
+pub struct Exp1(f64);
+
+// This could be done via `-f64::ln(rng.gen::<f64>())` but that is slower.
+impl Rand for Exp1 {
+    #[inline]
+    fn rand<R:Rng>(rng: &R) -> Exp1 {
+        #[inline(always)]
+        fn pdf(x: f64) -> f64 {
+            f64::exp(-x)
+        }
+        #[inline(always)]
+        fn zero_case<R:Rng>(rng: &R, _u: f64) -> f64 {
+            ziggurat_tables::ZIG_EXP_R - f64::ln(rng.gen())
+        }
+
+        Exp1(ziggurat(rng, false,
+                      &ziggurat_tables::ZIG_EXP_X,
+                      &ziggurat_tables::ZIG_EXP_F, &ziggurat_tables::ZIG_EXP_F_DIFF,
+                      pdf, zero_case))
+    }
+}
diff --git a/src/libcore/rand/ziggurat_tables.rs b/src/libcore/rand/ziggurat_tables.rs
new file mode 100644
index 00000000000..aca2457cac4
--- /dev/null
+++ b/src/libcore/rand/ziggurat_tables.rs
@@ -0,0 +1,412 @@
+// 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.
+
+// Tables for distributions which are sampled using the ziggurat
+// algorithm. Autogenerated by `ziggurat_tables.py`.
+
+pub type ZigTable = &'static [f64, .. 257];
+pub static ZIG_NORM_R: f64 = 3.654152885361008796;
+pub static ZIG_NORM_X: [f64, .. 257] =
+    [3.910757959537090045, 3.654152885361008796, 3.449278298560964462, 3.320244733839166074,
+     3.224575052047029100, 3.147889289517149969, 3.083526132001233044, 3.027837791768635434,
+     2.978603279880844834, 2.934366867207854224, 2.894121053612348060, 2.857138730872132548,
+     2.822877396825325125, 2.790921174000785765, 2.760944005278822555, 2.732685359042827056,
+     2.705933656121858100, 2.680514643284522158, 2.656283037575502437, 2.633116393630324570,
+     2.610910518487548515, 2.589575986706995181, 2.569035452680536569, 2.549221550323460761,
+     2.530075232158516929, 2.511544441625342294, 2.493583041269680667, 2.476149939669143318,
+     2.459208374333311298, 2.442725318198956774, 2.426670984935725972, 2.411018413899685520,
+     2.395743119780480601, 2.380822795170626005, 2.366237056715818632, 2.351967227377659952,
+     2.337996148795031370, 2.324308018869623016, 2.310888250599850036, 2.297723348901329565,
+     2.284800802722946056, 2.272108990226823888, 2.259637095172217780, 2.247375032945807760,
+     2.235313384928327984, 2.223443340090905718, 2.211756642882544366, 2.200245546609647995,
+     2.188902771624720689, 2.177721467738641614, 2.166695180352645966, 2.155817819875063268,
+     2.145083634046203613, 2.134487182844320152, 2.124023315687815661, 2.113687150684933957,
+     2.103474055713146829, 2.093379631137050279, 2.083399693996551783, 2.073530263516978778,
+     2.063767547809956415, 2.054107931648864849, 2.044547965215732788, 2.035084353727808715,
+     2.025713947862032960, 2.016433734904371722, 2.007240830558684852, 1.998132471356564244,
+     1.989106007615571325, 1.980158896898598364, 1.971288697931769640, 1.962493064942461896,
+     1.953769742382734043, 1.945116560006753925, 1.936531428273758904, 1.928012334050718257,
+     1.919557336591228847, 1.911164563769282232, 1.902832208548446369, 1.894558525668710081,
+     1.886341828534776388, 1.878180486290977669, 1.870072921069236838, 1.862017605397632281,
+     1.854013059758148119, 1.846057850283119750, 1.838150586580728607, 1.830289919680666566,
+     1.822474540091783224, 1.814703175964167636, 1.806974591348693426, 1.799287584547580199,
+     1.791640986550010028, 1.784033659547276329, 1.776464495522344977, 1.768932414909077933,
+     1.761436365316706665, 1.753975320315455111, 1.746548278279492994, 1.739154261283669012,
+     1.731792314050707216, 1.724461502945775715, 1.717160915015540690, 1.709889657069006086,
+     1.702646854797613907, 1.695431651932238548, 1.688243209434858727, 1.681080704722823338,
+     1.673943330923760353, 1.666830296159286684, 1.659740822855789499, 1.652674147080648526,
+     1.645629517902360339, 1.638606196773111146, 1.631603456932422036, 1.624620582830568427,
+     1.617656869570534228, 1.610711622367333673, 1.603784156023583041, 1.596873794420261339,
+     1.589979870021648534, 1.583101723393471438, 1.576238702733332886, 1.569390163412534456,
+     1.562555467528439657, 1.555733983466554893, 1.548925085471535512, 1.542128153226347553,
+     1.535342571438843118, 1.528567729435024614, 1.521803020758293101, 1.515047842773992404,
+     1.508301596278571965, 1.501563685112706548, 1.494833515777718391, 1.488110497054654369,
+     1.481394039625375747, 1.474683555695025516, 1.467978458615230908, 1.461278162507407830,
+     1.454582081885523293, 1.447889631277669675, 1.441200224845798017, 1.434513276002946425,
+     1.427828197027290358, 1.421144398672323117, 1.414461289772464658, 1.407778276843371534,
+     1.401094763676202559, 1.394410150925071257, 1.387723835686884621, 1.381035211072741964,
+     1.374343665770030531, 1.367648583594317957, 1.360949343030101844, 1.354245316759430606,
+     1.347535871177359290, 1.340820365893152122, 1.334098153216083604, 1.327368577624624679,
+     1.320630975217730096, 1.313884673146868964, 1.307128989027353860, 1.300363230327433728,
+     1.293586693733517645, 1.286798664489786415, 1.279998415710333237, 1.273185207661843732,
+     1.266358287014688333, 1.259516886060144225, 1.252660221891297887, 1.245787495544997903,
+     1.238897891102027415, 1.231990574742445110, 1.225064693752808020, 1.218119375481726552,
+     1.211153726239911244, 1.204166830140560140, 1.197157747875585931, 1.190125515422801650,
+     1.183069142678760732, 1.175987612011489825, 1.168879876726833800, 1.161744859441574240,
+     1.154581450355851802, 1.147388505416733873, 1.140164844363995789, 1.132909248648336975,
+     1.125620459211294389, 1.118297174115062909, 1.110938046009249502, 1.103541679420268151,
+     1.096106627847603487, 1.088631390649514197, 1.081114409698889389, 1.073554065787871714,
+     1.065948674757506653, 1.058296483326006454, 1.050595664586207123, 1.042844313139370538,
+     1.035040439828605274, 1.027181966030751292, 1.019266717460529215, 1.011292417434978441,
+     1.003256679539591412, 0.995156999629943084, 0.986990747093846266, 0.978755155288937750,
+     0.970447311058864615, 0.962064143217605250, 0.953602409875572654, 0.945058684462571130,
+     0.936429340280896860, 0.927710533396234771, 0.918898183643734989, 0.909987953490768997,
+     0.900975224455174528, 0.891855070726792376, 0.882622229578910122, 0.873271068082494550,
+     0.863795545546826915, 0.854189171001560554, 0.844444954902423661, 0.834555354079518752,
+     0.824512208745288633, 0.814306670128064347, 0.803929116982664893, 0.793369058833152785,
+     0.782615023299588763, 0.771654424216739354, 0.760473406422083165, 0.749056662009581653,
+     0.737387211425838629, 0.725446140901303549, 0.713212285182022732, 0.700661841097584448,
+     0.687767892786257717, 0.674499822827436479, 0.660822574234205984, 0.646695714884388928,
+     0.632072236375024632, 0.616896989996235545, 0.601104617743940417, 0.584616766093722262,
+     0.567338257040473026, 0.549151702313026790, 0.529909720646495108, 0.509423329585933393,
+     0.487443966121754335, 0.463634336771763245, 0.437518402186662658, 0.408389134588000746,
+     0.375121332850465727, 0.335737519180459465, 0.286174591747260509, 0.215241895913273806,
+     0.000000000000000000];
+pub static ZIG_NORM_F: [f64, .. 257] =
+    [0.000477467764586655, 0.001260285930498598, 0.002609072746106363, 0.004037972593371872,
+     0.005522403299264754, 0.007050875471392110, 0.008616582769422917, 0.010214971439731100,
+     0.011842757857943104, 0.013497450601780807, 0.015177088307982072, 0.016880083152595839,
+     0.018605121275783350, 0.020351096230109354, 0.022117062707379922, 0.023902203305873237,
+     0.025705804008632656, 0.027527235669693315, 0.029365939758230111, 0.031221417192023690,
+     0.033093219458688698, 0.034980941461833073, 0.036884215688691151, 0.038802707404656918,
+     0.040736110656078753, 0.042684144916619378, 0.044646552251446536, 0.046623094902089664,
+     0.048613553216035145, 0.050617723861121788, 0.052635418276973649, 0.054666461325077916,
+     0.056710690106399467, 0.058767952921137984, 0.060838108349751806, 0.062921024437977854,
+     0.065016577971470438, 0.067124653828023989, 0.069245144397250269, 0.071377949059141965,
+     0.073522973714240991, 0.075680130359194964, 0.077849336702372207, 0.080030515814947509,
+     0.082223595813495684, 0.084428509570654661, 0.086645194450867782, 0.088873592068594229,
+     0.091113648066700734, 0.093365311913026619, 0.095628536713353335, 0.097903279039215627,
+     0.100189498769172020, 0.102487158942306270, 0.104796225622867056, 0.107116667775072880,
+     0.109448457147210021, 0.111791568164245583, 0.114145977828255210, 0.116511665626037014,
+     0.118888613443345698, 0.121276805485235437, 0.123676228202051403, 0.126086870220650349,
+     0.128508722280473636, 0.130941777174128166, 0.133386029692162844, 0.135841476571757352,
+     0.138308116449064322, 0.140785949814968309, 0.143274978974047118, 0.145775208006537926,
+     0.148286642733128721, 0.150809290682410169, 0.153343161060837674, 0.155888264725064563,
+     0.158444614156520225, 0.161012223438117663, 0.163591108232982951, 0.166181285765110071,
+     0.168782774801850333, 0.171395595638155623, 0.174019770082499359, 0.176655321444406654,
+     0.179302274523530397, 0.181960655600216487, 0.184630492427504539, 0.187311814224516926,
+     0.190004651671193070, 0.192709036904328807, 0.195425003514885592, 0.198152586546538112,
+     0.200891822495431333, 0.203642749311121501, 0.206405406398679298, 0.209179834621935651,
+     0.211966076307852941, 0.214764175252008499, 0.217574176725178370, 0.220396127481011589,
+     0.223230075764789593, 0.226076071323264877, 0.228934165415577484, 0.231804410825248525,
+     0.234686861873252689, 0.237581574432173676, 0.240488605941449107, 0.243408015423711988,
+     0.246339863502238771, 0.249284212419516704, 0.252241126056943765, 0.255210669955677150,
+     0.258192911338648023, 0.261187919133763713, 0.264195763998317568, 0.267216518344631837,
+     0.270250256366959984, 0.273297054069675804, 0.276356989296781264, 0.279430141762765316,
+     0.282516593084849388, 0.285616426816658109, 0.288729728483353931, 0.291856585618280984,
+     0.294997087801162572, 0.298151326697901342, 0.301319396102034120, 0.304501391977896274,
+     0.307697412505553769, 0.310907558127563710, 0.314131931597630143, 0.317370638031222396,
+     0.320623784958230129, 0.323891482377732021, 0.327173842814958593, 0.330470981380537099,
+     0.333783015832108509, 0.337110066638412809, 0.340452257045945450, 0.343809713148291340,
+     0.347182563958251478, 0.350570941482881204, 0.353974980801569250, 0.357394820147290515,
+     0.360830600991175754, 0.364282468130549597, 0.367750569780596226, 0.371235057669821344,
+     0.374736087139491414, 0.378253817247238111, 0.381788410875031348, 0.385340034841733958,
+     0.388908860020464597, 0.392495061461010764, 0.396098818517547080, 0.399720314981931668,
+     0.403359739222868885, 0.407017284331247953, 0.410693148271983222, 0.414387534042706784,
+     0.418100649839684591, 0.421832709231353298, 0.425583931339900579, 0.429354541031341519,
+     0.433144769114574058, 0.436954852549929273, 0.440785034667769915, 0.444635565397727750,
+     0.448506701509214067, 0.452398706863882505, 0.456311852680773566, 0.460246417814923481,
+     0.464202689050278838, 0.468180961407822172, 0.472181538469883255, 0.476204732721683788,
+     0.480250865911249714, 0.484320269428911598, 0.488413284707712059, 0.492530263646148658,
+     0.496671569054796314, 0.500837575128482149, 0.505028667945828791, 0.509245245998136142,
+     0.513487720749743026, 0.517756517232200619, 0.522052074674794864, 0.526374847174186700,
+     0.530725304406193921, 0.535103932383019565, 0.539511234259544614, 0.543947731192649941,
+     0.548413963257921133, 0.552910490428519918, 0.557437893621486324, 0.561996775817277916,
+     0.566587763258951771, 0.571211506738074970, 0.575868682975210544, 0.580559996103683473,
+     0.585286179266300333, 0.590047996335791969, 0.594846243770991268, 0.599681752622167719,
+     0.604555390700549533, 0.609468064928895381, 0.614420723892076803, 0.619414360609039205,
+     0.624450015550274240, 0.629528779928128279, 0.634651799290960050, 0.639820277456438991,
+     0.645035480824251883, 0.650298743114294586, 0.655611470583224665, 0.660975147780241357,
+     0.666391343912380640, 0.671861719900766374, 0.677388036222513090, 0.682972161648791376,
+     0.688616083008527058, 0.694321916130032579, 0.700091918140490099, 0.705928501336797409,
+     0.711834248882358467, 0.717811932634901395, 0.723864533472881599, 0.729995264565802437,
+     0.736207598131266683, 0.742505296344636245, 0.748892447223726720, 0.755373506511754500,
+     0.761953346841546475, 0.768637315803334831, 0.775431304986138326, 0.782341832659861902,
+     0.789376143571198563, 0.796542330428254619, 0.803849483176389490, 0.811307874318219935,
+     0.818929191609414797, 0.826726833952094231, 0.834716292992930375, 0.842915653118441077,
+     0.851346258465123684, 0.860033621203008636, 0.869008688043793165, 0.878309655816146839,
+     0.887984660763399880, 0.898095921906304051, 0.908726440060562912, 0.919991505048360247,
+     0.932060075968990209, 0.945198953453078028, 0.959879091812415930, 0.977101701282731328,
+     1.000000000000000000];
+pub static ZIG_NORM_F_DIFF: [f64, .. 257] =
+    [0.000000000000000000, 0.000782818165911943, 0.001348786815607765, 0.001428899847265509,
+     0.001484430705892882, 0.001528472172127356, 0.001565707298030807, 0.001598388670308183,
+     0.001627786418212004, 0.001654692743837703, 0.001679637706201265, 0.001702994844613767,
+     0.001725038123187510, 0.001745974954326004, 0.001765966477270568, 0.001785140598493315,
+     0.001803600702759419, 0.001821431661060659, 0.001838704088536796, 0.001855477433793579,
+     0.001871802266665008, 0.001887722003144375, 0.001903274226858077, 0.001918491715965767,
+     0.001933403251421835, 0.001948034260540625, 0.001962407334827158, 0.001976542650643127,
+     0.001990458313945481, 0.002004170645086643, 0.002017694415851860, 0.002031043048104267,
+     0.002044228781321551, 0.002057262814738517, 0.002070155428613822, 0.002082916088226049,
+     0.002095553533492583, 0.002108075856553551, 0.002120490569226280, 0.002132804661891696,
+     0.002145024655099026, 0.002157156644953973, 0.002169206343177243, 0.002181179112575302,
+     0.002193079998548175, 0.002204913757158977, 0.002216684880213121, 0.002228397617726446,
+     0.002240055998106505, 0.002251663846325885, 0.002263224800326716, 0.002274742325862292,
+     0.002286219729956393, 0.002297660173134250, 0.002309066680560787, 0.002320442152205823,
+     0.002331789372137141, 0.002343111017035562, 0.002354409664009627, 0.002365687797781804,
+     0.002376947817308683, 0.002388192041889739, 0.002399422716815966, 0.002410642018598946,
+     0.002421852059823287, 0.002433054893654529, 0.002444252518034679, 0.002455446879594508,
+     0.002466639877306970, 0.002477833365903986, 0.002489029159078809, 0.002500229032490808,
+     0.002511434726590794, 0.002522647949281448, 0.002533870378427505, 0.002545103664226889,
+     0.002556349431455662, 0.002567609281597438, 0.002578884794865288, 0.002590177532127119,
+     0.002601489036740262, 0.002612820836305291, 0.002624174444343735, 0.002635551361907296,
+     0.002646953079123743, 0.002658381076686089, 0.002669836827288052, 0.002681321797012387,
+     0.002692837446676144, 0.002704385233135737, 0.002715966610556786, 0.002727583031652520,
+     0.002739235948893221, 0.002750926815690169, 0.002762657087557796, 0.002774428223256353,
+     0.002786241685917290, 0.002798098944155558, 0.002810001473169871, 0.002821950755833219,
+     0.002833948283778004, 0.002845995558475284, 0.002858094092312607, 0.002870245409671041,
+     0.002882451048004164, 0.002894712558920987, 0.002907031509275432, 0.002919409482262880,
+     0.002931848078526783, 0.002944348917277934, 0.002956913637427061, 0.002969543898733384,
+     0.002982241382970874, 0.002995007795115689, 0.003007844864553855, 0.003020754346314269,
+     0.003033738022328147, 0.003046797702715820, 0.003059935227105459, 0.003073152465984053,
+     0.003086451322084072, 0.003099833731808721, 0.003113301666695822, 0.003126857134927052,
+     0.003140502182881588, 0.003154238896738770, 0.003168069404132778, 0.003181995875862154,
+     0.003196020527657495, 0.003210145622009941, 0.003224373470066433, 0.003238706433592253,
+     0.003253146927007733, 0.003267697419501892, 0.003282360437226572, 0.003297138565578506,
+     0.003312034451571411, 0.003327050806304299, 0.003342190407532641, 0.003357456102345890,
+     0.003372850809960137, 0.003388377524629727, 0.003404039318688046, 0.003419839345721265,
+     0.003435780843885239, 0.003451867139373843, 0.003468101650046629, 0.003484487889225119,
+     0.003501029469670069, 0.003517730107746697, 0.003534593627793237, 0.003551623966702611,
+     0.003568825178730639, 0.003586201440546166, 0.003603757056536316, 0.003621496464384588,
+     0.003639424240937217, 0.003657545108379068, 0.003675863940735269, 0.003694385770723563,
+     0.003713115796977806, 0.003732059391668707, 0.003751222108547281, 0.003770609691440940,
+     0.003790228083232539, 0.003810083435355216, 0.003830182117840641, 0.003850530729957835,
+     0.003871136111486317, 0.003892005354668437, 0.003913145816891062, 0.003934565134149914,
+     0.003956271235355358, 0.003978272357543333, 0.004000577062061084, 0.004023194251800533,
+     0.004046133189565926, 0.004069403517661885, 0.004093015278800460, 0.004116978938436600,
+     0.004141305408647655, 0.004166006073685835, 0.004191092817346642, 0.004216578052307351,
+     0.004242474751606884, 0.004268796482457593, 0.004295557442594244, 0.004322772499391836,
+     0.004350457232007221, 0.004378627976825644, 0.004407301876525049, 0.004436496933105327,
+     0.004466232065271192, 0.004496527170598785, 0.004527403192966406, 0.004558882195791591,
+     0.004590987441673855, 0.004623743479123199, 0.004657176237135574, 0.004691313128472929,
+     0.004726183162616859, 0.004761817069491636, 0.004798247435199299, 0.004835508851176451,
+     0.004873638078381815, 0.004912674228345848, 0.004952658963181422, 0.004993636716962402,
+     0.005035654941235035, 0.005078764377854039, 0.005123019362831771, 0.005168478165478940,
+     0.005215203367812893, 0.005263262290042703, 0.005312727468930079, 0.005363677197016692,
+     0.005416196132139284, 0.005470375988385734, 0.005526316321746716, 0.005584125426278286,
+     0.005643921359735682, 0.005705833121505521, 0.005770002010457520, 0.005836583196307310,
+     0.005905747545561058, 0.005977683752542928, 0.006052600837980204, 0.006130731092920838,
+     0.006212333565464245, 0.006297698213369562, 0.006387150879090475, 0.006481059288027780,
+     0.006579840329791975, 0.006683968961788356, 0.006793989182803495, 0.006910527673723577,
+     0.007034310911336661, 0.007166186857056056, 0.007307152748134871, 0.007458391141830445,
+     0.007621317291194862, 0.007797642342679434, 0.007989459040836144, 0.008199360125510702,
+     0.008430605346682607, 0.008687362737884952, 0.008975066840784529, 0.009300967772353674,
+     0.009675004947253041, 0.010111261142904171, 0.010630518154258861, 0.011265064987797335,
+     0.012068570920629962, 0.013138877484087819, 0.014680138359337902, 0.017222609470315398,
+     0.022898298717268672];
+pub static ZIG_EXP_R: f64 = 7.697117470131050077;
+pub static ZIG_EXP_X: [f64, .. 257] =
+    [8.697117470131052741, 7.697117470131050077, 6.941033629377212577, 6.478378493832569696,
+     6.144164665772472667, 5.882144315795399869, 5.666410167454033697, 5.482890627526062488,
+     5.323090505754398016, 5.181487281301500047, 5.054288489981304089, 4.938777085901250530,
+     4.832939741025112035, 4.735242996601741083, 4.644491885420085175, 4.559737061707351380,
+     4.480211746528421912, 4.405287693473573185, 4.334443680317273007, 4.267242480277365857,
+     4.203313713735184365, 4.142340865664051464, 4.084051310408297830, 4.028208544647936762,
+     3.974606066673788796, 3.923062500135489739, 3.873417670399509127, 3.825529418522336744,
+     3.779270992411667862, 3.734528894039797375, 3.691201090237418825, 3.649195515760853770,
+     3.608428813128909507, 3.568825265648337020, 3.530315889129343354, 3.492837654774059608,
+     3.456332821132760191, 3.420748357251119920, 3.386035442460300970, 3.352149030900109405,
+     3.319047470970748037, 3.286692171599068679, 3.255047308570449882, 3.224079565286264160,
+     3.193757903212240290, 3.164053358025972873, 3.134938858084440394, 3.106389062339824481,
+     3.078380215254090224, 3.050890016615455114, 3.023897504455676621, 2.997382949516130601,
+     2.971327759921089662, 2.945714394895045718, 2.920526286512740821, 2.895747768600141825,
+     2.871364012015536371, 2.847360965635188812, 2.823725302450035279, 2.800444370250737780,
+     2.777506146439756574, 2.754899196562344610, 2.732612636194700073, 2.710636095867928752,
+     2.688959688741803689, 2.667573980773266573, 2.646469963151809157, 2.625639026797788489,
+     2.605072938740835564, 2.584763820214140750, 2.564704126316905253, 2.544886627111869970,
+     2.525304390037828028, 2.505950763528594027, 2.486819361740209455, 2.467904050297364815,
+     2.449198932978249754, 2.430698339264419694, 2.412396812688870629, 2.394289099921457886,
+     2.376370140536140596, 2.358635057409337321, 2.341079147703034380, 2.323697874390196372,
+     2.306486858283579799, 2.289441870532269441, 2.272558825553154804, 2.255833774367219213,
+     2.239262898312909034, 2.222842503111036816, 2.206569013257663858, 2.190438966723220027,
+     2.174449009937774679, 2.158595893043885994, 2.142876465399842001, 2.127287671317368289,
+     2.111826546019042183, 2.096490211801715020, 2.081275874393225145, 2.066180819490575526,
+     2.051202409468584786, 2.036338080248769611, 2.021585338318926173, 2.006941757894518563,
+     1.992404978213576650, 1.977972700957360441, 1.963642687789548313, 1.949412758007184943,
+     1.935280786297051359, 1.921244700591528076, 1.907302480018387536, 1.893452152939308242,
+     1.879691795072211180, 1.866019527692827973, 1.852433515911175554, 1.838931967018879954,
+     1.825513128903519799, 1.812175288526390649, 1.798916770460290859, 1.785735935484126014,
+     1.772631179231305643, 1.759600930889074766, 1.746643651946074405, 1.733757834985571566,
+     1.720942002521935299, 1.708194705878057773, 1.695514524101537912, 1.682900062917553896,
+     1.670349953716452118, 1.657862852574172763, 1.645437439303723659, 1.633072416535991334,
+     1.620766508828257901, 1.608518461798858379, 1.596327041286483395, 1.584191032532688892,
+     1.572109239386229707, 1.560080483527888084, 1.548103603714513499, 1.536177455041032092,
+     1.524300908219226258, 1.512472848872117082, 1.500692176842816750, 1.488957805516746058,
+     1.477268661156133867, 1.465623682245745352, 1.454021818848793446, 1.442462031972012504,
+     1.430943292938879674, 1.419464582769983219, 1.408024891569535697, 1.396623217917042137,
+     1.385258568263121992, 1.373929956328490576, 1.362636402505086775, 1.351376933258335189,
+     1.340150580529504643, 1.328956381137116560, 1.317793376176324749, 1.306660610415174117,
+     1.295557131686601027, 1.284481990275012642, 1.273434238296241139, 1.262412929069615330,
+     1.251417116480852521, 1.240445854334406572, 1.229498195693849105, 1.218573192208790124,
+     1.207669893426761121, 1.196787346088403092, 1.185924593404202199, 1.175080674310911677,
+     1.164254622705678921, 1.153445466655774743, 1.142652227581672841, 1.131873919411078511,
+     1.121109547701330200, 1.110358108727411031, 1.099618588532597308, 1.088889961938546813,
+     1.078171191511372307, 1.067461226479967662, 1.056759001602551429, 1.046063435977044209,
+     1.035373431790528542, 1.024687873002617211, 1.014005623957096480, 1.003325527915696735,
+     0.992646405507275897, 0.981967053085062602, 0.971286240983903260, 0.960602711668666509,
+     0.949915177764075969, 0.939222319955262286, 0.928522784747210395, 0.917815182070044311,
+     0.907098082715690257, 0.896370015589889935, 0.885629464761751528, 0.874874866291025066,
+     0.864104604811004484, 0.853317009842373353, 0.842510351810368485, 0.831682837734273206,
+     0.820832606554411814, 0.809957724057418282, 0.799056177355487174, 0.788125868869492430,
+     0.777164609759129710, 0.766170112735434672, 0.755139984181982249, 0.744071715500508102,
+     0.732962673584365398, 0.721810090308756203, 0.710611050909655040, 0.699362481103231959,
+     0.688061132773747808, 0.676703568029522584, 0.665286141392677943, 0.653804979847664947,
+     0.642255960424536365, 0.630634684933490286, 0.618936451394876075, 0.607156221620300030,
+     0.595288584291502887, 0.583327712748769489, 0.571267316532588332, 0.559100585511540626,
+     0.546820125163310577, 0.534417881237165604, 0.521885051592135052, 0.509211982443654398,
+     0.496388045518671162, 0.483401491653461857, 0.470239275082169006, 0.456886840931420235,
+     0.443327866073552401, 0.429543940225410703, 0.415514169600356364, 0.401214678896277765,
+     0.386617977941119573, 0.371692145329917234, 0.356399760258393816, 0.340696481064849122,
+     0.324529117016909452, 0.307832954674932158, 0.290527955491230394, 0.272513185478464703,
+     0.253658363385912022, 0.233790483059674731, 0.212671510630966620, 0.189958689622431842,
+     0.165127622564187282, 0.137304980940012589, 0.104838507565818778, 0.063852163815001570,
+     0.000000000000000000];
+pub static ZIG_EXP_F: [f64, .. 257] =
+    [0.000167066692307963, 0.000454134353841497, 0.000967269282327174, 0.001536299780301573,
+     0.002145967743718907, 0.002788798793574076, 0.003460264777836904, 0.004157295120833797,
+     0.004877655983542396, 0.005619642207205489, 0.006381905937319183, 0.007163353183634991,
+     0.007963077438017043, 0.008780314985808977, 0.009614413642502212, 0.010464810181029981,
+     0.011331013597834600, 0.012212592426255378, 0.013109164931254991, 0.014020391403181943,
+     0.014945968011691148, 0.015885621839973156, 0.016839106826039941, 0.017806200410911355,
+     0.018786700744696024, 0.019780424338009740, 0.020787204072578114, 0.021806887504283581,
+     0.022839335406385240, 0.023884420511558174, 0.024942026419731787, 0.026012046645134221,
+     0.027094383780955803, 0.028188948763978646, 0.029295660224637411, 0.030414443910466622,
+     0.031545232172893622, 0.032687963508959555, 0.033842582150874358, 0.035009037697397431,
+     0.036187284781931443, 0.037377282772959382, 0.038578995503074871, 0.039792391023374139,
+     0.041017441380414840, 0.042254122413316254, 0.043502413568888197, 0.044762297732943289,
+     0.046033761076175184, 0.047316792913181561, 0.048611385573379504, 0.049917534282706379,
+     0.051235237055126281, 0.052564494593071685, 0.053905310196046080, 0.055257689676697030,
+     0.056621641283742870, 0.057997175631200659, 0.059384305633420280, 0.060783046445479660,
+     0.062193415408541036, 0.063615431999807376, 0.065049117786753805, 0.066494496385339816,
+     0.067951593421936643, 0.069420436498728783, 0.070901055162371843, 0.072393480875708752,
+     0.073897746992364746, 0.075413888734058410, 0.076941943170480517, 0.078481949201606435,
+     0.080033947542319905, 0.081597980709237419, 0.083174093009632397, 0.084762330532368146,
+     0.086362741140756927, 0.087975374467270231, 0.089600281910032886, 0.091237516631040197,
+     0.092887133556043569, 0.094549189376055873, 0.096223742550432825, 0.097910853311492213,
+     0.099610583670637132, 0.101322997425953631, 0.103048160171257702, 0.104786139306570145,
+     0.106537004050001632, 0.108300825451033755, 0.110077676405185357, 0.111867631670056283,
+     0.113670767882744286, 0.115487163578633506, 0.117316899211555525, 0.119160057175327641,
+     0.121016721826674792, 0.122886979509545108, 0.124770918580830933, 0.126668629437510671,
+     0.128580204545228199, 0.130505738468330773, 0.132445327901387494, 0.134399071702213602,
+     0.136367070926428829, 0.138349428863580176, 0.140346251074862399, 0.142357645432472146,
+     0.144383722160634720, 0.146424593878344889, 0.148480375643866735, 0.150551185001039839,
+     0.152637142027442801, 0.154738369384468027, 0.156854992369365148, 0.158987138969314129,
+     0.161134939917591952, 0.163298528751901734, 0.165478041874935922, 0.167673618617250081,
+     0.169885401302527550, 0.172113535315319977, 0.174358169171353411, 0.176619454590494829,
+     0.178897546572478278, 0.181192603475496261, 0.183504787097767436, 0.185834262762197083,
+     0.188181199404254262, 0.190545769663195363, 0.192928149976771296, 0.195328520679563189,
+     0.197747066105098818, 0.200183974691911210, 0.202639439093708962, 0.205113656293837654,
+     0.207606827724221982, 0.210119159388988230, 0.212650861992978224, 0.215202151075378628,
+     0.217773247148700472, 0.220364375843359439, 0.222975768058120111, 0.225607660116683956,
+     0.228260293930716618, 0.230933917169627356, 0.233628783437433291, 0.236345152457059560,
+     0.239083290262449094, 0.241843469398877131, 0.244625969131892024, 0.247431075665327543,
+     0.250259082368862240, 0.253110290015629402, 0.255985007030415324, 0.258883549749016173,
+     0.261806242689362922, 0.264753418835062149, 0.267725419932044739, 0.270722596799059967,
+     0.273745309652802915, 0.276793928448517301, 0.279868833236972869, 0.282970414538780746,
+     0.286099073737076826, 0.289255223489677693, 0.292439288161892630, 0.295651704281261252,
+     0.298892921015581847, 0.302163400675693528, 0.305463619244590256, 0.308794066934560185,
+     0.312155248774179606, 0.315547685227128949, 0.318971912844957239, 0.322428484956089223,
+     0.325917972393556354, 0.329440964264136438, 0.332998068761809096, 0.336589914028677717,
+     0.340217149066780189, 0.343880444704502575, 0.347580494621637148, 0.351318016437483449,
+     0.355093752866787626, 0.358908472948750001, 0.362762973354817997, 0.366658079781514379,
+     0.370594648435146223, 0.374573567615902381, 0.378595759409581067, 0.382662181496010056,
+     0.386773829084137932, 0.390931736984797384, 0.395136981833290435, 0.399390684475231350,
+     0.403694012530530555, 0.408048183152032673, 0.412454465997161457, 0.416914186433003209,
+     0.421428728997616908, 0.425999541143034677, 0.430628137288459167, 0.435316103215636907,
+     0.440065100842354173, 0.444876873414548846, 0.449753251162755330, 0.454696157474615836,
+     0.459707615642138023, 0.464789756250426511, 0.469944825283960310, 0.475175193037377708,
+     0.480483363930454543, 0.485871987341885248, 0.491343869594032867, 0.496901987241549881,
+     0.502549501841348056, 0.508289776410643213, 0.514126393814748894, 0.520063177368233931,
+     0.526104213983620062, 0.532253880263043655, 0.538516872002862246, 0.544898237672440056,
+     0.551403416540641733, 0.558038282262587892, 0.564809192912400615, 0.571723048664826150,
+     0.578787358602845359, 0.586010318477268366, 0.593400901691733762, 0.600968966365232560,
+     0.608725382079622346, 0.616682180915207878, 0.624852738703666200, 0.633251994214366398,
+     0.641896716427266423, 0.650805833414571433, 0.660000841079000145, 0.669506316731925177,
+     0.679350572264765806, 0.689566496117078431, 0.700192655082788606, 0.711274760805076456,
+     0.722867659593572465, 0.735038092431424039, 0.747868621985195658, 0.761463388849896838,
+     0.775956852040116218, 0.791527636972496285, 0.808421651523009044, 0.826993296643051101,
+     0.847785500623990496, 0.871704332381204705, 0.900469929925747703, 0.938143680862176477,
+     1.000000000000000000];
+pub static ZIG_EXP_F_DIFF: [f64, .. 257] =
+    [0.000000000000000000, 0.000287067661533533, 0.000513134928485678, 0.000569030497974398,
+     0.000609667963417335, 0.000642831049855169, 0.000671465984262828, 0.000697030342996893,
+     0.000720360862708599, 0.000741986223663093, 0.000762263730113694, 0.000781447246315807,
+     0.000799724254382053, 0.000817237547791934, 0.000834098656693235, 0.000850396538527769,
+     0.000866203416804620, 0.000881578828420777, 0.000896572504999613, 0.000911226471926952,
+     0.000925576608509206, 0.000939653828282008, 0.000953484986066785, 0.000967093584871414,
+     0.000980500333784669, 0.000993723593313716, 0.001006779734568374, 0.001019683431705467,
+     0.001032447902101660, 0.001045085105172934, 0.001057605908173612, 0.001070020225402434,
+     0.001082337135821582, 0.001094564983022843, 0.001106711460658764, 0.001118783685829211,
+     0.001130788262427001, 0.001142731336065933, 0.001154618641914802, 0.001166455546523074,
+     0.001178247084534012, 0.001189997991027938, 0.001201712730115490, 0.001213395520299268,
+     0.001225050357040701, 0.001236681032901414, 0.001248291155571943, 0.001259884164055092,
+     0.001271463343231895, 0.001283031837006378, 0.001294592660197942, 0.001306148709326875,
+     0.001317702772419903, 0.001329257537945404, 0.001340815602974395, 0.001352379480650950,
+     0.001363951607045839, 0.001375534347457789, 0.001387130002219621, 0.001398740812059381,
+     0.001410368963061376, 0.001422016591266340, 0.001433685786946429, 0.001445378598586011,
+     0.001457097036596827, 0.001468843076792140, 0.001480618663643060, 0.001492425713336909,
+     0.001504266116655995, 0.001516141741693663, 0.001528054436422108, 0.001540006031125918,
+     0.001551998340713470, 0.001564033166917514, 0.001576112300394977, 0.001588237522735750,
+     0.001600410608388780, 0.001612633326513305, 0.001624907442762655, 0.001637234721007311,
+     0.001649616925003372, 0.001662055820012304, 0.001674553174376953, 0.001687110761059388,
+     0.001699730359144919, 0.001712413755316500, 0.001725162745304071, 0.001737979135312442,
+     0.001750864743431488, 0.001763821401032123, 0.001776850954151601, 0.001789955264870927,
+     0.001803136212688003, 0.001816395695889220, 0.001829735632922019, 0.001843157963772116,
+     0.001856664651347151, 0.001870257682870316, 0.001883939071285826, 0.001897710856679738,
+     0.001911575107717528, 0.001925533923102574, 0.001939589433056721, 0.001953743800826108,
+     0.001967999224215228, 0.001982357937151347, 0.001996822211282223, 0.002011394357609747,
+     0.002026076728162574, 0.002040871717710169, 0.002055781765521847, 0.002070809357173103,
+     0.002085957026402963, 0.002101227357025226, 0.002116622984897121, 0.002132146599948981,
+     0.002147800948277823, 0.002163588834309782, 0.002179513123034188, 0.002195576742314159,
+     0.002211782685277469, 0.002228134012792427, 0.002244633856033434, 0.002261285419141418,
+     0.002278091981983449, 0.002295056903017983, 0.002312183622271174, 0.002329475664429648,
+     0.002346936642057179, 0.002364570258941101, 0.002382380313575932, 0.002400370702791893,
+     0.002418545425535629, 0.002436908586812392, 0.002455464401797752, 0.002474217200128692,
+     0.002493171430384328, 0.002512331664766249, 0.002531702603989994, 0.002551289082400404,
+     0.002571096073321844, 0.002591128694658967, 0.002611392214760672, 0.002631892058563845,
+     0.002652633814032662, 0.002673623238910738, 0.002694866267805934, 0.002716369019626269,
+     0.002738137805389534, 0.002760179136428037, 0.002782499733014893, 0.002805106533435520,
+     0.002828006703534697, 0.002851207646767162, 0.002874717014785921, 0.002898542718600849,
+     0.002922692940346749, 0.002947176145699226, 0.002972001096982591, 0.002997176867015228,
+     0.003022712853742948, 0.003048618795714386, 0.003074904788455568, 0.003101581301807876,
+     0.003128659198296080, 0.003156149752600867, 0.003184064672214937, 0.003212416119368622,
+     0.003241216734320596, 0.003270479660111680, 0.003300218568896729, 0.003330447689969929,
+     0.003361181839619420, 0.003392436452949343, 0.003424227617828290, 0.003456572111131984,
+     0.003489487437467131, 0.003522991870580083, 0.003557104497672658, 0.003591845266868621,
+     0.003627235038102472, 0.003663295637722386, 0.003700049917134574, 0.003737521815846301,
+     0.003775736429304177, 0.003814720081962375, 0.003854500406067995, 0.003895106426696382,
+     0.003936568653631844, 0.003978919180756157, 0.004022191793678687, 0.004066422086428989,
+     0.004111647588127876, 0.004157907900659452, 0.004205244848493050, 0.004253702641940915,
+     0.004303328055299205, 0.004354170621502118, 0.004406282845128784, 0.004459720435841752,
+     0.004514542564613699, 0.004570812145417769, 0.004628596145424491, 0.004687965927177740,
+     0.004748997626717266, 0.004811772572194672, 0.004876377748206484, 0.004942906311860507,
+     0.005011458167522187, 0.005082140608288488, 0.005155069033533799, 0.005230367753417398,
+     0.005308170893076836, 0.005388623411430704, 0.005471882252147620, 0.005558117647517014,
+     0.005647514599798176, 0.005740274569295156, 0.005836617404105682, 0.005936783553485037,
+     0.006041036615386131, 0.006149666279423593, 0.006262991739818591, 0.006381365669577810,
+     0.006505178868201678, 0.006634865721946159, 0.006770910649812723, 0.006913855752425535,
+     0.007064309938019209, 0.007222959874423007, 0.007390583214465396, 0.007568064673498798,
+     0.007756415714389786, 0.007956798835585532, 0.008170557788458321, 0.008399255510700199,
+     0.008644722212900025, 0.008909116987305010, 0.009195007664428712, 0.009505475652925033,
+     0.009844255532840629, 0.010215923852312625, 0.010626158965710175, 0.011082105722287849,
+     0.011592898788496009, 0.012170432837851575, 0.012830529553771619, 0.013594766864701180,
+     0.014493463190219380, 0.015570784932380066, 0.016894014550512759, 0.018571645120042057,
+     0.020792203980939394, 0.023918831757214210, 0.028765597544542998, 0.037673750936428774,
+     0.061856319137823523];
diff --git a/src/libcore/repr.rs b/src/libcore/repr.rs
index abcb727809e..3d525993259 100644
--- a/src/libcore/repr.rs
+++ b/src/libcore/repr.rs
@@ -564,7 +564,7 @@ pub fn write_repr<T>(writer: @Writer, object: &T) {
     }
 }
 
-#[test]
+#[cfg(test)]
 struct P {a: int, b: float}
 
 #[test]
diff --git a/src/libcore/rt/context.rs b/src/libcore/rt/context.rs
index 4714be9e3d5..9c1e566f218 100644
--- a/src/libcore/rt/context.rs
+++ b/src/libcore/rt/context.rs
@@ -207,4 +207,3 @@ pub fn mut_offset<T>(ptr: *mut T, count: int) -> *mut T {
     use core::sys::size_of;
     (ptr as int + count * (size_of::<T>() as int)) as *mut T
 }
-
diff --git a/src/libcore/rt/io/comm_adapters.rs b/src/libcore/rt/io/comm_adapters.rs
index 1d6893b3ca6..7e891f1718e 100644
--- a/src/libcore/rt/io/comm_adapters.rs
+++ b/src/libcore/rt/io/comm_adapters.rs
@@ -56,4 +56,3 @@ impl<W: Writer> WriterChan<W> {
 impl<W: Writer> GenericChan<~[u8]> for WriterChan<W> {
     fn send(&self, _x: ~[u8]) { fail!() }
 }
-
diff --git a/src/libcore/rt/io/util.rs b/src/libcore/rt/io/extensions.rs
index cff224a80be..cff224a80be 100644
--- a/src/libcore/rt/io/util.rs
+++ b/src/libcore/rt/io/extensions.rs
diff --git a/src/libcore/rt/io/file.rs b/src/libcore/rt/io/file.rs
index e041183b584..85dc180452f 100644
--- a/src/libcore/rt/io/file.rs
+++ b/src/libcore/rt/io/file.rs
@@ -9,13 +9,9 @@
 // except according to those terms.
 
 use prelude::*;
-use super::misc::PathLike;
+use super::support::PathLike;
 use super::{Reader, Writer, Seek, Close};
-use super::{IoError, SeekStyle};
-
-/// Open a file with the default FileMode and FileAccess
-/// # XXX are there sane defaults here?
-pub fn open_file<P: PathLike>(_path: &P) -> FileStream { fail!() }
+use super::SeekStyle;
 
 /// # XXX
 /// * Ugh, this is ridiculous. What is the best way to represent these options?
@@ -46,7 +42,7 @@ impl FileStream {
     pub fn open<P: PathLike>(_path: &P,
                              _mode: FileMode,
                              _access: FileAccess
-                            ) -> Result<FileStream, IoError> {
+                            ) -> Option<FileStream> {
         fail!()
     }
 }
diff --git a/src/libcore/rt/io/mem.rs b/src/libcore/rt/io/mem.rs
index 600968a3c71..06e1466831d 100644
--- a/src/libcore/rt/io/mem.rs
+++ b/src/libcore/rt/io/mem.rs
@@ -17,7 +17,7 @@
 
 use prelude::*;
 use super::*;
-
+use cmp::min;
 
 /// Writes to an owned, growable byte vector
 pub struct MemWriter {
@@ -29,13 +29,15 @@ impl MemWriter {
 }
 
 impl Writer for MemWriter {
-    fn write(&mut self, _buf: &[u8]) { fail!() }
+    fn write(&mut self, buf: &[u8]) {
+        self.buf.push_all(buf)
+    }
 
     fn flush(&mut self) { /* no-op */ }
 }
 
 impl Seek for MemWriter {
-    fn tell(&self) -> u64 { fail!() }
+    fn tell(&self) -> u64 { self.buf.len() as u64 }
 
     fn seek(&mut self, _pos: i64, _style: SeekStyle) { fail!() }
 }
@@ -77,13 +79,27 @@ impl MemReader {
 }
 
 impl Reader for MemReader {
-    fn read(&mut self, _buf: &mut [u8]) -> Option<uint> { fail!() }
+    fn read(&mut self, buf: &mut [u8]) -> Option<uint> {
+        { if self.eof() { return None; } }
+
+        let write_len = min(buf.len(), self.buf.len() - self.pos);
+        {
+            let input = self.buf.slice(self.pos, self.pos + write_len);
+            let output = vec::mut_slice(buf, 0, write_len);
+            assert!(input.len() == output.len());
+            vec::bytes::copy_memory(output, input, write_len);
+        }
+        self.pos += write_len;
+        assert!(self.pos <= self.buf.len());
 
-    fn eof(&mut self) -> bool { fail!() }
+        return Some(write_len);
+    }
+
+    fn eof(&mut self) -> bool { self.pos == self.buf.len() }
 }
 
 impl Seek for MemReader {
-    fn tell(&self) -> u64 { fail!() }
+    fn tell(&self) -> u64 { self.pos as u64 }
 
     fn seek(&mut self, _pos: i64, _style: SeekStyle) { fail!() }
 }
@@ -163,4 +179,43 @@ impl<'self> Seek for BufReader<'self> {
     fn tell(&self) -> u64 { fail!() }
 
     fn seek(&mut self, _pos: i64, _style: SeekStyle) { fail!() }
-}
\ No newline at end of file
+}
+
+#[cfg(test)]
+mod test {
+    use prelude::*;
+    use super::*;
+
+    #[test]
+    fn test_mem_writer() {
+        let mut writer = MemWriter::new();
+        assert!(writer.tell() == 0);
+        writer.write([0]);
+        assert!(writer.tell() == 1);
+        writer.write([1, 2, 3]);
+        writer.write([4, 5, 6, 7]);
+        assert!(writer.tell() == 8);
+        assert!(writer.inner() == ~[0, 1, 2, 3, 4, 5 , 6, 7]);
+    }
+
+    #[test]
+    fn test_mem_reader() {
+        let mut reader = MemReader::new(~[0, 1, 2, 3, 4, 5, 6, 7]);
+        let mut buf = [];
+        assert!(reader.read(buf) == Some(0));
+        assert!(reader.tell() == 0);
+        let mut buf = [0];
+        assert!(reader.read(buf) == Some(1));
+        assert!(reader.tell() == 1);
+        assert!(buf == [0]);
+        let mut buf = [0, ..4];
+        assert!(reader.read(buf) == Some(4));
+        assert!(reader.tell() == 5);
+        assert!(buf == [1, 2, 3, 4]);
+        assert!(reader.read(buf) == Some(3));
+        assert!(buf.slice(0, 3) == [5, 6, 7]);
+        assert!(reader.eof());
+        assert!(reader.read(buf) == None);
+        assert!(reader.eof());
+    }
+}
diff --git a/src/libcore/rt/io/mod.rs b/src/libcore/rt/io/mod.rs
index cb00b02d9d1..97b3ee3e30e 100644
--- a/src/libcore/rt/io/mod.rs
+++ b/src/libcore/rt/io/mod.rs
@@ -11,7 +11,13 @@
 /*! Synchronous I/O
 
 This module defines the Rust interface for synchronous I/O.
-It supports file access,
+It models byte-oriented input and output with the Reader and Writer traits.
+Types that implement both `Reader` and `Writer` and called 'streams',
+and automatically implement trait `Stream`.
+Implementations are provided for common I/O streams like
+file, TCP, UDP, Unix domain sockets.
+Readers and Writers may be composed to add capabilities like string
+parsing, encoding, and compression.
 
 This will likely live in core::io, not core::rt::io.
 
@@ -27,44 +33,177 @@ Some examples of obvious things you might want to do
 
 * Read a complete file to a string, (converting newlines?)
 
-    let contents = open("message.txt").read_to_str(); // read_to_str??
+    let contents = File::open("message.txt").read_to_str(); // read_to_str??
 
 * Write a line to a file
 
-    let file = FileStream::open("message.txt", Create, Write);
+    let file = File::open("message.txt", Create, Write);
     file.write_line("hello, file!");
 
 * Iterate over the lines of a file
 
+    do File::open("message.txt").each_line |line| {
+        println(line)
+    }
+
 * Pull the lines of a file into a vector of strings
 
+    let lines = File::open("message.txt").line_iter().to_vec();
+
+* Make an simple HTTP request
+
+    let socket = TcpStream::open("localhost:8080");
+    socket.write_line("GET / HTTP/1.0");
+    socket.write_line("");
+    let response = socket.read_to_end();
+
 * Connect based on URL? Requires thinking about where the URL type lives
   and how to make protocol handlers extensible, e.g. the "tcp" protocol
   yields a `TcpStream`.
 
-    connect("tcp://localhost:8080").write_line("HTTP 1.0 GET /");
+    connect("tcp://localhost:8080");
 
 # Terms
 
-* reader
-* writer
-* stream
-* Blocking vs. non-blocking
-* synchrony and asynchrony
-
-I tend to call this implementation non-blocking, because performing I/O
-doesn't block the progress of other tasks. Is that how we want to present
-it, 'synchronous but non-blocking'?
+* Reader - An I/O source, reads bytes into a buffer
+* Writer - An I/O sink, writes bytes from a buffer
+* Stream - Typical I/O sources like files and sockets are both Readers and Writers,
+  and are collectively referred to a `streams`.
+* Decorator - A Reader or Writer that composes with others to add additional capabilities
+  such as encoding or decoding
+
+# Blocking and synchrony
+
+When discussing I/O you often hear the terms 'synchronous' and
+'asynchronous', along with 'blocking' and 'non-blocking' compared and
+contrasted. A synchronous I/O interface performs each I/O operation to
+completion before proceeding to the next. Synchronous interfaces are
+usually used in imperative style as a sequence of commands. An
+asynchronous interface allows multiple I/O requests to be issued
+simultaneously, without waiting for each to complete before proceeding
+to the next.
+
+Asynchronous interfaces are used to achieve 'non-blocking' I/O. In
+traditional single-threaded systems, performing a synchronous I/O
+operation means that the program stops all activity (it 'blocks')
+until the I/O is complete. Blocking is bad for performance when
+there are other computations that could be done.
+
+Asynchronous interfaces are most often associated with the callback
+(continuation-passing) style popularised by node.js. Such systems rely
+on all computations being run inside an event loop which maintains a
+list of all pending I/O events; when one completes the registered
+callback is run and the code that made the I/O request continiues.
+Such interfaces achieve non-blocking at the expense of being more
+difficult to reason about.
+
+Rust's I/O interface is synchronous - easy to read - and non-blocking by default.
+
+Remember that Rust tasks are 'green threads', lightweight threads that
+are multiplexed onto a single operating system thread. If that system
+thread blocks then no other task may proceed. Rust tasks are
+relatively cheap to create, so as long as other tasks are free to
+execute then non-blocking code may be written by simply creating a new
+task.
+
+When discussing blocking in regards to Rust's I/O model, we are
+concerned with whether performing I/O blocks other Rust tasks from
+proceeding. In other words, when a task calls `read`, it must then
+wait (or 'sleep', or 'block') until the call to `read` is complete.
+During this time, other tasks may or may not be executed, depending on
+how `read` is implemented.
+
+
+Rust's default I/O implementation is non-blocking; by cooperating
+directly with the task scheduler it arranges to never block progress
+of *other* tasks. Under the hood, Rust uses asynchronous I/O via a
+per-scheduler (and hence per-thread) event loop. Synchronous I/O
+requests are implemented by descheduling the running task and
+performing an asynchronous request; the task is only resumed once the
+asynchronous request completes.
+
+For blocking (but possibly more efficient) implementations, look
+in the `io::native` module.
 
 # Error Handling
 
+I/O is an area where nearly every operation can result in unexpected
+errors. It should allow errors to be handled efficiently.
+It needs to be convenient to use I/O when you don't care
+about dealing with specific errors.
+
+Rust's I/O employs a combination of techniques to reduce boilerplate
+while still providing feedback about errors. The basic strategy:
+
+* Errors are fatal by default, resulting in task failure
+* Errors raise the `io_error` conditon which provides an opportunity to inspect
+  an IoError object containing details.
+* Return values must have a sensible null or zero value which is returned
+  if a condition is handled successfully. This may be an `Option`, an empty
+  vector, or other designated error value.
+* Common traits are implemented for `Option`, e.g. `impl<R: Reader> Reader for Option<R>`,
+  so that nullable values do not have to be 'unwrapped' before use.
+
+These features combine in the API to allow for expressions like
+`File::new("diary.txt").write_line("met a girl")` without having to
+worry about whether "diary.txt" exists or whether the write
+succeeds. As written, if either `new` or `write_line` encounters
+an error the task will fail.
+
+If you wanted to handle the error though you might write
+
+    let mut error = None;
+    do io_error::cond(|e: IoError| {
+        error = Some(e);
+    }).in {
+        File::new("diary.txt").write_line("met a girl");
+    }
+
+    if error.is_some() {
+        println("failed to write my diary");
+    }
+
+XXX: Need better condition handling syntax
+
+In this case the condition handler will have the opportunity to
+inspect the IoError raised by either the call to `new` or the call to
+`write_line`, but then execution will continue.
+
+So what actually happens if `new` encounters an error? To understand
+that it's important to know that what `new` returns is not a `File`
+but an `Option<File>`.  If the file does not open, and the condition
+is handled, then `new` will simply return `None`. Because there is an
+implementation of `Writer` (the trait required ultimately required for
+types to implement `write_line`) there is no need to inspect or unwrap
+the `Option<File>` and we simply call `write_line` on it.  If `new`
+returned a `None` then the followup call to `write_line` will also
+raise an error.
+
+## Concerns about this strategy
+
+This structure will encourage a programming style that is prone
+to errors similar to null pointer dereferences.
+In particular code written to ignore errors and expect conditions to be unhandled
+will start passing around null or zero objects when wrapped in a condition handler.
+
+* XXX: How should we use condition handlers that return values?
+
+
+# Issues withi/o scheduler affinity, work stealing, task pinning
+
 # Resource management
 
 * `close` vs. RAII
 
-# Paths and URLs
+# Paths, URLs and overloaded constructors
+
+
+
+# Scope
 
-# std
+In scope for core
+
+* Url?
 
 Some I/O things don't belong in core
 
@@ -73,7 +212,12 @@ Some I/O things don't belong in core
     - http
   - flate
 
-# XXX
+Out of scope
+
+* Async I/O. We'll probably want it eventually
+
+
+# XXX Questions and issues
 
 * Should default constructors take `Path` or `&str`? `Path` makes simple cases verbose.
   Overloading would be nice.
@@ -83,6 +227,7 @@ Some I/O things don't belong in core
 * fsync
 * relationship with filesystem querying, Directory, File types etc.
 * Rename Reader/Writer to ByteReader/Writer, make Reader/Writer generic?
+* Can Port and Chan be implementations of a generic Reader<T>/Writer<T>?
 * Trait for things that are both readers and writers, Stream?
 * How to handle newline conversion
 * String conversion
@@ -92,6 +237,7 @@ Some I/O things don't belong in core
 * Do we need `close` at all? dtors might be good enough
 * How does I/O relate to the Iterator trait?
 * std::base64 filters
+* Using conditions is a big unknown since we don't have much experience with them
 
 */
 
@@ -104,25 +250,29 @@ pub use self::stdio::stderr;
 pub use self::stdio::print;
 pub use self::stdio::println;
 
-pub use self::file::open_file;
 pub use self::file::FileStream;
-pub use self::net::Listener;
 pub use self::net::ip::IpAddr;
 pub use self::net::tcp::TcpListener;
 pub use self::net::tcp::TcpStream;
 pub use self::net::udp::UdpStream;
 
 // Some extension traits that all Readers and Writers get.
-pub use self::util::ReaderUtil;
-pub use self::util::ReaderByteConversions;
-pub use self::util::WriterByteConversions;
+pub use self::extensions::ReaderUtil;
+pub use self::extensions::ReaderByteConversions;
+pub use self::extensions::WriterByteConversions;
 
 /// Synchronous, non-blocking file I/O.
 pub mod file;
 
 /// Synchronous, non-blocking network I/O.
-#[path = "net/mod.rs"]
-pub mod net;
+pub mod net {
+    pub mod tcp;
+    pub mod udp;
+    pub mod ip;
+    #[cfg(unix)]
+    pub mod unix;
+    pub mod http;
+}
 
 /// Readers and Writers for memory buffers and strings.
 pub mod mem;
@@ -130,6 +280,10 @@ pub mod mem;
 /// Non-blocking access to stdin, stdout, stderr
 pub mod stdio;
 
+/// Implementations for Option
+#[cfg(not(stage0))] // Requires condition! fixes
+mod option;
+
 /// Basic stream compression. XXX: Belongs with other flate code
 pub mod flate;
 
@@ -137,10 +291,10 @@ pub mod flate;
 pub mod comm_adapters;
 
 /// Extension traits
-mod util;
+mod extensions;
 
 /// Non-I/O things needed by the I/O module
-mod misc;
+mod support;
 
 /// Thread-blocking implementations
 pub mod native {
@@ -170,12 +324,14 @@ pub struct IoError {
     detail: Option<~str>
 }
 
+#[deriving(Eq)]
 pub enum IoErrorKind {
     FileNotFound,
     FilePermission,
     ConnectionFailed,
     Closed,
-    OtherIoError
+    OtherIoError,
+    PreviousIoError
 }
 
 // XXX: Can't put doc comments on macros
@@ -208,9 +364,9 @@ pub trait Reader {
     ///         println(reader.read_line());
     ///     }
     ///
-    /// # XXX
+    /// # Failue
     ///
-    /// What does this return if the Reader is in an error state?
+    /// Returns `true` on failure.
     fn eof(&mut self) -> bool;
 }
 
@@ -250,9 +406,30 @@ pub enum SeekStyle {
 /// * Are `u64` and `i64` the right choices?
 pub trait Seek {
     fn tell(&self) -> u64;
+
+    /// Seek to an offset in a stream
+    ///
+    /// A successful seek clears the EOF indicator.
+    ///
+    /// # XXX
+    ///
+    /// * What is the behavior when seeking past the end of a stream?
     fn seek(&mut self, pos: i64, style: SeekStyle);
 }
 
+/// A listener is a value that listens for connections
+pub trait Listener<S> {
+    /// Wait for and accept an incoming connection
+    ///
+    /// Returns `None` on timeout.
+    ///
+    /// # Failure
+    ///
+    /// Raises `io_error` condition. If the condition is handled,
+    /// then `accept` returns `None`.
+    fn accept(&mut self) -> Option<S>;
+}
+
 /// Common trait for decorator types.
 ///
 /// Provides accessors to get the inner, 'decorated' values. The I/O library
@@ -278,3 +455,16 @@ pub trait Decorator<T> {
     /// Take a mutable reference to the decorated value
     fn inner_mut_ref<'a>(&'a mut self) -> &'a mut T;
 }
+
+pub fn standard_error(kind: IoErrorKind) -> IoError {
+    match kind {
+        PreviousIoError => {
+            IoError {
+                kind: PreviousIoError,
+                desc: "Failing due to a previous I/O error",
+                detail: None
+            }
+        }
+        _ => fail!()
+    }
+}
diff --git a/src/libcore/rt/io/net/ip.rs b/src/libcore/rt/io/net/ip.rs
index d9b7f4e6e40..df1dfe4d38a 100644
--- a/src/libcore/rt/io/net/ip.rs
+++ b/src/libcore/rt/io/net/ip.rs
@@ -12,4 +12,3 @@ pub enum IpAddr {
     Ipv4(u8, u8, u8, u8, u16),
     Ipv6
 }
-
diff --git a/src/libcore/rt/io/net/mod.rs b/src/libcore/rt/io/net/mod.rs
deleted file mode 100644
index 130ff6b38fa..00000000000
--- a/src/libcore/rt/io/net/mod.rs
+++ /dev/null
@@ -1,31 +0,0 @@
-// 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.
-
-use prelude::*;
-
-pub mod tcp;
-pub mod udp;
-pub mod ip;
-#[cfg(unix)]
-pub mod unix;
-pub mod http;
-
-/// A listener is a value that listens for connections
-pub trait Listener<S> {
-    /// Wait for and accept an incoming connection
-    ///
-    /// Returns `None` on timeout.
-    ///
-    /// # Failure
-    ///
-    /// Raises `io_error` condition. If the condition is handled,
-    /// then `accept` returns `None`.
-    fn accept(&mut self) -> Option<S>;
-}
diff --git a/src/libcore/rt/io/net/tcp.rs b/src/libcore/rt/io/net/tcp.rs
index e3f71dca8c8..c95b4344fe7 100644
--- a/src/libcore/rt/io/net/tcp.rs
+++ b/src/libcore/rt/io/net/tcp.rs
@@ -9,14 +9,13 @@
 // except according to those terms.
 
 use prelude::*;
-use super::*;
 use super::super::*;
 use super::ip::IpAddr;
 
 pub struct TcpStream;
 
 impl TcpStream {
-    pub fn connect(_addr: IpAddr) -> Result<TcpStream, IoError> {
+    pub fn connect(_addr: IpAddr) -> Option<TcpStream> {
         fail!()
     }
 }
@@ -40,7 +39,7 @@ impl Close for TcpStream {
 pub struct TcpListener;
 
 impl TcpListener {
-    pub fn new(_addr: IpAddr) -> TcpListener {
+    pub fn bind(_addr: IpAddr) -> Option<TcpListener> {
         fail!()
     }
 }
@@ -48,3 +47,28 @@ impl TcpListener {
 impl Listener<TcpStream> for TcpListener {
     fn accept(&mut self) -> Option<TcpStream> { fail!() }
 }
+
+#[cfg(test)]
+mod test {
+
+    #[test] #[ignore]
+    fn smoke_test() {
+        /*do run_in_newsched_task {
+            let addr = next_test_ip4();
+
+            do spawn_immediately {
+                let listener = TcpListener::bind(addr);
+                do listener.accept() {
+                    let mut buf = [0];
+                    listener.read(buf);
+                    assert!(buf[0] == 99);
+                }
+            }
+
+            do spawn_immediately {
+                let stream = TcpStream::connect(addr);
+                stream.write([99]);
+            }
+        }*/
+    }
+}
diff --git a/src/libcore/rt/io/net/udp.rs b/src/libcore/rt/io/net/udp.rs
index f76bb58a45e..1f1254a7029 100644
--- a/src/libcore/rt/io/net/udp.rs
+++ b/src/libcore/rt/io/net/udp.rs
@@ -9,14 +9,13 @@
 // except according to those terms.
 
 use prelude::*;
-use super::*;
 use super::super::*;
 use super::ip::IpAddr;
 
 pub struct UdpStream;
 
 impl UdpStream {
-    pub fn connect(_addr: IpAddr) -> Result<UdpStream, IoError> {
+    pub fn connect(_addr: IpAddr) -> Option<UdpStream> {
         fail!()
     }
 }
@@ -40,7 +39,7 @@ impl Close for UdpStream {
 pub struct UdpListener;
 
 impl UdpListener {
-    pub fn new(_addr: IpAddr) -> UdpListener {
+    pub fn bind(_addr: IpAddr) -> Option<UdpListener> {
         fail!()
     }
 }
@@ -48,4 +47,3 @@ impl UdpListener {
 impl Listener<UdpStream> for UdpListener {
     fn accept(&mut self) -> Option<UdpStream> { fail!() }
 }
-
diff --git a/src/libcore/rt/io/net/unix.rs b/src/libcore/rt/io/net/unix.rs
index 35eabe21b2a..f449a857467 100644
--- a/src/libcore/rt/io/net/unix.rs
+++ b/src/libcore/rt/io/net/unix.rs
@@ -9,14 +9,13 @@
 // except according to those terms.
 
 use prelude::*;
-use super::*;
 use super::super::*;
-use super::super::misc::PathLike;
+use super::super::support::PathLike;
 
 pub struct UnixStream;
 
 impl UnixStream {
-    pub fn connect<P: PathLike>(_path: &P) -> Result<UnixStream, IoError> {
+    pub fn connect<P: PathLike>(_path: &P) -> Option<UnixStream> {
         fail!()
     }
 }
@@ -40,7 +39,7 @@ impl Close for UnixStream {
 pub struct UnixListener;
 
 impl UnixListener {
-    pub fn new<P: PathLike>(_path: &P) -> UnixListener {
+    pub fn bind<P: PathLike>(_path: &P) -> Option<UnixListener> {
         fail!()
     }
 }
@@ -48,4 +47,3 @@ impl UnixListener {
 impl Listener<UnixStream> for UnixListener {
     fn accept(&mut self) -> Option<UnixStream> { fail!() }
 }
-
diff --git a/src/libcore/rt/io/option.rs b/src/libcore/rt/io/option.rs
new file mode 100644
index 00000000000..95f8711cb5b
--- /dev/null
+++ b/src/libcore/rt/io/option.rs
@@ -0,0 +1,153 @@
+// 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.
+
+//! Implementations of I/O traits for the Option type
+//!
+//! I/O constructors return option types to allow errors to be handled.
+//! These implementations allow e.g. `Option<FileStream>` to be used
+//! as a `Reader` without unwrapping the option first.
+//!
+//! # XXX Seek and Close
+
+use option::*;
+use super::{Reader, Writer, Listener};
+use super::{standard_error, PreviousIoError, io_error, IoError};
+
+fn prev_io_error() -> IoError {
+    standard_error(PreviousIoError)
+}
+
+impl<W: Writer> Writer for Option<W> {
+    fn write(&mut self, buf: &[u8]) {
+        match *self {
+            Some(ref mut writer) => writer.write(buf),
+            None => io_error::cond.raise(prev_io_error())
+        }
+    }
+
+    fn flush(&mut self) {
+        match *self {
+            Some(ref mut writer) => writer.flush(),
+            None => io_error::cond.raise(prev_io_error())
+        }
+    }
+}
+
+impl<R: Reader> Reader for Option<R> {
+    fn read(&mut self, buf: &mut [u8]) -> Option<uint> {
+        match *self {
+            Some(ref mut reader) => reader.read(buf),
+            None => {
+                io_error::cond.raise(prev_io_error());
+                None
+            }
+        }
+    }
+
+    fn eof(&mut self) -> bool {
+        match *self {
+            Some(ref mut reader) => reader.eof(),
+            None => {
+                io_error::cond.raise(prev_io_error());
+                true
+            }
+        }
+    }
+}
+
+impl<L: Listener<S>, S> Listener<S> for Option<L> {
+    fn accept(&mut self) -> Option<S> {
+        match *self {
+            Some(ref mut listener) => listener.accept(),
+            None => {
+                io_error::cond.raise(prev_io_error());
+                None
+            }
+        }
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use option::*;
+    use super::super::mem::*;
+    use rt::test::*;
+    use super::super::{PreviousIoError, io_error};
+
+    #[test]
+    fn test_option_writer() {
+        do run_in_newsched_task {
+            let mut writer: Option<MemWriter> = Some(MemWriter::new());
+            writer.write([0, 1, 2]);
+            writer.flush();
+            assert!(writer.unwrap().inner() == ~[0, 1, 2]);
+        }
+    }
+
+    #[test]
+    fn test_option_writer_error() {
+        do run_in_newsched_task {
+            let mut writer: Option<MemWriter> = None;
+
+            let mut called = false;
+            do io_error::cond.trap(|err| {
+                assert!(err.kind == PreviousIoError);
+                called = true;
+            }).in {
+                writer.write([0, 0, 0]);
+            }
+            assert!(called);
+
+            let mut called = false;
+            do io_error::cond.trap(|err| {
+                assert!(err.kind == PreviousIoError);
+                called = true;
+            }).in {
+                writer.flush();
+            }
+            assert!(called);
+        }
+    }
+
+    #[test]
+    fn test_option_reader() {
+        do run_in_newsched_task {
+            let mut reader: Option<MemReader> = Some(MemReader::new(~[0, 1, 2, 3]));
+            let mut buf = [0, 0];
+            reader.read(buf);
+            assert!(buf == [0, 1]);
+            assert!(!reader.eof());
+        }
+    }
+
+    #[test]
+    fn test_option_reader_error() {
+        let mut reader: Option<MemReader> = None;
+        let mut buf = [];
+
+        let mut called = false;
+        do io_error::cond.trap(|err| {
+            assert!(err.kind == PreviousIoError);
+            called = true;
+        }).in {
+            reader.read(buf);
+        }
+        assert!(called);
+
+        let mut called = false;
+        do io_error::cond.trap(|err| {
+            assert!(err.kind == PreviousIoError);
+            called = true;
+        }).in {
+            assert!(reader.eof());
+        }
+        assert!(called);
+    }
+}
diff --git a/src/libcore/rt/io/misc.rs b/src/libcore/rt/io/support.rs
index 7bace5d6df2..7bace5d6df2 100644
--- a/src/libcore/rt/io/misc.rs
+++ b/src/libcore/rt/io/support.rs
diff --git a/src/libcore/rt/local_heap.rs b/src/libcore/rt/local_heap.rs
new file mode 100644
index 00000000000..6bf228a1b22
--- /dev/null
+++ b/src/libcore/rt/local_heap.rs
@@ -0,0 +1,80 @@
+// 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.
+
+//! The local, garbage collected heap
+
+use libc::{c_void, uintptr_t, size_t};
+use ops::Drop;
+
+type MemoryRegion = c_void;
+type BoxedRegion = c_void;
+
+pub type OpaqueBox = c_void;
+pub type TypeDesc = c_void;
+
+pub struct LocalHeap {
+    memory_region: *MemoryRegion,
+    boxed_region: *BoxedRegion
+}
+
+impl LocalHeap {
+    pub fn new() -> LocalHeap {
+        unsafe {
+            // Don't need synchronization for the single-threaded local heap
+            let synchronized = false as uintptr_t;
+            // XXX: These usually come from the environment
+            let detailed_leaks = false as uintptr_t;
+            let poison_on_free = false as uintptr_t;
+            let region = rust_new_memory_region(synchronized, detailed_leaks, poison_on_free);
+            assert!(region.is_not_null());
+            let boxed = rust_new_boxed_region(region, poison_on_free);
+            assert!(boxed.is_not_null());
+            LocalHeap {
+                memory_region: region,
+                boxed_region: boxed
+            }
+        }
+    }
+
+    pub fn alloc(&mut self, td: *TypeDesc, size: uint) -> *OpaqueBox {
+        unsafe {
+            return rust_boxed_region_malloc(self.boxed_region, td, size as size_t);
+        }
+    }
+
+    pub fn free(&mut self, box: *OpaqueBox) {
+        unsafe {
+            return rust_boxed_region_free(self.boxed_region, box);
+        }
+    }
+}
+
+impl Drop for LocalHeap {
+    fn finalize(&self) {
+        unsafe {
+            rust_delete_boxed_region(self.boxed_region);
+            rust_delete_memory_region(self.memory_region);
+        }
+    }
+}
+
+extern {
+    fn rust_new_memory_region(synchronized: uintptr_t,
+                               detailed_leaks: uintptr_t,
+                               poison_on_free: uintptr_t) -> *MemoryRegion;
+    fn rust_delete_memory_region(region: *MemoryRegion);
+    fn rust_new_boxed_region(region: *MemoryRegion,
+                             poison_on_free: uintptr_t) -> *BoxedRegion;
+    fn rust_delete_boxed_region(region: *BoxedRegion);
+    fn rust_boxed_region_malloc(region: *BoxedRegion,
+                                td: *TypeDesc,
+                                size: size_t) -> *OpaqueBox;
+    fn rust_boxed_region_free(region: *BoxedRegion, box: *OpaqueBox);
+}
diff --git a/src/libcore/rt/local_services.rs b/src/libcore/rt/local_services.rs
new file mode 100644
index 00000000000..a03bc6c409f
--- /dev/null
+++ b/src/libcore/rt/local_services.rs
@@ -0,0 +1,223 @@
+// 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.
+
+//! Language-level runtime services that should reasonably expected
+//! to be available 'everywhere'. Local heaps, GC, unwinding,
+//! local storage, and logging. Even a 'freestanding' Rust would likely want
+//! to implement this.
+
+//! Local services may exist in at least three different contexts:
+//! when running as a task, when running in the scheduler's context,
+//! or when running outside of a scheduler but with local services
+//! (freestanding rust with local services?).
+
+use prelude::*;
+use libc::{c_void, uintptr_t};
+use cast::transmute;
+use super::sched::local_sched;
+use super::local_heap::LocalHeap;
+
+pub struct LocalServices {
+    heap: LocalHeap,
+    gc: GarbageCollector,
+    storage: LocalStorage,
+    logger: Logger,
+    unwinder: Option<Unwinder>,
+    destroyed: bool
+}
+
+pub struct GarbageCollector;
+pub struct LocalStorage(*c_void, Option<~fn(*c_void)>);
+pub struct Logger;
+
+pub struct Unwinder {
+    unwinding: bool,
+}
+
+impl LocalServices {
+    pub fn new() -> LocalServices {
+        LocalServices {
+            heap: LocalHeap::new(),
+            gc: GarbageCollector,
+            storage: LocalStorage(ptr::null(), None),
+            logger: Logger,
+            unwinder: Some(Unwinder { unwinding: false }),
+            destroyed: false
+        }
+    }
+
+    pub fn without_unwinding() -> LocalServices {
+        LocalServices {
+            heap: LocalHeap::new(),
+            gc: GarbageCollector,
+            storage: LocalStorage(ptr::null(), None),
+            logger: Logger,
+            unwinder: None,
+            destroyed: false
+        }
+    }
+
+    pub fn run(&mut self, f: &fn()) {
+        // This is just an assertion that `run` was called unsafely
+        // and this instance of LocalServices is still accessible.
+        do borrow_local_services |sched| {
+            assert!(ptr::ref_eq(sched, self));
+        }
+
+        match self.unwinder {
+            Some(ref mut unwinder) => {
+                // If there's an unwinder then set up the catch block
+                unwinder.try(f);
+            }
+            None => {
+                // Otherwise, just run the body
+                f()
+            }
+        }
+        self.destroy();
+    }
+
+    /// Must be called manually before finalization to clean up
+    /// thread-local resources. Some of the routines here expect
+    /// LocalServices to be available recursively so this must be
+    /// called unsafely, without removing LocalServices from
+    /// thread-local-storage.
+    fn destroy(&mut self) {
+        // This is just an assertion that `destroy` was called unsafely
+        // and this instance of LocalServices is still accessible.
+        do borrow_local_services |sched| {
+            assert!(ptr::ref_eq(sched, self));
+        }
+        match self.storage {
+            LocalStorage(ptr, Some(ref dtor)) => {
+                (*dtor)(ptr)
+            }
+            _ => ()
+        }
+        self.destroyed = true;
+    }
+}
+
+impl Drop for LocalServices {
+    fn finalize(&self) { assert!(self.destroyed) }
+}
+
+// Just a sanity check to make sure we are catching a Rust-thrown exception
+static UNWIND_TOKEN: uintptr_t = 839147;
+
+impl Unwinder {
+    pub fn try(&mut self, f: &fn()) {
+        use sys::Closure;
+
+        unsafe {
+            let closure: Closure = transmute(f);
+            let code = transmute(closure.code);
+            let env = transmute(closure.env);
+
+            let token = rust_try(try_fn, code, env);
+            assert!(token == 0 || token == UNWIND_TOKEN);
+        }
+
+        extern fn try_fn(code: *c_void, env: *c_void) {
+            unsafe {
+                let closure: Closure = Closure {
+                    code: transmute(code),
+                    env: transmute(env),
+                };
+                let closure: &fn() = transmute(closure);
+                closure();
+            }
+        }
+
+        extern {
+            #[rust_stack]
+            fn rust_try(f: *u8, code: *c_void, data: *c_void) -> uintptr_t;
+        }
+    }
+
+    pub fn begin_unwind(&mut self) -> ! {
+        self.unwinding = true;
+        unsafe {
+            rust_begin_unwind(UNWIND_TOKEN);
+            return transmute(());
+        }
+        extern {
+            fn rust_begin_unwind(token: uintptr_t);
+        }
+    }
+}
+
+/// Borrow a pointer to the installed local services.
+/// Fails (likely aborting the process) if local services are not available.
+pub fn borrow_local_services(f: &fn(&mut LocalServices)) {
+    do local_sched::borrow |sched| {
+        match sched.current_task {
+            Some(~ref mut task) => {
+                f(&mut task.local_services)
+            }
+            None => {
+                fail!(~"no local services for schedulers yet")
+            }
+        }
+    }
+}
+
+pub unsafe fn unsafe_borrow_local_services() -> &mut LocalServices {
+    use cast::transmute_mut_region;
+
+    match local_sched::unsafe_borrow().current_task {
+        Some(~ref mut task) => {
+            transmute_mut_region(&mut task.local_services)
+        }
+        None => {
+            fail!(~"no local services for schedulers yet")
+        }
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use rt::test::*;
+
+    #[test]
+    fn local_heap() {
+        do run_in_newsched_task() {
+            let a = @5;
+            let b = a;
+            assert!(*a == 5);
+            assert!(*b == 5);
+        }
+    }
+
+    #[test]
+    fn tls() {
+        use task::local_data::*;
+        do run_in_newsched_task() {
+            unsafe {
+                fn key(_x: @~str) { }
+                local_data_set(key, @~"data");
+                assert!(*local_data_get(key).get() == ~"data");
+                fn key2(_x: @~str) { }
+                local_data_set(key2, @~"data");
+                assert!(*local_data_get(key2).get() == ~"data");
+            }
+        }
+    }
+
+    #[test]
+    fn unwind() {
+        do run_in_newsched_task() {
+            let result = spawntask_try(||());
+            assert!(result.is_ok());
+            let result = spawntask_try(|| fail!());
+            assert!(result.is_err());
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/libcore/rt/mod.rs b/src/libcore/rt/mod.rs
index e77ec82637e..a072fccd33d 100644
--- a/src/libcore/rt/mod.rs
+++ b/src/libcore/rt/mod.rs
@@ -8,30 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+/*! The Rust runtime, including the scheduler and I/O interface */
+
 #[doc(hidden)];
 
 use libc::c_char;
 
-// Some basic logging
-macro_rules! rtdebug_ (
-    ($( $arg:expr),+) => ( {
-        dumb_println(fmt!( $($arg),+ ));
-
-        fn dumb_println(s: &str) {
-            use io::WriterUtil;
-            let dbg = ::libc::STDERR_FILENO as ::io::fd_t;
-            dbg.write_str(s);
-            dbg.write_str("\n");
-        }
-
-    } )
-)
-
-// An alternate version with no output, for turning off logging
-macro_rules! rtdebug (
-    ($( $arg:expr),+) => ( $(let _ = $arg)*; )
-)
-
 #[path = "sched/mod.rs"]
 mod sched;
 mod rtio;
@@ -48,6 +30,12 @@ mod stack;
 mod context;
 mod thread;
 pub mod env;
+pub mod local_services;
+mod local_heap;
+
+/// Tools for testing the runtime
+#[cfg(test)]
+pub mod test;
 
 pub fn start(main: *u8, _argc: int, _argv: **c_char, _crate_map: *u8) -> int {
     use self::sched::{Scheduler, Task};
@@ -72,7 +60,7 @@ pub fn start(main: *u8, _argc: int, _argv: **c_char, _crate_map: *u8) -> int {
 /// Different runtime services are available depending on context.
 #[deriving(Eq)]
 pub enum RuntimeContext {
-    // Only default services, e.g. exchange heap
+    // Only the exchange heap is available
     GlobalContext,
     // The scheduler may be accessed
     SchedulerContext,
@@ -139,24 +127,3 @@ fn test_context() {
         sched.run();
     }
 }
-
-// For setting up tests of the new scheduler
-#[cfg(test)]
-pub fn run_in_newsched_task(f: ~fn()) {
-    use cell::Cell;
-    use unstable::run_in_bare_thread;
-    use self::sched::Task;
-    use self::uvio::UvEventLoop;
-
-    let f = Cell(Cell(f));
-
-    do run_in_bare_thread {
-        let mut sched = ~UvEventLoop::new_scheduler();
-        let f = f.take();
-        let task = ~do Task::new(&mut sched.stack_pool) {
-            (f.take())();
-        };
-        sched.task_queue.push_back(task);
-        sched.run();
-    }
-}
diff --git a/src/libcore/rt/sched/local_sched.rs b/src/libcore/rt/sched/local_sched.rs
index 2d1e06163be..a7e02f30e01 100644
--- a/src/libcore/rt/sched/local_sched.rs
+++ b/src/libcore/rt/sched/local_sched.rs
@@ -143,4 +143,3 @@ fn borrow_smoke_test() {
     }
     let _scheduler = take();
 }
-
diff --git a/src/libcore/rt/sched/mod.rs b/src/libcore/rt/sched/mod.rs
index 333146394ee..663fe3e62d0 100644
--- a/src/libcore/rt/sched/mod.rs
+++ b/src/libcore/rt/sched/mod.rs
@@ -16,6 +16,7 @@ use super::work_queue::WorkQueue;
 use super::stack::{StackPool, StackSegment};
 use super::rtio::{EventLoop, EventLoopObject};
 use super::context::Context;
+use super::local_services::LocalServices;
 use cell::Cell;
 
 #[cfg(test)] use super::uvio::UvEventLoop;
@@ -38,7 +39,7 @@ pub struct Scheduler {
     /// Always valid when a task is executing, otherwise not
     priv saved_context: Context,
     /// The currently executing task
-    priv current_task: Option<~Task>,
+    current_task: Option<~Task>,
     /// An action performed after a context switch on behalf of the
     /// code running before the context switch
     priv cleanup_job: Option<CleanupJob>
@@ -147,7 +148,7 @@ pub impl Scheduler {
             }
         }
 
-        // Control never reaches here
+        abort!("control reached end of task");
     }
 
     fn schedule_new_task(~self, task: ~Task) {
@@ -324,10 +325,18 @@ pub struct Task {
     /// These are always valid when the task is not running, unless
     /// the task is dead
     priv saved_context: Context,
+    /// The heap, GC, unwinding, local storage, logging
+    local_services: LocalServices
 }
 
 pub impl Task {
     fn new(stack_pool: &mut StackPool, start: ~fn()) -> Task {
+        Task::with_local(stack_pool, LocalServices::new(), start)
+    }
+
+    fn with_local(stack_pool: &mut StackPool,
+                  local_services: LocalServices,
+                  start: ~fn()) -> Task {
         let start = Task::build_start_wrapper(start);
         let mut stack = stack_pool.take_segment(TASK_MIN_STACK_SIZE);
         // NB: Context holds a pointer to that ~fn
@@ -335,6 +344,7 @@ pub impl Task {
         return Task {
             current_stack_segment: stack,
             saved_context: initial_context,
+            local_services: local_services
         };
     }
 
@@ -347,9 +357,12 @@ pub impl Task {
             unsafe {
                 let sched = local_sched::unsafe_borrow();
                 sched.run_cleanup_job();
-            }
 
-            start();
+                let sched = local_sched::unsafe_borrow();
+                let task = sched.current_task.get_mut_ref();
+                // FIXME #6141: shouldn't neet to put `start()` in another closure
+                task.local_services.run(||start());
+            }
 
             let sched = local_sched::take();
             sched.terminate_current_task();
diff --git a/src/libcore/rt/test.rs b/src/libcore/rt/test.rs
new file mode 100644
index 00000000000..63db7054088
--- /dev/null
+++ b/src/libcore/rt/test.rs
@@ -0,0 +1,120 @@
+// 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.
+
+use cell::Cell;
+use result::{Result, Ok, Err};
+use super::io::net::ip::{IpAddr, Ipv4};
+use rt::local_services::LocalServices;
+
+/// Creates a new scheduler in a new thread and runs a task in it,
+/// then waits for the scheduler to exit. Failure of the task
+/// will abort the process.
+pub fn run_in_newsched_task(f: ~fn()) {
+    use unstable::run_in_bare_thread;
+    use super::sched::Task;
+    use super::uvio::UvEventLoop;
+
+    let f = Cell(f);
+
+    do run_in_bare_thread {
+        let mut sched = ~UvEventLoop::new_scheduler();
+        let task = ~Task::with_local(&mut sched.stack_pool,
+                                     LocalServices::without_unwinding(),
+                                     f.take());
+        sched.task_queue.push_back(task);
+        sched.run();
+    }
+}
+
+/// Test tasks will abort on failure instead of unwinding
+pub fn spawntask(f: ~fn()) {
+    use super::sched::*;
+
+    let mut sched = local_sched::take();
+    let task = ~Task::with_local(&mut sched.stack_pool,
+                                 LocalServices::without_unwinding(),
+                                 f);
+    do sched.switch_running_tasks_and_then(task) |task| {
+        let task = Cell(task);
+        let sched = local_sched::take();
+        sched.schedule_new_task(task.take());
+    }
+}
+
+/// Create a new task and run it right now. Aborts on failure
+pub fn spawntask_immediately(f: ~fn()) {
+    use super::sched::*;
+
+    let mut sched = local_sched::take();
+    let task = ~Task::with_local(&mut sched.stack_pool,
+                                 LocalServices::without_unwinding(),
+                                 f);
+    do sched.switch_running_tasks_and_then(task) |task| {
+        let task = Cell(task);
+        do local_sched::borrow |sched| {
+            sched.task_queue.push_front(task.take());
+        }
+    }
+}
+
+/// Spawn a task and wait for it to finish, returning whether it completed successfully or failed
+pub fn spawntask_try(f: ~fn()) -> Result<(), ()> {
+    use cell::Cell;
+    use super::sched::*;
+    use task;
+    use unstable::finally::Finally;
+
+    // Our status variables will be filled in from the scheduler context
+    let mut failed = false;
+    let failed_ptr: *mut bool = &mut failed;
+
+    // Switch to the scheduler
+    let f = Cell(Cell(f));
+    let mut sched = local_sched::take();
+    do sched.deschedule_running_task_and_then() |old_task| {
+        let old_task = Cell(old_task);
+        let f = f.take();
+        let mut sched = local_sched::take();
+        let new_task = ~do Task::new(&mut sched.stack_pool) {
+            do (|| {
+                (f.take())()
+            }).finally {
+                // Check for failure then resume the parent task
+                unsafe { *failed_ptr = task::failing(); }
+                let sched = local_sched::take();
+                do sched.switch_running_tasks_and_then(old_task.take()) |new_task| {
+                    let new_task = Cell(new_task);
+                    do local_sched::borrow |sched| {
+                        sched.task_queue.push_front(new_task.take());
+                    }
+                }
+            }
+        };
+
+        sched.resume_task_immediately(new_task);
+    }
+
+    if !failed { Ok(()) } else { Err(()) }
+}
+
+/// Get a port number, starting at 9600, for use in tests
+pub fn next_test_port() -> u16 {
+    unsafe {
+        return rust_dbg_next_port() as u16;
+    }
+    extern {
+        fn rust_dbg_next_port() -> ::libc::uintptr_t;
+    }
+}
+
+/// Get a unique localhost:port pair starting at 9600
+pub fn next_test_ip4() -> IpAddr {
+    Ipv4(127, 0, 0, 1, next_test_port())
+}
diff --git a/src/libcore/rt/uv/mod.rs b/src/libcore/rt/uv/mod.rs
index cb7925abdcd..013a28abf28 100644
--- a/src/libcore/rt/uv/mod.rs
+++ b/src/libcore/rt/uv/mod.rs
@@ -301,7 +301,8 @@ struct WatcherData {
     write_cb: Option<ConnectionCallback>,
     connect_cb: Option<ConnectionCallback>,
     close_cb: Option<NullCallback>,
-    alloc_cb: Option<AllocCallback>
+    alloc_cb: Option<AllocCallback>,
+    buf: Option<Buf>
 }
 
 pub fn install_watcher_data<H, W: Watcher + NativeHandle<*H>>(watcher: &mut W) {
@@ -311,7 +312,8 @@ pub fn install_watcher_data<H, W: Watcher + NativeHandle<*H>>(watcher: &mut W) {
             write_cb: None,
             connect_cb: None,
             close_cb: None,
-            alloc_cb: None
+            alloc_cb: None,
+            buf: None
         };
         let data = transmute::<~WatcherData, *c_void>(data);
         uvll::set_data_for_uv_handle(watcher.native_handle(), data);
diff --git a/src/libcore/rt/uv/net.rs b/src/libcore/rt/uv/net.rs
index bcfe8b2cfdf..04b9008b067 100644
--- a/src/libcore/rt/uv/net.rs
+++ b/src/libcore/rt/uv/net.rs
@@ -19,12 +19,10 @@ use super::{Loop, Watcher, Request, UvError, Buf, Callback, NativeHandle, NullCa
             vec_to_uv_buf, vec_from_uv_buf};
 use super::super::io::net::ip::{IpAddr, Ipv4, Ipv6};
 
-#[cfg(test)]
-use unstable::run_in_bare_thread;
-#[cfg(test)]
-use super::super::thread::Thread;
-#[cfg(test)]
-use cell::Cell;
+#[cfg(test)] use cell::Cell;
+#[cfg(test)] use unstable::run_in_bare_thread;
+#[cfg(test)] use super::super::thread::Thread;
+#[cfg(test)] use super::super::test::*;
 
 fn ip4_as_uv_ip4(addr: IpAddr, f: &fn(*sockaddr_in)) {
     match addr {
@@ -109,21 +107,25 @@ pub impl StreamWatcher {
 
         let req = WriteRequest::new();
         let buf = vec_to_uv_buf(msg);
-        // XXX: Allocation
-        let bufs = ~[buf];
+        assert!(data.buf.is_none());
+        data.buf = Some(buf);
+        let bufs = [buf];
         unsafe {
             assert!(0 == uvll::write(req.native_handle(),
                                           self.native_handle(),
-                                          &bufs, write_cb));
+                                          bufs, write_cb));
         }
-        // XXX: Freeing immediately after write. Is this ok?
-        let _v = vec_from_uv_buf(buf);
 
         extern fn write_cb(req: *uvll::uv_write_t, status: c_int) {
             let write_request: WriteRequest = NativeHandle::from_native_handle(req);
             let mut stream_watcher = write_request.stream();
             write_request.delete();
-            let cb = get_watcher_data(&mut stream_watcher).write_cb.swap_unwrap();
+            let cb = {
+                let data = get_watcher_data(&mut stream_watcher);
+                let _vec = vec_from_uv_buf(data.buf.swap_unwrap());
+                let cb = data.write_cb.swap_unwrap();
+                cb
+            };
             let status = status_to_maybe_uv_error(stream_watcher.native_handle(), status);
             cb(stream_watcher, status);
         }
@@ -361,7 +363,7 @@ fn connect_close() {
         let mut loop_ = Loop::new();
         let mut tcp_watcher = { TcpWatcher::new(&mut loop_) };
         // Connect to a port where nobody is listening
-        let addr = Ipv4(127, 0, 0, 1, 2923);
+        let addr = next_test_ip4();
         do tcp_watcher.connect(addr) |stream_watcher, status| {
             rtdebug!("tcp_watcher.connect!");
             assert!(status.is_some());
@@ -374,46 +376,12 @@ fn connect_close() {
 }
 
 #[test]
-#[ignore(reason = "need a server to connect to")]
-fn connect_read() {
-    do run_in_bare_thread() {
-        let mut loop_ = Loop::new();
-        let mut tcp_watcher = { TcpWatcher::new(&mut loop_) };
-        let addr = Ipv4(127, 0, 0, 1, 2924);
-        do tcp_watcher.connect(addr) |stream_watcher, status| {
-            let mut stream_watcher = stream_watcher;
-            rtdebug!("tcp_watcher.connect!");
-            assert!(status.is_none());
-            let alloc: AllocCallback = |size| {
-                vec_to_uv_buf(vec::from_elem(size, 0))
-            };
-            do stream_watcher.read_start(alloc)
-                |stream_watcher, _nread, buf, status| {
-
-                let buf = vec_from_uv_buf(buf);
-                rtdebug!("read cb!");
-                if status.is_none() {
-                    let _bytes = buf.unwrap();
-                    rtdebug!("%s", bytes.slice(0, nread as uint).to_str());
-                } else {
-                    rtdebug!("status after read: %s", status.get().to_str());
-                    rtdebug!("closing");
-                    stream_watcher.close(||());
-                }
-            }
-        }
-        loop_.run();
-        loop_.close();
-    }
-}
-
-#[test]
 fn listen() {
     do run_in_bare_thread() {
         static MAX: int = 10;
         let mut loop_ = Loop::new();
         let mut server_tcp_watcher = { TcpWatcher::new(&mut loop_) };
-        let addr = Ipv4(127, 0, 0, 1, 2925);
+        let addr = next_test_ip4();
         server_tcp_watcher.bind(addr);
         let loop_ = loop_;
         rtdebug!("listening");
diff --git a/src/libcore/rt/uvio.rs b/src/libcore/rt/uvio.rs
index fba91dd7d8a..ab8aea2b63c 100644
--- a/src/libcore/rt/uvio.rs
+++ b/src/libcore/rt/uvio.rs
@@ -19,10 +19,9 @@ use cell::{Cell, empty_cell};
 use cast::transmute;
 use super::sched::{Scheduler, local_sched};
 
-#[cfg(test)] use super::io::net::ip::Ipv4;
-#[cfg(test)] use super::sched::Task;
-#[cfg(test)] use unstable::run_in_bare_thread;
 #[cfg(test)] use uint;
+#[cfg(test)] use unstable::run_in_bare_thread;
+#[cfg(test)] use super::test::*;
 
 pub struct UvEventLoop {
     uvio: UvIoFactory
@@ -319,38 +318,22 @@ impl Stream for UvStream {
 }
 
 #[test]
-#[ignore(reason = "ffi struct issues")]
 fn test_simple_io_no_connect() {
-    do run_in_bare_thread {
-        let mut sched = ~UvEventLoop::new_scheduler();
-        let task = ~do Task::new(&mut sched.stack_pool) {
-            let io = unsafe { local_sched::unsafe_borrow_io() };
-            let addr = Ipv4(127, 0, 0, 1, 2926);
-            let maybe_chan = io.connect(addr);
-            assert!(maybe_chan.is_none());
-        };
-        sched.task_queue.push_back(task);
-        sched.run();
+    do run_in_newsched_task {
+        let io = unsafe { local_sched::unsafe_borrow_io() };
+        let addr = next_test_ip4();
+        let maybe_chan = io.connect(addr);
+        assert!(maybe_chan.is_none());
     }
 }
 
 #[test]
-#[ignore(reason = "ffi struct issues")]
 fn test_simple_tcp_server_and_client() {
-    do run_in_bare_thread {
-        let mut sched = ~UvEventLoop::new_scheduler();
-        let addr = Ipv4(127, 0, 0, 1, 2929);
-
-        let client_task = ~do Task::new(&mut sched.stack_pool) {
-            unsafe {
-                let io = local_sched::unsafe_borrow_io();
-                let mut stream = io.connect(addr).unwrap();
-                stream.write([0, 1, 2, 3, 4, 5, 6, 7]);
-                stream.close();
-            }
-        };
+    do run_in_newsched_task {
+        let addr = next_test_ip4();
 
-        let server_task = ~do Task::new(&mut sched.stack_pool) {
+        // Start the server first so it's listening when we connect
+        do spawntask_immediately {
             unsafe {
                 let io = local_sched::unsafe_borrow_io();
                 let mut listener = io.bind(addr).unwrap();
@@ -365,32 +348,25 @@ fn test_simple_tcp_server_and_client() {
                 stream.close();
                 listener.close();
             }
-        };
+        }
 
-        // Start the server first so it listens before the client connects
-        sched.task_queue.push_back(server_task);
-        sched.task_queue.push_back(client_task);
-        sched.run();
+        do spawntask_immediately {
+            unsafe {
+                let io = local_sched::unsafe_borrow_io();
+                let mut stream = io.connect(addr).unwrap();
+                stream.write([0, 1, 2, 3, 4, 5, 6, 7]);
+                stream.close();
+            }
+        }
     }
 }
 
 #[test] #[ignore(reason = "busted")]
 fn test_read_and_block() {
-    do run_in_bare_thread {
-        let mut sched = ~UvEventLoop::new_scheduler();
-        let addr = Ipv4(127, 0, 0, 1, 2930);
+    do run_in_newsched_task {
+        let addr = next_test_ip4();
 
-        let client_task = ~do Task::new(&mut sched.stack_pool) {
-            let io = unsafe { local_sched::unsafe_borrow_io() };
-            let mut stream = io.connect(addr).unwrap();
-            stream.write([0, 1, 2, 3, 4, 5, 6, 7]);
-            stream.write([0, 1, 2, 3, 4, 5, 6, 7]);
-            stream.write([0, 1, 2, 3, 4, 5, 6, 7]);
-            stream.write([0, 1, 2, 3, 4, 5, 6, 7]);
-            stream.close();
-        };
-
-        let server_task = ~do Task::new(&mut sched.stack_pool) {
+        do spawntask_immediately {
             let io = unsafe { local_sched::unsafe_borrow_io() };
             let mut listener = io.bind(addr).unwrap();
             let mut stream = listener.listen().unwrap();
@@ -426,36 +402,58 @@ fn test_read_and_block() {
 
             stream.close();
             listener.close();
-        };
+        }
+
+        do spawntask_immediately {
+            let io = unsafe { local_sched::unsafe_borrow_io() };
+            let mut stream = io.connect(addr).unwrap();
+            stream.write([0, 1, 2, 3, 4, 5, 6, 7]);
+            stream.write([0, 1, 2, 3, 4, 5, 6, 7]);
+            stream.write([0, 1, 2, 3, 4, 5, 6, 7]);
+            stream.write([0, 1, 2, 3, 4, 5, 6, 7]);
+            stream.close();
+        }
 
-        // Start the server first so it listens before the client connects
-        sched.task_queue.push_back(server_task);
-        sched.task_queue.push_back(client_task);
-        sched.run();
     }
 }
 
-#[test] #[ignore(reason = "needs server")]
+#[test]
 fn test_read_read_read() {
-    do run_in_bare_thread {
-        let mut sched = ~UvEventLoop::new_scheduler();
-        let addr = Ipv4(127, 0, 0, 1, 2931);
+    do run_in_newsched_task {
+        let addr = next_test_ip4();
+        static MAX: uint = 500000;
 
-        let client_task = ~do Task::new(&mut sched.stack_pool) {
+        do spawntask_immediately {
+            unsafe {
+                let io = local_sched::unsafe_borrow_io();
+                let mut listener = io.bind(addr).unwrap();
+                let mut stream = listener.listen().unwrap();
+                let mut buf = [1, .. 2048];
+                let mut total_bytes_written = 0;
+                while total_bytes_written < MAX {
+                    stream.write(buf);
+                    total_bytes_written += buf.len();
+                }
+                stream.close();
+                listener.close();
+            }
+        }
+
+        do spawntask_immediately {
             let io = unsafe { local_sched::unsafe_borrow_io() };
             let mut stream = io.connect(addr).unwrap();
             let mut buf = [0, .. 2048];
             let mut total_bytes_read = 0;
-            while total_bytes_read < 500000000 {
+            while total_bytes_read < MAX {
                 let nread = stream.read(buf).unwrap();
                 rtdebug!("read %u bytes", nread as uint);
                 total_bytes_read += nread;
+                for uint::range(0, nread) |i| {
+                    assert!(buf[i] == 1);
+                }
             }
-            rtdebug_!("read %u bytes total", total_bytes_read as uint);
+            rtdebug!("read %u bytes total", total_bytes_read as uint);
             stream.close();
-        };
-
-        sched.task_queue.push_back(client_task);
-        sched.run();
+        }
     }
 }
diff --git a/src/libcore/rt/uvll.rs b/src/libcore/rt/uvll.rs
index c9a696fcd15..3eb7f8006b9 100644
--- a/src/libcore/rt/uvll.rs
+++ b/src/libcore/rt/uvll.rs
@@ -219,9 +219,9 @@ pub unsafe fn accept(server: *c_void, client: *c_void) -> c_int {
     return rust_uv_accept(server as *c_void, client as *c_void);
 }
 
-pub unsafe fn write<T>(req: *uv_write_t, stream: *T, buf_in: *~[uv_buf_t], cb: *u8) -> c_int {
-    let buf_ptr = vec::raw::to_ptr(*buf_in);
-    let buf_cnt = vec::len(*buf_in) as i32;
+pub unsafe fn write<T>(req: *uv_write_t, stream: *T, buf_in: &[uv_buf_t], cb: *u8) -> c_int {
+    let buf_ptr = vec::raw::to_ptr(buf_in);
+    let buf_cnt = vec::len(buf_in) as i32;
     return rust_uv_write(req as *c_void, stream as *c_void, buf_ptr, buf_cnt, cb);
 }
 pub unsafe fn read_start(stream: *uv_stream_t, on_alloc: *u8, on_read: *u8) -> c_int {
diff --git a/src/libcore/run.rs b/src/libcore/run.rs
index 37401788ca2..7e73b3a3f80 100644
--- a/src/libcore/run.rs
+++ b/src/libcore/run.rs
@@ -22,31 +22,6 @@ use str;
 use task;
 use vec;
 
-pub mod rustrt {
-    use libc::{c_int, c_void};
-    use libc;
-    use run;
-
-    #[abi = "cdecl"]
-    pub extern {
-        unsafe fn rust_run_program(argv: **libc::c_char,
-                                   envp: *c_void,
-                                   dir: *libc::c_char,
-                                   in_fd: c_int,
-                                   out_fd: c_int,
-                                   err_fd: c_int) -> run::RunProgramResult;
-        unsafe fn rust_process_wait(pid: c_int) -> c_int;
-    }
-}
-
-pub struct RunProgramResult {
-    // the process id of the program, or -1 if in case of errors
-    pid: pid_t,
-    // a handle to the process - on unix this will always be NULL, but on windows it will be a
-    // HANDLE to the process, which will prevent the pid being re-used until the handle is closed.
-    handle: *(),
-}
-
 /// A value representing a child process
 pub struct Program {
     priv pid: pid_t,
@@ -191,21 +166,262 @@ pub fn spawn_process(prog: &str, args: &[~str],
     return res.pid;
 }
 
+struct RunProgramResult {
+    // the process id of the program (this should never be negative)
+    pid: pid_t,
+    // a handle to the process - on unix this will always be NULL, but on windows it will be a
+    // HANDLE to the process, which will prevent the pid being re-used until the handle is closed.
+    handle: *(),
+}
+
+#[cfg(windows)]
 fn spawn_process_internal(prog: &str, args: &[~str],
                           env: &Option<~[(~str,~str)]>,
                           dir: &Option<~str>,
                           in_fd: c_int, out_fd: c_int, err_fd: c_int) -> RunProgramResult {
+
+    use libc::types::os::arch::extra::{DWORD, HANDLE, STARTUPINFO};
+    use libc::consts::os::extra::{
+        TRUE, FALSE,
+        STARTF_USESTDHANDLES,
+        INVALID_HANDLE_VALUE,
+        DUPLICATE_SAME_ACCESS
+    };
+    use libc::funcs::extra::kernel32::{
+        GetCurrentProcess,
+        DuplicateHandle,
+        CloseHandle,
+        CreateProcessA
+    };
+    use libc::funcs::extra::msvcrt::get_osfhandle;
+
     unsafe {
-        do with_argv(prog, args) |argv| {
-            do with_envp(env) |envp| {
-                do with_dirp(dir) |dirp| {
-                    rustrt::rust_run_program(argv, envp, dirp, in_fd, out_fd, err_fd)
+
+        let mut si = zeroed_startupinfo();
+        si.cb = sys::size_of::<STARTUPINFO>() as DWORD;
+        si.dwFlags = STARTF_USESTDHANDLES;
+
+        let cur_proc = GetCurrentProcess();
+
+        let orig_std_in = get_osfhandle(if in_fd > 0 { in_fd } else { 0 }) as HANDLE;
+        if orig_std_in == INVALID_HANDLE_VALUE as HANDLE {
+            fail!(fmt!("failure in get_osfhandle: %s", os::last_os_error()));
+        }
+        if DuplicateHandle(cur_proc, orig_std_in, cur_proc, &mut si.hStdInput,
+                           0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE {
+            fail!(fmt!("failure in DuplicateHandle: %s", os::last_os_error()));
+        }
+
+        let orig_std_out = get_osfhandle(if out_fd > 0 { out_fd } else { 1 }) as HANDLE;
+        if orig_std_out == INVALID_HANDLE_VALUE as HANDLE {
+            fail!(fmt!("failure in get_osfhandle: %s", os::last_os_error()));
+        }
+        if DuplicateHandle(cur_proc, orig_std_out, cur_proc, &mut si.hStdOutput,
+                           0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE {
+            fail!(fmt!("failure in DuplicateHandle: %s", os::last_os_error()));
+        }
+
+        let orig_std_err = get_osfhandle(if err_fd > 0 { err_fd } else { 2 }) as HANDLE;
+        if orig_std_err as HANDLE == INVALID_HANDLE_VALUE as HANDLE {
+            fail!(fmt!("failure in get_osfhandle: %s", os::last_os_error()));
+        }
+        if DuplicateHandle(cur_proc, orig_std_err, cur_proc, &mut si.hStdError,
+                           0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE {
+            fail!(fmt!("failure in DuplicateHandle: %s", os::last_os_error()));
+        }
+
+        let cmd = make_command_line(prog, args);
+        let mut pi = zeroed_process_information();
+        let mut create_err = None;
+
+        do with_envp(env) |envp| {
+            do with_dirp(dir) |dirp| {
+                do str::as_c_str(cmd) |cmdp| {
+                    let created = CreateProcessA(ptr::null(), cast::transmute(cmdp),
+                                                 ptr::mut_null(), ptr::mut_null(), TRUE,
+                                                 0, envp, dirp, &mut si, &mut pi);
+                    if created == FALSE {
+                        create_err = Some(os::last_os_error());
+                    }
                 }
             }
         }
+
+        CloseHandle(si.hStdInput);
+        CloseHandle(si.hStdOutput);
+        CloseHandle(si.hStdError);
+
+        for create_err.each |msg| {
+            fail!(fmt!("failure in CreateProcess: %s", *msg));
+        }
+
+        // We close the thread handle because we don't care about keeping the thread id valid,
+        // and we aren't keeping the thread handle around to be able to close it later. We don't
+        // close the process handle however because we want the process id to stay valid at least
+        // until the calling code closes the process handle.
+        CloseHandle(pi.hThread);
+
+        RunProgramResult {
+            pid: pi.dwProcessId as pid_t,
+            handle: pi.hProcess as *()
+        }
+    }
+}
+
+#[cfg(windows)]
+fn zeroed_startupinfo() -> libc::types::os::arch::extra::STARTUPINFO {
+    libc::types::os::arch::extra::STARTUPINFO {
+        cb: 0,
+        lpReserved: ptr::mut_null(),
+        lpDesktop: ptr::mut_null(),
+        lpTitle: ptr::mut_null(),
+        dwX: 0,
+        dwY: 0,
+        dwXSize: 0,
+        dwYSize: 0,
+        dwXCountChars: 0,
+        dwYCountCharts: 0,
+        dwFillAttribute: 0,
+        dwFlags: 0,
+        wShowWindow: 0,
+        cbReserved2: 0,
+        lpReserved2: ptr::mut_null(),
+        hStdInput: ptr::mut_null(),
+        hStdOutput: ptr::mut_null(),
+        hStdError: ptr::mut_null()
     }
 }
 
+#[cfg(windows)]
+fn zeroed_process_information() -> libc::types::os::arch::extra::PROCESS_INFORMATION {
+    libc::types::os::arch::extra::PROCESS_INFORMATION {
+        hProcess: ptr::mut_null(),
+        hThread: ptr::mut_null(),
+        dwProcessId: 0,
+        dwThreadId: 0
+    }
+}
+
+// FIXME: this is only pub so it can be tested (see issue #4536)
+#[cfg(windows)]
+pub fn make_command_line(prog: &str, args: &[~str]) -> ~str {
+
+    let mut cmd = ~"";
+    append_arg(&mut cmd, prog);
+    for args.each |arg| {
+        cmd.push_char(' ');
+        append_arg(&mut cmd, *arg);
+    }
+    return cmd;
+
+    fn append_arg(cmd: &mut ~str, arg: &str) {
+        let quote = arg.any(|c| c == ' ' || c == '\t');
+        if quote {
+            cmd.push_char('"');
+        }
+        for uint::range(0, arg.len()) |i| {
+            append_char_at(cmd, arg, i);
+        }
+        if quote {
+            cmd.push_char('"');
+        }
+    }
+
+    fn append_char_at(cmd: &mut ~str, arg: &str, i: uint) {
+        match arg[i] as char {
+            '"' => {
+                // Escape quotes.
+                cmd.push_str("\\\"");
+            }
+            '\\' => {
+                if backslash_run_ends_in_quote(arg, i) {
+                    // Double all backslashes that are in runs before quotes.
+                    cmd.push_str("\\\\");
+                } else {
+                    // Pass other backslashes through unescaped.
+                    cmd.push_char('\\');
+                }
+            }
+            c => {
+                cmd.push_char(c);
+            }
+        }
+    }
+
+    fn backslash_run_ends_in_quote(s: &str, mut i: uint) -> bool {
+        while i < s.len() && s[i] as char == '\\' {
+            i += 1;
+        }
+        return i < s.len() && s[i] as char == '"';
+    }
+}
+
+#[cfg(unix)]
+fn spawn_process_internal(prog: &str, args: &[~str],
+                          env: &Option<~[(~str,~str)]>,
+                          dir: &Option<~str>,
+                          in_fd: c_int, out_fd: c_int, err_fd: c_int) -> RunProgramResult {
+
+    use libc::funcs::posix88::unistd::{fork, dup2, close, chdir, execvp};
+    use libc::funcs::bsd44::getdtablesize;
+
+    mod rustrt {
+        use libc::c_void;
+
+        #[abi = "cdecl"]
+        pub extern {
+            unsafe fn rust_unset_sigprocmask();
+            unsafe fn rust_set_environ(envp: *c_void);
+        }
+    }
+
+    unsafe {
+
+        let pid = fork();
+        if pid < 0 {
+            fail!(fmt!("failure in fork: %s", os::last_os_error()));
+        } else if pid > 0 {
+            return RunProgramResult {pid: pid, handle: ptr::null()};
+        }
+
+        rustrt::rust_unset_sigprocmask();
+
+        if in_fd > 0 && dup2(in_fd, 0) == -1 {
+            fail!(fmt!("failure in dup2(in_fd, 0): %s", os::last_os_error()));
+        }
+        if out_fd > 0 && dup2(out_fd, 1) == -1 {
+            fail!(fmt!("failure in dup2(out_fd, 1): %s", os::last_os_error()));
+        }
+        if err_fd > 0 && dup2(err_fd, 2) == -1 {
+            fail!(fmt!("failure in dup3(err_fd, 2): %s", os::last_os_error()));
+        }
+        // close all other fds
+        for int::range_rev(getdtablesize() as int - 1, 2) |fd| {
+            close(fd as c_int);
+        }
+
+        for dir.each |dir| {
+            do str::as_c_str(*dir) |dirp| {
+                if chdir(dirp) == -1 {
+                    fail!(fmt!("failure in chdir: %s", os::last_os_error()));
+                }
+            }
+        }
+
+        do with_envp(env) |envp| {
+            if !envp.is_null() {
+                rustrt::rust_set_environ(envp);
+            }
+            do with_argv(prog, args) |argv| {
+                execvp(*argv, argv);
+                // execvp only returns if an error occurred
+                fail!(fmt!("failure in execvp: %s", os::last_os_error()));
+            }
+        }
+    }
+}
+
+#[cfg(unix)]
 fn with_argv<T>(prog: &str, args: &[~str],
                 cb: &fn(**libc::c_char) -> T) -> T {
     let mut argptrs = str::as_c_str(prog, |b| ~[b]);
@@ -246,7 +462,7 @@ fn with_envp<T>(env: &Option<~[(~str,~str)]>,
 
 #[cfg(windows)]
 fn with_envp<T>(env: &Option<~[(~str,~str)]>,
-                cb: &fn(*c_void) -> T) -> T {
+                cb: &fn(*mut c_void) -> T) -> T {
     // On win32 we pass an "environment block" which is not a char**, but
     // rather a concatenation of null-terminated k=v\0 sequences, with a final
     // \0 to terminate.
@@ -264,11 +480,12 @@ fn with_envp<T>(env: &Option<~[(~str,~str)]>,
             blk += ~[0_u8];
             vec::as_imm_buf(blk, |p, _len| cb(::cast::transmute(p)))
           }
-          _ => cb(ptr::null())
+          _ => cb(ptr::mut_null())
         }
     }
 }
 
+#[cfg(windows)]
 fn with_dirp<T>(d: &Option<~str>,
                 cb: &fn(*libc::c_char) -> T) -> T {
     match *d {
@@ -312,8 +529,6 @@ priv fn free_handle(_handle: *()) {
 pub fn run_program(prog: &str, args: &[~str]) -> int {
     let res = spawn_process_internal(prog, args, &None, &None,
                                      0i32, 0i32, 0i32);
-    if res.pid == -1 as pid_t { fail!(); }
-
     let code = waitpid(res.pid);
     free_handle(res.handle);
     return code;
@@ -345,7 +560,6 @@ pub fn start_program(prog: &str, args: &[~str]) -> Program {
                                pipe_err.out);
 
     unsafe {
-        if res.pid == -1 as pid_t { fail!(); }
         libc::close(pipe_input.in);
         libc::close(pipe_output.out);
         libc::close(pipe_err.out);
@@ -398,13 +612,6 @@ pub fn program_output(prog: &str, args: &[~str]) -> ProgramOutput {
     os::close(pipe_in.in);
     os::close(pipe_out.out);
     os::close(pipe_err.out);
-    if res.pid == -1i32 {
-        os::close(pipe_in.out);
-        os::close(pipe_out.in);
-        os::close(pipe_err.in);
-        fail!();
-    }
-
     os::close(pipe_in.out);
 
     // Spawn two entire schedulers to read both stdout and sterr
@@ -485,11 +692,46 @@ pub fn waitpid(pid: pid_t) -> int {
 
     #[cfg(windows)]
     fn waitpid_os(pid: pid_t) -> int {
-        let status = unsafe { rustrt::rust_process_wait(pid) };
-        if status < 0 {
-            fail!(fmt!("failure in rust_process_wait: %s", os::last_os_error()));
+
+        use libc::types::os::arch::extra::DWORD;
+        use libc::consts::os::extra::{
+            SYNCHRONIZE,
+            PROCESS_QUERY_INFORMATION,
+            FALSE,
+            STILL_ACTIVE,
+            INFINITE,
+            WAIT_FAILED
+        };
+        use libc::funcs::extra::kernel32::{
+            OpenProcess,
+            GetExitCodeProcess,
+            CloseHandle,
+            WaitForSingleObject
+        };
+
+        unsafe {
+
+            let proc = OpenProcess(SYNCHRONIZE | PROCESS_QUERY_INFORMATION, FALSE, pid as DWORD);
+            if proc.is_null() {
+                fail!(fmt!("failure in OpenProcess: %s", os::last_os_error()));
+            }
+
+            loop {
+                let mut status = 0;
+                if GetExitCodeProcess(proc, &mut status) == FALSE {
+                    CloseHandle(proc);
+                    fail!(fmt!("failure in GetExitCodeProcess: %s", os::last_os_error()));
+                }
+                if status != STILL_ACTIVE {
+                    CloseHandle(proc);
+                    return status as int;
+                }
+                if WaitForSingleObject(proc, INFINITE) == WAIT_FAILED {
+                    CloseHandle(proc);
+                    fail!(fmt!("failure in WaitForSingleObject: %s", os::last_os_error()));
+                }
+            }
         }
-        return status as int;
     }
 
     #[cfg(unix)]
@@ -539,10 +781,30 @@ mod tests {
     use libc;
     use option::None;
     use os;
-    use path::Path;
     use run::{readclose, writeclose};
     use run;
 
+    #[test]
+    #[cfg(windows)]
+    fn test_make_command_line() {
+        assert_eq!(
+            run::make_command_line("prog", [~"aaa", ~"bbb", ~"ccc"]),
+            ~"prog aaa bbb ccc"
+        );
+        assert_eq!(
+            run::make_command_line("C:\\Program Files\\blah\\blah.exe", [~"aaa"]),
+            ~"\"C:\\Program Files\\blah\\blah.exe\" aaa"
+        );
+        assert_eq!(
+            run::make_command_line("C:\\Program Files\\test", [~"aa\"bb"]),
+            ~"\"C:\\Program Files\\test\" aa\\\"bb"
+        );
+        assert_eq!(
+            run::make_command_line("echo", [~"a b c"]),
+            ~"echo \"a b c\""
+        );
+    }
+
     // Regression test for memory leaks
     #[test]
     fn test_leaks() {
@@ -607,43 +869,60 @@ mod tests {
         p.destroy(); // ...and nor should this (and nor should the destructor)
     }
 
-    #[cfg(unix)] // there is no way to sleep on windows from inside libcore...
     fn test_destroy_actually_kills(force: bool) {
-        let path = Path(fmt!("test/core-run-test-destroy-actually-kills-%?.tmp", force));
 
-        os::remove_file(&path);
+        #[cfg(unix)]
+        static BLOCK_COMMAND: &'static str = "cat";
 
-        let cmd = fmt!("sleep 5 && echo MurderDeathKill > %s", path.to_str());
-        let mut p = run::start_program("sh", [~"-c", cmd]);
+        #[cfg(windows)]
+        static BLOCK_COMMAND: &'static str = "cmd";
 
-        p.destroy(); // destroy the program before it has a chance to echo its message
+        #[cfg(unix)]
+        fn process_exists(pid: libc::pid_t) -> bool {
+            run::program_output("ps", [~"-p", pid.to_str()]).out.contains(pid.to_str())
+        }
 
-        unsafe {
-            // wait to ensure the program is really destroyed and not just waiting itself
-            libc::sleep(10);
+        #[cfg(windows)]
+        fn process_exists(pid: libc::pid_t) -> bool {
+
+            use libc::types::os::arch::extra::DWORD;
+            use libc::funcs::extra::kernel32::{CloseHandle, GetExitCodeProcess, OpenProcess};
+            use libc::consts::os::extra::{FALSE, PROCESS_QUERY_INFORMATION, STILL_ACTIVE };
+
+            unsafe {
+                let proc = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid as DWORD);
+                if proc.is_null() {
+                    return false;
+                }
+                // proc will be non-null if the process is alive, or if it died recently
+                let mut status = 0;
+                GetExitCodeProcess(proc, &mut status);
+                CloseHandle(proc);
+                return status == STILL_ACTIVE;
+            }
         }
 
-        // the program should not have had chance to echo its message
-        assert!(!path.exists());
+        // this program will stay alive indefinitely trying to read from stdin
+        let mut p = run::start_program(BLOCK_COMMAND, []);
+
+        assert!(process_exists(p.get_id()));
+
+        if force {
+            p.force_destroy();
+        } else {
+            p.destroy();
+        }
+
+        assert!(!process_exists(p.get_id()));
     }
 
     #[test]
-    #[cfg(unix)]
     fn test_unforced_destroy_actually_kills() {
         test_destroy_actually_kills(false);
     }
 
     #[test]
-    #[cfg(unix)]
     fn test_forced_destroy_actually_kills() {
         test_destroy_actually_kills(true);
     }
 }
-
-// Local Variables:
-// mode: rust
-// fill-column: 78;
-// indent-tabs-mode: nil
-// c-basic-offset: 4
-// buffer-file-coding-system: utf-8-unix
-// End:
diff --git a/src/libcore/stackwalk.rs b/src/libcore/stackwalk.rs
index ebf36e4e09a..987d4064ab9 100644
--- a/src/libcore/stackwalk.rs
+++ b/src/libcore/stackwalk.rs
@@ -93,10 +93,6 @@ pub mod rustrt {
 pub mod rusti {
     #[abi = "rust-intrinsic"]
     pub extern "rust-intrinsic" {
-        #[cfg(stage0)]
-        pub fn frame_address(f: &once fn(x: *u8));
-        #[cfg(not(stage0))]
         pub fn frame_address(+f: &once fn(x: *u8));
     }
 }
-
diff --git a/src/libcore/str.rs b/src/libcore/str.rs
index f4430ca669f..a41c99b266b 100644
--- a/src/libcore/str.rs
+++ b/src/libcore/str.rs
@@ -77,6 +77,7 @@ pub fn from_bytes_slice<'a>(vector: &'a [u8]) -> &'a str {
 }
 
 /// Copy a slice into a new unique str
+#[inline(always)]
 pub fn from_slice(s: &str) -> ~str {
     unsafe { raw::slice_bytes_owned(s, 0, len(s)) }
 }
@@ -240,38 +241,132 @@ pub fn append(lhs: ~str, rhs: &str) -> ~str {
 
 /// Concatenate a vector of strings
 pub fn concat(v: &[~str]) -> ~str {
-    let mut s: ~str = ~"";
-    for vec::each(v) |ss| {
-        push_str(&mut s, *ss);
+    if v.is_empty() { return ~""; }
+
+    let mut len = 0;
+    for v.each |ss| {
+        len += ss.len();
+    }
+    let mut s = ~"";
+
+    reserve(&mut s, len);
+
+    unsafe {
+        do as_buf(s) |buf, _len| {
+            let mut buf = ::cast::transmute_mut_unsafe(buf);
+            for v.each |ss| {
+                do as_buf(*ss) |ssbuf, sslen| {
+                    let sslen = sslen - 1;
+                    ptr::copy_memory(buf, ssbuf, sslen);
+                    buf = buf.offset(sslen);
+                }
+            }
+        }
+        raw::set_len(&mut s, len);
     }
     s
 }
 
 /// Concatenate a vector of strings, placing a given separator between each
 pub fn connect(v: &[~str], sep: &str) -> ~str {
+    if v.is_empty() { return ~""; }
+
+    // concat is faster
+    if sep.is_empty() { return concat(v); }
+
+    // this is wrong without the guarantee that v is non-empty
+    let mut len = sep.len() * (v.len() - 1);
+    for v.each |ss| {
+        len += ss.len();
+    }
     let mut s = ~"", first = true;
-    for vec::each(v) |ss| {
-        if first { first = false; } else { push_str(&mut s, sep); }
-        push_str(&mut s, *ss);
+
+    reserve(&mut s, len);
+
+    unsafe {
+        do as_buf(s) |buf, _len| {
+            do as_buf(sep) |sepbuf, seplen| {
+                let seplen = seplen - 1;
+                let mut buf = ::cast::transmute_mut_unsafe(buf);
+                for v.each |ss| {
+                    do as_buf(*ss) |ssbuf, sslen| {
+                        let sslen = sslen - 1;
+                        if first {
+                            first = false;
+                        } else {
+                            ptr::copy_memory(buf, sepbuf, seplen);
+                            buf = buf.offset(seplen);
+                        }
+                        ptr::copy_memory(buf, ssbuf, sslen);
+                        buf = buf.offset(sslen);
+                    }
+                }
+            }
+        }
+        raw::set_len(&mut s, len);
     }
     s
 }
 
 /// Concatenate a vector of strings, placing a given separator between each
 pub fn connect_slices(v: &[&str], sep: &str) -> ~str {
+    if v.is_empty() { return ~""; }
+
+    // this is wrong without the guarantee that v is non-empty
+    let mut len = sep.len() * (v.len() - 1);
+    for v.each |ss| {
+        len += ss.len();
+    }
     let mut s = ~"", first = true;
-    for vec::each(v) |ss| {
-        if first { first = false; } else { push_str(&mut s, sep); }
-        push_str(&mut s, *ss);
+
+    reserve(&mut s, len);
+
+    unsafe {
+        do as_buf(s) |buf, _len| {
+            do as_buf(sep) |sepbuf, seplen| {
+                let seplen = seplen - 1;
+                let mut buf = ::cast::transmute_mut_unsafe(buf);
+                for vec::each(v) |ss| {
+                    do as_buf(*ss) |ssbuf, sslen| {
+                        let sslen = sslen - 1;
+                        if first {
+                            first = false;
+                        } else if seplen > 0 {
+                            ptr::copy_memory(buf, sepbuf, seplen);
+                            buf = buf.offset(seplen);
+                        }
+                        ptr::copy_memory(buf, ssbuf, sslen);
+                        buf = buf.offset(sslen);
+                    }
+                }
+            }
+        }
+        raw::set_len(&mut s, len);
     }
     s
 }
 
 /// Given a string, make a new string with repeated copies of it
 pub fn repeat(ss: &str, nn: uint) -> ~str {
-    let mut acc = ~"";
-    for nn.times { acc += ss; }
-    acc
+    do as_buf(ss) |buf, len| {
+        let mut ret = ~"";
+        // ignore the NULL terminator
+        let len = len - 1;
+        reserve(&mut ret, nn * len);
+
+        unsafe {
+            do as_buf(ret) |rbuf, _len| {
+                let mut rbuf = ::cast::transmute_mut_unsafe(rbuf);
+
+                for nn.times {
+                    ptr::copy_memory(rbuf, buf, len);
+                    rbuf = rbuf.offset(len);
+                }
+            }
+            raw::set_len(&mut ret, nn * len);
+        }
+        ret
+    }
 }
 
 /*
@@ -820,6 +915,7 @@ Section: Comparing strings
 /// Bytewise slice equality
 #[cfg(notest)]
 #[lang="str_eq"]
+#[inline]
 pub fn eq_slice(a: &str, b: &str) -> bool {
     do as_buf(a) |ap, alen| {
         do as_buf(b) |bp, blen| {
@@ -836,6 +932,7 @@ pub fn eq_slice(a: &str, b: &str) -> bool {
 }
 
 #[cfg(test)]
+#[inline]
 pub fn eq_slice(a: &str, b: &str) -> bool {
     do as_buf(a) |ap, alen| {
         do as_buf(b) |bp, blen| {
@@ -854,15 +951,18 @@ pub fn eq_slice(a: &str, b: &str) -> bool {
 /// Bytewise string equality
 #[cfg(notest)]
 #[lang="uniq_str_eq"]
+#[inline]
 pub fn eq(a: &~str, b: &~str) -> bool {
     eq_slice(*a, *b)
 }
 
 #[cfg(test)]
+#[inline]
 pub fn eq(a: &~str, b: &~str) -> bool {
     eq_slice(*a, *b)
 }
 
+#[inline]
 fn cmp(a: &str, b: &str) -> Ordering {
     let low = uint::min(a.len(), b.len());
 
@@ -879,20 +979,24 @@ fn cmp(a: &str, b: &str) -> Ordering {
 
 #[cfg(notest)]
 impl<'self> TotalOrd for &'self str {
+    #[inline]
     fn cmp(&self, other: & &'self str) -> Ordering { cmp(*self, *other) }
 }
 
 #[cfg(notest)]
 impl TotalOrd for ~str {
+    #[inline]
     fn cmp(&self, other: &~str) -> Ordering { cmp(*self, *other) }
 }
 
 #[cfg(notest)]
 impl TotalOrd for @str {
+    #[inline]
     fn cmp(&self, other: &@str) -> Ordering { cmp(*self, *other) }
 }
 
 /// Bytewise slice less than
+#[inline]
 fn lt(a: &str, b: &str) -> bool {
     let (a_len, b_len) = (a.len(), b.len());
     let end = uint::min(a_len, b_len);
@@ -909,16 +1013,19 @@ fn lt(a: &str, b: &str) -> bool {
 }
 
 /// Bytewise less than or equal
+#[inline]
 pub fn le(a: &str, b: &str) -> bool {
     !lt(b, a)
 }
 
 /// Bytewise greater than or equal
+#[inline]
 fn ge(a: &str, b: &str) -> bool {
     !lt(a, b)
 }
 
 /// Bytewise greater than
+#[inline]
 fn gt(a: &str, b: &str) -> bool {
     !le(a, b)
 }
@@ -1595,6 +1702,7 @@ Section: String properties
 */
 
 /// Returns true if the string has length 0
+#[inline(always)]
 pub fn is_empty(s: &str) -> bool { len(s) == 0u }
 
 /**
@@ -1616,11 +1724,13 @@ fn is_alphanumeric(s: &str) -> bool {
 }
 
 /// Returns the string length/size in bytes not counting the null terminator
+#[inline(always)]
 pub fn len(s: &str) -> uint {
     do as_buf(s) |_p, n| { n - 1u }
 }
 
 /// Returns the number of characters that a string holds
+#[inline(always)]
 pub fn char_len(s: &str) -> uint { count_chars(s, 0u, len(s)) }
 
 /*
@@ -1752,7 +1862,8 @@ pub fn count_chars(s: &str, start: uint, end: uint) -> uint {
     return len;
 }
 
-/// Counts the number of bytes taken by the `n` in `s` starting from `start`.
+/// Counts the number of bytes taken by the first `n` chars in `s`
+/// starting from `start`.
 pub fn count_bytes<'b>(s: &'b str, start: uint, n: uint) -> uint {
     assert!(is_char_boundary(s, start));
     let mut end = start, cnt = n;
@@ -1988,6 +2099,7 @@ static tag_six_b: uint = 252u;
  * let i = str::as_bytes("Hello World") { |bytes| vec::len(bytes) };
  * ~~~
  */
+#[inline]
 pub fn as_bytes<T>(s: &const ~str, f: &fn(&~[u8]) -> T) -> T {
     unsafe {
         let v: *~[u8] = cast::transmute(copy s);
@@ -2023,6 +2135,7 @@ pub fn as_bytes_slice<'a>(s: &'a str) -> &'a [u8] {
  * let s = str::as_c_str("PATH", { |path| libc::getenv(path) });
  * ~~~
  */
+#[inline]
 pub fn as_c_str<T>(s: &str, f: &fn(*libc::c_char) -> T) -> T {
     do as_buf(s) |buf, len| {
         // NB: len includes the trailing null.
@@ -2099,6 +2212,7 @@ pub fn subslice_offset(outer: &str, inner: &str) -> uint {
  * * s - A string
  * * n - The number of bytes to reserve space for
  */
+#[inline(always)]
 pub fn reserve(s: &mut ~str, n: uint) {
     unsafe {
         let v: *mut ~[u8] = cast::transmute(s);
@@ -2126,6 +2240,7 @@ pub fn reserve(s: &mut ~str, n: uint) {
  * * s - A string
  * * n - The number of bytes to reserve space for
  */
+#[inline(always)]
 pub fn reserve_at_least(s: &mut ~str, n: uint) {
     reserve(s, uint::next_power_of_two(n + 1u) - 1u)
 }
@@ -2314,6 +2429,7 @@ pub mod raw {
     }
 
     /// Sets the length of the string and adds the null terminator
+    #[inline]
     pub unsafe fn set_len(v: &mut ~str, new_len: uint) {
         let v: **mut vec::raw::VecRepr = cast::transmute(v);
         let repr: *mut vec::raw::VecRepr = *v;
@@ -2483,7 +2599,7 @@ impl<'self> StrSlice<'self> for &'self str {
     #[inline]
     fn is_alphanumeric(&self) -> bool { is_alphanumeric(*self) }
     /// Returns the size in bytes not counting the null terminator
-    #[inline]
+    #[inline(always)]
     fn len(&self) -> uint { len(*self) }
     /// Returns the number of characters that a string holds
     #[inline]
@@ -2593,10 +2709,11 @@ pub trait OwnedStr {
 }
 
 impl OwnedStr for ~str {
+    #[inline]
     fn push_str(&mut self, v: &str) {
         push_str(self, v);
     }
-
+    #[inline]
     fn push_char(&mut self, c: char) {
         push_char(self, c);
     }
diff --git a/src/libcore/str/ascii.rs b/src/libcore/str/ascii.rs
index 9180c995ca2..73f556518fa 100644
--- a/src/libcore/str/ascii.rs
+++ b/src/libcore/str/ascii.rs
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+//! Operations on ASCII strings and characters.
+
 use to_str::{ToStr,ToStrConsume};
 use str;
 use cast;
diff --git a/src/libcore/sys.rs b/src/libcore/sys.rs
index 8cad0a22886..4eca7ebbb37 100644
--- a/src/libcore/sys.rs
+++ b/src/libcore/sys.rs
@@ -10,6 +10,7 @@
 
 //! Misc low level stuff
 
+use option::{Some, None};
 use cast;
 use cmp::{Eq, Ord};
 use gc;
@@ -199,36 +200,33 @@ impl FailWithCause for &'static str {
     }
 }
 
-// NOTE: remove function after snapshot
-#[cfg(stage0)]
-pub fn begin_unwind(msg: ~str, file: ~str, line: uint) -> ! {
-    do str::as_buf(msg) |msg_buf, _msg_len| {
-        do str::as_buf(file) |file_buf, _file_len| {
+// FIXME #4427: Temporary until rt::rt_fail_ goes away
+pub fn begin_unwind_(msg: *c_char, file: *c_char, line: size_t) -> ! {
+    use rt::{context, OldTaskContext};
+    use rt::local_services::unsafe_borrow_local_services;
+
+    match context() {
+        OldTaskContext => {
             unsafe {
-                let msg_buf = cast::transmute(msg_buf);
-                let file_buf = cast::transmute(file_buf);
-                begin_unwind_(msg_buf, file_buf, line as libc::size_t)
+                gc::cleanup_stack_for_failure();
+                rustrt::rust_upcall_fail(msg, file, line);
+                cast::transmute(())
+            }
+        }
+        _ => {
+            // XXX: Need to print the failure message
+            gc::cleanup_stack_for_failure();
+            unsafe {
+                let local_services = unsafe_borrow_local_services();
+                match local_services.unwinder {
+                    Some(ref mut unwinder) => unwinder.begin_unwind(),
+                    None => abort!("failure without unwinder. aborting process")
+                }
             }
         }
     }
 }
 
-// FIXME #4427: Temporary until rt::rt_fail_ goes away
-pub fn begin_unwind_(msg: *c_char, file: *c_char, line: size_t) -> ! {
-    unsafe {
-        gc::cleanup_stack_for_failure();
-        rustrt::rust_upcall_fail(msg, file, line);
-        cast::transmute(())
-    }
-}
-
-// NOTE: remove function after snapshot
-#[cfg(stage0)]
-pub fn fail_assert(msg: &str, file: &str, line: uint) -> ! {
-    let (msg, file) = (msg.to_owned(), file.to_owned());
-    begin_unwind(~"assertion failed: " + msg, file, line)
-}
-
 #[cfg(test)]
 mod tests {
     use cast;
@@ -343,11 +341,3 @@ mod tests {
     #[should_fail]
     fn fail_owned() { FailWithCause::fail_with(~"cause", file!(), line!())  }
 }
-
-// Local Variables:
-// mode: rust;
-// fill-column: 78;
-// indent-tabs-mode: nil
-// c-basic-offset: 4
-// buffer-file-coding-system: utf-8-unix
-// End:
diff --git a/src/libcore/task/local_data.rs b/src/libcore/task/local_data.rs
index 6050aca6dc1..dff5908c047 100644
--- a/src/libcore/task/local_data.rs
+++ b/src/libcore/task/local_data.rs
@@ -27,8 +27,7 @@ magic.
 */
 
 use prelude::*;
-use task::local_data_priv::{local_get, local_pop, local_modify, local_set};
-use task::rt;
+use task::local_data_priv::{local_get, local_pop, local_modify, local_set, Handle};
 
 /**
  * Indexes a task-local data slot. The function's code pointer is used for
@@ -53,7 +52,7 @@ pub type LocalDataKey<'self,T> = &'self fn(v: @T);
 pub unsafe fn local_data_pop<T:Durable>(
     key: LocalDataKey<T>) -> Option<@T> {
 
-    local_pop(rt::rust_get_task(), key)
+    local_pop(Handle::new(), key)
 }
 /**
  * Retrieve a task-local data value. It will also be kept alive in the
@@ -62,7 +61,7 @@ pub unsafe fn local_data_pop<T:Durable>(
 pub unsafe fn local_data_get<T:Durable>(
     key: LocalDataKey<T>) -> Option<@T> {
 
-    local_get(rt::rust_get_task(), key)
+    local_get(Handle::new(), key)
 }
 /**
  * Store a value in task-local data. If this key already has a value,
@@ -71,7 +70,7 @@ pub unsafe fn local_data_get<T:Durable>(
 pub unsafe fn local_data_set<T:Durable>(
     key: LocalDataKey<T>, data: @T) {
 
-    local_set(rt::rust_get_task(), key, data)
+    local_set(Handle::new(), key, data)
 }
 /**
  * Modify a task-local data value. If the function returns 'None', the
@@ -81,7 +80,7 @@ pub unsafe fn local_data_modify<T:Durable>(
     key: LocalDataKey<T>,
     modify_fn: &fn(Option<@T>) -> Option<@T>) {
 
-    local_modify(rt::rust_get_task(), key, modify_fn)
+    local_modify(Handle::new(), key, modify_fn)
 }
 
 #[test]
diff --git a/src/libcore/task/local_data_priv.rs b/src/libcore/task/local_data_priv.rs
index 67bc3adeb41..10a40887e57 100644
--- a/src/libcore/task/local_data_priv.rs
+++ b/src/libcore/task/local_data_priv.rs
@@ -18,6 +18,30 @@ use task::rt;
 use task::local_data::LocalDataKey;
 
 use super::rt::rust_task;
+use rt::local_services::LocalStorage;
+
+pub enum Handle {
+    OldHandle(*rust_task),
+    NewHandle(*mut LocalStorage)
+}
+
+impl Handle {
+    pub fn new() -> Handle {
+        use rt::{context, OldTaskContext};
+        use rt::local_services::unsafe_borrow_local_services;
+        unsafe {
+            match context() {
+                OldTaskContext => {
+                    OldHandle(rt::rust_get_task())
+                }
+                _ => {
+                    let local_services = unsafe_borrow_local_services();
+                    NewHandle(&mut local_services.storage)
+                }
+            }
+        }
+    }
+}
 
 pub trait LocalData { }
 impl<T:Durable> LocalData for @T { }
@@ -25,8 +49,8 @@ impl<T:Durable> LocalData for @T { }
 impl Eq for @LocalData {
     fn eq(&self, other: &@LocalData) -> bool {
         unsafe {
-            let ptr_a: (uint, uint) = cast::transmute(*self);
-            let ptr_b: (uint, uint) = cast::transmute(*other);
+            let ptr_a: &(uint, uint) = cast::transmute(self);
+            let ptr_b: &(uint, uint) = cast::transmute(other);
             return ptr_a == ptr_b;
         }
     }
@@ -39,7 +63,7 @@ type TaskLocalElement = (*libc::c_void, *libc::c_void, @LocalData);
 // Has to be a pointer at outermost layer; the foreign call returns void *.
 type TaskLocalMap = @mut ~[Option<TaskLocalElement>];
 
-extern fn cleanup_task_local_map(map_ptr: *libc::c_void) {
+fn cleanup_task_local_map(map_ptr: *libc::c_void) {
     unsafe {
         assert!(!map_ptr.is_null());
         // Get and keep the single reference that was created at the
@@ -50,8 +74,19 @@ extern fn cleanup_task_local_map(map_ptr: *libc::c_void) {
 }
 
 // Gets the map from the runtime. Lazily initialises if not done so already.
+unsafe fn get_local_map(handle: Handle) -> TaskLocalMap {
+    match handle {
+        OldHandle(task) => get_task_local_map(task),
+        NewHandle(local_storage) => get_newsched_local_map(local_storage)
+    }
+}
+
 unsafe fn get_task_local_map(task: *rust_task) -> TaskLocalMap {
 
+    extern fn cleanup_task_local_map_extern_cb(map_ptr: *libc::c_void) {
+        cleanup_task_local_map(map_ptr);
+    }
+
     // Relies on the runtime initialising the pointer to null.
     // Note: The map's box lives in TLS invisibly referenced once. Each time
     // we retrieve it for get/set, we make another reference, which get/set
@@ -60,7 +95,7 @@ unsafe fn get_task_local_map(task: *rust_task) -> TaskLocalMap {
     if map_ptr.is_null() {
         let map: TaskLocalMap = @mut ~[];
         rt::rust_set_task_local_data(task, cast::transmute(map));
-        rt::rust_task_local_data_atexit(task, cleanup_task_local_map);
+        rt::rust_task_local_data_atexit(task, cleanup_task_local_map_extern_cb);
         // Also need to reference it an extra time to keep it for now.
         let nonmut = cast::transmute::<TaskLocalMap,
                                        @~[Option<TaskLocalElement>]>(map);
@@ -75,6 +110,27 @@ unsafe fn get_task_local_map(task: *rust_task) -> TaskLocalMap {
     }
 }
 
+unsafe fn get_newsched_local_map(local: *mut LocalStorage) -> TaskLocalMap {
+    match &mut *local {
+        &LocalStorage(map_ptr, Some(_)) => {
+            assert!(map_ptr.is_not_null());
+            let map = cast::transmute(map_ptr);
+            let nonmut = cast::transmute::<TaskLocalMap,
+            @~[Option<TaskLocalElement>]>(map);
+            cast::bump_box_refcount(nonmut);
+            return map;
+        }
+        &LocalStorage(ref mut map_ptr, ref mut at_exit) => {
+            assert!((*map_ptr).is_null());
+            let map: TaskLocalMap = @mut ~[];
+            *map_ptr = cast::transmute(map);
+            let at_exit_fn: ~fn(*libc::c_void) = |p|cleanup_task_local_map(p);
+            *at_exit = Some(at_exit_fn);
+            return map;
+        }
+    }
+}
+
 unsafe fn key_to_key_value<T:Durable>(key: LocalDataKey<T>) -> *libc::c_void {
     // Keys are closures, which are (fnptr,envptr) pairs. Use fnptr.
     // Use reintepret_cast -- transmute would leak (forget) the closure.
@@ -102,10 +158,10 @@ unsafe fn local_data_lookup<T:Durable>(
 }
 
 unsafe fn local_get_helper<T:Durable>(
-    task: *rust_task, key: LocalDataKey<T>,
+    handle: Handle, key: LocalDataKey<T>,
     do_pop: bool) -> Option<@T> {
 
-    let map = get_task_local_map(task);
+    let map = get_local_map(handle);
     // Interpreturn our findings from the map
     do local_data_lookup(map, key).map |result| {
         // A reference count magically appears on 'data' out of thin air. It
@@ -124,23 +180,23 @@ unsafe fn local_get_helper<T:Durable>(
 
 
 pub unsafe fn local_pop<T:Durable>(
-    task: *rust_task,
+    handle: Handle,
     key: LocalDataKey<T>) -> Option<@T> {
 
-    local_get_helper(task, key, true)
+    local_get_helper(handle, key, true)
 }
 
 pub unsafe fn local_get<T:Durable>(
-    task: *rust_task,
+    handle: Handle,
     key: LocalDataKey<T>) -> Option<@T> {
 
-    local_get_helper(task, key, false)
+    local_get_helper(handle, key, false)
 }
 
 pub unsafe fn local_set<T:Durable>(
-    task: *rust_task, key: LocalDataKey<T>, data: @T) {
+    handle: Handle, key: LocalDataKey<T>, data: @T) {
 
-    let map = get_task_local_map(task);
+    let map = get_local_map(handle);
     // Store key+data as *voids. Data is invisibly referenced once; key isn't.
     let keyval = key_to_key_value(key);
     // We keep the data in two forms: one as an unsafe pointer, so we can get
@@ -148,7 +204,7 @@ pub unsafe fn local_set<T:Durable>(
     // own on it can be dropped when the box is destroyed. The unsafe pointer
     // does not have a reference associated with it, so it may become invalid
     // when the box is destroyed.
-    let data_ptr = cast::transmute(data);
+    let data_ptr = *cast::transmute::<&@T, &*libc::c_void>(&data);
     let data_box = @data as @LocalData;
     // Construct new entry to store in the map.
     let new_entry = Some((keyval, data_ptr, data_box));
@@ -170,12 +226,12 @@ pub unsafe fn local_set<T:Durable>(
 }
 
 pub unsafe fn local_modify<T:Durable>(
-    task: *rust_task, key: LocalDataKey<T>,
+    handle: Handle, key: LocalDataKey<T>,
     modify_fn: &fn(Option<@T>) -> Option<@T>) {
 
     // Could be more efficient by doing the lookup work, but this is easy.
-    let newdata = modify_fn(local_pop(task, key));
+    let newdata = modify_fn(local_pop(handle, key));
     if newdata.is_some() {
-        local_set(task, key, newdata.unwrap());
+        local_set(handle, key, newdata.unwrap());
     }
 }
diff --git a/src/libcore/task/mod.rs b/src/libcore/task/mod.rs
index 96429932b18..fd695c16ea7 100644
--- a/src/libcore/task/mod.rs
+++ b/src/libcore/task/mod.rs
@@ -39,9 +39,10 @@ use result::Result;
 use comm::{stream, Chan, GenericChan, GenericPort, Port};
 use prelude::*;
 use result;
-use task::rt::{task_id, sched_id, rust_task};
+use task::rt::{task_id, sched_id};
 use util;
 use util::replace;
+use unstable::finally::Finally;
 
 #[cfg(test)] use comm::SharedChan;
 
@@ -558,8 +559,31 @@ pub fn yield() {
 pub fn failing() -> bool {
     //! True if the running task has failed
 
-    unsafe {
-        rt::rust_task_is_unwinding(rt::rust_get_task())
+    use rt::{context, OldTaskContext};
+    use rt::local_services::borrow_local_services;
+
+    match context() {
+        OldTaskContext => {
+            unsafe {
+                rt::rust_task_is_unwinding(rt::rust_get_task())
+            }
+        }
+        _ => {
+            let mut unwinding = false;
+            do borrow_local_services |local| {
+                unwinding = match local.unwinder {
+                    Some(unwinder) => {
+                        unwinder.unwinding
+                    }
+                    None => {
+                        // Because there is no unwinder we can't be unwinding.
+                        // (The process will abort on failure)
+                        false
+                    }
+                }
+            }
+            return unwinding;
+        }
     }
 }
 
@@ -591,48 +615,24 @@ pub fn get_scheduler() -> Scheduler {
  * ~~~
  */
 pub unsafe fn unkillable<U>(f: &fn() -> U) -> U {
-    struct AllowFailure {
-        t: *rust_task,
-        drop {
-            unsafe {
-                rt::rust_task_allow_kill(self.t);
-            }
-        }
-    }
-
-    fn AllowFailure(t: *rust_task) -> AllowFailure{
-        AllowFailure {
-            t: t
-        }
-    }
-
     let t = rt::rust_get_task();
-    let _allow_failure = AllowFailure(t);
-    rt::rust_task_inhibit_kill(t);
-    f()
+    do (|| {
+        rt::rust_task_inhibit_kill(t);
+        f()
+    }).finally {
+        rt::rust_task_allow_kill(t);
+    }
 }
 
 /// The inverse of unkillable. Only ever to be used nested in unkillable().
 pub unsafe fn rekillable<U>(f: &fn() -> U) -> U {
-    struct DisallowFailure {
-        t: *rust_task,
-        drop {
-            unsafe {
-                rt::rust_task_inhibit_kill(self.t);
-            }
-        }
-    }
-
-    fn DisallowFailure(t: *rust_task) -> DisallowFailure {
-        DisallowFailure {
-            t: t
-        }
-    }
-
     let t = rt::rust_get_task();
-    let _allow_failure = DisallowFailure(t);
-    rt::rust_task_allow_kill(t);
-    f()
+    do (|| {
+        rt::rust_task_allow_kill(t);
+        f()
+    }).finally {
+        rt::rust_task_inhibit_kill(t);
+    }
 }
 
 /**
@@ -640,27 +640,15 @@ pub unsafe fn rekillable<U>(f: &fn() -> U) -> U {
  * For use with exclusive ARCs, which use pthread mutexes directly.
  */
 pub unsafe fn atomically<U>(f: &fn() -> U) -> U {
-    struct DeferInterrupts {
-        t: *rust_task,
-        drop {
-            unsafe {
-                rt::rust_task_allow_yield(self.t);
-                rt::rust_task_allow_kill(self.t);
-            }
-        }
-    }
-
-    fn DeferInterrupts(t: *rust_task) -> DeferInterrupts {
-        DeferInterrupts {
-            t: t
-        }
-    }
-
     let t = rt::rust_get_task();
-    let _interrupts = DeferInterrupts(t);
-    rt::rust_task_inhibit_kill(t);
-    rt::rust_task_inhibit_yield(t);
-    f()
+    do (|| {
+        rt::rust_task_inhibit_kill(t);
+        rt::rust_task_inhibit_yield(t);
+        f()
+    }).finally {
+        rt::rust_task_allow_yield(t);
+        rt::rust_task_allow_kill(t);
+    }
 }
 
 #[test] #[should_fail] #[ignore(cfg(windows))]
@@ -832,7 +820,7 @@ fn test_run_basic() {
     po.recv();
 }
 
-#[test]
+#[cfg(test)]
 struct Wrapper {
     mut f: Option<Chan<()>>
 }
@@ -1229,7 +1217,7 @@ fn test_spawn_thread_on_demand() {
 
 #[test]
 fn test_simple_newsched_spawn() {
-    use rt::run_in_newsched_task;
+    use rt::test::run_in_newsched_task;
 
     do run_in_newsched_task {
         spawn(||())
diff --git a/src/libcore/task/spawn.rs b/src/libcore/task/spawn.rs
index 507643ea5ec..267250b3642 100644
--- a/src/libcore/task/spawn.rs
+++ b/src/libcore/task/spawn.rs
@@ -80,7 +80,7 @@ use prelude::*;
 use unstable;
 use ptr;
 use hashmap::HashSet;
-use task::local_data_priv::{local_get, local_set};
+use task::local_data_priv::{local_get, local_set, OldHandle};
 use task::rt::rust_task;
 use task::rt;
 use task::{Failure, ManualThreads, PlatformThread, SchedOpts, SingleThreaded};
@@ -451,7 +451,7 @@ fn gen_child_taskgroup(linked: bool, supervised: bool)
         /*##################################################################*
          * Step 1. Get spawner's taskgroup info.
          *##################################################################*/
-        let spawner_group = match local_get(spawner, taskgroup_key!()) {
+        let spawner_group = match local_get(OldHandle(spawner), taskgroup_key!()) {
             None => {
                 // Main task, doing first spawn ever. Lazily initialise here.
                 let mut members = new_taskset();
@@ -463,7 +463,7 @@ fn gen_child_taskgroup(linked: bool, supervised: bool)
                 // Main task/group has no ancestors, no notifier, etc.
                 let group =
                     @TCB(spawner, tasks, AncestorList(None), true, None);
-                local_set(spawner, taskgroup_key!(), group);
+                local_set(OldHandle(spawner), taskgroup_key!(), group);
                 group
             }
             Some(group) => group
@@ -627,7 +627,7 @@ fn spawn_raw_oldsched(opts: TaskOpts, f: ~fn()) {
                 let group = @TCB(child, child_arc, ancestors,
                                  is_main, notifier);
                 unsafe {
-                    local_set(child, taskgroup_key!(), group);
+                    local_set(OldHandle(child), taskgroup_key!(), group);
                 }
 
                 // Run the child's body.
diff --git a/src/libcore/to_bytes.rs b/src/libcore/to_bytes.rs
index 63dcf0f44dc..9e4da7ab488 100644
--- a/src/libcore/to_bytes.rs
+++ b/src/libcore/to_bytes.rs
@@ -419,8 +419,7 @@ impl<A> IterBytes for *const A {
     }
 }
 
-
-trait ToBytes {
+pub trait ToBytes {
     fn to_bytes(&self, lsb0: bool) -> ~[u8];
 }
 
diff --git a/src/libcore/unicode.rs b/src/libcore/unicode.rs
index a13d66c48ee..d6e2c5eee6a 100644
--- a/src/libcore/unicode.rs
+++ b/src/libcore/unicode.rs
@@ -10,6 +10,8 @@
 
 #[doc(hidden)]; // FIXME #3538
 
+// The following code was generated by "src/etc/unicode.py"
+
 pub mod general_category {
 
     fn bsearch_range_table(c: char, r: &'static [(char,char)]) -> bool {
@@ -2640,4 +2642,3 @@ pub mod derived_property {
         bsearch_range_table(c, XID_Start_table)
     }
 }
-
diff --git a/src/libcore/unstable/exchange_alloc.rs b/src/libcore/unstable/exchange_alloc.rs
index 8ca5486d929..57ed579e88d 100644
--- a/src/libcore/unstable/exchange_alloc.rs
+++ b/src/libcore/unstable/exchange_alloc.rs
@@ -81,4 +81,3 @@ extern {
     #[rust_stack]
     fn rust_get_exchange_count_ptr() -> *mut int;
 }
-
diff --git a/src/libcore/unstable/extfmt.rs b/src/libcore/unstable/extfmt.rs
index e5d32c4bb32..258da9ff383 100644
--- a/src/libcore/unstable/extfmt.rs
+++ b/src/libcore/unstable/extfmt.rs
@@ -688,11 +688,3 @@ mod test {
         let _s = fmt!("%s", s);
     }
 }
-
-// Local Variables:
-// mode: rust;
-// fill-column: 78;
-// indent-tabs-mode: nil
-// c-basic-offset: 4
-// buffer-file-coding-system: utf-8-unix
-// End:
diff --git a/src/libcore/unstable/intrinsics.rs b/src/libcore/unstable/intrinsics.rs
index b58429a10aa..65cfc6ec1fe 100644
--- a/src/libcore/unstable/intrinsics.rs
+++ b/src/libcore/unstable/intrinsics.rs
@@ -46,10 +46,6 @@ pub extern "rust-intrinsic" {
 
     pub fn forget<T>(_: T) -> ();
 
-    // XXX: intrinsic uses legacy modes
-    #[cfg(stage0)]
-    fn reinterpret_cast<T,U>(&&src: T) -> U;
-
     pub fn needs_drop<T>() -> bool;
 
     // XXX: intrinsic uses legacy modes and has reference to TyDesc
diff --git a/src/libcore/unstable/lang.rs b/src/libcore/unstable/lang.rs
index 6b61df31fdc..deff06d46f6 100644
--- a/src/libcore/unstable/lang.rs
+++ b/src/libcore/unstable/lang.rs
@@ -18,9 +18,11 @@ use str;
 use sys;
 use unstable::exchange_alloc;
 use cast::transmute;
-use task::rt::rust_get_task;
+use rt::{context, OldTaskContext};
+use rt::local_services::borrow_local_services;
 use option::{Option, Some, None};
 use io;
+use task::rt::rust_get_task;
 
 #[allow(non_camel_case_types)]
 pub type rust_task = c_void;
@@ -249,21 +251,36 @@ pub unsafe fn exchange_free(ptr: *c_char) {
 }
 
 #[lang="malloc"]
-#[inline(always)]
 pub unsafe fn local_malloc(td: *c_char, size: uintptr_t) -> *c_char {
-    let result = rustrt::rust_upcall_malloc_noswitch(td, size);
-    debug_mem("local_malloc: ", result);
-    return result;
+    match context() {
+        OldTaskContext => {
+            return rustrt::rust_upcall_malloc_noswitch(td, size);
+        }
+        _ => {
+            let mut alloc = ::ptr::null();
+            do borrow_local_services |srv| {
+                alloc = srv.heap.alloc(td as *c_void, size as uint) as *c_char;
+            }
+            return alloc;
+        }
+    }
 }
 
 // NB: Calls to free CANNOT be allowed to fail, as throwing an exception from
 // inside a landing pad may corrupt the state of the exception handler. If a
 // problem occurs, call exit instead.
 #[lang="free"]
-#[inline(always)]
 pub unsafe fn local_free(ptr: *c_char) {
-    debug_mem("local_free: ", ptr);
-    rustrt::rust_upcall_free_noswitch(ptr);
+    match context() {
+        OldTaskContext => {
+            rustrt::rust_upcall_free_noswitch(ptr);
+        }
+        _ => {
+            do borrow_local_services |srv| {
+                srv.heap.free(ptr as *c_void);
+            }
+        }
+    }
 }
 
 #[cfg(stage0)]
@@ -444,11 +461,3 @@ pub fn start(main: *u8, argc: int, argv: **c_char,
                       crate_map: *c_void) -> c_int;
     }
 }
-
-// Local Variables:
-// mode: rust;
-// fill-column: 78;
-// indent-tabs-mode: nil
-// c-basic-offset: 4
-// buffer-file-coding-system: utf-8-unix
-// End:
diff --git a/src/libcore/unstable/weak_task.rs b/src/libcore/unstable/weak_task.rs
index 7a30bb92111..6edbdcb51b0 100644
--- a/src/libcore/unstable/weak_task.rs
+++ b/src/libcore/unstable/weak_task.rs
@@ -205,4 +205,3 @@ fn test_select_stream_and_oneshot() {
     chan.send(());
     waitport.recv();
 }
-
diff --git a/src/libcore/vec.rs b/src/libcore/vec.rs
index 4c817da0819..ced3c300a35 100644
--- a/src/libcore/vec.rs
+++ b/src/libcore/vec.rs
@@ -134,9 +134,9 @@ pub fn uniq_len<T>(v: &const ~[T]) -> uint {
 }
 
 /**
- * Creates and initializes an immutable vector.
+ * Creates and initializes an owned vector.
  *
- * Creates an immutable vector of size `n_elts` and initializes the elements
+ * Creates an owned vector of size `n_elts` and initializes the elements
  * to the value returned by the function `op`.
  */
 pub fn from_fn<T>(n_elts: uint, op: old_iter::InitOp<T>) -> ~[T] {
@@ -156,9 +156,9 @@ pub fn from_fn<T>(n_elts: uint, op: old_iter::InitOp<T>) -> ~[T] {
 }
 
 /**
- * Creates and initializes an immutable vector.
+ * Creates and initializes an owned vector.
  *
- * Creates an immutable vector of size `n_elts` and initializes the elements
+ * Creates an owned vector of size `n_elts` and initializes the elements
  * to the value `t`.
  */
 pub fn from_elem<T:Copy>(n_elts: uint, t: T) -> ~[T] {