1935f40ecSlogin use core::{ 2935f40ecSlogin cell::UnsafeCell, 3935f40ecSlogin ops::{Deref, DerefMut}, 4935f40ecSlogin }; 5935f40ecSlogin 61496ba7bSLoGin use alloc::{collections::LinkedList, sync::Arc}; 7*91e9d4abSLoGin 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 // 检查当前进程是否处于等待队列中,如果不在,就加到等待队列内 671496ba7bSLoGin if self.check_pid_in_wait_list(&inner, ProcessManager::current_pcb().pid()) == false 681496ba7bSLoGin { 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)] 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内部的睡眠函数 106935f40ecSlogin fn __sleep(&self) { 1071496ba7bSLoGin let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() }; 1081496ba7bSLoGin ProcessManager::mark_sleep(true).ok(); 1091496ba7bSLoGin drop(irq_guard); 110935f40ecSlogin sched(); 111935f40ecSlogin } 112935f40ecSlogin 113935f40ecSlogin /// @brief 放锁。 114935f40ecSlogin /// 115935f40ecSlogin /// 本函数只能是私有的,且只能被守卫的drop方法调用,否则将无法保证并发安全。 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] 1351496ba7bSLoGin 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 152935f40ecSlogin 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> { 159935f40ecSlogin 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> { 166935f40ecSlogin fn drop(&mut self) { 167935f40ecSlogin self.lock.unlock(); 168935f40ecSlogin } 169935f40ecSlogin } 170