os/task/
processor.rs

1use super::__switch;
2use super::{ProcessControlBlock, TaskContext, TaskControlBlock};
3use super::{TaskStatus, fetch_task};
4use crate::sync::UPSafeCell;
5use crate::trap::TrapContext;
6use alloc::sync::Arc;
7use lazy_static::*;
8
9pub struct Processor {
10    current: Option<Arc<TaskControlBlock>>,
11    idle_task_cx: TaskContext,
12}
13
14impl Processor {
15    pub fn new() -> Self {
16        Self {
17            current: None,
18            idle_task_cx: TaskContext::zero_init(),
19        }
20    }
21    fn get_idle_task_cx_ptr(&mut self) -> *mut TaskContext {
22        &mut self.idle_task_cx as *mut _
23    }
24    pub fn take_current(&mut self) -> Option<Arc<TaskControlBlock>> {
25        self.current.take()
26    }
27    pub fn current(&self) -> Option<Arc<TaskControlBlock>> {
28        self.current.as_ref().map(Arc::clone)
29    }
30}
31
32lazy_static! {
33    pub static ref PROCESSOR: UPSafeCell<Processor> = unsafe { UPSafeCell::new(Processor::new()) };
34}
35
36pub fn run_tasks() {
37    loop {
38        let mut processor = PROCESSOR.exclusive_access();
39        if let Some(task) = fetch_task() {
40            let idle_task_cx_ptr = processor.get_idle_task_cx_ptr();
41            // access coming task TCB exclusively
42            let mut task_inner = task.inner_exclusive_access();
43            let next_task_cx_ptr = &task_inner.task_cx as *const TaskContext;
44            task_inner.task_status = TaskStatus::Running;
45            drop(task_inner);
46            // release coming task TCB manually
47            processor.current = Some(task);
48            // release processor manually
49            drop(processor);
50            unsafe {
51                __switch(idle_task_cx_ptr, next_task_cx_ptr);
52            }
53        } else {
54            println!("no tasks available in run_tasks");
55        }
56    }
57}
58
59pub fn take_current_task() -> Option<Arc<TaskControlBlock>> {
60    PROCESSOR.exclusive_access().take_current()
61}
62
63pub fn current_task() -> Option<Arc<TaskControlBlock>> {
64    PROCESSOR.exclusive_access().current()
65}
66
67pub fn current_process() -> Arc<ProcessControlBlock> {
68    current_task().unwrap().process.upgrade().unwrap()
69}
70
71pub fn current_user_token() -> usize {
72    let task = current_task().unwrap();
73    task.get_user_token()
74}
75
76pub fn current_trap_cx() -> &'static mut TrapContext {
77    current_task()
78        .unwrap()
79        .inner_exclusive_access()
80        .get_trap_cx()
81}
82
83pub fn current_trap_cx_user_va() -> usize {
84    current_task()
85        .unwrap()
86        .inner_exclusive_access()
87        .res
88        .as_ref()
89        .unwrap()
90        .trap_cx_user_va()
91}
92
93pub fn current_kstack_top() -> usize {
94    current_task().unwrap().kstack.get_top()
95}
96
97pub fn schedule(switched_task_cx_ptr: *mut TaskContext) {
98    let mut processor = PROCESSOR.exclusive_access();
99    let idle_task_cx_ptr = processor.get_idle_task_cx_ptr();
100    drop(processor);
101    unsafe {
102        __switch(switched_task_cx_ptr, idle_task_cx_ptr);
103    }
104}