Fix exceptions with semaphore

This commit is contained in:
Quentin Legot 2023-04-12 14:49:08 +02:00
parent 134e2bd2cc
commit 21f3a72a3d
5 changed files with 64 additions and 25 deletions

View File

@ -2,7 +2,7 @@ use std::{cell::RefCell, rc::Rc};
use crate::{simulator::{machine::{ExceptionType, Machine}, error::{MachineOk, MachineError}}}; 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; type Error = String;
@ -200,21 +200,12 @@ fn syscall(machine: &mut Machine, system: &mut System) -> Result<MachineOk, Mach
fn sc_p(machine: &mut Machine, system: &mut System) -> Result<MachineOk, MachineError> { fn sc_p(machine: &mut Machine, system: &mut System) -> Result<MachineOk, MachineError> {
let id_sema = machine.int_reg.get_reg(10); let id_sema = machine.int_reg.get_reg(10);
match system.get_obj_addrs().search_semaphore(id_sema as i32) { system.get_thread_manager().sem_p(id_sema as i32, machine)
Some(sema) => { sema.p(machine, system.get_thread_manager()); Ok(MachineOk::Ok) }
None => Err(format!("Coudn't find semaphore {}", id_sema))?
}
} }
fn sc_v(machine: &mut Machine, system: &mut System) -> Result<MachineOk, MachineError> { fn sc_v(machine: &mut Machine, system: &mut System) -> Result<MachineOk, MachineError> {
let id_sema = machine.int_reg.get_reg(10); let id_sema = machine.int_reg.get_reg(10);
match system.get_obj_addrs().search_semaphore(id_sema as i32) { system.get_thread_manager().sem_v(id_sema as i32, machine)
Some(sema) => {
sema.v(machine, system.get_thread_manager());
Ok(MachineOk::Ok)
},
None => Err(format!("Couldn't find semaphore {}", id_sema))?
}
} }
fn sc_sem_create(machine: &mut Machine) -> Result<MachineOk, MachineError> { fn sc_sem_create(machine: &mut Machine) -> Result<MachineOk, MachineError> {

View File

@ -7,12 +7,13 @@ use std::rc::Rc;
use super::thread_manager::ThreadManager; use super::thread_manager::ThreadManager;
/// Structure of a Semaphore used for synchronisation /// Structure of a Semaphore used for synchronisation
#[derive(PartialEq)]
pub struct Semaphore { pub struct Semaphore {
/// Counter of simultanous Semaphore /// Counter of simultanous Semaphore
counter:i32, pub counter:i32,
/// QUeue of Semaphore waiting to be exucated /// QUeue of Semaphore waiting to be exucated
waiting_queue:List<Rc<RefCell<Thread>>>, pub waiting_queue:List<Rc<RefCell<Thread>>>,
} }
@ -78,7 +79,8 @@ impl Semaphore {
/// Lock used for synchronisation, can be interpreted has a Semaphore with a /// Lock used for synchronisation, can be interpreted has a Semaphore with a
/// counter of 1 /// counter of 1
/// It's used for critical parts /// It's used for critical parts
pub struct Lock{ #[derive(PartialEq)]
pub struct Lock {
/// Thread owning the lock /// Thread owning the lock
owner: Option<Rc<RefCell<Thread>>>, owner: Option<Rc<RefCell<Thread>>>,

View File

@ -3,7 +3,6 @@
//! Module containing structs and methods pertaining to the state of the operating system //! Module containing structs and methods pertaining to the state of the operating system
use super::{thread_manager::ThreadManager}; use super::{thread_manager::ThreadManager};
use crate::utility::objaddr::ObjAddr;
/// # System /// # System
/// ///
@ -16,8 +15,7 @@ use crate::utility::objaddr::ObjAddr;
/// - The thread to be destroyed next /// - The thread to be destroyed next
/// - The scheduler which acts upon these threads /// - The scheduler which acts upon these threads
pub struct System { pub struct System {
thread_manager: ThreadManager, thread_manager: ThreadManager
obj_addrs: ObjAddr
} }
impl System { impl System {
@ -28,14 +26,12 @@ impl System {
&mut self.thread_manager &mut self.thread_manager
} }
pub fn get_obj_addrs(&mut self) -> &mut ObjAddr { &mut self.obj_addrs }
} }
impl Default for System { impl Default for System {
/// System constructor /// System constructor
fn default() -> Self { fn default() -> Self {
Self { thread_manager: ThreadManager::new(), obj_addrs: ObjAddr::init() } Self { thread_manager: ThreadManager::new() }
} }
} }

View File

@ -1,8 +1,8 @@
use std::{rc::Rc, cell::{RefCell, Ref}}; 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; pub const SIMULATORSTACKSIZE: usize = 32 * 1024;
@ -19,6 +19,7 @@ pub struct ThreadManager {
pub g_alive: List<Rc<RefCell<Thread>>>, pub g_alive: List<Rc<RefCell<Thread>>>,
/// Thread in ready state waiting to become active /// Thread in ready state waiting to become active
ready_list: List<Rc<RefCell<Thread>>>, ready_list: List<Rc<RefCell<Thread>>>,
obj_addrs: ObjAddr
} }
impl ThreadManager { impl ThreadManager {
@ -30,6 +31,7 @@ impl ThreadManager {
g_thread_to_be_destroyed: Option::None, g_thread_to_be_destroyed: Option::None,
g_alive: List::default(), g_alive: List::default(),
ready_list: List::default(), ready_list: List::default(),
obj_addrs: ObjAddr::init(),
} }
} }
@ -171,6 +173,49 @@ impl ThreadManager {
machine.pc = t.thread_context.pc; machine.pc = t.thread_context.pc;
} }
pub fn sem_p(&mut self, id_sema: i32, machine: &mut Machine) -> Result<MachineOk, MachineError> {
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<MachineOk, MachineError> {
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 /// Currently running thread
pub fn get_g_current_thread(&mut self) -> &Option<Rc<RefCell<Thread>>> { pub fn get_g_current_thread(&mut self) -> &Option<Rc<RefCell<Thread>>> {
&self.g_current_thread &self.g_current_thread
@ -198,6 +243,10 @@ impl ThreadManager {
self.g_thread_to_be_destroyed = thread self.g_thread_to_be_destroyed = thread
} }
pub fn get_obj_addrs(&mut self) -> &mut ObjAddr {
&mut self.obj_addrs
}
} }
#[cfg(test)] #[cfg(test)]

View File

@ -15,6 +15,7 @@ use crate::kernel::synch::{ Semaphore, Lock };
/// A method allows to detect of an object corresponding to a given /// A method allows to detect of an object corresponding to a given
/// identifier exists; this is used to check the parameters of system /// identifier exists; this is used to check the parameters of system
/// calls. /// calls.
#[derive(PartialEq)]
pub struct ObjAddr { pub struct ObjAddr {
last_id: i32, last_id: i32,
semaphores: HashMap<i32, Semaphore>, semaphores: HashMap<i32, Semaphore>,
@ -47,12 +48,12 @@ impl ObjAddr {
} }
/// Searches for a semaphore of id **id** in self /// 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) self.semaphores.get_mut(&id)
} }
/// Searches for a lock of id **id** in self /// 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) self.locks.get_mut(&id)
} }