1 use core::{ 2 cell::UnsafeCell, 3 ops::{Deref, DerefMut}, 4 }; 5 6 use alloc::{collections::LinkedList, sync::Arc}; 7 use system_error::SystemError; 8 9 use crate::{ 10 arch::{sched::sched, CurrentIrqArch}, 11 exception::InterruptArch, 12 libs::spinlock::SpinLockGuard, 13 process::{Pid, ProcessControlBlock, ProcessManager}, 14 }; 15 16 use super::spinlock::SpinLock; 17 18 #[derive(Debug)] 19 struct MutexInner { 20 /// 当前Mutex是否已经被上锁(上锁时,为true) 21 is_locked: bool, 22 /// 等待获得这个锁的进程的链表 23 wait_list: LinkedList<Arc<ProcessControlBlock>>, 24 } 25 26 /// @brief Mutex互斥量结构体 27 /// 请注意!由于Mutex属于休眠锁,因此,如果您的代码可能在中断上下文内执行,请勿采用Mutex! 28 #[derive(Debug)] 29 pub struct Mutex<T> { 30 /// 该Mutex保护的数据 31 data: UnsafeCell<T>, 32 /// Mutex内部的信息 33 inner: SpinLock<MutexInner>, 34 } 35 36 /// @brief Mutex的守卫 37 #[derive(Debug)] 38 pub struct MutexGuard<'a, T: 'a> { 39 lock: &'a Mutex<T>, 40 } 41 42 unsafe impl<T> Sync for Mutex<T> where T: Send {} 43 44 impl<T> Mutex<T> { 45 /// @brief 初始化一个新的Mutex对象 46 #[allow(dead_code)] 47 pub const fn new(value: T) -> Self { 48 return Self { 49 data: UnsafeCell::new(value), 50 inner: SpinLock::new(MutexInner { 51 is_locked: false, 52 wait_list: LinkedList::new(), 53 }), 54 }; 55 } 56 57 /// @brief 对Mutex加锁 58 /// @return MutexGuard<T> 返回Mutex的守卫,您可以使用这个守卫来操作被保护的数据 59 #[inline(always)] 60 #[allow(dead_code)] 61 pub fn lock(&self) -> MutexGuard<T> { 62 loop { 63 let mut inner: SpinLockGuard<MutexInner> = self.inner.lock(); 64 // 当前mutex已经上锁 65 if inner.is_locked { 66 // 检查当前进程是否处于等待队列中,如果不在,就加到等待队列内 67 if !self.check_pid_in_wait_list(&inner, ProcessManager::current_pcb().pid()) { 68 inner.wait_list.push_back(ProcessManager::current_pcb()); 69 } 70 71 // 加到等待唤醒的队列,然后睡眠 72 drop(inner); 73 self.__sleep(); 74 } else { 75 // 加锁成功 76 inner.is_locked = true; 77 drop(inner); 78 break; 79 } 80 } 81 82 // 加锁成功,返回一个守卫 83 return MutexGuard { lock: self }; 84 } 85 86 /// @brief 尝试对Mutex加锁。如果加锁失败,不会将当前进程加入等待队列。 87 /// @return Ok 加锁成功,返回Mutex的守卫 88 /// @return Err 如果Mutex当前已经上锁,则返回Err. 89 #[inline(always)] 90 #[allow(dead_code)] 91 pub fn try_lock(&self) -> Result<MutexGuard<T>, SystemError> { 92 let mut inner = self.inner.lock(); 93 94 // 如果当前mutex已经上锁,则失败 95 if inner.is_locked { 96 return Err(SystemError::EBUSY); 97 } else { 98 // 加锁成功 99 inner.is_locked = true; 100 return Ok(MutexGuard { lock: self }); 101 } 102 } 103 104 /// @brief Mutex内部的睡眠函数 105 fn __sleep(&self) { 106 let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() }; 107 ProcessManager::mark_sleep(true).ok(); 108 drop(irq_guard); 109 sched(); 110 } 111 112 /// @brief 放锁。 113 /// 114 /// 本函数只能是私有的,且只能被守卫的drop方法调用,否则将无法保证并发安全。 115 fn unlock(&self) { 116 let mut inner: SpinLockGuard<MutexInner> = self.inner.lock(); 117 // 当前mutex一定是已经加锁的状态 118 assert!(inner.is_locked); 119 // 标记mutex已经解锁 120 inner.is_locked = false; 121 if inner.wait_list.is_empty() { 122 return; 123 } 124 125 // wait_list不为空,则获取下一个要被唤醒的进程的pcb 126 let to_wakeup: Arc<ProcessControlBlock> = inner.wait_list.pop_front().unwrap(); 127 drop(inner); 128 129 ProcessManager::wakeup(&to_wakeup).ok(); 130 } 131 132 /// @brief 检查进程是否在该mutex的等待队列内 133 #[inline] 134 fn check_pid_in_wait_list(&self, inner: &MutexInner, pid: Pid) -> bool { 135 for p in inner.wait_list.iter() { 136 if p.pid() == pid { 137 // 在等待队列内 138 return true; 139 } 140 } 141 142 // 不在等待队列内 143 return false; 144 } 145 } 146 147 /// 实现Deref trait,支持通过获取MutexGuard来获取临界区数据的不可变引用 148 impl<T> Deref for MutexGuard<'_, T> { 149 type Target = T; 150 151 fn deref(&self) -> &Self::Target { 152 return unsafe { &*self.lock.data.get() }; 153 } 154 } 155 156 /// 实现DerefMut trait,支持通过获取MutexGuard来获取临界区数据的可变引用 157 impl<T> DerefMut for MutexGuard<'_, T> { 158 fn deref_mut(&mut self) -> &mut Self::Target { 159 return unsafe { &mut *self.lock.data.get() }; 160 } 161 } 162 163 /// @brief 为MutexGuard实现Drop方法,那么,一旦守卫的生命周期结束,就会自动释放自旋锁,避免了忘记放锁的情况 164 impl<T> Drop for MutexGuard<'_, T> { 165 fn drop(&mut self) { 166 self.lock.unlock(); 167 } 168 } 169