1935f40ecSlogin use core::{ 2935f40ecSlogin cell::UnsafeCell, 3935f40ecSlogin ops::{Deref, DerefMut}, 4935f40ecSlogin }; 5935f40ecSlogin 61496ba7bSLoGin use alloc::{collections::LinkedList, sync::Arc}; 791e9d4abSLoGin use system_error::SystemError; 8935f40ecSlogin 9935f40ecSlogin use crate::{ 10*f0c87a89SGnoCiYeH arch::CurrentIrqArch, 111496ba7bSLoGin exception::InterruptArch, 1278bf93f0SYJwu2023 libs::spinlock::SpinLockGuard, 131496ba7bSLoGin process::{Pid, ProcessControlBlock, ProcessManager}, 14*f0c87a89SGnoCiYeH sched::{schedule, SchedMode}, 15935f40ecSlogin }; 16935f40ecSlogin 17935f40ecSlogin use super::spinlock::SpinLock; 18935f40ecSlogin 19935f40ecSlogin #[derive(Debug)] 20935f40ecSlogin struct MutexInner { 21935f40ecSlogin /// 当前Mutex是否已经被上锁(上锁时,为true) 22935f40ecSlogin is_locked: bool, 23935f40ecSlogin /// 等待获得这个锁的进程的链表 241496ba7bSLoGin wait_list: LinkedList<Arc<ProcessControlBlock>>, 25935f40ecSlogin } 26935f40ecSlogin 27935f40ecSlogin /// @brief Mutex互斥量结构体 28935f40ecSlogin /// 请注意!由于Mutex属于休眠锁,因此,如果您的代码可能在中断上下文内执行,请勿采用Mutex! 29935f40ecSlogin #[derive(Debug)] 30935f40ecSlogin pub struct Mutex<T> { 31935f40ecSlogin /// 该Mutex保护的数据 32935f40ecSlogin data: UnsafeCell<T>, 33935f40ecSlogin /// Mutex内部的信息 34935f40ecSlogin inner: SpinLock<MutexInner>, 35935f40ecSlogin } 36935f40ecSlogin 37935f40ecSlogin /// @brief Mutex的守卫 38935f40ecSlogin #[derive(Debug)] 39935f40ecSlogin pub struct MutexGuard<'a, T: 'a> { 40935f40ecSlogin lock: &'a Mutex<T>, 41935f40ecSlogin } 42935f40ecSlogin 43935f40ecSlogin unsafe impl<T> Sync for Mutex<T> where T: Send {} 44935f40ecSlogin 45935f40ecSlogin impl<T> Mutex<T> { 46935f40ecSlogin /// @brief 初始化一个新的Mutex对象 47935f40ecSlogin #[allow(dead_code)] new(value: T) -> Self48935f40ecSlogin pub const fn new(value: T) -> Self { 49935f40ecSlogin return Self { 50935f40ecSlogin data: UnsafeCell::new(value), 51935f40ecSlogin inner: SpinLock::new(MutexInner { 52935f40ecSlogin is_locked: false, 531496ba7bSLoGin wait_list: LinkedList::new(), 54935f40ecSlogin }), 55935f40ecSlogin }; 56935f40ecSlogin } 57935f40ecSlogin 58935f40ecSlogin /// @brief 对Mutex加锁 59935f40ecSlogin /// @return MutexGuard<T> 返回Mutex的守卫,您可以使用这个守卫来操作被保护的数据 60935f40ecSlogin #[inline(always)] 61935f40ecSlogin #[allow(dead_code)] lock(&self) -> MutexGuard<T>62935f40ecSlogin pub fn lock(&self) -> MutexGuard<T> { 63935f40ecSlogin loop { 64935f40ecSlogin let mut inner: SpinLockGuard<MutexInner> = self.inner.lock(); 65935f40ecSlogin // 当前mutex已经上锁 66935f40ecSlogin if inner.is_locked { 67935f40ecSlogin // 检查当前进程是否处于等待队列中,如果不在,就加到等待队列内 68b5b571e0SLoGin if !self.check_pid_in_wait_list(&inner, ProcessManager::current_pcb().pid()) { 691496ba7bSLoGin inner.wait_list.push_back(ProcessManager::current_pcb()); 70935f40ecSlogin } 71935f40ecSlogin 72935f40ecSlogin // 加到等待唤醒的队列,然后睡眠 73935f40ecSlogin drop(inner); 74935f40ecSlogin self.__sleep(); 75935f40ecSlogin } else { 76935f40ecSlogin // 加锁成功 77935f40ecSlogin inner.is_locked = true; 78935f40ecSlogin drop(inner); 79935f40ecSlogin break; 80935f40ecSlogin } 81935f40ecSlogin } 82935f40ecSlogin 83935f40ecSlogin // 加锁成功,返回一个守卫 84935f40ecSlogin return MutexGuard { lock: self }; 85935f40ecSlogin } 86935f40ecSlogin 87935f40ecSlogin /// @brief 尝试对Mutex加锁。如果加锁失败,不会将当前进程加入等待队列。 88935f40ecSlogin /// @return Ok 加锁成功,返回Mutex的守卫 89935f40ecSlogin /// @return Err 如果Mutex当前已经上锁,则返回Err. 90935f40ecSlogin #[inline(always)] 91935f40ecSlogin #[allow(dead_code)] try_lock(&self) -> Result<MutexGuard<T>, SystemError>92676b8ef6SMork pub fn try_lock(&self) -> Result<MutexGuard<T>, SystemError> { 93935f40ecSlogin let mut inner = self.inner.lock(); 94935f40ecSlogin 95935f40ecSlogin // 如果当前mutex已经上锁,则失败 96935f40ecSlogin if inner.is_locked { 97676b8ef6SMork return Err(SystemError::EBUSY); 98935f40ecSlogin } else { 99935f40ecSlogin // 加锁成功 100935f40ecSlogin inner.is_locked = true; 101935f40ecSlogin return Ok(MutexGuard { lock: self }); 102935f40ecSlogin } 103935f40ecSlogin } 104935f40ecSlogin 105935f40ecSlogin /// @brief Mutex内部的睡眠函数 __sleep(&self)106935f40ecSlogin fn __sleep(&self) { 1071496ba7bSLoGin let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() }; 1081496ba7bSLoGin ProcessManager::mark_sleep(true).ok(); 1091496ba7bSLoGin drop(irq_guard); 110*f0c87a89SGnoCiYeH schedule(SchedMode::SM_NONE); 111935f40ecSlogin } 112935f40ecSlogin 113935f40ecSlogin /// @brief 放锁。 114935f40ecSlogin /// 115935f40ecSlogin /// 本函数只能是私有的,且只能被守卫的drop方法调用,否则将无法保证并发安全。 unlock(&self)116935f40ecSlogin fn unlock(&self) { 117935f40ecSlogin let mut inner: SpinLockGuard<MutexInner> = self.inner.lock(); 118935f40ecSlogin // 当前mutex一定是已经加锁的状态 119935f40ecSlogin assert!(inner.is_locked); 120935f40ecSlogin // 标记mutex已经解锁 121935f40ecSlogin inner.is_locked = false; 122935f40ecSlogin if inner.wait_list.is_empty() { 123935f40ecSlogin return; 124935f40ecSlogin } 125935f40ecSlogin 126935f40ecSlogin // wait_list不为空,则获取下一个要被唤醒的进程的pcb 1271496ba7bSLoGin let to_wakeup: Arc<ProcessControlBlock> = inner.wait_list.pop_front().unwrap(); 128935f40ecSlogin drop(inner); 129935f40ecSlogin 1301496ba7bSLoGin ProcessManager::wakeup(&to_wakeup).ok(); 131935f40ecSlogin } 132935f40ecSlogin 133935f40ecSlogin /// @brief 检查进程是否在该mutex的等待队列内 134935f40ecSlogin #[inline] check_pid_in_wait_list(&self, inner: &MutexInner, pid: Pid) -> bool1351496ba7bSLoGin fn check_pid_in_wait_list(&self, inner: &MutexInner, pid: Pid) -> bool { 136935f40ecSlogin for p in inner.wait_list.iter() { 1371496ba7bSLoGin if p.pid() == pid { 138935f40ecSlogin // 在等待队列内 139935f40ecSlogin return true; 140935f40ecSlogin } 141935f40ecSlogin } 142935f40ecSlogin 143935f40ecSlogin // 不在等待队列内 144935f40ecSlogin return false; 145935f40ecSlogin } 146935f40ecSlogin } 147935f40ecSlogin 148935f40ecSlogin /// 实现Deref trait,支持通过获取MutexGuard来获取临界区数据的不可变引用 149935f40ecSlogin impl<T> Deref for MutexGuard<'_, T> { 150935f40ecSlogin type Target = T; 151935f40ecSlogin deref(&self) -> &Self::Target152935f40ecSlogin fn deref(&self) -> &Self::Target { 153935f40ecSlogin return unsafe { &*self.lock.data.get() }; 154935f40ecSlogin } 155935f40ecSlogin } 156935f40ecSlogin 157935f40ecSlogin /// 实现DerefMut trait,支持通过获取MutexGuard来获取临界区数据的可变引用 158935f40ecSlogin impl<T> DerefMut for MutexGuard<'_, T> { deref_mut(&mut self) -> &mut Self::Target159935f40ecSlogin fn deref_mut(&mut self) -> &mut Self::Target { 160935f40ecSlogin return unsafe { &mut *self.lock.data.get() }; 161935f40ecSlogin } 162935f40ecSlogin } 163935f40ecSlogin 164935f40ecSlogin /// @brief 为MutexGuard实现Drop方法,那么,一旦守卫的生命周期结束,就会自动释放自旋锁,避免了忘记放锁的情况 165935f40ecSlogin impl<T> Drop for MutexGuard<'_, T> { drop(&mut self)166935f40ecSlogin fn drop(&mut self) { 167935f40ecSlogin self.lock.unlock(); 168935f40ecSlogin } 169935f40ecSlogin } 170