1 #![allow(dead_code)] 2 use alloc::{collections::LinkedList, sync::Arc, vec::Vec}; 3 4 use crate::{ 5 arch::{sched::sched, CurrentIrqArch}, 6 exception::InterruptArch, 7 kerror, 8 process::{ProcessControlBlock, ProcessManager, ProcessState}, 9 }; 10 11 use super::{ 12 mutex::MutexGuard, 13 spinlock::{SpinLock, SpinLockGuard}, 14 }; 15 16 #[derive(Debug)] 17 struct InnerWaitQueue { 18 /// 等待队列的链表 19 wait_list: LinkedList<Arc<ProcessControlBlock>>, 20 } 21 22 /// 被自旋锁保护的等待队列 23 #[derive(Debug)] 24 pub struct WaitQueue(SpinLock<InnerWaitQueue>); 25 26 impl WaitQueue { 27 pub const INIT: WaitQueue = WaitQueue(SpinLock::new(InnerWaitQueue::INIT)); 28 29 /// @brief 让当前进程在等待队列上进行等待,并且,允许被信号打断 30 pub fn sleep(&self) { 31 let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock_irqsave(); 32 ProcessManager::mark_sleep(true).unwrap_or_else(|e| { 33 panic!("sleep error: {:?}", e); 34 }); 35 guard.wait_list.push_back(ProcessManager::current_pcb()); 36 drop(guard); 37 sched(); 38 } 39 40 /// @brief 让当前进程在等待队列上进行等待,并且,在释放waitqueue的锁之前,执行f函数闭包 41 pub fn sleep_with_func<F>(&self, f: F) 42 where 43 F: FnOnce(), 44 { 45 let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock(); 46 let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() }; 47 ProcessManager::mark_sleep(true).unwrap_or_else(|e| { 48 panic!("sleep error: {:?}", e); 49 }); 50 drop(irq_guard); 51 guard.wait_list.push_back(ProcessManager::current_pcb()); 52 f(); 53 drop(guard); 54 sched(); 55 } 56 57 /// @brief 让当前进程在等待队列上进行等待. 但是,在释放waitqueue的锁之后,不会调用调度函数。 58 /// 这样的设计,是为了让调用者可以在执行本函数之后,执行一些操作,然后再【手动调用调度函数】。 59 /// 60 /// 执行本函数前,需要确保处于【中断禁止】状态。 61 /// 62 /// 尽管sleep_with_func和sleep_without_schedule都可以实现这个功能,但是,sleep_with_func会在释放锁之前,执行f函数闭包。 63 /// 64 /// 考虑这样一个场景: 65 /// 等待队列位于某个自旋锁保护的数据结构A中,我们希望在进程睡眠的同时,释放数据结构A的锁。 66 /// 在这种情况下,如果使用sleep_with_func,所有权系统不会允许我们这么做。 67 /// 因此,sleep_without_schedule的设计,正是为了解决这个问题。 68 /// 69 /// 由于sleep_without_schedule不会调用调度函数,因此,如果开发者忘记在执行本函数之后,手动调用调度函数, 70 /// 由于时钟中断到来或者‘其他cpu kick了当前cpu’,可能会导致一些未定义的行为。 71 pub unsafe fn sleep_without_schedule(&self) { 72 // 安全检查:确保当前处于中断禁止状态 73 assert!(CurrentIrqArch::is_irq_enabled() == false); 74 let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock(); 75 ProcessManager::mark_sleep(true).unwrap_or_else(|e| { 76 panic!("sleep error: {:?}", e); 77 }); 78 guard.wait_list.push_back(ProcessManager::current_pcb()); 79 drop(guard); 80 } 81 82 pub unsafe fn sleep_without_schedule_uninterruptible(&self) { 83 // 安全检查:确保当前处于中断禁止状态 84 assert!(CurrentIrqArch::is_irq_enabled() == false); 85 let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock(); 86 ProcessManager::mark_sleep(false).unwrap_or_else(|e| { 87 panic!("sleep error: {:?}", e); 88 }); 89 guard.wait_list.push_back(ProcessManager::current_pcb()); 90 drop(guard); 91 } 92 /// @brief 让当前进程在等待队列上进行等待,并且,不允许被信号打断 93 pub fn sleep_uninterruptible(&self) { 94 let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock(); 95 let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() }; 96 ProcessManager::mark_sleep(false).unwrap_or_else(|e| { 97 panic!("sleep error: {:?}", e); 98 }); 99 drop(irq_guard); 100 guard.wait_list.push_back(ProcessManager::current_pcb()); 101 drop(guard); 102 sched(); 103 } 104 105 /// @brief 让当前进程在等待队列上进行等待,并且,允许被信号打断。 106 /// 在当前进程的pcb加入队列后,解锁指定的自旋锁。 107 pub fn sleep_unlock_spinlock<T>(&self, to_unlock: SpinLockGuard<T>) { 108 let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock(); 109 let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() }; 110 ProcessManager::mark_sleep(true).unwrap_or_else(|e| { 111 panic!("sleep error: {:?}", e); 112 }); 113 drop(irq_guard); 114 guard.wait_list.push_back(ProcessManager::current_pcb()); 115 drop(to_unlock); 116 drop(guard); 117 sched(); 118 } 119 120 /// @brief 让当前进程在等待队列上进行等待,并且,允许被信号打断。 121 /// 在当前进程的pcb加入队列后,解锁指定的Mutex。 122 pub fn sleep_unlock_mutex<T>(&self, to_unlock: MutexGuard<T>) { 123 let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock(); 124 let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() }; 125 ProcessManager::mark_sleep(true).unwrap_or_else(|e| { 126 panic!("sleep error: {:?}", e); 127 }); 128 drop(irq_guard); 129 guard.wait_list.push_back(ProcessManager::current_pcb()); 130 drop(to_unlock); 131 drop(guard); 132 sched(); 133 } 134 135 /// @brief 让当前进程在等待队列上进行等待,并且,不允许被信号打断。 136 /// 在当前进程的pcb加入队列后,解锁指定的自旋锁。 137 pub fn sleep_uninterruptible_unlock_spinlock<T>(&self, to_unlock: SpinLockGuard<T>) { 138 let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock(); 139 let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() }; 140 ProcessManager::mark_sleep(false).unwrap_or_else(|e| { 141 panic!("sleep error: {:?}", e); 142 }); 143 drop(irq_guard); 144 guard.wait_list.push_back(ProcessManager::current_pcb()); 145 drop(to_unlock); 146 drop(guard); 147 sched(); 148 } 149 150 /// @brief 让当前进程在等待队列上进行等待,并且,不允许被信号打断。 151 /// 在当前进程的pcb加入队列后,解锁指定的Mutex。 152 pub fn sleep_uninterruptible_unlock_mutex<T>(&self, to_unlock: MutexGuard<T>) { 153 let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock(); 154 let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() }; 155 ProcessManager::mark_sleep(false).unwrap_or_else(|e| { 156 panic!("sleep error: {:?}", e); 157 }); 158 drop(irq_guard); 159 160 guard.wait_list.push_back(ProcessManager::current_pcb()); 161 162 drop(to_unlock); 163 drop(guard); 164 sched(); 165 } 166 167 /// @brief 唤醒在队列中等待的第一个进程。 168 /// 如果这个进程的state与给定的state进行and操作之后,结果不为0,则唤醒它。 169 /// 170 /// @param state 用于判断的state,如果队列第一个进程与这个state相同,或者为None(表示不进行这个判断),则唤醒这个进程。 171 /// 172 /// @return true 成功唤醒进程 173 /// @return false 没有唤醒进程 174 pub fn wakeup(&self, state: Option<ProcessState>) -> bool { 175 let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock(); 176 // 如果队列为空,则返回 177 if guard.wait_list.is_empty() { 178 return false; 179 } 180 // 如果队列头部的pcb的state与给定的state相与,结果不为0,则唤醒 181 if let Some(state) = state { 182 if guard.wait_list.front().unwrap().sched_info().state() != state { 183 return false; 184 } 185 } 186 let to_wakeup = guard.wait_list.pop_front().unwrap(); 187 let res = ProcessManager::wakeup(&to_wakeup).is_ok(); 188 return res; 189 } 190 191 /// @brief 唤醒在队列中,符合条件的所有进程。 192 /// 193 /// @param state 用于判断的state,如果一个进程与这个state相同,或者为None(表示不进行这个判断),则唤醒这个进程。 194 pub fn wakeup_all(&self, state: Option<ProcessState>) { 195 let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock_irqsave(); 196 // 如果队列为空,则返回 197 if guard.wait_list.is_empty() { 198 return; 199 } 200 201 let mut to_push_back: Vec<Arc<ProcessControlBlock>> = Vec::new(); 202 // 如果队列头部的pcb的state与给定的state相与,结果不为0,则唤醒 203 while let Some(to_wakeup) = guard.wait_list.pop_front() { 204 let mut wake = false; 205 if let Some(state) = state { 206 if to_wakeup.sched_info().state() == state { 207 wake = true; 208 } 209 } else { 210 wake = true; 211 } 212 213 if wake { 214 ProcessManager::wakeup(&to_wakeup).unwrap_or_else(|e| { 215 kerror!("wakeup pid: {:?} error: {:?}", to_wakeup.pid(), e); 216 }); 217 continue; 218 } else { 219 to_push_back.push(to_wakeup); 220 } 221 } 222 223 for to_wakeup in to_push_back { 224 guard.wait_list.push_back(to_wakeup); 225 } 226 } 227 228 /// @brief 获得当前等待队列的大小 229 pub fn len(&self) -> usize { 230 return self.0.lock().wait_list.len(); 231 } 232 } 233 234 impl InnerWaitQueue { 235 pub const INIT: InnerWaitQueue = InnerWaitQueue { 236 wait_list: LinkedList::new(), 237 }; 238 } 239