|
|
@ -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) {
|
|
|
|