diff --git a/src/kernel/mod.rs b/src/kernel/mod.rs index f1abafa..1988e43 100644 --- a/src/kernel/mod.rs +++ b/src/kernel/mod.rs @@ -4,4 +4,5 @@ pub mod scheduler; pub mod mgerror; pub mod system; mod ucontext; -mod synch; \ No newline at end of file +mod synch; +mod thread_manager; \ No newline at end of file diff --git a/src/kernel/system.rs b/src/kernel/system.rs index 8ef7ecb..863bdc2 100644 --- a/src/kernel/system.rs +++ b/src/kernel/system.rs @@ -1,12 +1,6 @@ -use std::rc::Rc; -use crate::{ - kernel::{ - thread::Thread, - scheduler::Scheduler - }, - utility::list::List, - simulator::machine::Machine -}; +use crate::simulator::machine::Machine; + +use super::thread_manager::ThreadManager; /// # System /// @@ -19,26 +13,24 @@ use crate::{ /// - The thread to be destroyed next /// - The scheduler which acts upon these threads #[derive(PartialEq)] -pub struct System { +pub struct System<'a> { g_machine: Machine, - g_current_thread: Option, - g_thread_to_be_destroyed: Option, - g_alive: List>, - g_scheduler: Scheduler + thread_manager: ThreadManager<'a> } -impl System { +impl<'a> System<'a> { /// System constructor - pub fn new(machine: Machine, scheduler: Scheduler) -> Self { + pub fn new(machine: Machine) -> System<'a> { Self { g_machine: machine, - g_current_thread: None, - g_thread_to_be_destroyed: None, - g_alive: List::new(), - g_scheduler: scheduler + thread_manager: ThreadManager::new() } - } + } + + pub fn freeze(&'a mut self) { + self.thread_manager.system.set(Option::Some(self)); + } // GETTERS @@ -49,28 +41,6 @@ impl System { &mut self.g_machine } - /// 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 - } - // Setters /// Assign a machine to the system @@ -78,21 +48,6 @@ impl System { self.g_machine = machine } - /// 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 - } - } #[derive(PartialEq)] diff --git a/src/kernel/thread.rs b/src/kernel/thread.rs index 3ffbba6..68bc7c9 100644 --- a/src/kernel/thread.rs +++ b/src/kernel/thread.rs @@ -1,6 +1,4 @@ -use std::{sync::Arc, rc::Rc}; - -use super::{process::Process, mgerror::ErrorCode, system::{ObjectType, System}, ucontext::UContextT}; +use super::{process::Process, system::ObjectType}; use crate::{simulator::machine::{NUM_INT_REGS, NUM_FP_REGS, STACK_REG}}; const SIMULATORSTACKSIZE: usize = 32 * 1024; @@ -16,18 +14,17 @@ struct ThreadContext { #[derive(PartialEq)] pub struct Thread { name: String, - process: Option, + pub process: Option, // simulation_context: UContextT, thread_context: ThreadContext, stack_pointer: i32, - object_type: ObjectType, - system: Rc + object_type: ObjectType } impl Thread { /// Thread constructor - pub fn new(name: String, system: Rc) -> Self { + pub fn new(name: String) -> Self { Self { name, process: None, @@ -39,31 +36,16 @@ impl Thread { }, stack_pointer: 0, object_type: ObjectType::ThreadType, - system } } - /// 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; - let this = Rc::new(self); - self.system.get_g_alive().push(Rc::clone(&this)); - self.system.g_scheduler().ready_to_run(Rc::clone(&this)); - Result::Ok(()) - } - - fn init_thread_context(&mut self, initial_pc_reg: i64, initial_sp: i64, arg: i64) { + pub 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]) { + pub 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); @@ -78,20 +60,6 @@ impl Thread { // self.simulation_context.stackBottom[0] = STACK_FENCEPOST; } - /// Wait for another thread to finish its execution - pub fn join(&self, id_thread: Rc) { - while self.system.get_g_alive().contains(&Rc::clone(&id_thread)) { - self.t_yield(); - } - } - - /// 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!(); diff --git a/src/kernel/thread_manager.rs b/src/kernel/thread_manager.rs new file mode 100644 index 0000000..28e5eaa --- /dev/null +++ b/src/kernel/thread_manager.rs @@ -0,0 +1,95 @@ +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, thread: &mut 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)); + // self.g_scheduler().ready_to_run(Rc::clone(&thread)); + 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 + } + +} \ No newline at end of file diff --git a/src/kernel/ucontext.rs b/src/kernel/ucontext.rs index 16c29f1..567d144 100644 --- a/src/kernel/ucontext.rs +++ b/src/kernel/ucontext.rs @@ -1,5 +1,5 @@ -use std::mem::MaybeUninit; +// use std::mem::MaybeUninit; /// Safe wrapper for ucontext_t struct of linux-gnu libc /// diff --git a/src/main.rs b/src/main.rs index f703804..a19b258 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,15 +2,11 @@ mod simulator; mod kernel; pub mod utility; -use kernel::{ - scheduler::Scheduler, - system::System -}; +use kernel::system::System; use simulator::machine::Machine; use simulator::mem_cmp; fn main() { let machine = Machine::_init_machine(); - let scheduler = Scheduler::new(); - let system = System::new(machine, scheduler); + let _system = System::new(machine); }