use std::sync::Arc; use super::{process::Process, mgerror::ErrorCode, system::{ObjectType, G_ALIVE, G_SCHEDULER}}; use crate::{simulator::machine::{NUM_INT_REGS, NUM_FP_REGS, STACK_REG}}; const SIMULATORSTACKSIZE: usize = 32 * 1024; #[derive(PartialEq)] struct SimulatorContext { // todo } #[derive(PartialEq)] struct ThreadContext { pub int_registers: [i64; NUM_INT_REGS], pub float_registers: [i64; NUM_FP_REGS], pc: i64, } #[derive(PartialEq)] pub struct Thread { name: String, process: Option, simulation_context: SimulatorContext, thread_context: ThreadContext, stack_pointer: i32, object_type: ObjectType } impl Thread { pub fn new(name: String) -> Self { Self { name, process: None, simulation_context: SimulatorContext { }, thread_context: ThreadContext { int_registers: [0; NUM_INT_REGS], float_registers: [0; NUM_FP_REGS], pc: 0 }, stack_pointer: 0, object_type: ObjectType::ThreadType } } /// Start a thread, attaching it to a process pub fn start(mut self, owner: Process, func: i64, arg: i64) -> Result<(), ErrorCode> { self.process = Option::Some(owner); let ptr = 0; // todo addrspace self.init_thread_context(func, ptr, arg); let base_stack_addr: [i8; SIMULATORSTACKSIZE] = [0; SIMULATORSTACKSIZE]; // todo AllocBoundedArray self.init_simulator_context(base_stack_addr); self.process.as_mut().unwrap().num_thread += 1; match G_ALIVE.write() { Ok(mut alive) => { let this = Arc::new(self); alive.push(Arc::clone(&this)); match G_SCHEDULER.write() { Ok(mut scheduler) => { scheduler.ready_to_run(Arc::clone(&this)); }, Err(err) => { panic!("RwLock poisonned, {}", err); } } }, Err(err) => { panic!("RwLock poisonned, {}", err); } } Result::Ok(()) } fn init_thread_context(&mut self, initial_pc_reg: i64, initial_sp: i64, arg: i64) { self.thread_context.pc = initial_pc_reg; self.thread_context.int_registers[10] = arg; self.thread_context.int_registers[STACK_REG] = initial_sp; } fn init_simulator_context(&self, base_stack_addr: [i8; SIMULATORSTACKSIZE]) { todo!(); } /// Wait for another thread to finish its execution pub fn join(&self, id_thread: Arc) { match G_ALIVE.write() { Ok(alive) => { while alive.contains(&Arc::clone(&id_thread)) { self.t_yield(); } }, Err(err) => { panic!("RwLock poisonned, {}", err) } } } /// Relinquish the CPU if any other thread is runnable. /// /// Cannot use yield as a function name -> reserved name in rust pub fn t_yield(&self) { todo!(); } /// Put the thread to sleep and relinquish the processor pub fn sleep(&self) { todo!(); } /// Finish the execution of the thread and prepare its deallocation pub fn finish(&self) { todo!(); } /// Check if a thread has overflowed its stack pub fn check_overflow(&self) { todo!(); } pub fn save_processor_state(&self) { todo!(); } pub fn restore_processor_state(&self) { todo!(); } pub fn save_simulator_state(&self) { todo!(); } pub fn restore_simulator_state(&self) { todo!(); } pub fn get_name(&self) -> String { self.name.clone() } } impl Drop for Thread { fn drop(&mut self) { self.object_type = ObjectType::InvalidType; todo!(); } }