1151251b5Slogin #![allow(dead_code)] 2*2f6f547aSGnoCiYeH use core::intrinsics::unlikely; 3*2f6f547aSGnoCiYeH 41496ba7bSLoGin use alloc::{collections::LinkedList, sync::Arc, vec::Vec}; 5c8025a88Slogin 6151251b5Slogin use crate::{ 71496ba7bSLoGin arch::{sched::sched, CurrentIrqArch}, 8f678331aShanjiezhou exception::InterruptArch, 91496ba7bSLoGin kerror, 101496ba7bSLoGin process::{ProcessControlBlock, ProcessManager, ProcessState}, 11151251b5Slogin }; 12151251b5Slogin 13151251b5Slogin use super::{ 14151251b5Slogin mutex::MutexGuard, 15151251b5Slogin spinlock::{SpinLock, SpinLockGuard}, 16151251b5Slogin }; 17c8025a88Slogin 18151251b5Slogin #[derive(Debug)] 19151251b5Slogin struct InnerWaitQueue { 20151251b5Slogin /// 等待队列的链表 211496ba7bSLoGin wait_list: LinkedList<Arc<ProcessControlBlock>>, 22151251b5Slogin } 23151251b5Slogin 24151251b5Slogin /// 被自旋锁保护的等待队列 25151251b5Slogin #[derive(Debug)] 26151251b5Slogin pub struct WaitQueue(SpinLock<InnerWaitQueue>); 27151251b5Slogin 28151251b5Slogin impl WaitQueue { 29151251b5Slogin pub const INIT: WaitQueue = WaitQueue(SpinLock::new(InnerWaitQueue::INIT)); 30151251b5Slogin 31*2f6f547aSGnoCiYeH fn before_sleep_check(&self, max_preempt: usize) { 32*2f6f547aSGnoCiYeH let pcb = ProcessManager::current_pcb(); 33*2f6f547aSGnoCiYeH if unlikely(pcb.preempt_count() > max_preempt) { 34*2f6f547aSGnoCiYeH kwarn!( 35*2f6f547aSGnoCiYeH "Process {:?}: Try to sleep when preempt count is {}", 36*2f6f547aSGnoCiYeH pcb.pid(), 37*2f6f547aSGnoCiYeH pcb.preempt_count() 38*2f6f547aSGnoCiYeH ); 39*2f6f547aSGnoCiYeH } 40*2f6f547aSGnoCiYeH } 41*2f6f547aSGnoCiYeH 42151251b5Slogin /// @brief 让当前进程在等待队列上进行等待,并且,允许被信号打断 43151251b5Slogin pub fn sleep(&self) { 44*2f6f547aSGnoCiYeH self.before_sleep_check(0); 451496ba7bSLoGin let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock_irqsave(); 461496ba7bSLoGin ProcessManager::mark_sleep(true).unwrap_or_else(|e| { 471496ba7bSLoGin panic!("sleep error: {:?}", e); 481496ba7bSLoGin }); 491496ba7bSLoGin guard.wait_list.push_back(ProcessManager::current_pcb()); 50151251b5Slogin drop(guard); 51151251b5Slogin sched(); 52151251b5Slogin } 53151251b5Slogin 54f678331aShanjiezhou /// @brief 让当前进程在等待队列上进行等待,并且,在释放waitqueue的锁之前,执行f函数闭包 55f678331aShanjiezhou pub fn sleep_with_func<F>(&self, f: F) 56f678331aShanjiezhou where 57f678331aShanjiezhou F: FnOnce(), 58f678331aShanjiezhou { 59*2f6f547aSGnoCiYeH self.before_sleep_check(0); 60f678331aShanjiezhou let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock(); 611496ba7bSLoGin let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() }; 621496ba7bSLoGin ProcessManager::mark_sleep(true).unwrap_or_else(|e| { 631496ba7bSLoGin panic!("sleep error: {:?}", e); 641496ba7bSLoGin }); 651496ba7bSLoGin drop(irq_guard); 661496ba7bSLoGin guard.wait_list.push_back(ProcessManager::current_pcb()); 67f678331aShanjiezhou f(); 68*2f6f547aSGnoCiYeH 69f678331aShanjiezhou drop(guard); 70f678331aShanjiezhou sched(); 71f678331aShanjiezhou } 72f678331aShanjiezhou 73f678331aShanjiezhou /// @brief 让当前进程在等待队列上进行等待. 但是,在释放waitqueue的锁之后,不会调用调度函数。 74f678331aShanjiezhou /// 这样的设计,是为了让调用者可以在执行本函数之后,执行一些操作,然后再【手动调用调度函数】。 75f678331aShanjiezhou /// 76f678331aShanjiezhou /// 执行本函数前,需要确保处于【中断禁止】状态。 77f678331aShanjiezhou /// 78f678331aShanjiezhou /// 尽管sleep_with_func和sleep_without_schedule都可以实现这个功能,但是,sleep_with_func会在释放锁之前,执行f函数闭包。 79f678331aShanjiezhou /// 80f678331aShanjiezhou /// 考虑这样一个场景: 81f678331aShanjiezhou /// 等待队列位于某个自旋锁保护的数据结构A中,我们希望在进程睡眠的同时,释放数据结构A的锁。 82f678331aShanjiezhou /// 在这种情况下,如果使用sleep_with_func,所有权系统不会允许我们这么做。 83f678331aShanjiezhou /// 因此,sleep_without_schedule的设计,正是为了解决这个问题。 84f678331aShanjiezhou /// 85f678331aShanjiezhou /// 由于sleep_without_schedule不会调用调度函数,因此,如果开发者忘记在执行本函数之后,手动调用调度函数, 86f678331aShanjiezhou /// 由于时钟中断到来或者‘其他cpu kick了当前cpu’,可能会导致一些未定义的行为。 87f678331aShanjiezhou pub unsafe fn sleep_without_schedule(&self) { 88*2f6f547aSGnoCiYeH self.before_sleep_check(0); 89f678331aShanjiezhou // 安全检查:确保当前处于中断禁止状态 90f678331aShanjiezhou assert!(CurrentIrqArch::is_irq_enabled() == false); 91f678331aShanjiezhou let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock(); 921496ba7bSLoGin ProcessManager::mark_sleep(true).unwrap_or_else(|e| { 931496ba7bSLoGin panic!("sleep error: {:?}", e); 941496ba7bSLoGin }); 951496ba7bSLoGin guard.wait_list.push_back(ProcessManager::current_pcb()); 961496ba7bSLoGin drop(guard); 971496ba7bSLoGin } 981496ba7bSLoGin 991496ba7bSLoGin pub unsafe fn sleep_without_schedule_uninterruptible(&self) { 100*2f6f547aSGnoCiYeH self.before_sleep_check(0); 1011496ba7bSLoGin // 安全检查:确保当前处于中断禁止状态 1021496ba7bSLoGin assert!(CurrentIrqArch::is_irq_enabled() == false); 1031496ba7bSLoGin let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock(); 1041496ba7bSLoGin ProcessManager::mark_sleep(false).unwrap_or_else(|e| { 1051496ba7bSLoGin panic!("sleep error: {:?}", e); 1061496ba7bSLoGin }); 1071496ba7bSLoGin guard.wait_list.push_back(ProcessManager::current_pcb()); 108f678331aShanjiezhou drop(guard); 109f678331aShanjiezhou } 110151251b5Slogin /// @brief 让当前进程在等待队列上进行等待,并且,不允许被信号打断 111151251b5Slogin pub fn sleep_uninterruptible(&self) { 112*2f6f547aSGnoCiYeH self.before_sleep_check(0); 113151251b5Slogin let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock(); 1141496ba7bSLoGin let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() }; 1151496ba7bSLoGin ProcessManager::mark_sleep(false).unwrap_or_else(|e| { 1161496ba7bSLoGin panic!("sleep error: {:?}", e); 1171496ba7bSLoGin }); 1181496ba7bSLoGin drop(irq_guard); 1191496ba7bSLoGin guard.wait_list.push_back(ProcessManager::current_pcb()); 120151251b5Slogin drop(guard); 121151251b5Slogin sched(); 122151251b5Slogin } 123151251b5Slogin 124151251b5Slogin /// @brief 让当前进程在等待队列上进行等待,并且,允许被信号打断。 125151251b5Slogin /// 在当前进程的pcb加入队列后,解锁指定的自旋锁。 126151251b5Slogin pub fn sleep_unlock_spinlock<T>(&self, to_unlock: SpinLockGuard<T>) { 127*2f6f547aSGnoCiYeH self.before_sleep_check(1); 128151251b5Slogin let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock(); 1291496ba7bSLoGin let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() }; 1301496ba7bSLoGin ProcessManager::mark_sleep(true).unwrap_or_else(|e| { 1311496ba7bSLoGin panic!("sleep error: {:?}", e); 1321496ba7bSLoGin }); 1331496ba7bSLoGin drop(irq_guard); 1341496ba7bSLoGin guard.wait_list.push_back(ProcessManager::current_pcb()); 135151251b5Slogin drop(to_unlock); 136151251b5Slogin drop(guard); 137151251b5Slogin sched(); 138151251b5Slogin } 139151251b5Slogin 140151251b5Slogin /// @brief 让当前进程在等待队列上进行等待,并且,允许被信号打断。 141151251b5Slogin /// 在当前进程的pcb加入队列后,解锁指定的Mutex。 142151251b5Slogin pub fn sleep_unlock_mutex<T>(&self, to_unlock: MutexGuard<T>) { 143*2f6f547aSGnoCiYeH self.before_sleep_check(1); 144151251b5Slogin let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock(); 1451496ba7bSLoGin let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() }; 1461496ba7bSLoGin ProcessManager::mark_sleep(true).unwrap_or_else(|e| { 1471496ba7bSLoGin panic!("sleep error: {:?}", e); 1481496ba7bSLoGin }); 1491496ba7bSLoGin drop(irq_guard); 1501496ba7bSLoGin guard.wait_list.push_back(ProcessManager::current_pcb()); 151151251b5Slogin drop(to_unlock); 152151251b5Slogin drop(guard); 153151251b5Slogin sched(); 154151251b5Slogin } 155151251b5Slogin 156151251b5Slogin /// @brief 让当前进程在等待队列上进行等待,并且,不允许被信号打断。 157151251b5Slogin /// 在当前进程的pcb加入队列后,解锁指定的自旋锁。 158151251b5Slogin pub fn sleep_uninterruptible_unlock_spinlock<T>(&self, to_unlock: SpinLockGuard<T>) { 159*2f6f547aSGnoCiYeH self.before_sleep_check(1); 160151251b5Slogin let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock(); 1611496ba7bSLoGin let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() }; 1621496ba7bSLoGin ProcessManager::mark_sleep(false).unwrap_or_else(|e| { 1631496ba7bSLoGin panic!("sleep error: {:?}", e); 1641496ba7bSLoGin }); 1651496ba7bSLoGin drop(irq_guard); 1661496ba7bSLoGin guard.wait_list.push_back(ProcessManager::current_pcb()); 167151251b5Slogin drop(to_unlock); 168151251b5Slogin drop(guard); 169151251b5Slogin sched(); 170151251b5Slogin } 171151251b5Slogin 172151251b5Slogin /// @brief 让当前进程在等待队列上进行等待,并且,不允许被信号打断。 173151251b5Slogin /// 在当前进程的pcb加入队列后,解锁指定的Mutex。 174151251b5Slogin pub fn sleep_uninterruptible_unlock_mutex<T>(&self, to_unlock: MutexGuard<T>) { 175*2f6f547aSGnoCiYeH self.before_sleep_check(1); 176151251b5Slogin let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock(); 1771496ba7bSLoGin let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() }; 1781496ba7bSLoGin ProcessManager::mark_sleep(false).unwrap_or_else(|e| { 1791496ba7bSLoGin panic!("sleep error: {:?}", e); 1801496ba7bSLoGin }); 1811496ba7bSLoGin drop(irq_guard); 1821496ba7bSLoGin 1831496ba7bSLoGin guard.wait_list.push_back(ProcessManager::current_pcb()); 1841496ba7bSLoGin 185151251b5Slogin drop(to_unlock); 186151251b5Slogin drop(guard); 187151251b5Slogin sched(); 188151251b5Slogin } 189151251b5Slogin 190151251b5Slogin /// @brief 唤醒在队列中等待的第一个进程。 191151251b5Slogin /// 如果这个进程的state与给定的state进行and操作之后,结果不为0,则唤醒它。 192151251b5Slogin /// 1931496ba7bSLoGin /// @param state 用于判断的state,如果队列第一个进程与这个state相同,或者为None(表示不进行这个判断),则唤醒这个进程。 194151251b5Slogin /// 195151251b5Slogin /// @return true 成功唤醒进程 196151251b5Slogin /// @return false 没有唤醒进程 1971496ba7bSLoGin pub fn wakeup(&self, state: Option<ProcessState>) -> bool { 198151251b5Slogin let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock(); 199151251b5Slogin // 如果队列为空,则返回 200151251b5Slogin if guard.wait_list.is_empty() { 201151251b5Slogin return false; 202151251b5Slogin } 203151251b5Slogin // 如果队列头部的pcb的state与给定的state相与,结果不为0,则唤醒 2041496ba7bSLoGin if let Some(state) = state { 2051496ba7bSLoGin if guard.wait_list.front().unwrap().sched_info().state() != state { 206151251b5Slogin return false; 207151251b5Slogin } 208151251b5Slogin } 2091496ba7bSLoGin let to_wakeup = guard.wait_list.pop_front().unwrap(); 2101496ba7bSLoGin let res = ProcessManager::wakeup(&to_wakeup).is_ok(); 2111496ba7bSLoGin return res; 2121496ba7bSLoGin } 213151251b5Slogin 214cde5492fSlogin /// @brief 唤醒在队列中,符合条件的所有进程。 215cde5492fSlogin /// 2161496ba7bSLoGin /// @param state 用于判断的state,如果一个进程与这个state相同,或者为None(表示不进行这个判断),则唤醒这个进程。 2171496ba7bSLoGin pub fn wakeup_all(&self, state: Option<ProcessState>) { 218cde5492fSlogin let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock_irqsave(); 219cde5492fSlogin // 如果队列为空,则返回 220cde5492fSlogin if guard.wait_list.is_empty() { 221cde5492fSlogin return; 222cde5492fSlogin } 223cde5492fSlogin 2241496ba7bSLoGin let mut to_push_back: Vec<Arc<ProcessControlBlock>> = Vec::new(); 225cde5492fSlogin // 如果队列头部的pcb的state与给定的state相与,结果不为0,则唤醒 226cde5492fSlogin while let Some(to_wakeup) = guard.wait_list.pop_front() { 227a03c4f9dSLoGin let mut wake = false; 2281496ba7bSLoGin if let Some(state) = state { 2291496ba7bSLoGin if to_wakeup.sched_info().state() == state { 230a03c4f9dSLoGin wake = true; 231a03c4f9dSLoGin } 232a03c4f9dSLoGin } else { 233a03c4f9dSLoGin wake = true; 234a03c4f9dSLoGin } 235a03c4f9dSLoGin 236a03c4f9dSLoGin if wake { 2371496ba7bSLoGin ProcessManager::wakeup(&to_wakeup).unwrap_or_else(|e| { 2381496ba7bSLoGin kerror!("wakeup pid: {:?} error: {:?}", to_wakeup.pid(), e); 2391496ba7bSLoGin }); 2401496ba7bSLoGin continue; 241a03c4f9dSLoGin } else { 242cde5492fSlogin to_push_back.push(to_wakeup); 243cde5492fSlogin } 244a03c4f9dSLoGin } 245a03c4f9dSLoGin 246cde5492fSlogin for to_wakeup in to_push_back { 247cde5492fSlogin guard.wait_list.push_back(to_wakeup); 248cde5492fSlogin } 249cde5492fSlogin } 250cde5492fSlogin 251151251b5Slogin /// @brief 获得当前等待队列的大小 252151251b5Slogin pub fn len(&self) -> usize { 253151251b5Slogin return self.0.lock().wait_list.len(); 254151251b5Slogin } 255151251b5Slogin } 256151251b5Slogin 257151251b5Slogin impl InnerWaitQueue { 258151251b5Slogin pub const INIT: InnerWaitQueue = InnerWaitQueue { 259151251b5Slogin wait_list: LinkedList::new(), 260151251b5Slogin }; 261151251b5Slogin } 262