1mod context;
2mod id;
3mod manager;
4mod process;
5mod processor;
6mod signal;
7mod switch;
8#[allow(clippy::module_inception)]
9mod task;
10
11use self::id::TaskUserRes;
12use crate::fs::{OpenFlags, open_file};
13use crate::sbi::shutdown;
14use alloc::{sync::Arc, vec::Vec};
15use lazy_static::*;
16use manager::fetch_task;
17use process::ProcessControlBlock;
18use switch::__switch;
19
20pub use context::TaskContext;
21pub use id::{IDLE_PID, KernelStack, PidHandle, kstack_alloc, pid_alloc};
22pub use manager::{add_task, pid2process, remove_from_pid2process, wakeup_task};
23pub use processor::{
24 current_kstack_top, current_process, current_task, current_trap_cx, current_trap_cx_user_va,
25 current_user_token, run_tasks, schedule, take_current_task,
26};
27pub use signal::SignalFlags;
28pub use task::{TaskControlBlock, TaskStatus};
29
30pub fn suspend_current_and_run_next() {
31 let task = take_current_task().unwrap();
33
34 let mut task_inner = task.inner_exclusive_access();
36 let task_cx_ptr = &mut task_inner.task_cx as *mut TaskContext;
37 task_inner.task_status = TaskStatus::Ready;
39 drop(task_inner);
40 add_task(task);
44 schedule(task_cx_ptr);
46}
47
48pub fn block_current_task() -> *mut TaskContext {
50 let task = take_current_task().unwrap();
51 let mut task_inner = task.inner_exclusive_access();
52 task_inner.task_status = TaskStatus::Blocked;
53 &mut task_inner.task_cx as *mut TaskContext
54}
55
56pub fn block_current_and_run_next() {
57 let task_cx_ptr = block_current_task();
58 schedule(task_cx_ptr);
59}
60
61pub fn exit_current_and_run_next(exit_code: i32) {
63 let task = take_current_task().unwrap();
64 let mut task_inner = task.inner_exclusive_access();
65 let process = task.process.upgrade().unwrap();
66 let tid = task_inner.res.as_ref().unwrap().tid;
67 task_inner.exit_code = Some(exit_code);
69 task_inner.res = None;
70 drop(task_inner);
73 drop(task);
74 if tid == 0 {
77 let pid = process.getpid();
78 if pid == IDLE_PID {
79 println!(
80 "[kernel] Idle process exit with exit_code {} ...",
81 exit_code
82 );
83 if exit_code != 0 {
84 shutdown(true);
86 } else {
87 shutdown(false);
89 }
90 }
91 remove_from_pid2process(pid);
92 let mut process_inner = process.inner_exclusive_access();
93 process_inner.is_zombie = true;
95 process_inner.exit_code = exit_code;
97
98 {
99 let mut initproc_inner = INITPROC.inner_exclusive_access();
101 for child in process_inner.children.iter() {
102 child.inner_exclusive_access().parent = Some(Arc::downgrade(&INITPROC));
103 initproc_inner.children.push(child.clone());
104 }
105 }
106
107 let mut recycle_res = Vec::<TaskUserRes>::new();
111 for task in process_inner.tasks.iter().filter(|t| t.is_some()) {
112 let task = task.as_ref().unwrap();
113 let mut task_inner = task.inner_exclusive_access();
114 if let Some(res) = task_inner.res.take() {
115 recycle_res.push(res);
116 }
117 }
118 drop(process_inner);
122 recycle_res.clear();
123
124 let mut process_inner = process.inner_exclusive_access();
125 process_inner.children.clear();
126 process_inner.memory_set.recycle_data_pages();
128 process_inner.fd_table.clear();
130 while process_inner.tasks.len() > 1 {
135 process_inner.tasks.pop();
136 }
137 }
138 drop(process);
139 let mut _unused = TaskContext::zero_init();
141 schedule(&mut _unused as *mut _);
142}
143
144lazy_static! {
145 pub static ref INITPROC: Arc<ProcessControlBlock> = {
146 let inode = open_file("initproc", OpenFlags::RDONLY).unwrap();
147 let v = inode.read_all();
148 ProcessControlBlock::new(v.as_slice())
149 };
150}
151
152pub fn add_initproc() {
153 let _initproc = INITPROC.clone();
154}
155
156pub fn check_signals_of_current() -> Option<(i32, &'static str)> {
157 let process = current_process();
158 let process_inner = process.inner_exclusive_access();
159 process_inner.signals.check_error()
160}
161
162pub fn current_add_signal(signal: SignalFlags) {
163 let process = current_process();
164 let mut process_inner = process.inner_exclusive_access();
165 process_inner.signals |= signal;
166}