Fix exceptions with semaphore
This commit is contained in:
parent
134e2bd2cc
commit
21f3a72a3d
@ -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> {
|
||||||
|
@ -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>>>,
|
||||||
|
@ -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() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)]
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user