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