wait_queue.rs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. #![allow(dead_code)]
  2. use core::intrinsics::unlikely;
  3. use alloc::{collections::LinkedList, sync::Arc, vec::Vec};
  4. use crate::{
  5. arch::{sched::sched, CurrentIrqArch},
  6. exception::InterruptArch,
  7. kerror,
  8. process::{ProcessControlBlock, ProcessManager, ProcessState},
  9. };
  10. use super::{
  11. mutex::MutexGuard,
  12. spinlock::{SpinLock, SpinLockGuard},
  13. };
  14. #[derive(Debug)]
  15. struct InnerWaitQueue {
  16. /// 等待队列的链表
  17. wait_list: LinkedList<Arc<ProcessControlBlock>>,
  18. }
  19. /// 被自旋锁保护的等待队列
  20. #[derive(Debug)]
  21. pub struct WaitQueue(SpinLock<InnerWaitQueue>);
  22. impl WaitQueue {
  23. pub const INIT: WaitQueue = WaitQueue(SpinLock::new(InnerWaitQueue::INIT));
  24. fn before_sleep_check(&self, max_preempt: usize) {
  25. let pcb = ProcessManager::current_pcb();
  26. if unlikely(pcb.preempt_count() > max_preempt) {
  27. kwarn!(
  28. "Process {:?}: Try to sleep when preempt count is {}",
  29. pcb.pid(),
  30. pcb.preempt_count()
  31. );
  32. }
  33. }
  34. /// @brief 让当前进程在等待队列上进行等待,并且,允许被信号打断
  35. pub fn sleep(&self) {
  36. self.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. /// @brief 让当前进程在等待队列上进行等待,并且,在释放waitqueue的锁之前,执行f函数闭包
  46. pub fn sleep_with_func<F>(&self, f: F)
  47. where
  48. F: FnOnce(),
  49. {
  50. self.before_sleep_check(0);
  51. let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock();
  52. let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
  53. ProcessManager::mark_sleep(true).unwrap_or_else(|e| {
  54. panic!("sleep error: {:?}", e);
  55. });
  56. drop(irq_guard);
  57. guard.wait_list.push_back(ProcessManager::current_pcb());
  58. f();
  59. drop(guard);
  60. sched();
  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. self.before_sleep_check(0);
  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. pub unsafe fn sleep_without_schedule_uninterruptible(&self) {
  88. self.before_sleep_check(0);
  89. // 安全检查:确保当前处于中断禁止状态
  90. assert!(CurrentIrqArch::is_irq_enabled() == false);
  91. let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock();
  92. ProcessManager::mark_sleep(false).unwrap_or_else(|e| {
  93. panic!("sleep error: {:?}", e);
  94. });
  95. guard.wait_list.push_back(ProcessManager::current_pcb());
  96. drop(guard);
  97. }
  98. /// @brief 让当前进程在等待队列上进行等待,并且,不允许被信号打断
  99. pub fn sleep_uninterruptible(&self) {
  100. self.before_sleep_check(0);
  101. let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock();
  102. let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
  103. ProcessManager::mark_sleep(false).unwrap_or_else(|e| {
  104. panic!("sleep error: {:?}", e);
  105. });
  106. drop(irq_guard);
  107. guard.wait_list.push_back(ProcessManager::current_pcb());
  108. drop(guard);
  109. sched();
  110. }
  111. /// @brief 让当前进程在等待队列上进行等待,并且,允许被信号打断。
  112. /// 在当前进程的pcb加入队列后,解锁指定的自旋锁。
  113. pub fn sleep_unlock_spinlock<T>(&self, to_unlock: SpinLockGuard<T>) {
  114. self.before_sleep_check(1);
  115. let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock();
  116. let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
  117. ProcessManager::mark_sleep(true).unwrap_or_else(|e| {
  118. panic!("sleep error: {:?}", e);
  119. });
  120. drop(irq_guard);
  121. guard.wait_list.push_back(ProcessManager::current_pcb());
  122. drop(to_unlock);
  123. drop(guard);
  124. sched();
  125. }
  126. /// @brief 让当前进程在等待队列上进行等待,并且,允许被信号打断。
  127. /// 在当前进程的pcb加入队列后,解锁指定的Mutex。
  128. pub fn sleep_unlock_mutex<T>(&self, to_unlock: MutexGuard<T>) {
  129. self.before_sleep_check(1);
  130. let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock();
  131. let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
  132. ProcessManager::mark_sleep(true).unwrap_or_else(|e| {
  133. panic!("sleep error: {:?}", e);
  134. });
  135. drop(irq_guard);
  136. guard.wait_list.push_back(ProcessManager::current_pcb());
  137. drop(to_unlock);
  138. drop(guard);
  139. sched();
  140. }
  141. /// @brief 让当前进程在等待队列上进行等待,并且,不允许被信号打断。
  142. /// 在当前进程的pcb加入队列后,解锁指定的自旋锁。
  143. pub fn sleep_uninterruptible_unlock_spinlock<T>(&self, to_unlock: SpinLockGuard<T>) {
  144. self.before_sleep_check(1);
  145. let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock();
  146. let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
  147. ProcessManager::mark_sleep(false).unwrap_or_else(|e| {
  148. panic!("sleep error: {:?}", e);
  149. });
  150. drop(irq_guard);
  151. guard.wait_list.push_back(ProcessManager::current_pcb());
  152. drop(to_unlock);
  153. drop(guard);
  154. sched();
  155. }
  156. /// @brief 让当前进程在等待队列上进行等待,并且,不允许被信号打断。
  157. /// 在当前进程的pcb加入队列后,解锁指定的Mutex。
  158. pub fn sleep_uninterruptible_unlock_mutex<T>(&self, to_unlock: MutexGuard<T>) {
  159. self.before_sleep_check(1);
  160. let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock();
  161. let irq_guard = unsafe { CurrentIrqArch::save_and_disable_irq() };
  162. ProcessManager::mark_sleep(false).unwrap_or_else(|e| {
  163. panic!("sleep error: {:?}", e);
  164. });
  165. drop(irq_guard);
  166. guard.wait_list.push_back(ProcessManager::current_pcb());
  167. drop(to_unlock);
  168. drop(guard);
  169. sched();
  170. }
  171. /// @brief 唤醒在队列中等待的第一个进程。
  172. /// 如果这个进程的state与给定的state进行and操作之后,结果不为0,则唤醒它。
  173. ///
  174. /// @param state 用于判断的state,如果队列第一个进程与这个state相同,或者为None(表示不进行这个判断),则唤醒这个进程。
  175. ///
  176. /// @return true 成功唤醒进程
  177. /// @return false 没有唤醒进程
  178. pub fn wakeup(&self, state: Option<ProcessState>) -> bool {
  179. let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock();
  180. // 如果队列为空,则返回
  181. if guard.wait_list.is_empty() {
  182. return false;
  183. }
  184. // 如果队列头部的pcb的state与给定的state相与,结果不为0,则唤醒
  185. if let Some(state) = state {
  186. if guard.wait_list.front().unwrap().sched_info().state() != state {
  187. return false;
  188. }
  189. }
  190. let to_wakeup = guard.wait_list.pop_front().unwrap();
  191. let res = ProcessManager::wakeup(&to_wakeup).is_ok();
  192. return res;
  193. }
  194. /// @brief 唤醒在队列中,符合条件的所有进程。
  195. ///
  196. /// @param state 用于判断的state,如果一个进程与这个state相同,或者为None(表示不进行这个判断),则唤醒这个进程。
  197. pub fn wakeup_all(&self, state: Option<ProcessState>) {
  198. let mut guard: SpinLockGuard<InnerWaitQueue> = self.0.lock_irqsave();
  199. // 如果队列为空,则返回
  200. if guard.wait_list.is_empty() {
  201. return;
  202. }
  203. let mut to_push_back: Vec<Arc<ProcessControlBlock>> = Vec::new();
  204. // 如果队列头部的pcb的state与给定的state相与,结果不为0,则唤醒
  205. while let Some(to_wakeup) = guard.wait_list.pop_front() {
  206. let mut wake = false;
  207. if let Some(state) = state {
  208. if to_wakeup.sched_info().state() == state {
  209. wake = true;
  210. }
  211. } else {
  212. wake = true;
  213. }
  214. if wake {
  215. ProcessManager::wakeup(&to_wakeup).unwrap_or_else(|e| {
  216. kerror!("wakeup pid: {:?} error: {:?}", to_wakeup.pid(), e);
  217. });
  218. continue;
  219. } else {
  220. to_push_back.push(to_wakeup);
  221. }
  222. }
  223. for to_wakeup in to_push_back {
  224. guard.wait_list.push_back(to_wakeup);
  225. }
  226. }
  227. /// @brief 获得当前等待队列的大小
  228. pub fn len(&self) -> usize {
  229. return self.0.lock().wait_list.len();
  230. }
  231. }
  232. impl InnerWaitQueue {
  233. pub const INIT: InnerWaitQueue = InnerWaitQueue {
  234. wait_list: LinkedList::new(),
  235. };
  236. }