1use super::id::TaskUserRes;
2use super::{KernelStack, ProcessControlBlock, TaskContext, kstack_alloc};
3use crate::trap::TrapContext;
4use crate::{mm::PhysPageNum, sync::UPSafeCell};
5use alloc::sync::{Arc, Weak};
6use core::cell::RefMut;
7
8pub struct TaskControlBlock {
9 pub process: Weak<ProcessControlBlock>,
11 pub kstack: KernelStack,
12 inner: UPSafeCell<TaskControlBlockInner>,
14}
15
16impl TaskControlBlock {
17 pub fn inner_exclusive_access(&self) -> RefMut<'_, TaskControlBlockInner> {
18 self.inner.exclusive_access()
19 }
20
21 pub fn get_user_token(&self) -> usize {
22 let process = self.process.upgrade().unwrap();
23 let inner = process.inner_exclusive_access();
24 inner.memory_set.token()
25 }
26}
27
28pub struct TaskControlBlockInner {
29 pub res: Option<TaskUserRes>,
30 pub trap_cx_ppn: PhysPageNum,
31 pub task_cx: TaskContext,
32 pub task_status: TaskStatus,
33 pub exit_code: Option<i32>,
34}
35
36impl TaskControlBlockInner {
37 pub fn get_trap_cx(&self) -> &'static mut TrapContext {
38 self.trap_cx_ppn.get_mut()
39 }
40
41 #[allow(unused)]
42 fn get_status(&self) -> TaskStatus {
43 self.task_status
44 }
45}
46
47impl TaskControlBlock {
48 pub fn new(
49 process: Arc<ProcessControlBlock>,
50 ustack_base: usize,
51 alloc_user_res: bool,
52 ) -> Self {
53 let res = TaskUserRes::new(Arc::clone(&process), ustack_base, alloc_user_res);
54 let trap_cx_ppn = res.trap_cx_ppn();
55 let kstack = kstack_alloc();
56 let kstack_top = kstack.get_top();
57 Self {
58 process: Arc::downgrade(&process),
59 kstack,
60 inner: unsafe {
61 UPSafeCell::new(TaskControlBlockInner {
62 res: Some(res),
63 trap_cx_ppn,
64 task_cx: TaskContext::goto_trap_return(kstack_top),
65 task_status: TaskStatus::Ready,
66 exit_code: None,
67 })
68 },
69 }
70 }
71}
72
73#[derive(Copy, Clone, PartialEq)]
74pub enum TaskStatus {
75 Ready,
76 Running,
77 Blocked,
78}