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