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