sparreal_kernel/task/
schedule.rs

1use alloc::collections::vec_deque::VecDeque;
2use log::debug;
3use spin::Mutex;
4
5use crate::platform_if::PlatformImpl;
6
7use super::tcb::{TaskControlBlock, TaskState, current};
8
9static IDLE: Mutex<VecDeque<TaskControlBlock>> = Mutex::new(VecDeque::new());
10static FINISHED: Mutex<VecDeque<TaskControlBlock>> = Mutex::new(VecDeque::new());
11
12pub fn schedule() {
13    let idle = idle_pop();
14    if let Some(mut idle) = idle {
15        let mut cu = current();
16        if matches!(cu.state, TaskState::Running) {
17            cu.state = TaskState::Suspend;
18        }
19        idle.state = TaskState::Running;
20
21        cu.switch_to(&idle);
22    } else {
23        debug!("No task idle");
24        loop {
25            PlatformImpl::wait_for_interrupt();
26        }
27    }
28}
29
30pub fn idle_push(tcb: TaskControlBlock) {
31    IDLE.lock().push_back(tcb);
32}
33
34pub fn idle_pop() -> Option<TaskControlBlock> {
35    let mut g = IDLE.lock();
36    while let Some(one) = g.pop_front() {
37        if matches!(one.state, TaskState::Stopped) {
38            unsafe { one.drop() };
39            continue;
40        }
41        return Some(one);
42    }
43    None
44}
45
46pub fn finished_push(tcb: TaskControlBlock) {
47    FINISHED.lock().push_back(tcb);
48}
49
50pub fn suspend() {
51    let mut current = current();
52    current.state = TaskState::Suspend;
53    schedule();
54}