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