From 997719c13d449821691fcae927d3b94960b5bc03 Mon Sep 17 00:00:00 2001 From: toddaaro Date: Mon, 29 Jul 2013 12:06:36 -0700 Subject: [PATCH] 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. --- src/libstd/rt/local.rs | 2 +- src/libstd/rt/sched.rs | 41 ++++++++++++++++++++++++++++++++++------- 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, 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 } 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) -> 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());