xref: /DragonOS/kernel/src/libs/wait_queue.rs (revision 78bf93f02f84bf5e024ddfb559f040e68ce39ccf)
1 #![allow(dead_code)]
2 use alloc::collections::LinkedList;
3 
4 use crate::{
5     arch::{asm::current::current_pcb, sched::sched},
6     include::bindings::bindings::{
7         process_control_block, process_wakeup, wait_queue_head_t, PROC_INTERRUPTIBLE,
8         PROC_UNINTERRUPTIBLE,
9     },
10 };
11 
12 use super::{
13     list::list_init,
14     mutex::MutexGuard,
15     spinlock::{SpinLock, SpinLockGuard},
16 };
17 
18 impl Default for wait_queue_head_t {
19     fn default() -> Self {
20         let mut x = Self {
21             wait_list: Default::default(),
22             lock: Default::default(),
23         };
24         list_init(&mut x.wait_list);
25         return x;
26     }
27 }
28 
29 #[derive(Debug)]
30 struct InnerWaitQueue {
31     /// 等待队列的链表
32     wait_list: LinkedList<&'static mut process_control_block>,
33 }
34 
35 /// 被自旋锁保护的等待队列
36 #[derive(Debug)]
37 pub struct WaitQueue(SpinLock<InnerWaitQueue>);
38 
39 impl WaitQueue {
40     pub const INIT: WaitQueue = WaitQueue(SpinLock::new(InnerWaitQueue::INIT));
41 
42     /// @brief 让当前进程在等待队列上进行等待,并且,允许被信号打断
43     pub fn sleep(&self) {
44         let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock();
45         current_pcb().state = PROC_INTERRUPTIBLE as u64;
46         guard.wait_list.push_back(current_pcb());
47         drop(guard);
48         sched();
49     }
50 
51     /// @brief 让当前进程在等待队列上进行等待,并且,不允许被信号打断
52     pub fn sleep_uninterruptible(&self) {
53         let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock();
54         current_pcb().state = PROC_UNINTERRUPTIBLE as u64;
55         guard.wait_list.push_back(current_pcb());
56         drop(guard);
57         sched();
58     }
59 
60     /// @brief 让当前进程在等待队列上进行等待,并且,允许被信号打断。
61     /// 在当前进程的pcb加入队列后,解锁指定的自旋锁。
62     pub fn sleep_unlock_spinlock<T>(&self, to_unlock: SpinLockGuard<T>) {
63         let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock();
64         current_pcb().state = PROC_INTERRUPTIBLE as u64;
65         guard.wait_list.push_back(current_pcb());
66         drop(to_unlock);
67         drop(guard);
68         sched();
69     }
70 
71     /// @brief 让当前进程在等待队列上进行等待,并且,允许被信号打断。
72     /// 在当前进程的pcb加入队列后,解锁指定的Mutex。
73     pub fn sleep_unlock_mutex<T>(&self, to_unlock: MutexGuard<T>) {
74         let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock();
75         current_pcb().state = PROC_INTERRUPTIBLE as u64;
76         guard.wait_list.push_back(current_pcb());
77         drop(to_unlock);
78         drop(guard);
79         sched();
80     }
81 
82     /// @brief 让当前进程在等待队列上进行等待,并且,不允许被信号打断。
83     /// 在当前进程的pcb加入队列后,解锁指定的自旋锁。
84     pub fn sleep_uninterruptible_unlock_spinlock<T>(&self, to_unlock: SpinLockGuard<T>) {
85         let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock();
86         current_pcb().state = PROC_UNINTERRUPTIBLE as u64;
87         guard.wait_list.push_back(current_pcb());
88         drop(to_unlock);
89         drop(guard);
90         sched();
91     }
92 
93     /// @brief 让当前进程在等待队列上进行等待,并且,不允许被信号打断。
94     /// 在当前进程的pcb加入队列后,解锁指定的Mutex。
95     pub fn sleep_uninterruptible_unlock_mutex<T>(&self, to_unlock: MutexGuard<T>) {
96         let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock();
97         current_pcb().state = PROC_UNINTERRUPTIBLE as u64;
98         guard.wait_list.push_back(current_pcb());
99         drop(to_unlock);
100         drop(guard);
101         sched();
102     }
103 
104     /// @brief 唤醒在队列中等待的第一个进程。
105     /// 如果这个进程的state与给定的state进行and操作之后,结果不为0,则唤醒它。
106     ///
107     /// @param state 用于判断的state,如果队列中第一个进程的state与它进行and操作之后,结果不为0,则唤醒这个进程。
108     ///
109     /// @return true 成功唤醒进程
110     /// @return false 没有唤醒进程
111     pub fn wakeup(&self, state: u64) -> bool {
112         let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock();
113         // 如果队列为空,则返回
114         if guard.wait_list.is_empty() {
115             return false;
116         }
117 
118         // 如果队列头部的pcb的state与给定的state相与,结果不为0,则唤醒
119         if (guard.wait_list.front().unwrap().state & state) != 0 {
120             let to_wakeup = guard.wait_list.pop_front().unwrap();
121             unsafe {
122                 process_wakeup(to_wakeup);
123             }
124             return true;
125         } else {
126             return false;
127         }
128     }
129 
130     /// @brief 获得当前等待队列的大小
131     pub fn len(&self) -> usize {
132         return self.0.lock().wait_list.len();
133     }
134 }
135 
136 impl InnerWaitQueue {
137     pub const INIT: InnerWaitQueue = InnerWaitQueue {
138         wait_list: LinkedList::new(),
139     };
140 }
141