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; 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![], 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) { 'run: loop { match self.eval_op() { Ok(EvalRes { cycles, advance }) => { if cycles > 0 { std::thread::sleep(self.info.cycle_time * (cycles as u32)); } 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); break 'run; } } } debug!("Thread ended."); } }