use std::{rc::Rc, cell::Cell}; use crate::utility::list::List; use super::{scheduler::Scheduler, thread::Thread, system::System, mgerror::ErrorCode, process::Process}; const SIMULATORSTACKSIZE: usize = 32 * 1024; #[derive(PartialEq)] pub struct ThreadManager<'a> { pub g_current_thread: Option, pub g_thread_to_be_destroyed: Option, pub g_alive: List>, pub g_scheduler: Scheduler, pub system: Cell>> } impl<'a> ThreadManager<'a> { pub fn new() -> Self { Self { g_current_thread: Option::None, g_thread_to_be_destroyed: Option::None, g_alive: List::new(), g_scheduler: Scheduler::new(), system: Cell::new(None) } } /// Start a thread, attaching it to a process pub fn start_thread(&mut self, mut thread: Thread, owner: Process, func_pc: i64, argument: i64) -> Result<(), ErrorCode> { thread.process = Option::Some(owner); let ptr = 0; // todo addrspace thread.init_thread_context(func_pc, ptr, argument); let base_stack_addr: [i8; SIMULATORSTACKSIZE] = [0; SIMULATORSTACKSIZE]; // todo AllocBoundedArray thread.init_simulator_context(base_stack_addr); thread.process.as_mut().unwrap().num_thread += 1; let thread_m = Rc::new(thread); self.get_g_alive().push(Rc::clone(&thread_m)); self.g_scheduler().ready_to_run(Rc::clone(&thread_m)); Result::Ok(()) } /// Wait for another thread to finish its execution pub fn thread_join(&mut self, id_thread: Rc) { while self.get_g_alive().contains(&Rc::clone(&id_thread)) { self.thread_yield(); } } /// Relinquish the CPU if any other thread is runnable. /// /// Cannot use yield as a function name -> reserved name in rust pub fn thread_yield(&mut self) { todo!(); } /// Currently running thread pub fn get_g_current_thread(&mut self) -> &mut Option { &mut self.g_current_thread } /// Thread to be destroyed by [...] /// /// TODO: Finish the comment with the relevant value pub fn get_g_thread_to_be_destroyed(&mut self) -> &mut Option { &mut self.g_thread_to_be_destroyed } /// List of alive threads pub fn get_g_alive(&mut self) -> &mut List> { &mut self.g_alive } /// Current scheduler pub fn g_scheduler(&mut self) -> &mut Scheduler { &mut self.g_scheduler } /// Set currently running thread pub fn set_g_current_thread(&mut self, thread: Option) { self.g_current_thread = thread } /// Set thread to be destroyed next pub fn set_g_thread_to_be_destroyed(&mut self, thread: Option) { self.g_thread_to_be_destroyed = thread } /// Set Scheduler which will manage the threads pub fn set_g_scheduler(&mut self, scheduler: Scheduler) { self.g_scheduler = scheduler } }