os/kernel/task/
work_queue.rs1#![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
21pub struct WorkItem {
23 pub task: fn(),
25}
26
27impl WorkItem {
28 pub fn new(task: fn()) -> Self {
30 WorkItem { task }
31 }
32}
33
34pub struct WorkQueue {
36 sleeping: usize,
38 worker: Vec<SharedTask>,
40 work_queue: VecDeque<WorkItem>,
42}
43
44impl WorkQueue {
45 pub fn new() -> Self {
47 WorkQueue {
48 worker: Vec::new(),
49 work_queue: VecDeque::new(),
50 sleeping: 0,
51 }
52 }
53
54 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 pub fn add_worker(&mut self, task: SharedTask) {
69 self.worker.push(task);
70 }
71}
72
73pub 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}