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