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