about summary refs log tree commit diff
path: root/src/libstd/task
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2013-07-09 18:28:46 -0700
committerbors <bors@rust-lang.org>2013-07-09 18:28:46 -0700
commit41dcec2fe16e272016ae77d10a6a5ff3a737f192 (patch)
tree6eebc49e7033a0d696c93c8e23d7caeb28d4eca1 /src/libstd/task
parent137d1fb210a844a76f89d7355a1aaf9f7a88af33 (diff)
parent413d51e32debf0c3f7dda2434b64d73585df21ef (diff)
downloadrust-41dcec2fe16e272016ae77d10a6a5ff3a737f192.tar.gz
rust-41dcec2fe16e272016ae77d10a6a5ff3a737f192.zip
auto merge of #7265 : brson/rust/io-upstream, r=brson
r? @graydon, @nikomatsakis, @pcwalton, or @catamorphism

Sorry this is so huge, but it's been accumulating for about a month. There's lots of stuff here, mostly oriented toward enabling multithreaded scheduling and improving compatibility between the old and new runtimes. Adds task pinning so that we can create the 'platform thread' in servo.

[Here](https://github.com/brson/rust/blob/e1555f9b5628af2b6c6ed344cad621399cb7684d/src/libstd/rt/mod.rs#L201) is the current runtime setup code.

About half of this has already been reviewed.
Diffstat (limited to 'src/libstd/task')
-rw-r--r--src/libstd/task/mod.rs39
-rw-r--r--src/libstd/task/spawn.rs38
2 files changed, 56 insertions, 21 deletions
diff --git a/src/libstd/task/mod.rs b/src/libstd/task/mod.rs
index a8e8cfd163a..5a3ff10ae83 100644
--- a/src/libstd/task/mod.rs
+++ b/src/libstd/task/mod.rs
@@ -497,11 +497,26 @@ pub fn try<T:Send>(f: ~fn() -> T) -> Result<T,()> {
 pub fn yield() {
     //! Yield control to the task scheduler
 
+    use rt::{context, OldTaskContext};
+    use rt::local::Local;
+    use rt::sched::Scheduler;
+
     unsafe {
-        let task_ = rt::rust_get_task();
-        let killed = rt::rust_task_yield(task_);
-        if killed && !failing() {
-            fail!("killed");
+        match context() {
+            OldTaskContext => {
+                let task_ = rt::rust_get_task();
+                let killed = rt::rust_task_yield(task_);
+                if killed && !failing() {
+                    fail!("killed");
+                }
+            }
+            _ => {
+                // XXX: What does yield really mean in newsched?
+                let sched = Local::take::<Scheduler>();
+                do sched.deschedule_running_task_and_then |sched, task| {
+                    sched.enqueue_task(task);
+                }
+            }
         }
     }
 }
@@ -520,20 +535,9 @@ pub fn failing() -> bool {
             }
         }
         _ => {
-            let mut unwinding = false;
-            do Local::borrow::<Task> |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
-                    }
-                }
+            do Local::borrow::<Task, bool> |local| {
+                local.unwinder.unwinding
             }
-            return unwinding;
         }
     }
 }
@@ -1191,3 +1195,4 @@ fn test_simple_newsched_spawn() {
         spawn(||())
     }
 }
+
diff --git a/src/libstd/task/spawn.rs b/src/libstd/task/spawn.rs
index 190485a720a..bcb7e06bf1f 100644
--- a/src/libstd/task/spawn.rs
+++ b/src/libstd/task/spawn.rs
@@ -91,6 +91,7 @@ use uint;
 use util;
 use unstable::sync::{Exclusive, exclusive};
 use rt::local::Local;
+use rt::task::Task;
 use iterator::IteratorUtil;
 
 #[cfg(test)] use task::default_task_opts;
@@ -581,12 +582,41 @@ pub fn spawn_raw(opts: TaskOpts, f: ~fn()) {
     }
 }
 
-fn spawn_raw_newsched(_opts: TaskOpts, f: ~fn()) {
+fn spawn_raw_newsched(mut opts: TaskOpts, f: ~fn()) {
     use rt::sched::*;
 
-    let mut sched = Local::take::<Scheduler>();
-    let task = ~Coroutine::new(&mut sched.stack_pool, f);
-    sched.schedule_new_task(task);
+    let f = Cell::new(f);
+
+    let mut task = unsafe {
+        let sched = Local::unsafe_borrow::<Scheduler>();
+        rtdebug!("unsafe borrowed sched");
+
+        if opts.linked {
+            do Local::borrow::<Task, ~Task>() |running_task| {
+                ~running_task.new_child(&mut (*sched).stack_pool, f.take())
+            }
+        } else {
+            // An unlinked task is a new root in the task tree
+            ~Task::new_root(&mut (*sched).stack_pool, f.take())
+        }
+    };
+
+    if opts.notify_chan.is_some() {
+        let notify_chan = opts.notify_chan.swap_unwrap();
+        let notify_chan = Cell::new(notify_chan);
+        let on_exit: ~fn(bool) = |success| {
+            notify_chan.take().send(
+                if success { Success } else { Failure }
+            )
+        };
+        task.on_exit = Some(on_exit);
+    }
+
+    rtdebug!("spawn about to take scheduler");
+
+    let sched = Local::take::<Scheduler>();
+    rtdebug!("took sched in spawn");
+    sched.schedule_task(task);
 }
 
 fn spawn_raw_oldsched(mut opts: TaskOpts, f: ~fn()) {