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_irqsave(); 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 195 .wait_list 196 .front() 197 .unwrap() 198 .sched_info() 199 .inner_lock_read_irqsave() 200 .state() 201 != state 202 { 203 return false; 204 } 205 } 206 let to_wakeup = guard.wait_list.pop_front().unwrap(); 207 drop(guard); 208 let res = ProcessManager::wakeup(&to_wakeup).is_ok(); 209 return res; 210 } 211 212 /// @brief 唤醒在队列中,符合条件的所有进程。 213 /// 214 /// @param state 用于判断的state,如果一个进程与这个state相同,或者为None(表示不进行这个判断),则唤醒这个进程。 215 pub fn wakeup_all(&self, state: Option<ProcessState>) { 216 let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock_irqsave(); 217 // 如果队列为空,则返回 218 if guard.wait_list.is_empty() { 219 return; 220 } 221 222 let mut to_push_back: Vec<Arc<ProcessControlBlock>> = Vec::new(); 223 // 如果队列头部的pcb的state与给定的state相与,结果不为0,则唤醒 224 while let Some(to_wakeup) = guard.wait_list.pop_front() { 225 let mut wake = false; 226 if let Some(state) = state { 227 if to_wakeup.sched_info().inner_lock_read_irqsave().state() == state { 228 wake = true; 229 } 230 } else { 231 wake = true; 232 } 233 234 if wake { 235 ProcessManager::wakeup(&to_wakeup).unwrap_or_else(|e| { 236 kerror!("wakeup pid: {:?} error: {:?}", to_wakeup.pid(), e); 237 }); 238 continue; 239 } else { 240 to_push_back.push(to_wakeup); 241 } 242 } 243 244 for to_wakeup in to_push_back { 245 guard.wait_list.push_back(to_wakeup); 246 } 247 } 248 249 /// @brief 获得当前等待队列的大小 250 pub fn len(&self) -> usize { 251 return self.0.lock().wait_list.len(); 252 } 253 } 254 255 impl InnerWaitQueue { 256 pub const INIT: InnerWaitQueue = InnerWaitQueue { 257 wait_list: LinkedList::new(), 258 }; 259 } 260 261 fn before_sleep_check(max_preempt: usize) { 262 let pcb = ProcessManager::current_pcb(); 263 if unlikely(pcb.preempt_count() > max_preempt) { 264 kwarn!( 265 "Process {:?}: Try to sleep when preempt count is {}", 266 pcb.pid(), 267 pcb.preempt_count() 268 ); 269 } 270 } 271 272 /// 事件等待队列 273 #[derive(Debug)] 274 pub struct EventWaitQueue { 275 wait_list: SpinLock<Vec<(u64, Arc<ProcessControlBlock>)>>, 276 } 277 278 impl EventWaitQueue { 279 pub fn new() -> Self { 280 Self { 281 wait_list: SpinLock::new(Vec::new()), 282 } 283 } 284 285 /// ## 让当前进程在该队列上等待感兴趣的事件 286 /// 287 /// ### 参数 288 /// - events: 进程感兴趣的事件,events最好是为位表示,一位表示一个事件 289 /// 290 /// 注意,使用前应该注意有可能其他地方定义了冲突的事件,可能会导致未定义行为 291 pub fn sleep(&self, events: u64) { 292 before_sleep_check(0); 293 let mut guard = self.wait_list.lock_irqsave(); 294 ProcessManager::mark_sleep(true).unwrap_or_else(|e| { 295 panic!("sleep error: {:?}", e); 296 }); 297 guard.push((events, ProcessManager::current_pcb())); 298 drop(guard); 299 sched(); 300 } 301 302 pub unsafe fn sleep_without_schedule(&self, events: u64) { 303 before_sleep_check(1); 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 } 311 312 pub fn sleep_unlock_spinlock<T>(&self, events: u64, to_unlock: SpinLockGuard<T>) { 313 before_sleep_check(1); 314 let mut guard = self.wait_list.lock_irqsave(); 315 let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() }; 316 ProcessManager::mark_sleep(true).unwrap_or_else(|e| { 317 panic!("sleep error: {:?}", e); 318 }); 319 drop(irq_guard); 320 guard.push((events, ProcessManager::current_pcb())); 321 drop(to_unlock); 322 drop(guard); 323 sched(); 324 } 325 326 /// ### 唤醒该队列上等待events的进程 327 /// 328 /// ### 参数 329 /// - events: 发生的事件 330 /// 331 /// 需要注意的是,只要触发了events中的任意一件事件,进程都会被唤醒 332 pub fn wakeup_any(&self, events: u64) -> usize { 333 let mut ret = 0; 334 335 let mut wq_guard = self.wait_list.lock_irqsave(); 336 wq_guard.retain(|(es, pcb)| { 337 if *es & events > 0 { 338 // 有感兴趣的事件 339 if ProcessManager::wakeup(pcb).is_ok() { 340 ret += 1; 341 return true; 342 } else { 343 return false; 344 } 345 } else { 346 return false; 347 } 348 }); 349 ret 350 } 351 352 /// ### 唤醒该队列上等待events的进程 353 /// 354 /// ### 参数 355 /// - events: 发生的事件 356 /// 357 /// 需要注意的是,只有满足所有事件的进程才会被唤醒 358 pub fn wakeup(&self, events: u64) -> usize { 359 let mut ret = 0; 360 let mut wq_guard = self.wait_list.lock_irqsave(); 361 wq_guard.retain(|(es, pcb)| { 362 if *es == events { 363 // 有感兴趣的事件 364 if ProcessManager::wakeup(pcb).is_ok() { 365 ret += 1; 366 return true; 367 } else { 368 return false; 369 } 370 } else { 371 return false; 372 } 373 }); 374 ret 375 } 376 377 pub fn wakeup_all(&self) { 378 self.wakeup_any(u64::MAX); 379 } 380 } 381