1use super::__switch;
3use super::{TaskContext, TaskControlBlock};
4use super::{TaskStatus, fetch_task};
5use crate::sync::UPSafeCell;
6use crate::trap::TrapContext;
7use alloc::sync::Arc;
8use lazy_static::*;
9pub struct Processor {
11 current: Option<Arc<TaskControlBlock>>,
13 idle_task_cx: TaskContext,
15}
16
17impl Processor {
18 pub fn new() -> Self {
20 Self {
21 current: None,
22 idle_task_cx: TaskContext::zero_init(),
23 }
24 }
25 fn get_idle_task_cx_ptr(&mut self) -> *mut TaskContext {
27 &mut self.idle_task_cx as *mut _
28 }
29 pub fn take_current(&mut self) -> Option<Arc<TaskControlBlock>> {
31 self.current.take()
32 }
33 pub fn current(&self) -> Option<Arc<TaskControlBlock>> {
35 self.current.as_ref().map(Arc::clone)
36 }
37}
38
39lazy_static! {
40 pub static ref PROCESSOR: UPSafeCell<Processor> = unsafe { UPSafeCell::new(Processor::new()) };
41}
42pub fn run_tasks() {
45 loop {
46 let mut processor = PROCESSOR.exclusive_access();
47 if let Some(task) = fetch_task() {
48 let idle_task_cx_ptr = processor.get_idle_task_cx_ptr();
49 let mut task_inner = task.inner_exclusive_access();
51 let next_task_cx_ptr = &task_inner.task_cx as *const TaskContext;
52 task_inner.task_status = TaskStatus::Running;
53 drop(task_inner);
54 processor.current = Some(task);
56 drop(processor);
58 unsafe {
59 __switch(idle_task_cx_ptr, next_task_cx_ptr);
60 }
61 }
62 }
63}
64pub fn take_current_task() -> Option<Arc<TaskControlBlock>> {
66 PROCESSOR.exclusive_access().take_current()
67}
68pub fn current_task() -> Option<Arc<TaskControlBlock>> {
70 PROCESSOR.exclusive_access().current()
71}
72pub fn current_user_token() -> usize {
74 let task = current_task().unwrap();
75 let token = task.inner_exclusive_access().get_user_token();
76 token
77}
78pub fn current_trap_cx() -> &'static mut TrapContext {
80 current_task()
81 .unwrap()
82 .inner_exclusive_access()
83 .get_trap_cx()
84}
85pub fn schedule(switched_task_cx_ptr: *mut TaskContext) {
87 let mut processor = PROCESSOR.exclusive_access();
88 let idle_task_cx_ptr = processor.get_idle_task_cx_ptr();
89 drop(processor);
90 unsafe {
91 __switch(switched_task_cx_ptr, idle_task_cx_ptr);
92 }
93}