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