os/kernel/task/
work_queue.rs

1//! 任务工作队列模块
2//!
3//! 任务工作队列用于延迟执行某些任务相关的操作,以避免在关键路径上执行耗时操作。
4//! 例如,当任务终止时,我们不希望立即清理任务资源,而是将清理操作放入工作队列中,
5//! 由专门的工作线程在合适的时机执行。
6#![allow(dead_code)]
7
8use alloc::{collections::vec_deque::VecDeque, vec::Vec};
9
10use crate::{
11    kernel::{
12        SharedTask, TaskState, current_task, sleep_task_with_block, wake_up_with_block, yield_task,
13    },
14    sync::SpinLock,
15};
16
17lazy_static::lazy_static! {
18    pub static ref GLOBAL_WORK_QUEUE: SpinLock<WorkQueue> = SpinLock::new(WorkQueue::new());
19}
20
21/// 工作项结构体
22pub struct WorkItem {
23    /// 任务函数
24    pub task: fn(),
25}
26
27impl WorkItem {
28    /// 创建一个新的工作项
29    pub fn new(task: fn()) -> Self {
30        WorkItem { task }
31    }
32}
33
34/// 工作队列结构体
35pub struct WorkQueue {
36    /// 当前处于休眠状态的工作线程数量
37    sleeping: usize,
38    /// 工作线程列表
39    worker: Vec<SharedTask>,
40    /// 待处理的工作项队列
41    work_queue: VecDeque<WorkItem>,
42}
43
44impl WorkQueue {
45    /// 创建一个新的工作队列实例
46    pub fn new() -> Self {
47        WorkQueue {
48            worker: Vec::new(),
49            work_queue: VecDeque::new(),
50            sleeping: 0,
51        }
52    }
53
54    /// 将工作项加入工作队列,并唤醒工作线程
55    pub fn schedule_work(&mut self, work: WorkItem) {
56        self.work_queue.push_back(work);
57        if self.sleeping > 0 {
58            for task in &self.worker {
59                if task.lock().state == TaskState::Interruptible {
60                    wake_up_with_block(task.clone());
61                    break;
62                }
63            }
64        }
65    }
66
67    /// 添加工作线程到工作队列
68    pub fn add_worker(&mut self, task: SharedTask) {
69        self.worker.push(task);
70    }
71}
72
73/// 工作线程主函数
74pub fn kworker() {
75    GLOBAL_WORK_QUEUE.lock().add_worker(current_task());
76    loop {
77        let mut queue = GLOBAL_WORK_QUEUE.lock();
78
79        if let Some(work) = queue.work_queue.pop_front() {
80            (work.task)();
81        } else {
82            queue.sleeping += 1;
83            sleep_task_with_block(current_task(), true);
84            drop(queue);
85            yield_task();
86            GLOBAL_WORK_QUEUE.lock().sleeping -= 1;
87        }
88    }
89}