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