xref: /DragonOS/kernel/src/libs/wait_queue.rs (revision 1496ba7b24a5e6954291ca9643b9f3cec567479a)
1151251b5Slogin #![allow(dead_code)]
2*1496ba7bSLoGin use alloc::{collections::LinkedList, sync::Arc, vec::Vec};
3c8025a88Slogin 
4151251b5Slogin use crate::{
5*1496ba7bSLoGin     arch::{sched::sched, CurrentIrqArch},
6f678331aShanjiezhou     exception::InterruptArch,
7*1496ba7bSLoGin     kerror,
8*1496ba7bSLoGin     process::{ProcessControlBlock, ProcessManager, ProcessState},
9151251b5Slogin };
10151251b5Slogin 
11151251b5Slogin use super::{
12151251b5Slogin     mutex::MutexGuard,
13151251b5Slogin     spinlock::{SpinLock, SpinLockGuard},
14151251b5Slogin };
15c8025a88Slogin 
16151251b5Slogin #[derive(Debug)]
17151251b5Slogin struct InnerWaitQueue {
18151251b5Slogin     /// 等待队列的链表
19*1496ba7bSLoGin     wait_list: LinkedList<Arc<ProcessControlBlock>>,
20151251b5Slogin }
21151251b5Slogin 
22151251b5Slogin /// 被自旋锁保护的等待队列
23151251b5Slogin #[derive(Debug)]
24151251b5Slogin pub struct WaitQueue(SpinLock<InnerWaitQueue>);
25151251b5Slogin 
26151251b5Slogin impl WaitQueue {
27151251b5Slogin     pub const INIT: WaitQueue = WaitQueue(SpinLock::new(InnerWaitQueue::INIT));
28151251b5Slogin 
29151251b5Slogin     /// @brief 让当前进程在等待队列上进行等待,并且,允许被信号打断
30151251b5Slogin     pub fn sleep(&self) {
31*1496ba7bSLoGin         let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock_irqsave();
32*1496ba7bSLoGin         ProcessManager::mark_sleep(true).unwrap_or_else(|e| {
33*1496ba7bSLoGin             panic!("sleep error: {:?}", e);
34*1496ba7bSLoGin         });
35*1496ba7bSLoGin         guard.wait_list.push_back(ProcessManager::current_pcb());
36151251b5Slogin         drop(guard);
37151251b5Slogin         sched();
38151251b5Slogin     }
39151251b5Slogin 
40f678331aShanjiezhou     /// @brief 让当前进程在等待队列上进行等待,并且,在释放waitqueue的锁之前,执行f函数闭包
41f678331aShanjiezhou     pub fn sleep_with_func<F>(&self, f: F)
42f678331aShanjiezhou     where
43f678331aShanjiezhou         F: FnOnce(),
44f678331aShanjiezhou     {
45f678331aShanjiezhou         let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock();
46*1496ba7bSLoGin         let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
47*1496ba7bSLoGin         ProcessManager::mark_sleep(true).unwrap_or_else(|e| {
48*1496ba7bSLoGin             panic!("sleep error: {:?}", e);
49*1496ba7bSLoGin         });
50*1496ba7bSLoGin         drop(irq_guard);
51*1496ba7bSLoGin         guard.wait_list.push_back(ProcessManager::current_pcb());
52f678331aShanjiezhou         f();
53f678331aShanjiezhou         drop(guard);
54f678331aShanjiezhou         sched();
55f678331aShanjiezhou     }
56f678331aShanjiezhou 
57f678331aShanjiezhou     /// @brief 让当前进程在等待队列上进行等待. 但是,在释放waitqueue的锁之后,不会调用调度函数。
58f678331aShanjiezhou     /// 这样的设计,是为了让调用者可以在执行本函数之后,执行一些操作,然后再【手动调用调度函数】。
59f678331aShanjiezhou     ///
60f678331aShanjiezhou     /// 执行本函数前,需要确保处于【中断禁止】状态。
61f678331aShanjiezhou     ///
62f678331aShanjiezhou     /// 尽管sleep_with_func和sleep_without_schedule都可以实现这个功能,但是,sleep_with_func会在释放锁之前,执行f函数闭包。
63f678331aShanjiezhou     ///
64f678331aShanjiezhou     /// 考虑这样一个场景:
65f678331aShanjiezhou     /// 等待队列位于某个自旋锁保护的数据结构A中,我们希望在进程睡眠的同时,释放数据结构A的锁。
66f678331aShanjiezhou     /// 在这种情况下,如果使用sleep_with_func,所有权系统不会允许我们这么做。
67f678331aShanjiezhou     /// 因此,sleep_without_schedule的设计,正是为了解决这个问题。
68f678331aShanjiezhou     ///
69f678331aShanjiezhou     /// 由于sleep_without_schedule不会调用调度函数,因此,如果开发者忘记在执行本函数之后,手动调用调度函数,
70f678331aShanjiezhou     /// 由于时钟中断到来或者‘其他cpu kick了当前cpu’,可能会导致一些未定义的行为。
71f678331aShanjiezhou     pub unsafe fn sleep_without_schedule(&self) {
72f678331aShanjiezhou         // 安全检查:确保当前处于中断禁止状态
73f678331aShanjiezhou         assert!(CurrentIrqArch::is_irq_enabled() == false);
74f678331aShanjiezhou         let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock();
75*1496ba7bSLoGin         ProcessManager::mark_sleep(true).unwrap_or_else(|e| {
76*1496ba7bSLoGin             panic!("sleep error: {:?}", e);
77*1496ba7bSLoGin         });
78*1496ba7bSLoGin         guard.wait_list.push_back(ProcessManager::current_pcb());
79*1496ba7bSLoGin         drop(guard);
80*1496ba7bSLoGin     }
81*1496ba7bSLoGin 
82*1496ba7bSLoGin     pub unsafe fn sleep_without_schedule_uninterruptible(&self) {
83*1496ba7bSLoGin         // 安全检查:确保当前处于中断禁止状态
84*1496ba7bSLoGin         assert!(CurrentIrqArch::is_irq_enabled() == false);
85*1496ba7bSLoGin         let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock();
86*1496ba7bSLoGin         ProcessManager::mark_sleep(false).unwrap_or_else(|e| {
87*1496ba7bSLoGin             panic!("sleep error: {:?}", e);
88*1496ba7bSLoGin         });
89*1496ba7bSLoGin         guard.wait_list.push_back(ProcessManager::current_pcb());
90f678331aShanjiezhou         drop(guard);
91f678331aShanjiezhou     }
92151251b5Slogin     /// @brief 让当前进程在等待队列上进行等待,并且,不允许被信号打断
93151251b5Slogin     pub fn sleep_uninterruptible(&self) {
94151251b5Slogin         let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock();
95*1496ba7bSLoGin         let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
96*1496ba7bSLoGin         ProcessManager::mark_sleep(false).unwrap_or_else(|e| {
97*1496ba7bSLoGin             panic!("sleep error: {:?}", e);
98*1496ba7bSLoGin         });
99*1496ba7bSLoGin         drop(irq_guard);
100*1496ba7bSLoGin         guard.wait_list.push_back(ProcessManager::current_pcb());
101151251b5Slogin         drop(guard);
102151251b5Slogin         sched();
103151251b5Slogin     }
104151251b5Slogin 
105151251b5Slogin     /// @brief 让当前进程在等待队列上进行等待,并且,允许被信号打断。
106151251b5Slogin     /// 在当前进程的pcb加入队列后,解锁指定的自旋锁。
107151251b5Slogin     pub fn sleep_unlock_spinlock<T>(&self, to_unlock: SpinLockGuard<T>) {
108151251b5Slogin         let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock();
109*1496ba7bSLoGin         let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
110*1496ba7bSLoGin         ProcessManager::mark_sleep(true).unwrap_or_else(|e| {
111*1496ba7bSLoGin             panic!("sleep error: {:?}", e);
112*1496ba7bSLoGin         });
113*1496ba7bSLoGin         drop(irq_guard);
114*1496ba7bSLoGin         guard.wait_list.push_back(ProcessManager::current_pcb());
115151251b5Slogin         drop(to_unlock);
116151251b5Slogin         drop(guard);
117151251b5Slogin         sched();
118151251b5Slogin     }
119151251b5Slogin 
120151251b5Slogin     /// @brief 让当前进程在等待队列上进行等待,并且,允许被信号打断。
121151251b5Slogin     /// 在当前进程的pcb加入队列后,解锁指定的Mutex。
122151251b5Slogin     pub fn sleep_unlock_mutex<T>(&self, to_unlock: MutexGuard<T>) {
123151251b5Slogin         let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock();
124*1496ba7bSLoGin         let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
125*1496ba7bSLoGin         ProcessManager::mark_sleep(true).unwrap_or_else(|e| {
126*1496ba7bSLoGin             panic!("sleep error: {:?}", e);
127*1496ba7bSLoGin         });
128*1496ba7bSLoGin         drop(irq_guard);
129*1496ba7bSLoGin         guard.wait_list.push_back(ProcessManager::current_pcb());
130151251b5Slogin         drop(to_unlock);
131151251b5Slogin         drop(guard);
132151251b5Slogin         sched();
133151251b5Slogin     }
134151251b5Slogin 
135151251b5Slogin     /// @brief 让当前进程在等待队列上进行等待,并且,不允许被信号打断。
136151251b5Slogin     /// 在当前进程的pcb加入队列后,解锁指定的自旋锁。
137151251b5Slogin     pub fn sleep_uninterruptible_unlock_spinlock<T>(&self, to_unlock: SpinLockGuard<T>) {
138151251b5Slogin         let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock();
139*1496ba7bSLoGin         let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
140*1496ba7bSLoGin         ProcessManager::mark_sleep(false).unwrap_or_else(|e| {
141*1496ba7bSLoGin             panic!("sleep error: {:?}", e);
142*1496ba7bSLoGin         });
143*1496ba7bSLoGin         drop(irq_guard);
144*1496ba7bSLoGin         guard.wait_list.push_back(ProcessManager::current_pcb());
145151251b5Slogin         drop(to_unlock);
146151251b5Slogin         drop(guard);
147151251b5Slogin         sched();
148151251b5Slogin     }
149151251b5Slogin 
150151251b5Slogin     /// @brief 让当前进程在等待队列上进行等待,并且,不允许被信号打断。
151151251b5Slogin     /// 在当前进程的pcb加入队列后,解锁指定的Mutex。
152151251b5Slogin     pub fn sleep_uninterruptible_unlock_mutex<T>(&self, to_unlock: MutexGuard<T>) {
153151251b5Slogin         let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock();
154*1496ba7bSLoGin         let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
155*1496ba7bSLoGin         ProcessManager::mark_sleep(false).unwrap_or_else(|e| {
156*1496ba7bSLoGin             panic!("sleep error: {:?}", e);
157*1496ba7bSLoGin         });
158*1496ba7bSLoGin         drop(irq_guard);
159*1496ba7bSLoGin 
160*1496ba7bSLoGin         guard.wait_list.push_back(ProcessManager::current_pcb());
161*1496ba7bSLoGin 
162151251b5Slogin         drop(to_unlock);
163151251b5Slogin         drop(guard);
164151251b5Slogin         sched();
165151251b5Slogin     }
166151251b5Slogin 
167151251b5Slogin     /// @brief 唤醒在队列中等待的第一个进程。
168151251b5Slogin     /// 如果这个进程的state与给定的state进行and操作之后,结果不为0,则唤醒它。
169151251b5Slogin     ///
170*1496ba7bSLoGin     /// @param state 用于判断的state,如果队列第一个进程与这个state相同,或者为None(表示不进行这个判断),则唤醒这个进程。
171151251b5Slogin     ///
172151251b5Slogin     /// @return true 成功唤醒进程
173151251b5Slogin     /// @return false 没有唤醒进程
174*1496ba7bSLoGin     pub fn wakeup(&self, state: Option<ProcessState>) -> bool {
175151251b5Slogin         let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock();
176151251b5Slogin         // 如果队列为空,则返回
177151251b5Slogin         if guard.wait_list.is_empty() {
178151251b5Slogin             return false;
179151251b5Slogin         }
180151251b5Slogin         // 如果队列头部的pcb的state与给定的state相与,结果不为0,则唤醒
181*1496ba7bSLoGin         if let Some(state) = state {
182*1496ba7bSLoGin             if guard.wait_list.front().unwrap().sched_info().state() != state {
183151251b5Slogin                 return false;
184151251b5Slogin             }
185151251b5Slogin         }
186*1496ba7bSLoGin         let to_wakeup = guard.wait_list.pop_front().unwrap();
187*1496ba7bSLoGin         let res = ProcessManager::wakeup(&to_wakeup).is_ok();
188*1496ba7bSLoGin         return res;
189*1496ba7bSLoGin     }
190151251b5Slogin 
191cde5492fSlogin     /// @brief 唤醒在队列中,符合条件的所有进程。
192cde5492fSlogin     ///
193*1496ba7bSLoGin     /// @param state 用于判断的state,如果一个进程与这个state相同,或者为None(表示不进行这个判断),则唤醒这个进程。
194*1496ba7bSLoGin     pub fn wakeup_all(&self, state: Option<ProcessState>) {
195cde5492fSlogin         let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock_irqsave();
196cde5492fSlogin         // 如果队列为空,则返回
197cde5492fSlogin         if guard.wait_list.is_empty() {
198cde5492fSlogin             return;
199cde5492fSlogin         }
200cde5492fSlogin 
201*1496ba7bSLoGin         let mut to_push_back: Vec<Arc<ProcessControlBlock>> = Vec::new();
202cde5492fSlogin         // 如果队列头部的pcb的state与给定的state相与,结果不为0,则唤醒
203cde5492fSlogin         while let Some(to_wakeup) = guard.wait_list.pop_front() {
204*1496ba7bSLoGin             if let Some(state) = state {
205*1496ba7bSLoGin                 if to_wakeup.sched_info().state() == state {
206*1496ba7bSLoGin                     ProcessManager::wakeup(&to_wakeup).unwrap_or_else(|e| {
207*1496ba7bSLoGin                         kerror!("wakeup pid: {:?} error: {:?}", to_wakeup.pid(), e);
208*1496ba7bSLoGin                     });
209*1496ba7bSLoGin                     continue;
210cde5492fSlogin                 }
211*1496ba7bSLoGin             }
212cde5492fSlogin             to_push_back.push(to_wakeup);
213cde5492fSlogin         }
214cde5492fSlogin         for to_wakeup in to_push_back {
215cde5492fSlogin             guard.wait_list.push_back(to_wakeup);
216cde5492fSlogin         }
217cde5492fSlogin     }
218cde5492fSlogin 
219151251b5Slogin     /// @brief 获得当前等待队列的大小
220151251b5Slogin     pub fn len(&self) -> usize {
221151251b5Slogin         return self.0.lock().wait_list.len();
222151251b5Slogin     }
223151251b5Slogin }
224151251b5Slogin 
225151251b5Slogin impl InnerWaitQueue {
226151251b5Slogin     pub const INIT: InnerWaitQueue = InnerWaitQueue {
227151251b5Slogin         wait_list: LinkedList::new(),
228151251b5Slogin     };
229151251b5Slogin }
230