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