use std::sync::Arc; use std::sync::atomic::AtomicU64; 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; 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: ThreadInfo, pub(crate) state: RunState, } pub mod info; pub mod state; pub fn new_uniq() -> Arc { Arc::new(AtomicU64::new(info::UNIQ_BASE)) } impl RunThread { pub fn new(id: ThreadToken, uniq: Option>, program: Arc, pc: Addr, args: &[u64]) -> Self { Self { info: ThreadInfo { id, uniq: uniq.unwrap_or_else(new_uniq), program, cycle_time: Duration::default(), }, state: RunState { frame: StackFrame::new(pc, args), call_stack: vec![], ext_data: Default::default(), }, } } pub fn set_speed(&mut self, cycle_time: Duration) { self.info.cycle_time = cycle_time; } pub fn start(self) -> JoinHandle<()> { std::thread::spawn(move || { self.run(); }) } fn run(mut self) { 'run: loop { match self.eval_op() { Ok(EvalRes { cycles, advance }) => { std::thread::sleep(self.info.cycle_time * (cycles as u32)); trace!("Step {}; Status = {}", advance, self.state.frame.status); self.state.frame.pc.advance(advance); if self.state.frame.status.invalid { warn!("Operation failed with INVALID status!"); } } Err(Fault::Halt) => { info!("Program ended."); break 'run; } Err(e) => { error!("Fault: {:?}", e); break 'run; } } } } }