xref: /DragonOS/kernel/src/libs/wait_queue.rs (revision 406099704eb939ae23b18f0cfb3ed36c534c1c84)
1151251b5Slogin #![allow(dead_code)]
22f6f547aSGnoCiYeH use core::intrinsics::unlikely;
32f6f547aSGnoCiYeH 
41496ba7bSLoGin use alloc::{collections::LinkedList, sync::Arc, vec::Vec};
5c8025a88Slogin 
6151251b5Slogin use crate::{
71496ba7bSLoGin     arch::{sched::sched, CurrentIrqArch},
8f678331aShanjiezhou     exception::InterruptArch,
91496ba7bSLoGin     kerror,
101496ba7bSLoGin     process::{ProcessControlBlock, ProcessManager, ProcessState},
11151251b5Slogin };
12151251b5Slogin 
13151251b5Slogin use super::{
14151251b5Slogin     mutex::MutexGuard,
15151251b5Slogin     spinlock::{SpinLock, SpinLockGuard},
16151251b5Slogin };
17c8025a88Slogin 
18151251b5Slogin #[derive(Debug)]
19151251b5Slogin struct InnerWaitQueue {
20151251b5Slogin     /// 等待队列的链表
211496ba7bSLoGin     wait_list: LinkedList<Arc<ProcessControlBlock>>,
22151251b5Slogin }
23151251b5Slogin 
24151251b5Slogin /// 被自旋锁保护的等待队列
25151251b5Slogin #[derive(Debug)]
26151251b5Slogin pub struct WaitQueue(SpinLock<InnerWaitQueue>);
27151251b5Slogin 
28151251b5Slogin impl WaitQueue {
29151251b5Slogin     pub const INIT: WaitQueue = WaitQueue(SpinLock::new(InnerWaitQueue::INIT));
30151251b5Slogin 
31151251b5Slogin     /// @brief 让当前进程在等待队列上进行等待,并且,允许被信号打断
32151251b5Slogin     pub fn sleep(&self) {
33*40609970SGnoCiYeH         before_sleep_check(0);
341496ba7bSLoGin         let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock_irqsave();
351496ba7bSLoGin         ProcessManager::mark_sleep(true).unwrap_or_else(|e| {
361496ba7bSLoGin             panic!("sleep error: {:?}", e);
371496ba7bSLoGin         });
381496ba7bSLoGin         guard.wait_list.push_back(ProcessManager::current_pcb());
39151251b5Slogin         drop(guard);
40151251b5Slogin         sched();
41151251b5Slogin     }
42151251b5Slogin 
43f678331aShanjiezhou     /// @brief 让当前进程在等待队列上进行等待,并且,在释放waitqueue的锁之前,执行f函数闭包
44f678331aShanjiezhou     pub fn sleep_with_func<F>(&self, f: F)
45f678331aShanjiezhou     where
46f678331aShanjiezhou         F: FnOnce(),
47f678331aShanjiezhou     {
48*40609970SGnoCiYeH         before_sleep_check(0);
49f678331aShanjiezhou         let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock();
501496ba7bSLoGin         let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
511496ba7bSLoGin         ProcessManager::mark_sleep(true).unwrap_or_else(|e| {
521496ba7bSLoGin             panic!("sleep error: {:?}", e);
531496ba7bSLoGin         });
541496ba7bSLoGin         drop(irq_guard);
551496ba7bSLoGin         guard.wait_list.push_back(ProcessManager::current_pcb());
56f678331aShanjiezhou         f();
572f6f547aSGnoCiYeH 
58f678331aShanjiezhou         drop(guard);
59f678331aShanjiezhou         sched();
60f678331aShanjiezhou     }
61f678331aShanjiezhou 
62f678331aShanjiezhou     /// @brief 让当前进程在等待队列上进行等待. 但是,在释放waitqueue的锁之后,不会调用调度函数。
63f678331aShanjiezhou     /// 这样的设计,是为了让调用者可以在执行本函数之后,执行一些操作,然后再【手动调用调度函数】。
64f678331aShanjiezhou     ///
65f678331aShanjiezhou     /// 执行本函数前,需要确保处于【中断禁止】状态。
66f678331aShanjiezhou     ///
67f678331aShanjiezhou     /// 尽管sleep_with_func和sleep_without_schedule都可以实现这个功能,但是,sleep_with_func会在释放锁之前,执行f函数闭包。
68f678331aShanjiezhou     ///
69f678331aShanjiezhou     /// 考虑这样一个场景:
70f678331aShanjiezhou     /// 等待队列位于某个自旋锁保护的数据结构A中,我们希望在进程睡眠的同时,释放数据结构A的锁。
71f678331aShanjiezhou     /// 在这种情况下,如果使用sleep_with_func,所有权系统不会允许我们这么做。
72f678331aShanjiezhou     /// 因此,sleep_without_schedule的设计,正是为了解决这个问题。
73f678331aShanjiezhou     ///
74f678331aShanjiezhou     /// 由于sleep_without_schedule不会调用调度函数,因此,如果开发者忘记在执行本函数之后,手动调用调度函数,
75f678331aShanjiezhou     /// 由于时钟中断到来或者‘其他cpu kick了当前cpu’,可能会导致一些未定义的行为。
76f678331aShanjiezhou     pub unsafe fn sleep_without_schedule(&self) {
77*40609970SGnoCiYeH         before_sleep_check(1);
78f678331aShanjiezhou         // 安全检查:确保当前处于中断禁止状态
79f678331aShanjiezhou         assert!(CurrentIrqArch::is_irq_enabled() == false);
80f678331aShanjiezhou         let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock();
811496ba7bSLoGin         ProcessManager::mark_sleep(true).unwrap_or_else(|e| {
821496ba7bSLoGin             panic!("sleep error: {:?}", e);
831496ba7bSLoGin         });
841496ba7bSLoGin         guard.wait_list.push_back(ProcessManager::current_pcb());
851496ba7bSLoGin         drop(guard);
861496ba7bSLoGin     }
871496ba7bSLoGin 
881496ba7bSLoGin     pub unsafe fn sleep_without_schedule_uninterruptible(&self) {
89*40609970SGnoCiYeH         before_sleep_check(0);
901496ba7bSLoGin         // 安全检查:确保当前处于中断禁止状态
911496ba7bSLoGin         assert!(CurrentIrqArch::is_irq_enabled() == false);
921496ba7bSLoGin         let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock();
931496ba7bSLoGin         ProcessManager::mark_sleep(false).unwrap_or_else(|e| {
941496ba7bSLoGin             panic!("sleep error: {:?}", e);
951496ba7bSLoGin         });
961496ba7bSLoGin         guard.wait_list.push_back(ProcessManager::current_pcb());
97f678331aShanjiezhou         drop(guard);
98f678331aShanjiezhou     }
99151251b5Slogin     /// @brief 让当前进程在等待队列上进行等待,并且,不允许被信号打断
100151251b5Slogin     pub fn sleep_uninterruptible(&self) {
101*40609970SGnoCiYeH         before_sleep_check(0);
102151251b5Slogin         let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock();
1031496ba7bSLoGin         let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
1041496ba7bSLoGin         ProcessManager::mark_sleep(false).unwrap_or_else(|e| {
1051496ba7bSLoGin             panic!("sleep error: {:?}", e);
1061496ba7bSLoGin         });
1071496ba7bSLoGin         drop(irq_guard);
1081496ba7bSLoGin         guard.wait_list.push_back(ProcessManager::current_pcb());
109151251b5Slogin         drop(guard);
110151251b5Slogin         sched();
111151251b5Slogin     }
112151251b5Slogin 
113151251b5Slogin     /// @brief 让当前进程在等待队列上进行等待,并且,允许被信号打断。
114151251b5Slogin     /// 在当前进程的pcb加入队列后,解锁指定的自旋锁。
115151251b5Slogin     pub fn sleep_unlock_spinlock<T>(&self, to_unlock: SpinLockGuard<T>) {
116*40609970SGnoCiYeH         before_sleep_check(1);
117151251b5Slogin         let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock();
1181496ba7bSLoGin         let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
1191496ba7bSLoGin         ProcessManager::mark_sleep(true).unwrap_or_else(|e| {
1201496ba7bSLoGin             panic!("sleep error: {:?}", e);
1211496ba7bSLoGin         });
1221496ba7bSLoGin         drop(irq_guard);
1231496ba7bSLoGin         guard.wait_list.push_back(ProcessManager::current_pcb());
124151251b5Slogin         drop(to_unlock);
125151251b5Slogin         drop(guard);
126151251b5Slogin         sched();
127151251b5Slogin     }
128151251b5Slogin 
129151251b5Slogin     /// @brief 让当前进程在等待队列上进行等待,并且,允许被信号打断。
130151251b5Slogin     /// 在当前进程的pcb加入队列后,解锁指定的Mutex。
131151251b5Slogin     pub fn sleep_unlock_mutex<T>(&self, to_unlock: MutexGuard<T>) {
132*40609970SGnoCiYeH         before_sleep_check(1);
133151251b5Slogin         let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock();
1341496ba7bSLoGin         let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
1351496ba7bSLoGin         ProcessManager::mark_sleep(true).unwrap_or_else(|e| {
1361496ba7bSLoGin             panic!("sleep error: {:?}", e);
1371496ba7bSLoGin         });
1381496ba7bSLoGin         drop(irq_guard);
1391496ba7bSLoGin         guard.wait_list.push_back(ProcessManager::current_pcb());
140151251b5Slogin         drop(to_unlock);
141151251b5Slogin         drop(guard);
142151251b5Slogin         sched();
143151251b5Slogin     }
144151251b5Slogin 
145151251b5Slogin     /// @brief 让当前进程在等待队列上进行等待,并且,不允许被信号打断。
146151251b5Slogin     /// 在当前进程的pcb加入队列后,解锁指定的自旋锁。
147151251b5Slogin     pub fn sleep_uninterruptible_unlock_spinlock<T>(&self, to_unlock: SpinLockGuard<T>) {
148*40609970SGnoCiYeH         before_sleep_check(1);
149151251b5Slogin         let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock();
1501496ba7bSLoGin         let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
1511496ba7bSLoGin         ProcessManager::mark_sleep(false).unwrap_or_else(|e| {
1521496ba7bSLoGin             panic!("sleep error: {:?}", e);
1531496ba7bSLoGin         });
1541496ba7bSLoGin         drop(irq_guard);
1551496ba7bSLoGin         guard.wait_list.push_back(ProcessManager::current_pcb());
156151251b5Slogin         drop(to_unlock);
157151251b5Slogin         drop(guard);
158151251b5Slogin         sched();
159151251b5Slogin     }
160151251b5Slogin 
161151251b5Slogin     /// @brief 让当前进程在等待队列上进行等待,并且,不允许被信号打断。
162151251b5Slogin     /// 在当前进程的pcb加入队列后,解锁指定的Mutex。
163151251b5Slogin     pub fn sleep_uninterruptible_unlock_mutex<T>(&self, to_unlock: MutexGuard<T>) {
164*40609970SGnoCiYeH         before_sleep_check(1);
165151251b5Slogin         let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock();
1661496ba7bSLoGin         let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
1671496ba7bSLoGin         ProcessManager::mark_sleep(false).unwrap_or_else(|e| {
1681496ba7bSLoGin             panic!("sleep error: {:?}", e);
1691496ba7bSLoGin         });
1701496ba7bSLoGin         drop(irq_guard);
1711496ba7bSLoGin 
1721496ba7bSLoGin         guard.wait_list.push_back(ProcessManager::current_pcb());
1731496ba7bSLoGin 
174151251b5Slogin         drop(to_unlock);
175151251b5Slogin         drop(guard);
176151251b5Slogin         sched();
177151251b5Slogin     }
178151251b5Slogin 
179151251b5Slogin     /// @brief 唤醒在队列中等待的第一个进程。
180151251b5Slogin     /// 如果这个进程的state与给定的state进行and操作之后,结果不为0,则唤醒它。
181151251b5Slogin     ///
1821496ba7bSLoGin     /// @param state 用于判断的state,如果队列第一个进程与这个state相同,或者为None(表示不进行这个判断),则唤醒这个进程。
183151251b5Slogin     ///
184151251b5Slogin     /// @return true 成功唤醒进程
185151251b5Slogin     /// @return false 没有唤醒进程
1861496ba7bSLoGin     pub fn wakeup(&self, state: Option<ProcessState>) -> bool {
187151251b5Slogin         let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock();
188151251b5Slogin         // 如果队列为空,则返回
189151251b5Slogin         if guard.wait_list.is_empty() {
190151251b5Slogin             return false;
191151251b5Slogin         }
192151251b5Slogin         // 如果队列头部的pcb的state与给定的state相与,结果不为0,则唤醒
1931496ba7bSLoGin         if let Some(state) = state {
1941496ba7bSLoGin             if guard.wait_list.front().unwrap().sched_info().state() != state {
195151251b5Slogin                 return false;
196151251b5Slogin             }
197151251b5Slogin         }
1981496ba7bSLoGin         let to_wakeup = guard.wait_list.pop_front().unwrap();
1991496ba7bSLoGin         let res = ProcessManager::wakeup(&to_wakeup).is_ok();
2001496ba7bSLoGin         return res;
2011496ba7bSLoGin     }
202151251b5Slogin 
203cde5492fSlogin     /// @brief 唤醒在队列中,符合条件的所有进程。
204cde5492fSlogin     ///
2051496ba7bSLoGin     /// @param state 用于判断的state,如果一个进程与这个state相同,或者为None(表示不进行这个判断),则唤醒这个进程。
2061496ba7bSLoGin     pub fn wakeup_all(&self, state: Option<ProcessState>) {
207cde5492fSlogin         let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock_irqsave();
208cde5492fSlogin         // 如果队列为空,则返回
209cde5492fSlogin         if guard.wait_list.is_empty() {
210cde5492fSlogin             return;
211cde5492fSlogin         }
212cde5492fSlogin 
2131496ba7bSLoGin         let mut to_push_back: Vec<Arc<ProcessControlBlock>> = Vec::new();
214cde5492fSlogin         // 如果队列头部的pcb的state与给定的state相与,结果不为0,则唤醒
215cde5492fSlogin         while let Some(to_wakeup) = guard.wait_list.pop_front() {
216a03c4f9dSLoGin             let mut wake = false;
2171496ba7bSLoGin             if let Some(state) = state {
2181496ba7bSLoGin                 if to_wakeup.sched_info().state() == state {
219a03c4f9dSLoGin                     wake = true;
220a03c4f9dSLoGin                 }
221a03c4f9dSLoGin             } else {
222a03c4f9dSLoGin                 wake = true;
223a03c4f9dSLoGin             }
224a03c4f9dSLoGin 
225a03c4f9dSLoGin             if wake {
2261496ba7bSLoGin                 ProcessManager::wakeup(&to_wakeup).unwrap_or_else(|e| {
2271496ba7bSLoGin                     kerror!("wakeup pid: {:?} error: {:?}", to_wakeup.pid(), e);
2281496ba7bSLoGin                 });
2291496ba7bSLoGin                 continue;
230a03c4f9dSLoGin             } else {
231cde5492fSlogin                 to_push_back.push(to_wakeup);
232cde5492fSlogin             }
233a03c4f9dSLoGin         }
234a03c4f9dSLoGin 
235cde5492fSlogin         for to_wakeup in to_push_back {
236cde5492fSlogin             guard.wait_list.push_back(to_wakeup);
237cde5492fSlogin         }
238cde5492fSlogin     }
239cde5492fSlogin 
240151251b5Slogin     /// @brief 获得当前等待队列的大小
241151251b5Slogin     pub fn len(&self) -> usize {
242151251b5Slogin         return self.0.lock().wait_list.len();
243151251b5Slogin     }
244151251b5Slogin }
245151251b5Slogin 
246151251b5Slogin impl InnerWaitQueue {
247151251b5Slogin     pub const INIT: InnerWaitQueue = InnerWaitQueue {
248151251b5Slogin         wait_list: LinkedList::new(),
249151251b5Slogin     };
250151251b5Slogin }
251*40609970SGnoCiYeH 
252*40609970SGnoCiYeH fn before_sleep_check(max_preempt: usize) {
253*40609970SGnoCiYeH     let pcb = ProcessManager::current_pcb();
254*40609970SGnoCiYeH     if unlikely(pcb.preempt_count() > max_preempt) {
255*40609970SGnoCiYeH         kwarn!(
256*40609970SGnoCiYeH             "Process {:?}: Try to sleep when preempt count is {}",
257*40609970SGnoCiYeH             pcb.pid(),
258*40609970SGnoCiYeH             pcb.preempt_count()
259*40609970SGnoCiYeH         );
260*40609970SGnoCiYeH     }
261*40609970SGnoCiYeH }
262*40609970SGnoCiYeH 
263*40609970SGnoCiYeH /// 事件等待队列
264*40609970SGnoCiYeH #[derive(Debug)]
265*40609970SGnoCiYeH pub struct EventWaitQueue {
266*40609970SGnoCiYeH     wait_list: SpinLock<Vec<(u64, Arc<ProcessControlBlock>)>>,
267*40609970SGnoCiYeH }
268*40609970SGnoCiYeH 
269*40609970SGnoCiYeH impl EventWaitQueue {
270*40609970SGnoCiYeH     pub fn new() -> Self {
271*40609970SGnoCiYeH         Self {
272*40609970SGnoCiYeH             wait_list: SpinLock::new(Vec::new()),
273*40609970SGnoCiYeH         }
274*40609970SGnoCiYeH     }
275*40609970SGnoCiYeH 
276*40609970SGnoCiYeH     /// ## 让当前进程在该队列上等待感兴趣的事件
277*40609970SGnoCiYeH     ///
278*40609970SGnoCiYeH     /// ### 参数
279*40609970SGnoCiYeH     /// - events: 进程感兴趣的事件,events最好是为位表示,一位表示一个事件
280*40609970SGnoCiYeH     ///
281*40609970SGnoCiYeH     /// 注意,使用前应该注意有可能其他地方定义了冲突的事件,可能会导致未定义行为
282*40609970SGnoCiYeH     pub fn sleep(&self, events: u64) {
283*40609970SGnoCiYeH         before_sleep_check(0);
284*40609970SGnoCiYeH         let mut guard = self.wait_list.lock_irqsave();
285*40609970SGnoCiYeH         ProcessManager::mark_sleep(true).unwrap_or_else(|e| {
286*40609970SGnoCiYeH             panic!("sleep error: {:?}", e);
287*40609970SGnoCiYeH         });
288*40609970SGnoCiYeH         guard.push((events, ProcessManager::current_pcb()));
289*40609970SGnoCiYeH         drop(guard);
290*40609970SGnoCiYeH         sched();
291*40609970SGnoCiYeH     }
292*40609970SGnoCiYeH 
293*40609970SGnoCiYeH     pub unsafe fn sleep_without_schedule(&self, events: u64) {
294*40609970SGnoCiYeH         before_sleep_check(1);
295*40609970SGnoCiYeH         let mut guard = self.wait_list.lock_irqsave();
296*40609970SGnoCiYeH         ProcessManager::mark_sleep(true).unwrap_or_else(|e| {
297*40609970SGnoCiYeH             panic!("sleep error: {:?}", e);
298*40609970SGnoCiYeH         });
299*40609970SGnoCiYeH         guard.push((events, ProcessManager::current_pcb()));
300*40609970SGnoCiYeH         drop(guard);
301*40609970SGnoCiYeH     }
302*40609970SGnoCiYeH 
303*40609970SGnoCiYeH     pub fn sleep_unlock_spinlock<T>(&self, events: u64, to_unlock: SpinLockGuard<T>) {
304*40609970SGnoCiYeH         before_sleep_check(1);
305*40609970SGnoCiYeH         let mut guard = self.wait_list.lock();
306*40609970SGnoCiYeH         let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
307*40609970SGnoCiYeH         ProcessManager::mark_sleep(true).unwrap_or_else(|e| {
308*40609970SGnoCiYeH             panic!("sleep error: {:?}", e);
309*40609970SGnoCiYeH         });
310*40609970SGnoCiYeH         drop(irq_guard);
311*40609970SGnoCiYeH         guard.push((events, ProcessManager::current_pcb()));
312*40609970SGnoCiYeH         drop(to_unlock);
313*40609970SGnoCiYeH         drop(guard);
314*40609970SGnoCiYeH         sched();
315*40609970SGnoCiYeH     }
316*40609970SGnoCiYeH 
317*40609970SGnoCiYeH     /// ### 唤醒该队列上等待events的进程
318*40609970SGnoCiYeH     ///
319*40609970SGnoCiYeH     ///  ### 参数
320*40609970SGnoCiYeH     /// - events: 发生的事件
321*40609970SGnoCiYeH     ///
322*40609970SGnoCiYeH     /// 需要注意的是,只要触发了events中的任意一件事件,进程都会被唤醒
323*40609970SGnoCiYeH     pub fn wakeup_any(&self, events: u64) -> usize {
324*40609970SGnoCiYeH         let mut ret = 0;
325*40609970SGnoCiYeH         let _ = self.wait_list.lock().extract_if(|(es, pcb)| {
326*40609970SGnoCiYeH             if *es & events > 0 {
327*40609970SGnoCiYeH                 // 有感兴趣的事件
328*40609970SGnoCiYeH                 if ProcessManager::wakeup(pcb).is_ok() {
329*40609970SGnoCiYeH                     ret += 1;
330*40609970SGnoCiYeH                     return true;
331*40609970SGnoCiYeH                 } else {
332*40609970SGnoCiYeH                     return false;
333*40609970SGnoCiYeH                 }
334*40609970SGnoCiYeH             } else {
335*40609970SGnoCiYeH                 return false;
336*40609970SGnoCiYeH             }
337*40609970SGnoCiYeH         });
338*40609970SGnoCiYeH         ret
339*40609970SGnoCiYeH     }
340*40609970SGnoCiYeH 
341*40609970SGnoCiYeH     /// ### 唤醒该队列上等待events的进程
342*40609970SGnoCiYeH     ///
343*40609970SGnoCiYeH     ///  ### 参数
344*40609970SGnoCiYeH     /// - events: 发生的事件
345*40609970SGnoCiYeH     ///
346*40609970SGnoCiYeH     /// 需要注意的是,只有满足所有事件的进程才会被唤醒
347*40609970SGnoCiYeH     pub fn wakeup(&self, events: u64) -> usize {
348*40609970SGnoCiYeH         let mut ret = 0;
349*40609970SGnoCiYeH         let _ = self.wait_list.lock().extract_if(|(es, pcb)| {
350*40609970SGnoCiYeH             if *es == events {
351*40609970SGnoCiYeH                 // 有感兴趣的事件
352*40609970SGnoCiYeH                 if ProcessManager::wakeup(pcb).is_ok() {
353*40609970SGnoCiYeH                     ret += 1;
354*40609970SGnoCiYeH                     return true;
355*40609970SGnoCiYeH                 } else {
356*40609970SGnoCiYeH                     return false;
357*40609970SGnoCiYeH                 }
358*40609970SGnoCiYeH             } else {
359*40609970SGnoCiYeH                 return false;
360*40609970SGnoCiYeH             }
361*40609970SGnoCiYeH         });
362*40609970SGnoCiYeH         ret
363*40609970SGnoCiYeH     }
364*40609970SGnoCiYeH 
365*40609970SGnoCiYeH     pub fn wakeup_all(&self) {
366*40609970SGnoCiYeH         self.wakeup_any(u64::MAX);
367*40609970SGnoCiYeH     }
368*40609970SGnoCiYeH }
369