From 05f72af035ce3010235558000c2fdb084a728e4c Mon Sep 17 00:00:00 2001 From: Samy Solhi Date: Thu, 13 Apr 2023 00:17:34 +0200 Subject: [PATCH] added lock acquire system call --- src/kernel/exception.rs | 9 +++++++-- src/kernel/synch.rs | 6 +++--- src/kernel/thread_manager.rs | 38 ++++++++++++++++++++++++++++++++++++ 3 files changed, 48 insertions(+), 5 deletions(-) diff --git a/src/kernel/exception.rs b/src/kernel/exception.rs index d03668b..d920143 100644 --- a/src/kernel/exception.rs +++ b/src/kernel/exception.rs @@ -177,7 +177,7 @@ fn syscall(machine: &mut Machine, system: &mut System) -> Result 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 Result { + 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 { 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); diff --git a/src/kernel/synch.rs b/src/kernel/synch.rs index 9f8eb02..0ca7d24 100644 --- a/src/kernel/synch.rs +++ b/src/kernel/synch.rs @@ -37,11 +37,11 @@ impl Semaphore { pub struct Lock { /// Thread owning the lock - owner: Option>>, + pub owner: Option>>, /// The queue of threads waiting for execution - waiting_queue:List>>, + pub waiting_queue:List>>, /// A boolean definig if the lock is free or not - free: bool + pub free: bool } diff --git a/src/kernel/thread_manager.rs b/src/kernel/thread_manager.rs index 33e768b..96c73eb 100644 --- a/src/kernel/thread_manager.rs +++ b/src/kernel/thread_manager.rs @@ -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 { + 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>> { &self.g_current_thread