Fix exceptions with semaphore
This commit is contained in:
@ -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<Rc<RefCell<Thread>>>,
|
||||
/// Thread in ready state waiting to become active
|
||||
ready_list: List<Rc<RefCell<Thread>>>,
|
||||
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<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
|
||||
pub fn get_g_current_thread(&mut self) -> &Option<Rc<RefCell<Thread>>> {
|
||||
&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)]
|
||||
|
Reference in New Issue
Block a user