xref: /DragonOS/kernel/src/libs/wait_queue.rs (revision 338f6903262c5031abad3c8e361813355a27fcdb)
1 // #![allow(dead_code)]
2 use core::intrinsics::unlikely;
3 
4 use alloc::{collections::LinkedList, sync::Arc, vec::Vec};
5 
6 use crate::{
7     arch::{sched::sched, CurrentIrqArch},
8     exception::InterruptArch,
9     kerror,
10     process::{ProcessControlBlock, ProcessManager, ProcessState},
11 };
12 
13 use super::{
14     mutex::MutexGuard,
15     spinlock::{SpinLock, SpinLockGuard},
16 };
17 
18 #[derive(Debug)]
19 struct InnerWaitQueue {
20     /// 等待队列的链表
21     wait_list: LinkedList<Arc<ProcessControlBlock>>,
22 }
23 
24 /// 被自旋锁保护的等待队列
25 #[derive(Debug)]
26 pub struct WaitQueue(SpinLock<InnerWaitQueue>);
27 
28 #[allow(dead_code)]
29 impl WaitQueue {
30     pub const INIT: WaitQueue = WaitQueue(SpinLock::new(InnerWaitQueue::INIT));
31 
32     /// @brief 让当前进程在等待队列上进行等待,并且,允许被信号打断
33     pub fn sleep(&self) {
34         before_sleep_check(0);
35         let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock_irqsave();
36         ProcessManager::mark_sleep(true).unwrap_or_else(|e| {
37             panic!("sleep error: {:?}", e);
38         });
39         guard.wait_list.push_back(ProcessManager::current_pcb());
40         drop(guard);
41         sched();
42     }
43 
44     /// @brief 让当前进程在等待队列上进行等待,并且,在释放waitqueue的锁之前,执行f函数闭包
45     pub fn sleep_with_func<F>(&self, f: F)
46     where
47         F: FnOnce(),
48     {
49         before_sleep_check(0);
50         let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock();
51         let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
52         ProcessManager::mark_sleep(true).unwrap_or_else(|e| {
53             panic!("sleep error: {:?}", e);
54         });
55         drop(irq_guard);
56         guard.wait_list.push_back(ProcessManager::current_pcb());
57         f();
58 
59         drop(guard);
60         sched();
61     }
62 
63     /// @brief 让当前进程在等待队列上进行等待. 但是,在释放waitqueue的锁之后,不会调用调度函数。
64     /// 这样的设计,是为了让调用者可以在执行本函数之后,执行一些操作,然后再【手动调用调度函数】。
65     ///
66     /// 执行本函数前,需要确保处于【中断禁止】状态。
67     ///
68     /// 尽管sleep_with_func和sleep_without_schedule都可以实现这个功能,但是,sleep_with_func会在释放锁之前,执行f函数闭包。
69     ///
70     /// 考虑这样一个场景:
71     /// 等待队列位于某个自旋锁保护的数据结构A中,我们希望在进程睡眠的同时,释放数据结构A的锁。
72     /// 在这种情况下,如果使用sleep_with_func,所有权系统不会允许我们这么做。
73     /// 因此,sleep_without_schedule的设计,正是为了解决这个问题。
74     ///
75     /// 由于sleep_without_schedule不会调用调度函数,因此,如果开发者忘记在执行本函数之后,手动调用调度函数,
76     /// 由于时钟中断到来或者‘其他cpu kick了当前cpu’,可能会导致一些未定义的行为。
77     pub unsafe fn sleep_without_schedule(&self) {
78         before_sleep_check(1);
79         // 安全检查:确保当前处于中断禁止状态
80         assert!(CurrentIrqArch::is_irq_enabled() == false);
81         let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock();
82         ProcessManager::mark_sleep(true).unwrap_or_else(|e| {
83             panic!("sleep error: {:?}", e);
84         });
85         guard.wait_list.push_back(ProcessManager::current_pcb());
86         drop(guard);
87     }
88 
89     pub unsafe fn sleep_without_schedule_uninterruptible(&self) {
90         before_sleep_check(0);
91         // 安全检查:确保当前处于中断禁止状态
92         assert!(CurrentIrqArch::is_irq_enabled() == false);
93         let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock();
94         ProcessManager::mark_sleep(false).unwrap_or_else(|e| {
95             panic!("sleep error: {:?}", e);
96         });
97         guard.wait_list.push_back(ProcessManager::current_pcb());
98         drop(guard);
99     }
100     /// @brief 让当前进程在等待队列上进行等待,并且,不允许被信号打断
101     pub fn sleep_uninterruptible(&self) {
102         before_sleep_check(0);
103         let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock();
104         let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
105         ProcessManager::mark_sleep(false).unwrap_or_else(|e| {
106             panic!("sleep error: {:?}", e);
107         });
108         drop(irq_guard);
109         guard.wait_list.push_back(ProcessManager::current_pcb());
110         drop(guard);
111         sched();
112     }
113 
114     /// @brief 让当前进程在等待队列上进行等待,并且,允许被信号打断。
115     /// 在当前进程的pcb加入队列后,解锁指定的自旋锁。
116     pub fn sleep_unlock_spinlock<T>(&self, to_unlock: SpinLockGuard<T>) {
117         before_sleep_check(1);
118         let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock();
119         let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
120         ProcessManager::mark_sleep(true).unwrap_or_else(|e| {
121             panic!("sleep error: {:?}", e);
122         });
123         drop(irq_guard);
124         guard.wait_list.push_back(ProcessManager::current_pcb());
125         drop(to_unlock);
126         drop(guard);
127         sched();
128     }
129 
130     /// @brief 让当前进程在等待队列上进行等待,并且,允许被信号打断。
131     /// 在当前进程的pcb加入队列后,解锁指定的Mutex。
132     pub fn sleep_unlock_mutex<T>(&self, to_unlock: MutexGuard<T>) {
133         before_sleep_check(1);
134         let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock();
135         let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
136         ProcessManager::mark_sleep(true).unwrap_or_else(|e| {
137             panic!("sleep error: {:?}", e);
138         });
139         drop(irq_guard);
140         guard.wait_list.push_back(ProcessManager::current_pcb());
141         drop(to_unlock);
142         drop(guard);
143         sched();
144     }
145 
146     /// @brief 让当前进程在等待队列上进行等待,并且,不允许被信号打断。
147     /// 在当前进程的pcb加入队列后,解锁指定的自旋锁。
148     pub fn sleep_uninterruptible_unlock_spinlock<T>(&self, to_unlock: SpinLockGuard<T>) {
149         before_sleep_check(1);
150         let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock();
151         let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
152         ProcessManager::mark_sleep(false).unwrap_or_else(|e| {
153             panic!("sleep error: {:?}", e);
154         });
155         drop(irq_guard);
156         guard.wait_list.push_back(ProcessManager::current_pcb());
157         drop(to_unlock);
158         drop(guard);
159         sched();
160     }
161 
162     /// @brief 让当前进程在等待队列上进行等待,并且,不允许被信号打断。
163     /// 在当前进程的pcb加入队列后,解锁指定的Mutex。
164     pub fn sleep_uninterruptible_unlock_mutex<T>(&self, to_unlock: MutexGuard<T>) {
165         before_sleep_check(1);
166         let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock();
167         let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
168         ProcessManager::mark_sleep(false).unwrap_or_else(|e| {
169             panic!("sleep error: {:?}", e);
170         });
171         drop(irq_guard);
172 
173         guard.wait_list.push_back(ProcessManager::current_pcb());
174 
175         drop(to_unlock);
176         drop(guard);
177         sched();
178     }
179 
180     /// @brief 唤醒在队列中等待的第一个进程。
181     /// 如果这个进程的state与给定的state进行and操作之后,结果不为0,则唤醒它。
182     ///
183     /// @param state 用于判断的state,如果队列第一个进程与这个state相同,或者为None(表示不进行这个判断),则唤醒这个进程。
184     ///
185     /// @return true 成功唤醒进程
186     /// @return false 没有唤醒进程
187     pub fn wakeup(&self, state: Option<ProcessState>) -> bool {
188         let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock_irqsave();
189         // 如果队列为空,则返回
190         if guard.wait_list.is_empty() {
191             return false;
192         }
193         // 如果队列头部的pcb的state与给定的state相与,结果不为0,则唤醒
194         if let Some(state) = state {
195             if guard
196                 .wait_list
197                 .front()
198                 .unwrap()
199                 .sched_info()
200                 .inner_lock_read_irqsave()
201                 .state()
202                 != state
203             {
204                 return false;
205             }
206         }
207         let to_wakeup = guard.wait_list.pop_front().unwrap();
208         drop(guard);
209         let res = ProcessManager::wakeup(&to_wakeup).is_ok();
210         return res;
211     }
212 
213     /// @brief 唤醒在队列中,符合条件的所有进程。
214     ///
215     /// @param state 用于判断的state,如果一个进程与这个state相同,或者为None(表示不进行这个判断),则唤醒这个进程。
216     pub fn wakeup_all(&self, state: Option<ProcessState>) {
217         let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock_irqsave();
218         // 如果队列为空,则返回
219         if guard.wait_list.is_empty() {
220             return;
221         }
222 
223         let mut to_push_back: Vec<Arc<ProcessControlBlock>> = Vec::new();
224         // 如果队列头部的pcb的state与给定的state相与,结果不为0,则唤醒
225         while let Some(to_wakeup) = guard.wait_list.pop_front() {
226             let mut wake = false;
227             if let Some(state) = state {
228                 if to_wakeup.sched_info().inner_lock_read_irqsave().state() == state {
229                     wake = true;
230                 }
231             } else {
232                 wake = true;
233             }
234 
235             if wake {
236                 ProcessManager::wakeup(&to_wakeup).unwrap_or_else(|e| {
237                     kerror!("wakeup pid: {:?} error: {:?}", to_wakeup.pid(), e);
238                 });
239                 continue;
240             } else {
241                 to_push_back.push(to_wakeup);
242             }
243         }
244 
245         for to_wakeup in to_push_back {
246             guard.wait_list.push_back(to_wakeup);
247         }
248     }
249 
250     /// @brief 获得当前等待队列的大小
251     pub fn len(&self) -> usize {
252         return self.0.lock().wait_list.len();
253     }
254 }
255 
256 impl InnerWaitQueue {
257     pub const INIT: InnerWaitQueue = InnerWaitQueue {
258         wait_list: LinkedList::new(),
259     };
260 }
261 
262 fn before_sleep_check(max_preempt: usize) {
263     let pcb = ProcessManager::current_pcb();
264     if unlikely(pcb.preempt_count() > max_preempt) {
265         kwarn!(
266             "Process {:?}: Try to sleep when preempt count is {}",
267             pcb.pid(),
268             pcb.preempt_count()
269         );
270     }
271 }
272 
273 /// 事件等待队列
274 #[derive(Debug)]
275 pub struct EventWaitQueue {
276     wait_list: SpinLock<Vec<(u64, Arc<ProcessControlBlock>)>>,
277 }
278 
279 #[allow(dead_code)]
280 impl EventWaitQueue {
281     pub fn new() -> Self {
282         Self {
283             wait_list: SpinLock::new(Vec::new()),
284         }
285     }
286 
287     /// ## 让当前进程在该队列上等待感兴趣的事件
288     ///
289     /// ### 参数
290     /// - events: 进程感兴趣的事件,events最好是为位表示,一位表示一个事件
291     ///
292     /// 注意,使用前应该注意有可能其他地方定义了冲突的事件,可能会导致未定义行为
293     pub fn sleep(&self, events: u64) {
294         before_sleep_check(0);
295         let mut guard = self.wait_list.lock_irqsave();
296         ProcessManager::mark_sleep(true).unwrap_or_else(|e| {
297             panic!("sleep error: {:?}", e);
298         });
299         guard.push((events, ProcessManager::current_pcb()));
300         drop(guard);
301         sched();
302     }
303 
304     pub unsafe fn sleep_without_schedule(&self, events: u64) {
305         before_sleep_check(1);
306         let mut guard = self.wait_list.lock_irqsave();
307         ProcessManager::mark_sleep(true).unwrap_or_else(|e| {
308             panic!("sleep error: {:?}", e);
309         });
310         guard.push((events, ProcessManager::current_pcb()));
311         drop(guard);
312     }
313 
314     pub fn sleep_unlock_spinlock<T>(&self, events: u64, to_unlock: SpinLockGuard<T>) {
315         before_sleep_check(1);
316         let mut guard = self.wait_list.lock_irqsave();
317         let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
318         ProcessManager::mark_sleep(true).unwrap_or_else(|e| {
319             panic!("sleep error: {:?}", e);
320         });
321         drop(irq_guard);
322         guard.push((events, ProcessManager::current_pcb()));
323         drop(to_unlock);
324         drop(guard);
325         sched();
326     }
327 
328     /// ### 唤醒该队列上等待events的进程
329     ///
330     ///  ### 参数
331     /// - events: 发生的事件
332     ///
333     /// 需要注意的是,只要触发了events中的任意一件事件,进程都会被唤醒
334     pub fn wakeup_any(&self, events: u64) -> usize {
335         let mut ret = 0;
336 
337         let mut wq_guard = self.wait_list.lock_irqsave();
338         wq_guard.retain(|(es, pcb)| {
339             if *es & events > 0 {
340                 // 有感兴趣的事件
341                 if ProcessManager::wakeup(pcb).is_ok() {
342                     ret += 1;
343                     return false;
344                 } else {
345                     return true;
346                 }
347             } else {
348                 return true;
349             }
350         });
351         ret
352     }
353 
354     /// ### 唤醒该队列上等待events的进程
355     ///
356     ///  ### 参数
357     /// - events: 发生的事件
358     ///
359     /// 需要注意的是,只有满足所有事件的进程才会被唤醒
360     pub fn wakeup(&self, events: u64) -> usize {
361         let mut ret = 0;
362         let mut wq_guard = self.wait_list.lock_irqsave();
363         wq_guard.retain(|(es, pcb)| {
364             if *es == events {
365                 // 有感兴趣的事件
366                 if ProcessManager::wakeup(pcb).is_ok() {
367                     ret += 1;
368                     return false;
369                 } else {
370                     return true;
371                 }
372             } else {
373                 return true;
374             }
375         });
376         ret
377     }
378 
379     pub fn wakeup_all(&self) {
380         self.wakeup_any(u64::MAX);
381     }
382 }
383