|
|
@ -91,6 +91,7 @@ impl RunThread { |
|
|
|
loop_helper.loop_start(); |
|
|
|
loop_helper.loop_start(); |
|
|
|
} |
|
|
|
} |
|
|
|
trace!("Step {}; Status = {}", advance, self.state.cr.frame.status); |
|
|
|
trace!("Step {}; Status = {}", advance, self.state.cr.frame.status); |
|
|
|
|
|
|
|
let orig_pc = self.state.cr.frame.pc; |
|
|
|
self.state.cr.frame.pc.advance(advance); |
|
|
|
self.state.cr.frame.pc.advance(advance); |
|
|
|
|
|
|
|
|
|
|
|
if let Some(dl) = self.state.cr_deadline { |
|
|
|
if let Some(dl) = self.state.cr_deadline { |
|
|
@ -100,14 +101,17 @@ impl RunThread { |
|
|
|
match sched { |
|
|
|
match sched { |
|
|
|
SchedSignal::Normal => {} |
|
|
|
SchedSignal::Normal => {} |
|
|
|
SchedSignal::Yield(None) => { |
|
|
|
SchedSignal::Yield(None) => { |
|
|
|
|
|
|
|
trace!("yield"); |
|
|
|
self.state.cr.cr_state = CoroutineState::Ready; |
|
|
|
self.state.cr.cr_state = CoroutineState::Ready; |
|
|
|
want_switch = true; |
|
|
|
want_switch = true; |
|
|
|
} |
|
|
|
} |
|
|
|
SchedSignal::Yield(Some(value)) => { |
|
|
|
SchedSignal::Yield(Some(value)) => { |
|
|
|
|
|
|
|
trace!("yield {}", value); |
|
|
|
self.state.cr.cr_state = CoroutineState::YieldedValue(value); |
|
|
|
self.state.cr.cr_state = CoroutineState::YieldedValue(value); |
|
|
|
want_switch = true; |
|
|
|
want_switch = true; |
|
|
|
} |
|
|
|
} |
|
|
|
SchedSignal::Sleep(time) => { |
|
|
|
SchedSignal::Sleep(time) => { |
|
|
|
|
|
|
|
trace!("sleep {:?}", time); |
|
|
|
self.state.cr.cr_state = CoroutineState::Sleep { due: Instant::now() + time }; |
|
|
|
self.state.cr.cr_state = CoroutineState::Sleep { due: Instant::now() + time }; |
|
|
|
want_switch = true; |
|
|
|
want_switch = true; |
|
|
|
} |
|
|
|
} |
|
|
@ -117,27 +121,33 @@ impl RunThread { |
|
|
|
// TODO prioritize a thread that is waiting for this return value
|
|
|
|
// TODO prioritize a thread that is waiting for this return value
|
|
|
|
} |
|
|
|
} |
|
|
|
SchedSignal::Join(handle) => { |
|
|
|
SchedSignal::Join(handle) => { |
|
|
|
|
|
|
|
trace!("Join cr {:#}", handle); |
|
|
|
let mut found = false; |
|
|
|
let mut found = false; |
|
|
|
'find: for (n, th) in self.state.parked.iter_mut().enumerate() { |
|
|
|
'find: for (n, th) in self.state.parked.iter_mut().enumerate() { |
|
|
|
if th.handle == handle { |
|
|
|
if th.handle == handle { |
|
|
|
if let CoroutineState::Finished(_) = &th.cr_state { |
|
|
|
if let CoroutineState::Finished(_) = &th.cr_state { |
|
|
|
let mut crs = mem::replace(&mut th.cr_state, CoroutineState::Ready); |
|
|
|
let mut crs = mem::replace(&mut th.cr_state, CoroutineState::Ready); |
|
|
|
self.state.parked.remove(n); // delete it
|
|
|
|
self.state.parked.remove(n); // delete it
|
|
|
|
|
|
|
|
found = true; |
|
|
|
|
|
|
|
|
|
|
|
if let CoroutineState::Finished(vals) = crs { |
|
|
|
if let CoroutineState::Finished(vals) = crs { |
|
|
|
self.state.cr.frame.set_retvals(&vals); |
|
|
|
self.state.cr.frame.set_retvals(&vals); |
|
|
|
found = true; |
|
|
|
|
|
|
|
break 'find; |
|
|
|
break 'find; |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
unreachable!(); |
|
|
|
unreachable!(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
self.state.cr.frame.pc = orig_pc; // Retry
|
|
|
|
|
|
|
|
self.state.cr.cr_state = CoroutineState::Ready; |
|
|
|
|
|
|
|
want_switch = true; |
|
|
|
|
|
|
|
found = true; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if !found { |
|
|
|
if !found { |
|
|
|
self.state.set_flag(Flag::Invalid, true); |
|
|
|
self.state.set_flag(Flag::Invalid, true); |
|
|
|
warn!("Join with invalid thread handle!"); |
|
|
|
warn!("Join with invalid thread handle {:#}!", handle); |
|
|
|
self.state.cr.frame.set_retvals(&[]); |
|
|
|
self.state.cr.frame.set_retvals(&[]); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
@ -214,7 +224,7 @@ impl RunThread { |
|
|
|
let n_alive = self.state.parked.iter() |
|
|
|
let n_alive = self.state.parked.iter() |
|
|
|
.filter(|p| p.cr_state.is_alive()).count(); |
|
|
|
.filter(|p| p.cr_state.is_alive()).count(); |
|
|
|
|
|
|
|
|
|
|
|
if n_alive <= 1 { |
|
|
|
if n_alive == 0 { |
|
|
|
trace!("Stop task switching, no parked threads are alive"); |
|
|
|
trace!("Stop task switching, no parked threads are alive"); |
|
|
|
self.state.cr_deadline = None; |
|
|
|
self.state.cr_deadline = None; |
|
|
|
} |
|
|
|
} |
|
|
|