1151251b5Slogin #![allow(dead_code)] 2cde5492fSlogin use alloc::{collections::LinkedList, vec::Vec}; 3c8025a88Slogin 4151251b5Slogin use crate::{ 5*f678331aShanjiezhou arch::{asm::current::current_pcb, sched::sched, CurrentIrqArch}, 6*f678331aShanjiezhou exception::InterruptArch, 7151251b5Slogin include::bindings::bindings::{ 8151251b5Slogin process_control_block, process_wakeup, wait_queue_head_t, PROC_INTERRUPTIBLE, 9151251b5Slogin PROC_UNINTERRUPTIBLE, 10151251b5Slogin }, 11151251b5Slogin }; 12151251b5Slogin 13151251b5Slogin use super::{ 14151251b5Slogin list::list_init, 15151251b5Slogin mutex::MutexGuard, 16151251b5Slogin spinlock::{SpinLock, SpinLockGuard}, 17151251b5Slogin }; 18c8025a88Slogin 19c8025a88Slogin impl Default for wait_queue_head_t { 20c8025a88Slogin fn default() -> Self { 2106b09f34Skong let mut x = Self { 2206b09f34Skong wait_list: Default::default(), 2306b09f34Skong lock: Default::default(), 2406b09f34Skong }; 25c8025a88Slogin list_init(&mut x.wait_list); 26c8025a88Slogin return x; 27c8025a88Slogin } 28c8025a88Slogin } 29151251b5Slogin 30151251b5Slogin #[derive(Debug)] 31151251b5Slogin struct InnerWaitQueue { 32151251b5Slogin /// 等待队列的链表 33151251b5Slogin wait_list: LinkedList<&'static mut process_control_block>, 34151251b5Slogin } 35151251b5Slogin 36151251b5Slogin /// 被自旋锁保护的等待队列 37151251b5Slogin #[derive(Debug)] 38151251b5Slogin pub struct WaitQueue(SpinLock<InnerWaitQueue>); 39151251b5Slogin 40151251b5Slogin impl WaitQueue { 41151251b5Slogin pub const INIT: WaitQueue = WaitQueue(SpinLock::new(InnerWaitQueue::INIT)); 42151251b5Slogin 43151251b5Slogin /// @brief 让当前进程在等待队列上进行等待,并且,允许被信号打断 44151251b5Slogin pub fn sleep(&self) { 45151251b5Slogin let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock(); 46151251b5Slogin current_pcb().state = PROC_INTERRUPTIBLE as u64; 47151251b5Slogin guard.wait_list.push_back(current_pcb()); 48151251b5Slogin drop(guard); 49*f678331aShanjiezhou 50151251b5Slogin sched(); 51151251b5Slogin } 52151251b5Slogin 53*f678331aShanjiezhou /// @brief 让当前进程在等待队列上进行等待,并且,在释放waitqueue的锁之前,执行f函数闭包 54*f678331aShanjiezhou pub fn sleep_with_func<F>(&self, f: F) 55*f678331aShanjiezhou where 56*f678331aShanjiezhou F: FnOnce(), 57*f678331aShanjiezhou { 58*f678331aShanjiezhou let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock(); 59*f678331aShanjiezhou current_pcb().state = PROC_INTERRUPTIBLE as u64; 60*f678331aShanjiezhou guard.wait_list.push_back(current_pcb()); 61*f678331aShanjiezhou f(); 62*f678331aShanjiezhou drop(guard); 63*f678331aShanjiezhou sched(); 64*f678331aShanjiezhou } 65*f678331aShanjiezhou 66*f678331aShanjiezhou /// @brief 让当前进程在等待队列上进行等待. 但是,在释放waitqueue的锁之后,不会调用调度函数。 67*f678331aShanjiezhou /// 这样的设计,是为了让调用者可以在执行本函数之后,执行一些操作,然后再【手动调用调度函数】。 68*f678331aShanjiezhou /// 69*f678331aShanjiezhou /// 执行本函数前,需要确保处于【中断禁止】状态。 70*f678331aShanjiezhou /// 71*f678331aShanjiezhou /// 尽管sleep_with_func和sleep_without_schedule都可以实现这个功能,但是,sleep_with_func会在释放锁之前,执行f函数闭包。 72*f678331aShanjiezhou /// 73*f678331aShanjiezhou /// 考虑这样一个场景: 74*f678331aShanjiezhou /// 等待队列位于某个自旋锁保护的数据结构A中,我们希望在进程睡眠的同时,释放数据结构A的锁。 75*f678331aShanjiezhou /// 在这种情况下,如果使用sleep_with_func,所有权系统不会允许我们这么做。 76*f678331aShanjiezhou /// 因此,sleep_without_schedule的设计,正是为了解决这个问题。 77*f678331aShanjiezhou /// 78*f678331aShanjiezhou /// 由于sleep_without_schedule不会调用调度函数,因此,如果开发者忘记在执行本函数之后,手动调用调度函数, 79*f678331aShanjiezhou /// 由于时钟中断到来或者‘其他cpu kick了当前cpu’,可能会导致一些未定义的行为。 80*f678331aShanjiezhou pub unsafe fn sleep_without_schedule(&self) { 81*f678331aShanjiezhou // 安全检查:确保当前处于中断禁止状态 82*f678331aShanjiezhou assert!(CurrentIrqArch::is_irq_enabled() == false); 83*f678331aShanjiezhou let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock(); 84*f678331aShanjiezhou current_pcb().state = PROC_INTERRUPTIBLE as u64; 85*f678331aShanjiezhou guard.wait_list.push_back(current_pcb()); 86*f678331aShanjiezhou drop(guard); 87*f678331aShanjiezhou } 88151251b5Slogin /// @brief 让当前进程在等待队列上进行等待,并且,不允许被信号打断 89151251b5Slogin pub fn sleep_uninterruptible(&self) { 90151251b5Slogin let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock(); 91151251b5Slogin current_pcb().state = PROC_UNINTERRUPTIBLE as u64; 92151251b5Slogin guard.wait_list.push_back(current_pcb()); 93151251b5Slogin drop(guard); 94151251b5Slogin sched(); 95151251b5Slogin } 96151251b5Slogin 97151251b5Slogin /// @brief 让当前进程在等待队列上进行等待,并且,允许被信号打断。 98151251b5Slogin /// 在当前进程的pcb加入队列后,解锁指定的自旋锁。 99151251b5Slogin pub fn sleep_unlock_spinlock<T>(&self, to_unlock: SpinLockGuard<T>) { 100151251b5Slogin let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock(); 101151251b5Slogin current_pcb().state = PROC_INTERRUPTIBLE as u64; 102151251b5Slogin guard.wait_list.push_back(current_pcb()); 103151251b5Slogin drop(to_unlock); 104151251b5Slogin drop(guard); 105151251b5Slogin sched(); 106151251b5Slogin } 107151251b5Slogin 108151251b5Slogin /// @brief 让当前进程在等待队列上进行等待,并且,允许被信号打断。 109151251b5Slogin /// 在当前进程的pcb加入队列后,解锁指定的Mutex。 110151251b5Slogin pub fn sleep_unlock_mutex<T>(&self, to_unlock: MutexGuard<T>) { 111151251b5Slogin let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock(); 112151251b5Slogin current_pcb().state = PROC_INTERRUPTIBLE as u64; 113151251b5Slogin guard.wait_list.push_back(current_pcb()); 114151251b5Slogin drop(to_unlock); 115151251b5Slogin drop(guard); 116151251b5Slogin sched(); 117151251b5Slogin } 118151251b5Slogin 119151251b5Slogin /// @brief 让当前进程在等待队列上进行等待,并且,不允许被信号打断。 120151251b5Slogin /// 在当前进程的pcb加入队列后,解锁指定的自旋锁。 121151251b5Slogin pub fn sleep_uninterruptible_unlock_spinlock<T>(&self, to_unlock: SpinLockGuard<T>) { 122151251b5Slogin let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock(); 123151251b5Slogin current_pcb().state = PROC_UNINTERRUPTIBLE as u64; 124151251b5Slogin guard.wait_list.push_back(current_pcb()); 125151251b5Slogin drop(to_unlock); 126151251b5Slogin drop(guard); 127151251b5Slogin sched(); 128151251b5Slogin } 129151251b5Slogin 130151251b5Slogin /// @brief 让当前进程在等待队列上进行等待,并且,不允许被信号打断。 131151251b5Slogin /// 在当前进程的pcb加入队列后,解锁指定的Mutex。 132151251b5Slogin pub fn sleep_uninterruptible_unlock_mutex<T>(&self, to_unlock: MutexGuard<T>) { 133151251b5Slogin let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock(); 134151251b5Slogin current_pcb().state = PROC_UNINTERRUPTIBLE as u64; 135151251b5Slogin guard.wait_list.push_back(current_pcb()); 136151251b5Slogin drop(to_unlock); 137151251b5Slogin drop(guard); 138151251b5Slogin sched(); 139151251b5Slogin } 140151251b5Slogin 141151251b5Slogin /// @brief 唤醒在队列中等待的第一个进程。 142151251b5Slogin /// 如果这个进程的state与给定的state进行and操作之后,结果不为0,则唤醒它。 143151251b5Slogin /// 144151251b5Slogin /// @param state 用于判断的state,如果队列中第一个进程的state与它进行and操作之后,结果不为0,则唤醒这个进程。 145151251b5Slogin /// 146151251b5Slogin /// @return true 成功唤醒进程 147151251b5Slogin /// @return false 没有唤醒进程 148151251b5Slogin pub fn wakeup(&self, state: u64) -> bool { 149151251b5Slogin let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock(); 150151251b5Slogin // 如果队列为空,则返回 151151251b5Slogin if guard.wait_list.is_empty() { 152151251b5Slogin return false; 153151251b5Slogin } 154151251b5Slogin 155151251b5Slogin // 如果队列头部的pcb的state与给定的state相与,结果不为0,则唤醒 156151251b5Slogin if (guard.wait_list.front().unwrap().state & state) != 0 { 157151251b5Slogin let to_wakeup = guard.wait_list.pop_front().unwrap(); 158151251b5Slogin unsafe { 159151251b5Slogin process_wakeup(to_wakeup); 160151251b5Slogin } 161151251b5Slogin return true; 162151251b5Slogin } else { 163151251b5Slogin return false; 164151251b5Slogin } 165151251b5Slogin } 166151251b5Slogin 167cde5492fSlogin /// @brief 唤醒在队列中,符合条件的所有进程。 168cde5492fSlogin /// 169cde5492fSlogin /// @param state 用于判断的state,如果队列中第一个进程的state与它进行and操作之后,结果不为0,则唤醒这个进程。 170cde5492fSlogin pub fn wakeup_all(&self, state: u64) { 171cde5492fSlogin let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock_irqsave(); 172cde5492fSlogin // 如果队列为空,则返回 173cde5492fSlogin if guard.wait_list.is_empty() { 174cde5492fSlogin return; 175cde5492fSlogin } 176cde5492fSlogin 177cde5492fSlogin let mut to_push_back: Vec<&mut process_control_block> = Vec::new(); 178cde5492fSlogin // 如果队列头部的pcb的state与给定的state相与,结果不为0,则唤醒 179cde5492fSlogin while let Some(to_wakeup) = guard.wait_list.pop_front() { 180cde5492fSlogin if (to_wakeup.state & state) != 0 { 181cde5492fSlogin unsafe { 182cde5492fSlogin process_wakeup(to_wakeup); 183cde5492fSlogin } 184cde5492fSlogin } else { 185cde5492fSlogin to_push_back.push(to_wakeup); 186cde5492fSlogin } 187cde5492fSlogin } 188cde5492fSlogin 189cde5492fSlogin for to_wakeup in to_push_back { 190cde5492fSlogin guard.wait_list.push_back(to_wakeup); 191cde5492fSlogin } 192cde5492fSlogin } 193cde5492fSlogin 194151251b5Slogin /// @brief 获得当前等待队列的大小 195151251b5Slogin pub fn len(&self) -> usize { 196151251b5Slogin return self.0.lock().wait_list.len(); 197151251b5Slogin } 198151251b5Slogin } 199151251b5Slogin 200151251b5Slogin impl InnerWaitQueue { 201151251b5Slogin pub const INIT: InnerWaitQueue = InnerWaitQueue { 202151251b5Slogin wait_list: LinkedList::new(), 203151251b5Slogin }; 204151251b5Slogin } 205