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, pub(crate) state: RunState, } pub mod info; pub mod state; pub struct ThreadParams<'a> { pub id: ThreadToken, pub uniq: Arc, pub program: Arc, 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."); } }