xref: /DragonOS/kernel/src/libs/wait_queue.rs (revision cde5492f725681ed89abe1e6eb088e05d943d793)
1151251b5Slogin #![allow(dead_code)]
2*cde5492fSlogin use alloc::{collections::LinkedList, vec::Vec};
3c8025a88Slogin 
4151251b5Slogin use crate::{
5151251b5Slogin     arch::{asm::current::current_pcb, sched::sched},
6151251b5Slogin     include::bindings::bindings::{
7151251b5Slogin         process_control_block, process_wakeup, wait_queue_head_t, PROC_INTERRUPTIBLE,
8151251b5Slogin         PROC_UNINTERRUPTIBLE,
9151251b5Slogin     },
10151251b5Slogin };
11151251b5Slogin 
12151251b5Slogin use super::{
13151251b5Slogin     list::list_init,
14151251b5Slogin     mutex::MutexGuard,
15151251b5Slogin     spinlock::{SpinLock, SpinLockGuard},
16151251b5Slogin };
17c8025a88Slogin 
18c8025a88Slogin impl Default for wait_queue_head_t {
19c8025a88Slogin     fn default() -> Self {
2006b09f34Skong         let mut x = Self {
2106b09f34Skong             wait_list: Default::default(),
2206b09f34Skong             lock: Default::default(),
2306b09f34Skong         };
24c8025a88Slogin         list_init(&mut x.wait_list);
25c8025a88Slogin         return x;
26c8025a88Slogin     }
27c8025a88Slogin }
28151251b5Slogin 
29151251b5Slogin #[derive(Debug)]
30151251b5Slogin struct InnerWaitQueue {
31151251b5Slogin     /// 等待队列的链表
32151251b5Slogin     wait_list: LinkedList<&'static mut process_control_block>,
33151251b5Slogin }
34151251b5Slogin 
35151251b5Slogin /// 被自旋锁保护的等待队列
36151251b5Slogin #[derive(Debug)]
37151251b5Slogin pub struct WaitQueue(SpinLock<InnerWaitQueue>);
38151251b5Slogin 
39151251b5Slogin impl WaitQueue {
40151251b5Slogin     pub const INIT: WaitQueue = WaitQueue(SpinLock::new(InnerWaitQueue::INIT));
41151251b5Slogin 
42151251b5Slogin     /// @brief 让当前进程在等待队列上进行等待,并且,允许被信号打断
43151251b5Slogin     pub fn sleep(&self) {
44151251b5Slogin         let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock();
45151251b5Slogin         current_pcb().state = PROC_INTERRUPTIBLE as u64;
46151251b5Slogin         guard.wait_list.push_back(current_pcb());
47151251b5Slogin         drop(guard);
48151251b5Slogin         sched();
49151251b5Slogin     }
50151251b5Slogin 
51151251b5Slogin     /// @brief 让当前进程在等待队列上进行等待,并且,不允许被信号打断
52151251b5Slogin     pub fn sleep_uninterruptible(&self) {
53151251b5Slogin         let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock();
54151251b5Slogin         current_pcb().state = PROC_UNINTERRUPTIBLE as u64;
55151251b5Slogin         guard.wait_list.push_back(current_pcb());
56151251b5Slogin         drop(guard);
57151251b5Slogin         sched();
58151251b5Slogin     }
59151251b5Slogin 
60151251b5Slogin     /// @brief 让当前进程在等待队列上进行等待,并且,允许被信号打断。
61151251b5Slogin     /// 在当前进程的pcb加入队列后,解锁指定的自旋锁。
62151251b5Slogin     pub fn sleep_unlock_spinlock<T>(&self, to_unlock: SpinLockGuard<T>) {
63151251b5Slogin         let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock();
64151251b5Slogin         current_pcb().state = PROC_INTERRUPTIBLE as u64;
65151251b5Slogin         guard.wait_list.push_back(current_pcb());
66151251b5Slogin         drop(to_unlock);
67151251b5Slogin         drop(guard);
68151251b5Slogin         sched();
69151251b5Slogin     }
70151251b5Slogin 
71151251b5Slogin     /// @brief 让当前进程在等待队列上进行等待,并且,允许被信号打断。
72151251b5Slogin     /// 在当前进程的pcb加入队列后,解锁指定的Mutex。
73151251b5Slogin     pub fn sleep_unlock_mutex<T>(&self, to_unlock: MutexGuard<T>) {
74151251b5Slogin         let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock();
75151251b5Slogin         current_pcb().state = PROC_INTERRUPTIBLE as u64;
76151251b5Slogin         guard.wait_list.push_back(current_pcb());
77151251b5Slogin         drop(to_unlock);
78151251b5Slogin         drop(guard);
79151251b5Slogin         sched();
80151251b5Slogin     }
81151251b5Slogin 
82151251b5Slogin     /// @brief 让当前进程在等待队列上进行等待,并且,不允许被信号打断。
83151251b5Slogin     /// 在当前进程的pcb加入队列后,解锁指定的自旋锁。
84151251b5Slogin     pub fn sleep_uninterruptible_unlock_spinlock<T>(&self, to_unlock: SpinLockGuard<T>) {
85151251b5Slogin         let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock();
86151251b5Slogin         current_pcb().state = PROC_UNINTERRUPTIBLE as u64;
87151251b5Slogin         guard.wait_list.push_back(current_pcb());
88151251b5Slogin         drop(to_unlock);
89151251b5Slogin         drop(guard);
90151251b5Slogin         sched();
91151251b5Slogin     }
92151251b5Slogin 
93151251b5Slogin     /// @brief 让当前进程在等待队列上进行等待,并且,不允许被信号打断。
94151251b5Slogin     /// 在当前进程的pcb加入队列后,解锁指定的Mutex。
95151251b5Slogin     pub fn sleep_uninterruptible_unlock_mutex<T>(&self, to_unlock: MutexGuard<T>) {
96151251b5Slogin         let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock();
97151251b5Slogin         current_pcb().state = PROC_UNINTERRUPTIBLE as u64;
98151251b5Slogin         guard.wait_list.push_back(current_pcb());
99151251b5Slogin         drop(to_unlock);
100151251b5Slogin         drop(guard);
101151251b5Slogin         sched();
102151251b5Slogin     }
103151251b5Slogin 
104151251b5Slogin     /// @brief 唤醒在队列中等待的第一个进程。
105151251b5Slogin     /// 如果这个进程的state与给定的state进行and操作之后,结果不为0,则唤醒它。
106151251b5Slogin     ///
107151251b5Slogin     /// @param state 用于判断的state,如果队列中第一个进程的state与它进行and操作之后,结果不为0,则唤醒这个进程。
108151251b5Slogin     ///
109151251b5Slogin     /// @return true 成功唤醒进程
110151251b5Slogin     /// @return false 没有唤醒进程
111151251b5Slogin     pub fn wakeup(&self, state: u64) -> bool {
112151251b5Slogin         let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock();
113151251b5Slogin         // 如果队列为空,则返回
114151251b5Slogin         if guard.wait_list.is_empty() {
115151251b5Slogin             return false;
116151251b5Slogin         }
117151251b5Slogin 
118151251b5Slogin         // 如果队列头部的pcb的state与给定的state相与,结果不为0,则唤醒
119151251b5Slogin         if (guard.wait_list.front().unwrap().state & state) != 0 {
120151251b5Slogin             let to_wakeup = guard.wait_list.pop_front().unwrap();
121151251b5Slogin             unsafe {
122151251b5Slogin                 process_wakeup(to_wakeup);
123151251b5Slogin             }
124151251b5Slogin             return true;
125151251b5Slogin         } else {
126151251b5Slogin             return false;
127151251b5Slogin         }
128151251b5Slogin     }
129151251b5Slogin 
130*cde5492fSlogin     /// @brief 唤醒在队列中,符合条件的所有进程。
131*cde5492fSlogin     ///
132*cde5492fSlogin     /// @param state 用于判断的state,如果队列中第一个进程的state与它进行and操作之后,结果不为0,则唤醒这个进程。
133*cde5492fSlogin     pub fn wakeup_all(&self, state: u64) {
134*cde5492fSlogin         let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock_irqsave();
135*cde5492fSlogin         // 如果队列为空,则返回
136*cde5492fSlogin         if guard.wait_list.is_empty() {
137*cde5492fSlogin             return;
138*cde5492fSlogin         }
139*cde5492fSlogin 
140*cde5492fSlogin         let mut to_push_back: Vec<&mut process_control_block> = Vec::new();
141*cde5492fSlogin         // 如果队列头部的pcb的state与给定的state相与,结果不为0,则唤醒
142*cde5492fSlogin         while let Some(to_wakeup) = guard.wait_list.pop_front() {
143*cde5492fSlogin             if (to_wakeup.state & state) != 0 {
144*cde5492fSlogin                 unsafe {
145*cde5492fSlogin                     process_wakeup(to_wakeup);
146*cde5492fSlogin                 }
147*cde5492fSlogin             } else {
148*cde5492fSlogin                 to_push_back.push(to_wakeup);
149*cde5492fSlogin             }
150*cde5492fSlogin         }
151*cde5492fSlogin 
152*cde5492fSlogin         for to_wakeup in to_push_back {
153*cde5492fSlogin             guard.wait_list.push_back(to_wakeup);
154*cde5492fSlogin         }
155*cde5492fSlogin     }
156*cde5492fSlogin 
157151251b5Slogin     /// @brief 获得当前等待队列的大小
158151251b5Slogin     pub fn len(&self) -> usize {
159151251b5Slogin         return self.0.lock().wait_list.len();
160151251b5Slogin     }
161151251b5Slogin }
162151251b5Slogin 
163151251b5Slogin impl InnerWaitQueue {
164151251b5Slogin     pub const INIT: InnerWaitQueue = InnerWaitQueue {
165151251b5Slogin         wait_list: LinkedList::new(),
166151251b5Slogin     };
167151251b5Slogin }
168