about summary refs log tree commit diff
diff options
context:
space:
mode:
authortoddaaro <github@opprobrio.us>2013-07-29 12:06:36 -0700
committertoddaaro <github@opprobrio.us>2013-08-01 15:16:01 -0700
commit997719c13d449821691fcae927d3b94960b5bc03 (patch)
treec2a194a3161ac8f341eb789c6825f6464d37af50
parent37f385e44bbe31a693a665a74b6b493e11b7cf1c (diff)
downloadrust-997719c13d449821691fcae927d3b94960b5bc03.tar.gz
rust-997719c13d449821691fcae927d3b94960b5bc03.zip
Fixed a race where a scheduler configured to only run tasks pinned to it would "bounch" a regular task in and out of the work queue without allowing a different scheduler to run it.
-rw-r--r--src/libstd/rt/local.rs2
-rw-r--r--src/libstd/rt/sched.rs41
2 files changed, 35 insertions, 8 deletions
diff --git a/src/libstd/rt/local.rs b/src/libstd/rt/local.rs
index 34e3a0241a9..2bfe0fafdd8 100644
--- a/src/libstd/rt/local.rs
+++ b/src/libstd/rt/local.rs
@@ -120,7 +120,7 @@ impl Local for IoFactoryObject {
 
 #[cfg(test)]
 mod test {
-    use unstable::run_in_bare_thread;
+//    use unstable::run_in_bare_thread;
     use rt::test::*;
 //    use rt::sched::Scheduler;
     use super::*;
diff --git a/src/libstd/rt/sched.rs b/src/libstd/rt/sched.rs
index 0326c2cbfe5..d22c5857a19 100644
--- a/src/libstd/rt/sched.rs
+++ b/src/libstd/rt/sched.rs
@@ -68,7 +68,10 @@ pub struct Scheduler {
     priv cleanup_job: Option<CleanupJob>,
     metrics: SchedMetrics,
     /// Should this scheduler run any task, or only pinned tasks?
-    run_anything: bool
+    run_anything: bool,
+    /// If the scheduler shouldn't run some tasks, a friend to send
+    /// them to.
+    friend_handle: Option<SchedHandle>
 }
 
 pub struct SchedHandle {
@@ -80,7 +83,8 @@ pub struct SchedHandle {
 pub enum SchedMessage {
     Wake,
     Shutdown,
-    PinnedTask(~Task)
+    PinnedTask(~Task),
+    TaskFromFriend(~Task)
 }
 
 enum CleanupJob {
@@ -97,7 +101,7 @@ impl Scheduler {
                sleeper_list: SleeperList)
         -> Scheduler {
 
-        Scheduler::new_special(event_loop, work_queue, sleeper_list, true)
+        Scheduler::new_special(event_loop, work_queue, sleeper_list, true, None)
 
     }
 
@@ -106,7 +110,8 @@ impl Scheduler {
     pub fn new_special(event_loop: ~EventLoopObject,
                        work_queue: WorkQueue<~Task>,
                        sleeper_list: SleeperList,
-                       run_anything: bool)
+                       run_anything: bool,
+                       friend: Option<SchedHandle>)
         -> Scheduler {
 
         Scheduler {
@@ -120,7 +125,8 @@ impl Scheduler {
             sched_task: None,
             cleanup_job: None,
             metrics: SchedMetrics::new(),
-            run_anything: run_anything
+            run_anything: run_anything,
+            friend_handle: friend
         }
     }
 
@@ -327,6 +333,10 @@ impl Scheduler {
                 this.resume_task_immediately(task);
                 return None;
             }
+            Some(TaskFromFriend(task)) => {
+                this.resume_task_immediately(task);
+                return None;
+            }
             Some(Wake) => {
                 this.sleepy = false;
                 return Some(this);
@@ -376,6 +386,19 @@ impl Scheduler {
         }
     }
 
+    /// Take a non-homed task we aren't allowed to run here and send
+    /// it to the designated friend scheduler to execute.
+    fn send_to_friend(&mut self, task: ~Task) {
+        match self.friend_handle {
+            Some(ref mut handle) => {
+                handle.send(TaskFromFriend(task));
+            }
+            None => {
+                rtabort!("tried to send task to a friend but scheduler has no friends");
+            }
+        }
+    }
+
     // Resume a task from the queue - but also take into account that
     // it might not belong here.
 
@@ -409,7 +432,8 @@ impl Scheduler {
                     }
                     AnySched => {
                         task.give_home(AnySched);
-                        this.enqueue_task(task);
+//                        this.enqueue_task(task);
+                        this.send_to_friend(task);
                         return Some(this);
                     }
                 }
@@ -816,12 +840,15 @@ mod test {
 
             let normal_handle = Cell::new(normal_sched.make_handle());
 
+            let friend_handle = normal_sched.make_handle();
+
             // Our special scheduler
             let mut special_sched = ~Scheduler::new_special(
                 ~UvEventLoop::new(),
                 work_queue.clone(),
                 sleepers.clone(),
-                false);
+                false,
+                Some(friend_handle));
 
             let special_handle = Cell::new(special_sched.make_handle());