You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
98 lines
2.6 KiB
98 lines
2.6 KiB
use std::sync::Arc;
|
|
|
|
use std::thread::JoinHandle;
|
|
use std::time::{Duration};
|
|
|
|
pub use info::ThreadInfo;
|
|
pub use state::RunState;
|
|
|
|
use crate::asm::data::literal::Addr;
|
|
use crate::module::{EvalRes, CrsnUniq};
|
|
use crate::runtime::fault::Fault;
|
|
use crate::runtime::frame::{StackFrame, REG_COUNT};
|
|
use crate::runtime::program::Program;
|
|
|
|
#[derive(Clone, Copy, Eq, PartialEq, Debug, Ord, PartialOrd)]
|
|
pub struct ThreadToken(pub u32);
|
|
|
|
pub struct RunThread {
|
|
pub(crate) info: Arc<ThreadInfo>,
|
|
pub(crate) state: RunState,
|
|
}
|
|
|
|
pub mod info;
|
|
pub mod state;
|
|
|
|
pub struct ThreadParams<'a> {
|
|
pub id: ThreadToken,
|
|
pub uniq: Arc<CrsnUniq>,
|
|
pub program: Arc<Program>,
|
|
pub pc: Addr,
|
|
pub cycle_time: Duration,
|
|
pub args: &'a [u64],
|
|
}
|
|
|
|
impl RunThread {
|
|
pub fn new(params: ThreadParams) -> Self {
|
|
let extensions = params.program.extensions.clone();
|
|
|
|
let ti = Arc::new(ThreadInfo {
|
|
id: params.id,
|
|
uniq: params.uniq,
|
|
program: params.program,
|
|
cycle_time: params.cycle_time,
|
|
extensions,
|
|
});
|
|
|
|
let rs = RunState {
|
|
thread_info: ti.clone(),
|
|
frame: StackFrame::new(params.pc, params.args),
|
|
call_stack: vec![],
|
|
global_regs: [0; REG_COUNT],
|
|
ext_data: Default::default(),
|
|
};
|
|
|
|
Self {
|
|
info: ti,
|
|
state: rs,
|
|
}
|
|
}
|
|
|
|
/// Spawn as a thread
|
|
pub fn spawn(self) -> JoinHandle<()> {
|
|
std::thread::spawn(move || {
|
|
self.run();
|
|
})
|
|
}
|
|
|
|
/// Start synchronously
|
|
pub fn run(mut self) {
|
|
let mut loop_helper = spin_sleep::LoopHelper::builder()
|
|
.build_with_target_rate(1.0/self.info.cycle_time.as_secs_f64());
|
|
|
|
loop_helper.loop_start();
|
|
'run: loop {
|
|
match self.eval_op() {
|
|
Ok(EvalRes { cycles, advance }) => {
|
|
for _ in 0..cycles {
|
|
loop_helper.loop_sleep();
|
|
loop_helper.loop_start();
|
|
}
|
|
trace!("Step {}; Status = {}", advance, self.state.frame.status);
|
|
self.state.frame.pc.advance(advance);
|
|
}
|
|
Err(Fault::Halt) => {
|
|
// TODO implement coordinated shutdown when more threads are running!
|
|
break 'run;
|
|
}
|
|
Err(e) => {
|
|
error!("Fault: {:?}", e);
|
|
error!("Core dump: {:?}", self.state);
|
|
break 'run;
|
|
}
|
|
}
|
|
}
|
|
|
|
debug!("Thread ended.");
|
|
}
|
|
}
|
|
|