about summary refs log tree commit diff
path: root/src/libstd/rt
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstd/rt')
-rw-r--r--src/libstd/rt/sched.rs9
-rw-r--r--src/libstd/rt/uv/uvio.rs76
2 files changed, 49 insertions, 36 deletions
diff --git a/src/libstd/rt/sched.rs b/src/libstd/rt/sched.rs
index 6e661884616..26f287d2f87 100644
--- a/src/libstd/rt/sched.rs
+++ b/src/libstd/rt/sched.rs
@@ -330,6 +330,12 @@ impl Scheduler {
                 this.process_task(task, Scheduler::resume_task_immediately_cl);
                 return None;
             }
+            Some(RunOnce(task)) => {
+                // bypass the process_task logic to force running this task once
+                // on this home scheduler. This is often used for I/O (homing).
+                Scheduler::resume_task_immediately_cl(this, task);
+                return None;
+            }
             Some(Wake) => {
                 this.sleepy = false;
                 Local::put(this);
@@ -789,7 +795,8 @@ pub enum SchedMessage {
     Wake,
     Shutdown,
     PinnedTask(~Task),
-    TaskFromFriend(~Task)
+    TaskFromFriend(~Task),
+    RunOnce(~Task),
 }
 
 pub struct SchedHandle {
diff --git a/src/libstd/rt/uv/uvio.rs b/src/libstd/rt/uv/uvio.rs
index 29370c484eb..63abd6eb92d 100644
--- a/src/libstd/rt/uv/uvio.rs
+++ b/src/libstd/rt/uv/uvio.rs
@@ -29,7 +29,7 @@ use rt::local::Local;
 use rt::rtio::*;
 use rt::sched::{Scheduler, SchedHandle};
 use rt::tube::Tube;
-use rt::task::SchedHome;
+use rt::task::Task;
 use rt::uv::*;
 use rt::uv::idle::IdleWatcher;
 use rt::uv::net::{UvIpv4SocketAddr, UvIpv6SocketAddr};
@@ -59,50 +59,56 @@ trait HomingIO {
 
     fn home<'r>(&'r mut self) -> &'r mut SchedHandle;
 
-    /* XXX This will move pinned tasks to do IO on the proper scheduler
-     * and then move them back to their home.
-     */
-    fn go_to_IO_home(&mut self) -> SchedHome {
-        use rt::sched::PinnedTask;
+    /// This function will move tasks to run on their home I/O scheduler. Note
+    /// that this function does *not* pin the task to the I/O scheduler, but
+    /// rather it simply moves it to running on the I/O scheduler.
+    fn go_to_IO_home(&mut self) -> uint {
+        use rt::sched::RunOnce;
 
-        do task::unkillable { // FIXME(#8674)
-            let mut old = None;
-            {
-                let ptr = &mut old;
+        let current_sched_id = do Local::borrow |sched: &mut Scheduler| {
+            sched.sched_id()
+        };
+
+        // Only need to invoke a context switch if we're not on the right
+        // scheduler.
+        if current_sched_id != self.home().sched_id {
+            do task::unkillable { // FIXME(#8674)
                 let scheduler: ~Scheduler = Local::take();
                 do scheduler.deschedule_running_task_and_then |_, task| {
                     /* FIXME(#8674) if the task was already killed then wake
-                     * will return None. In that case, the home pointer will never be set.
+                     * will return None. In that case, the home pointer will
+                     * never be set.
                      *
-                     * RESOLUTION IDEA: Since the task is dead, we should just abort the IO action.
+                     * RESOLUTION IDEA: Since the task is dead, we should
+                     * just abort the IO action.
                      */
-                    do task.wake().map |mut task| {
-                        *ptr = Some(task.take_unwrap_home());
-                        self.home().send(PinnedTask(task));
+                    do task.wake().map |task| {
+                        self.home().send(RunOnce(task));
                     };
                 }
             }
-            old.expect("No old home because task had already been killed.")
         }
+
+        self.home().sched_id
     }
 
-    // XXX dummy self param
-    fn restore_original_home(_dummy_self: Option<Self>, old: SchedHome) {
-        use rt::sched::TaskFromFriend;
+    // XXX: dummy self parameter
+    fn restore_original_home(_: Option<Self>, io_home: uint) {
+        // It would truly be a sad day if we had moved off the home I/O
+        // scheduler while we were doing I/O.
+        assert_eq!(Local::borrow(|sched: &mut Scheduler| sched.sched_id()),
+                   io_home);
 
-        let old = Cell::new(old);
-        do task::unkillable { // FIXME(#8674)
-            let scheduler: ~Scheduler = Local::take();
-            do scheduler.deschedule_running_task_and_then |scheduler, task| {
-                /* FIXME(#8674) if the task was already killed then wake
-                 * will return None. In that case, the home pointer will never be restored.
-                 *
-                 * RESOLUTION IDEA: Since the task is dead, we should just abort the IO action.
-                 */
-                do task.wake().map |mut task| {
-                    task.give_home(old.take());
-                    scheduler.make_handle().send(TaskFromFriend(task));
-                };
+        // If we were a homed task, then we must send ourselves back to the
+        // original scheduler. Otherwise, we can just return and keep running
+        if !Task::on_appropriate_sched() {
+            do task::unkillable { // FIXME(#8674)
+                let scheduler: ~Scheduler = Local::take();
+                do scheduler.deschedule_running_task_and_then |_, task| {
+                    do task.wake().map |task| {
+                        Scheduler::run_task(task);
+                    };
+                }
             }
         }
     }
@@ -110,7 +116,7 @@ trait HomingIO {
     fn home_for_io<A>(&mut self, io: &fn(&mut Self) -> A) -> A {
         let home = self.go_to_IO_home();
         let a = io(self); // do IO
-        HomingIO::restore_original_home(None::<Self> /* XXX dummy self */, home);
+        HomingIO::restore_original_home(None::<Self>, home);
         a // return the result of the IO
     }
 
@@ -118,7 +124,7 @@ trait HomingIO {
         let mut this = self;
         let home = this.go_to_IO_home();
         let a = io(this); // do IO
-        HomingIO::restore_original_home(None::<Self> /* XXX dummy self */, home);
+        HomingIO::restore_original_home(None::<Self>, home);
         a // return the result of the IO
     }
 
@@ -128,7 +134,7 @@ trait HomingIO {
             let scheduler: ~Scheduler = Local::take();
             io_sched(self, scheduler) // do IO and scheduling action
         };
-        HomingIO::restore_original_home(None::<Self> /* XXX dummy self */, home);
+        HomingIO::restore_original_home(None::<Self>, home);
         a // return result of IO
     }
 }