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