diff --git a/src/kernel/exception.rs b/src/kernel/exception.rs index 4a58876..cff65ca 100644 --- a/src/kernel/exception.rs +++ b/src/kernel/exception.rs @@ -2,7 +2,7 @@ use std::{cell::RefCell, rc::Rc}; use crate::{simulator::{machine::{ExceptionType, Machine}, error::{MachineOk, MachineError}}}; -use super::{system::System, thread::Thread, synch::Semaphore}; +use super::{system::System, thread::Thread}; type Error = String; @@ -200,21 +200,12 @@ fn syscall(machine: &mut Machine, system: &mut System) -> Result Result { let id_sema = machine.int_reg.get_reg(10); - match system.get_obj_addrs().search_semaphore(id_sema as i32) { - Some(sema) => { sema.p(machine, system.get_thread_manager()); Ok(MachineOk::Ok) } - None => Err(format!("Coudn't find semaphore {}", id_sema))? - } + system.get_thread_manager().sem_p(id_sema as i32, machine) } fn sc_v(machine: &mut Machine, system: &mut System) -> Result { let id_sema = machine.int_reg.get_reg(10); - match system.get_obj_addrs().search_semaphore(id_sema as i32) { - Some(sema) => { - sema.v(machine, system.get_thread_manager()); - Ok(MachineOk::Ok) - }, - None => Err(format!("Couldn't find semaphore {}", id_sema))? - } + system.get_thread_manager().sem_v(id_sema as i32, machine) } fn sc_sem_create(machine: &mut Machine) -> Result { diff --git a/src/kernel/synch.rs b/src/kernel/synch.rs index f3682f3..e4600ac 100644 --- a/src/kernel/synch.rs +++ b/src/kernel/synch.rs @@ -7,12 +7,13 @@ use std::rc::Rc; use super::thread_manager::ThreadManager; /// Structure of a Semaphore used for synchronisation +#[derive(PartialEq)] pub struct Semaphore { /// Counter of simultanous Semaphore - counter:i32, + pub counter:i32, /// QUeue of Semaphore waiting to be exucated - waiting_queue:List>>, + pub waiting_queue:List>>, } @@ -78,7 +79,8 @@ impl Semaphore { /// Lock used for synchronisation, can be interpreted has a Semaphore with a /// counter of 1 /// It's used for critical parts -pub struct Lock{ +#[derive(PartialEq)] +pub struct Lock { /// Thread owning the lock owner: Option>>, diff --git a/src/kernel/system.rs b/src/kernel/system.rs index 6e30fa2..9305444 100644 --- a/src/kernel/system.rs +++ b/src/kernel/system.rs @@ -3,7 +3,6 @@ //! Module containing structs and methods pertaining to the state of the operating system use super::{thread_manager::ThreadManager}; -use crate::utility::objaddr::ObjAddr; /// # System /// @@ -16,8 +15,7 @@ use crate::utility::objaddr::ObjAddr; /// - The thread to be destroyed next /// - The scheduler which acts upon these threads pub struct System { - thread_manager: ThreadManager, - obj_addrs: ObjAddr + thread_manager: ThreadManager } impl System { @@ -28,14 +26,12 @@ impl System { &mut self.thread_manager } - pub fn get_obj_addrs(&mut self) -> &mut ObjAddr { &mut self.obj_addrs } - } impl Default for System { /// System constructor fn default() -> Self { - Self { thread_manager: ThreadManager::new(), obj_addrs: ObjAddr::init() } + Self { thread_manager: ThreadManager::new() } } } diff --git a/src/kernel/thread_manager.rs b/src/kernel/thread_manager.rs index ee0bd86..b388163 100644 --- a/src/kernel/thread_manager.rs +++ b/src/kernel/thread_manager.rs @@ -1,8 +1,8 @@ use std::{rc::Rc, cell::{RefCell, Ref}}; -use crate::{utility::list::List, simulator::{machine::{NUM_INT_REGS, NUM_FP_REGS, Machine}, interrupt::InterruptStatus}}; +use crate::{utility::{list::List, objaddr::ObjAddr}, simulator::{machine::{NUM_INT_REGS, NUM_FP_REGS, Machine}, interrupt::InterruptStatus, error::{MachineOk, MachineError}}}; -use super::{thread::Thread, process::Process}; +use super::{thread::Thread, process::Process, synch::Semaphore}; pub const SIMULATORSTACKSIZE: usize = 32 * 1024; @@ -19,6 +19,7 @@ pub struct ThreadManager { pub g_alive: List>>, /// Thread in ready state waiting to become active ready_list: List>>, + obj_addrs: ObjAddr } impl ThreadManager { @@ -30,6 +31,7 @@ impl ThreadManager { g_thread_to_be_destroyed: Option::None, g_alive: List::default(), ready_list: List::default(), + obj_addrs: ObjAddr::init(), } } @@ -171,6 +173,49 @@ impl ThreadManager { machine.pc = t.thread_context.pc; } + pub fn sem_p(&mut self, id_sema: i32, machine: &mut Machine) -> Result { + match self.get_g_current_thread() { + Some(thread) => { + let rc1_thread = Rc::clone(thread); + let rc2_thread = Rc::clone(thread); + let sema = self.get_obj_addrs().search_semaphore(id_sema as i32); + if let Some(sema) = sema { + let old_status = machine.interrupt.set_status(InterruptStatus::InterruptOff); + sema.counter -= 1; + if sema.counter < 0 { + sema.waiting_queue.push(rc1_thread); + self.thread_sleep(machine, rc2_thread); + } + machine.interrupt.set_status(old_status); + Ok(MachineOk::Ok) + } else { + Err("Cannot find semaphore")? + } + }, + None => unreachable!("Current thread should not be None") + } + } + + pub fn sem_v(&mut self, id_sema: i32, machine: &mut Machine) -> Result { + let sema = self.get_obj_addrs().search_semaphore(id_sema as i32); + match sema { + Some(sema) => { + let old_status = machine.interrupt.set_status(InterruptStatus::InterruptOff); + sema.counter += 1; + match sema.waiting_queue.pop() { + Some(thread) => self.ready_to_run(thread), + None => () + } + machine.interrupt.set_status(old_status); + Ok(MachineOk::Ok) + }, + None => { + Err("Cannot find semaphore")? + } + } + + } + /// Currently running thread pub fn get_g_current_thread(&mut self) -> &Option>> { &self.g_current_thread @@ -198,6 +243,10 @@ impl ThreadManager { self.g_thread_to_be_destroyed = thread } + pub fn get_obj_addrs(&mut self) -> &mut ObjAddr { + &mut self.obj_addrs + } + } #[cfg(test)] diff --git a/src/utility/objaddr.rs b/src/utility/objaddr.rs index c898f63..92769aa 100644 --- a/src/utility/objaddr.rs +++ b/src/utility/objaddr.rs @@ -15,6 +15,7 @@ use crate::kernel::synch::{ Semaphore, Lock }; /// A method allows to detect of an object corresponding to a given /// identifier exists; this is used to check the parameters of system /// calls. +#[derive(PartialEq)] pub struct ObjAddr { last_id: i32, semaphores: HashMap, @@ -47,12 +48,12 @@ impl ObjAddr { } /// Searches for a semaphore of id **id** in self - pub fn search_semaphore(&self, id: i32) -> Option<&mut Semaphore> { + pub fn search_semaphore(&mut self, id: i32) -> Option<&mut Semaphore> { self.semaphores.get_mut(&id) } /// Searches for a lock of id **id** in self - pub fn search_lock(&self, id:i32) -> Option<&mut Lock> { + pub fn search_lock(&mut self, id:i32) -> Option<&mut Lock> { self.locks.get_mut(&id) }