forked from MightyPork/crsn
more docs, fixes, examples
This commit is contained in:
@@ -545,6 +545,9 @@ Jumping to a label is always safer than a manual skip.
|
||||
; The label can be a numeric or string label, its sole purpose is tying the two together. They must be unique in the program.
|
||||
(barrier-open LABEL)
|
||||
(barrier-close LABEL)
|
||||
|
||||
; Set coroutine scheduler timeslice (in microseconds). Set to zero to disable preemption.
|
||||
(rt-opt RT_TIMESLICE Rd'usec)
|
||||
```
|
||||
|
||||
## Arithmetic Module
|
||||
|
||||
@@ -613,7 +613,7 @@ mod test {
|
||||
global_regs: [0; REG_COUNT],
|
||||
ext_data: Default::default(),
|
||||
cr_deadline: None,
|
||||
critical_section: false,
|
||||
critical_section: 0,
|
||||
},
|
||||
const_eval_ti: ti.clone(),
|
||||
parsing_expr: false,
|
||||
|
||||
@@ -230,7 +230,9 @@ impl RunThread {
|
||||
// Do switch
|
||||
let old = mem::replace(&mut self.state.cr, cr);
|
||||
self.state.parked.push_back(old);
|
||||
self.state.cr_deadline = Some(now + *self.info.scheduler_interval.read());
|
||||
|
||||
self.state.start_task_switching();
|
||||
|
||||
} else if let Some(due) = closest_due {
|
||||
let time = due.saturating_duration_since(now);
|
||||
trace!("No thread to switch to, sleep {:?}", time);
|
||||
@@ -248,7 +250,7 @@ impl RunThread {
|
||||
|
||||
if n_alive == 0 {
|
||||
trace!("Stop task switching, no parked threads are alive");
|
||||
self.state.cr_deadline = None;
|
||||
self.state.stop_task_switching(); // This should improve performance in single-threaded mode
|
||||
}
|
||||
|
||||
match self.state.cr.cr_state {
|
||||
|
||||
@@ -12,7 +12,7 @@ use nudge::{likely};
|
||||
use crate::asm::instr::cond::Flag;
|
||||
use std::fmt::{Debug, Formatter};
|
||||
use std::fmt;
|
||||
use std::time::Instant;
|
||||
use std::time::{Instant, Duration};
|
||||
|
||||
pub struct RunState {
|
||||
pub thread_info: Arc<ThreadInfo>,
|
||||
@@ -95,10 +95,24 @@ impl RunState {
|
||||
});
|
||||
if self.cr_deadline.is_none() {
|
||||
// start context switching
|
||||
self.cr_deadline = Some(Instant::now() + *self.thread_info.scheduler_interval.read());
|
||||
self.start_task_switching();
|
||||
}
|
||||
handle
|
||||
}
|
||||
|
||||
pub(crate) fn start_task_switching(&mut self) {
|
||||
let ival = *self.thread_info.scheduler_interval.read();
|
||||
if ival > Duration::default() {
|
||||
self.cr_deadline = Some(Instant::now() + ival);
|
||||
} else {
|
||||
// Disabled
|
||||
self.cr_deadline = None;
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn stop_task_switching(&mut self) {
|
||||
self.cr_deadline = None;
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for RunState {
|
||||
|
||||
@@ -1,16 +1,21 @@
|
||||
(
|
||||
; This example shows the use of critical sections.
|
||||
|
||||
; Set short timeslice (50us) to make the effect more pronounced
|
||||
(rt-opt RT_TIMESLICE 50)
|
||||
|
||||
(spawn _ unsafe 'A' 'Z')
|
||||
(spawn _ safe '0' '9')
|
||||
(ssleep 2)
|
||||
(spawn _ unsafe 'a' 'z')
|
||||
(spawn _ safe '0' '9') ; Notice that the sequence 0-9 is always printed in its entirety - because it is in a critical section
|
||||
(msleep 200)
|
||||
(halt)
|
||||
|
||||
(proc unsafe start end
|
||||
; This can be interrupted any time
|
||||
(:x)
|
||||
(yield)
|
||||
(ld r0 start)
|
||||
(:l)
|
||||
(msleep 5)
|
||||
(ld @cout r0)
|
||||
(cmp r0 end)
|
||||
(j.eq :x)
|
||||
|
||||
Reference in New Issue
Block a user