1use super::__switch;
2use super::{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 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 processor.current = Some(task);
48 drop(processor);
50 unsafe {
51 __switch(idle_task_cx_ptr, next_task_cx_ptr);
52 }
53 }
54 }
55}
56
57pub fn take_current_task() -> Option<Arc<TaskControlBlock>> {
58 PROCESSOR.exclusive_access().take_current()
59}
60
61pub fn current_task() -> Option<Arc<TaskControlBlock>> {
62 PROCESSOR.exclusive_access().current()
63}
64
65pub fn current_user_token() -> usize {
66 let task = current_task().unwrap();
67 let token = task.inner_exclusive_access().get_user_token();
68 token
69}
70
71pub fn current_trap_cx() -> &'static mut TrapContext {
72 current_task()
73 .unwrap()
74 .inner_exclusive_access()
75 .get_trap_cx()
76}
77
78pub fn schedule(switched_task_cx_ptr: *mut TaskContext) {
79 let mut processor = PROCESSOR.exclusive_access();
80 let idle_task_cx_ptr = processor.get_idle_task_cx_ptr();
81 drop(processor);
82 unsafe {
83 __switch(switched_task_cx_ptr, idle_task_cx_ptr);
84 }
85}