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