xref: /DragonOS/kernel/src/libs/mutex.rs (revision 911132c4b8ea0e9c49a4e84b9fa1db114102acbb)
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