improve rescheduling

fix/scheduler-park
dignifiedquire 5 years ago
parent 77d3693112
commit 124aa76c4e

@ -50,6 +50,16 @@ struct Scheduler {
machines: Vec<Arc<Machine>>, machines: Vec<Arc<Machine>>,
} }
impl Scheduler {
/// Get the next machine that has no work yet, if there is any.
fn next_idle_machine(&self) -> Option<Arc<Machine>> {
self.machines
.iter()
.find(|m| !m.has_work())
.map(|m| m.clone())
}
}
struct ThreadState { struct ThreadState {
unparker: Unparker, unparker: Unparker,
parked: Arc<atomic::AtomicBool>, parked: Arc<atomic::AtomicBool>,
@ -258,8 +268,23 @@ impl Runtime {
// run it // run it
m.run(self); m.run(self);
// when run ends, go into parked mode again // when run ends
{ {
// see if there are any available processors
let mut sched = self.sched.lock().unwrap();
if let Some(p) = sched.processors.pop() {
// get a machine
if let Some(m) = sched.next_idle_machine(){
*m.processor.lock() = Some(p);
MACHINE.with(|machine| {
machine.borrow_mut().replace(m);
});
continue;
}
}
drop(sched);
// go into parked mode, no work
MACHINE.with(|machine| { MACHINE.with(|machine| {
*machine.borrow_mut() = None; *machine.borrow_mut() = None;
}); });
@ -314,9 +339,8 @@ impl Runtime {
#[cfg(feature = "tracing")] #[cfg(feature = "tracing")]
self.poll_count.fetch_add(1, Ordering::Relaxed); self.poll_count.fetch_add(1, Ordering::Relaxed);
// if !sched.progress { // if !sched.progress {
if let Some(p) = sched.processors.pop() { if let Some(p) = sched.processors.pop() {
if let Some(m) = sched.machines.iter().find(|m| m.processor.lock().is_none()) { if let Some(m) = sched.next_idle_machine() {
// find idle m // find idle m
*m.processor.lock() = Some(p); *m.processor.lock() = Some(p);
to_start.push(m.clone()); to_start.push(m.clone());
@ -370,6 +394,15 @@ impl Machine {
} }
} }
fn has_work(&self) -> bool {
if let Some(p) = &*self.processor.lock() {
// TODO: is this the right check?
p.has_work()
} else {
false
}
}
/// Schedules a task onto the machine. /// Schedules a task onto the machine.
fn schedule(&self, rt: &Runtime, task: Runnable) { fn schedule(&self, rt: &Runtime, task: Runnable) {
match self.processor.lock().as_mut() { match self.processor.lock().as_mut() {
@ -498,12 +531,7 @@ impl Machine {
// If another thread is already blocked on the reactor, there is no point in keeping // If another thread is already blocked on the reactor, there is no point in keeping
// the current thread around since there is too little work to do. // the current thread around since there is too little work to do.
if sched.polling { if sched.polling {
if sched.machines.len() > MIN_MACHINES { break;
break;
} else {
// thread::sleep(Duration::from_micros(10));
continue;
}
} }
// Take out the machine associated with the current thread. // Take out the machine associated with the current thread.
@ -566,6 +594,11 @@ impl Processor {
} }
} }
/// Is there any available work for this processor?
fn has_work(&self) -> bool {
self.slot.is_some() || !self.worker.is_empty()
}
/// Schedules a task to run on this processor. /// Schedules a task to run on this processor.
fn schedule(&mut self, rt: &Runtime, task: Runnable) { fn schedule(&mut self, rt: &Runtime, task: Runnable) {
match self.slot.replace(task) { match self.slot.replace(task) {

Loading…
Cancel
Save