use std::{sync::Arc}; use super::{process::Process, mgerror::ErrorCode, system::{ObjectType, G_ALIVE, G_SCHEDULER}, ucontext::UContextT}; use crate::{simulator::machine::{NUM_INT_REGS, NUM_FP_REGS, STACK_REG}, kernel::system::{G_MACHINE, G_THREAD_TO_BE_DESTROYED}}; const SIMULATORSTACKSIZE: usize = 32 * 1024; const STACK_FENCEPOST: u32 = 0xdeadbeef; #[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: UContextT, thread_context: ThreadContext, stack_pointer: i32, object_type: ObjectType } impl Thread { pub fn new(name: String) -> Self { Self { name, process: None, // simulation_context: UContextT::new(), 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]) { // let res = self.simulation_context.get_context(); // if res != 0 { // panic!("getcontext returns non-zero value {}", res); // } // self.simulation_context.buf.uc_stack.ss_sp = base_stack_addr; // self.simulation_context.buf.uc_stack.ss_size = base_stack_addr.len(); // self.simulation_context.buf.uc_stack.ss_flags = 0; // self.simulation_context.buf.uc_link = UContextT::new().buf; // self.simulation_context.make_context(start_thread_execution, 0); // self.simulation_context.stackBottom = base_stack_addr.to_vec(); // self.simulation_context.stackBottom[0] = STACK_FENCEPOST; } /// 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(mut self) { match G_MACHINE.write() { Ok(mut machine) => { let old_status = machine.interrupt.set_status(crate::simulator::interrupt::InterruptStatus::InterruptOff); match G_ALIVE.write() { Ok(alive) => { // todo alive.remove(T) à implémenter dans List }, Err(err) => { panic!("RwLock is poisoned: {}", err); } } match G_THREAD_TO_BE_DESTROYED.write() { Ok(mut thread_to_be_destroyed) => { thread_to_be_destroyed.replace(self); }, Err(err) => { panic!("RwLock is poisoned: {}", err); } } // self.sleep(); machine.interrupt.set_status(old_status); }, Err(err) => { panic!("RwLock is poisoned: {}", err); } } 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!(); } } fn start_thread_execution() { }