std::rt: Try stealing from all schedulers

This guarantees that if there is work to do it will be found
This commit is contained in:
Brian Anderson 2013-09-04 16:54:05 -07:00
parent 85c0fb7b8a
commit c767643f2b
1 changed files with 27 additions and 10 deletions

View File

@ -379,21 +379,20 @@ impl Scheduler {
return Some(task)
}
None => {
// Our naive stealing, try kinda hard.
rtdebug!("scheduler trying to steal");
let len = self.work_queues.len();
return self.try_steals(len/2);
return self.try_steals();
}
}
}
// With no backoff try stealing n times from the queues the
// scheduler knows about. This naive implementation can steal from
// our own queue or from other special schedulers.
fn try_steals(&mut self, n: uint) -> Option<~Task> {
for _ in range(0, n) {
let index = self.rng.gen_uint_range(0, self.work_queues.len());
let work_queues = &mut self.work_queues;
// Try stealing from all queues the scheduler knows about. This
// naive implementation can steal from our own queue or from other
// special schedulers.
fn try_steals(&mut self) -> Option<~Task> {
let work_queues = &mut self.work_queues;
let len = work_queues.len();
let start_index = self.rng.gen_uint_range(0, len);
for index in range(0, len).map(|i| (i + start_index) % len) {
match work_queues[index].steal() {
Some(task) => {
rtdebug!("found task by stealing");
@ -1213,4 +1212,22 @@ mod test {
}
}
#[test]
fn dont_starve_1() {
use rt::comm::oneshot;
do stress_factor().times {
do run_in_mt_newsched_task {
let (port, chan) = oneshot();
// This task should not be able to starve the sender;
// The sender should get stolen to another thread.
do spawntask {
while !port.peek() { }
}
chan.send(());
}
}
}
}