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