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