about summary refs log tree commit diff
path: root/src/libcore/task
diff options
context:
space:
mode:
authorBrian Anderson <banderson@mozilla.com>2013-04-23 15:16:04 -0700
committerBrian Anderson <banderson@mozilla.com>2013-04-23 19:19:32 -0700
commite944c7dadeed48b199df6891603ae063233ec5a8 (patch)
treebb1fe84012278b82d45eb7c6544da42f3be17285 /src/libcore/task
parent8708e0c099400f363a5b95806847bd12d780000a (diff)
parent2a819ae465c5f375df00ead0b3f4c9009da23f25 (diff)
downloadrust-e944c7dadeed48b199df6891603ae063233ec5a8.tar.gz
rust-e944c7dadeed48b199df6891603ae063233ec5a8.zip
Merge remote-tracking branch 'brson/io'
This also reverts some changes to TLS that were leaking memory.

Conflicts:
	src/libcore/rt/uv/net.rs
	src/libcore/task/local_data_priv.rs
	src/libcore/unstable/lang.rs
Diffstat (limited to 'src/libcore/task')
-rw-r--r--src/libcore/task/local_data.rs10
-rw-r--r--src/libcore/task/local_data_priv.rs95
-rw-r--r--src/libcore/task/mod.rs29
-rw-r--r--src/libcore/task/spawn.rs8
4 files changed, 113 insertions, 29 deletions
diff --git a/src/libcore/task/local_data.rs b/src/libcore/task/local_data.rs
index 6050aca6dc1..65e68931915 100644
--- a/src/libcore/task/local_data.rs
+++ b/src/libcore/task/local_data.rs
@@ -27,7 +27,7 @@ magic.
 */
 
 use prelude::*;
-use task::local_data_priv::{local_get, local_pop, local_modify, local_set};
+use task::local_data_priv::{local_get, local_pop, local_modify, local_set, Handle};
 use task::rt;
 
 /**
@@ -53,7 +53,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 +62,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 +71,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 +81,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 5d1cba79c05..66808bf21aa 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::reinterpret_cast(&(*self));
+            let ptr_b: (uint, uint) = cast::reinterpret_cast(other);
             return ptr_a == ptr_b;
         }
     }
@@ -39,19 +63,30 @@ 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
         // beginning.
-        let _map: TaskLocalMap = cast::transmute(map_ptr);
+        let _map: TaskLocalMap = cast::reinterpret_cast(&map_ptr);
         // All local_data will be destroyed along with the map.
     }
 }
 
 // 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_(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
@@ -62,7 +97,7 @@ unsafe fn get_task_local_map(task: *rust_task) -> TaskLocalMap {
         // Use reinterpret_cast -- transmute would take map away from us also.
         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_);
         // Also need to reference it an extra time to keep it for now.
         let nonmut = cast::transmute::<TaskLocalMap,
                                        @~[Option<TaskLocalElement>]>(map);
@@ -77,6 +112,32 @@ 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 ~[];
+            // Use reinterpret_cast -- transmute would take map away from us also.
+            *map_ptr = cast::reinterpret_cast(&map);
+            let at_exit_fn: ~fn(*libc::c_void) = |p|cleanup_task_local_map(p);
+            *at_exit = Some(at_exit_fn);
+            // Also need to reference it an extra time to keep it for now.
+            let nonmut = cast::transmute::<TaskLocalMap,
+            @~[Option<TaskLocalElement>]>(map);
+            cast::bump_box_refcount(nonmut);
+            return map;
+        }
+    }
+}
+
 unsafe fn key_to_key_value<T:Durable>(
     key: LocalDataKey<T>) -> *libc::c_void {
 
@@ -106,10 +167,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
@@ -128,23 +189,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
@@ -152,7 +213,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::reinterpret_cast(&data);
     let data_box = @data as @LocalData;
     // Construct new entry to store in the map.
     let new_entry = Some((keyval, data_ptr, data_box));
@@ -174,12 +235,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 a6c03638713..d31a511eca8 100644
--- a/src/libcore/task/mod.rs
+++ b/src/libcore/task/mod.rs
@@ -558,8 +558,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;
+        }
     }
 }
 
@@ -1229,7 +1252,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 43fdee67b7a..63b582326ec 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.