added lock acquire system call
This commit is contained in:
parent
6e6d3424f5
commit
05f72af035
@ -177,7 +177,7 @@ fn syscall(machine: &mut Machine, system: &mut System) -> Result<MachineOk, Mach
|
||||
SC_SEM_DESTROY => sc_sem_remove(machine, system),
|
||||
SC_LOCK_CREATE => sc_lock_create(machine, system),
|
||||
SC_LOCK_DESTROY => sc_lock_destroy(machine, system),
|
||||
SC_LOCK_ACQUIRE => todo!(),
|
||||
SC_LOCK_ACQUIRE => sc_lock_acquire(machine, system),
|
||||
SC_LOCK_RELEASE => todo!(),
|
||||
SC_COND_CREATE => todo!(),
|
||||
SC_COND_DESTROY => todo!(),
|
||||
@ -197,9 +197,14 @@ fn syscall(machine: &mut Machine, system: &mut System) -> Result<MachineOk, Mach
|
||||
}
|
||||
}
|
||||
|
||||
fn sc_lock_acquire(machine: &mut Machine, system: &mut System) -> Result<MachineOk, MachineError> {
|
||||
let id = machine.read_int_register(10) as i32;
|
||||
system.get_thread_manager().lock_acquire(id, machine)
|
||||
}
|
||||
|
||||
fn sc_lock_create(machine: &mut Machine, system: &mut System) -> Result<MachineOk, MachineError> {
|
||||
let addr_name = machine.read_int_register(10) as usize;
|
||||
let size = get_length_param(addr_name, &machine);
|
||||
let size = get_length_param(addr_name, machine);
|
||||
let _name = get_string_param(addr_name, size, machine);
|
||||
let lock = Lock::new();
|
||||
let id = system.get_thread_manager().get_obj_addrs().add_lock(lock);
|
||||
|
@ -37,11 +37,11 @@ impl Semaphore {
|
||||
pub struct Lock {
|
||||
|
||||
/// Thread owning the lock
|
||||
owner: Option<Rc<RefCell<Thread>>>,
|
||||
pub owner: Option<Rc<RefCell<Thread>>>,
|
||||
/// The queue of threads waiting for execution
|
||||
waiting_queue:List<Rc<RefCell<Thread>>>,
|
||||
pub waiting_queue:List<Rc<RefCell<Thread>>>,
|
||||
/// A boolean definig if the lock is free or not
|
||||
free: bool
|
||||
pub free: bool
|
||||
|
||||
}
|
||||
|
||||
|
@ -236,6 +236,44 @@ impl ThreadManager {
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// Wait until the lock become free. Checking the
|
||||
/// state of the lock (free or busy) and modify it must be done
|
||||
/// atomically, so we need to disable interrupts before checking
|
||||
/// the value of free.
|
||||
///
|
||||
/// Note that thread_manager::thread_seep assumes that interrupts are disabled
|
||||
/// when it is called.
|
||||
///
|
||||
/// ### Parameters
|
||||
/// - **id** id of the lock, stored in [`ObjAddr`], id given by user program thought exceptions
|
||||
/// - **machine** the machine where the threads are executed
|
||||
pub fn lock_acquire(&mut self, id: i32, machine: &mut Machine) -> Result<MachineOk, MachineError> {
|
||||
match self.get_g_current_thread() {
|
||||
Some(thread) => {
|
||||
let rc_thread = Rc::clone(thread);
|
||||
let lock = self.get_obj_addrs().search_lock(id);
|
||||
match lock {
|
||||
Some(lock) => {
|
||||
let old_status = machine.interrupt.set_status(InterruptStatus::InterruptOff);
|
||||
if lock.free {
|
||||
lock.free = false;
|
||||
lock.owner = Some(Rc::clone(&rc_thread))
|
||||
} else {
|
||||
let thread = Rc::clone(&rc_thread);
|
||||
lock.waiting_queue.push(Rc::clone(&thread));
|
||||
self.thread_sleep(machine, Rc::clone(&thread));
|
||||
}
|
||||
machine.interrupt.set_status(old_status);
|
||||
Ok(MachineOk::Ok)
|
||||
},
|
||||
None => Err("Cannot find lock")?
|
||||
}
|
||||
},
|
||||
None => unreachable!("Current thread should not be None")
|
||||
}
|
||||
}
|
||||
|
||||
/// Currently running thread
|
||||
pub fn get_g_current_thread(&mut self) -> &Option<Rc<RefCell<Thread>>> {
|
||||
&self.g_current_thread
|
||||
|
Loading…
Reference in New Issue
Block a user