Skip to content

Commit 997719c

Browse files
committed
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.
1 parent 37f385e commit 997719c

File tree

2 files changed

+35
-8
lines changed

2 files changed

+35
-8
lines changed

src/libstd/rt/local.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ impl Local for IoFactoryObject {
120120

121121
#[cfg(test)]
122122
mod test {
123-
use unstable::run_in_bare_thread;
123+
// use unstable::run_in_bare_thread;
124124
use rt::test::*;
125125
// use rt::sched::Scheduler;
126126
use super::*;

src/libstd/rt/sched.rs

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,10 @@ pub struct Scheduler {
6868
priv cleanup_job: Option<CleanupJob>,
6969
metrics: SchedMetrics,
7070
/// Should this scheduler run any task, or only pinned tasks?
71-
run_anything: bool
71+
run_anything: bool,
72+
/// If the scheduler shouldn't run some tasks, a friend to send
73+
/// them to.
74+
friend_handle: Option<SchedHandle>
7275
}
7376

7477
pub struct SchedHandle {
@@ -80,7 +83,8 @@ pub struct SchedHandle {
8083
pub enum SchedMessage {
8184
Wake,
8285
Shutdown,
83-
PinnedTask(~Task)
86+
PinnedTask(~Task),
87+
TaskFromFriend(~Task)
8488
}
8589

8690
enum CleanupJob {
@@ -97,7 +101,7 @@ impl Scheduler {
97101
sleeper_list: SleeperList)
98102
-> Scheduler {
99103

100-
Scheduler::new_special(event_loop, work_queue, sleeper_list, true)
104+
Scheduler::new_special(event_loop, work_queue, sleeper_list, true, None)
101105

102106
}
103107

@@ -106,7 +110,8 @@ impl Scheduler {
106110
pub fn new_special(event_loop: ~EventLoopObject,
107111
work_queue: WorkQueue<~Task>,
108112
sleeper_list: SleeperList,
109-
run_anything: bool)
113+
run_anything: bool,
114+
friend: Option<SchedHandle>)
110115
-> Scheduler {
111116

112117
Scheduler {
@@ -120,7 +125,8 @@ impl Scheduler {
120125
sched_task: None,
121126
cleanup_job: None,
122127
metrics: SchedMetrics::new(),
123-
run_anything: run_anything
128+
run_anything: run_anything,
129+
friend_handle: friend
124130
}
125131
}
126132

@@ -327,6 +333,10 @@ impl Scheduler {
327333
this.resume_task_immediately(task);
328334
return None;
329335
}
336+
Some(TaskFromFriend(task)) => {
337+
this.resume_task_immediately(task);
338+
return None;
339+
}
330340
Some(Wake) => {
331341
this.sleepy = false;
332342
return Some(this);
@@ -376,6 +386,19 @@ impl Scheduler {
376386
}
377387
}
378388

389+
/// Take a non-homed task we aren't allowed to run here and send
390+
/// it to the designated friend scheduler to execute.
391+
fn send_to_friend(&mut self, task: ~Task) {
392+
match self.friend_handle {
393+
Some(ref mut handle) => {
394+
handle.send(TaskFromFriend(task));
395+
}
396+
None => {
397+
rtabort!("tried to send task to a friend but scheduler has no friends");
398+
}
399+
}
400+
}
401+
379402
// Resume a task from the queue - but also take into account that
380403
// it might not belong here.
381404

@@ -409,7 +432,8 @@ impl Scheduler {
409432
}
410433
AnySched => {
411434
task.give_home(AnySched);
412-
this.enqueue_task(task);
435+
// this.enqueue_task(task);
436+
this.send_to_friend(task);
413437
return Some(this);
414438
}
415439
}
@@ -816,12 +840,15 @@ mod test {
816840

817841
let normal_handle = Cell::new(normal_sched.make_handle());
818842

843+
let friend_handle = normal_sched.make_handle();
844+
819845
// Our special scheduler
820846
let mut special_sched = ~Scheduler::new_special(
821847
~UvEventLoop::new(),
822848
work_queue.clone(),
823849
sleepers.clone(),
824-
false);
850+
false,
851+
Some(friend_handle));
825852

826853
let special_handle = Cell::new(special_sched.make_handle());
827854

0 commit comments

Comments
 (0)