coroutine fixes, first example
This commit is contained in:
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -82,7 +82,10 @@ impl RunState {
|
|||||||
/// Add a coroutine, marked as Ready, to run next
|
/// Add a coroutine, marked as Ready, to run next
|
||||||
pub fn add_coroutine(&mut self, frame : StackFrame) -> Value {
|
pub fn add_coroutine(&mut self, frame : StackFrame) -> Value {
|
||||||
let handle = self.thread_info.unique_handle();
|
let handle = self.thread_info.unique_handle();
|
||||||
self.parked.push_back(CoroutineContext {
|
trace!("Spawn cr {:#}", handle);
|
||||||
|
|
||||||
|
// front - so it runs ASAP
|
||||||
|
self.parked.push_front(CoroutineContext {
|
||||||
handle,
|
handle,
|
||||||
frame,
|
frame,
|
||||||
call_stack: vec![],
|
call_stack: vec![],
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
(
|
||||||
|
(lds @cout "main\n")
|
||||||
|
(msleep 500)
|
||||||
|
(lds @cout "main\n")
|
||||||
|
(msleep 500)
|
||||||
|
|
||||||
|
(lds @cout "Spawnign bg\n")
|
||||||
|
|
||||||
|
(spawn r15 bg 10)
|
||||||
|
|
||||||
|
(msleep 500)
|
||||||
|
(lds @cout "FG\n")
|
||||||
|
(msleep 500)
|
||||||
|
(lds @cout "FG\n")
|
||||||
|
(msleep 500)
|
||||||
|
(lds @cout "FG\n")
|
||||||
|
|
||||||
|
(msleep 1000)
|
||||||
|
|
||||||
|
(lds @cout "Wait for BG\n")
|
||||||
|
(join @r15)
|
||||||
|
(lds @cout "Joined\n")
|
||||||
|
(msleep 500)
|
||||||
|
(lds @cout "main\n")
|
||||||
|
(msleep 500)
|
||||||
|
(lds @cout "main\n")
|
||||||
|
(msleep 500)
|
||||||
|
|
||||||
|
(proc bg times
|
||||||
|
(ld r0 times)
|
||||||
|
(:x)
|
||||||
|
(msleep 500)
|
||||||
|
(lds @cout "***BG\n")
|
||||||
|
(dec r0 (nz? (j :x)))
|
||||||
|
(lds @cout "***BG done.\n")
|
||||||
|
(ret)
|
||||||
|
)
|
||||||
|
)
|
||||||
Reference in New Issue
Block a user