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 crate::timer::remove_timer;
15use alloc::{sync::Arc, vec::Vec};
16use lazy_static::*;
17use manager::fetch_task;
18use process::ProcessControlBlock;
19use switch::__switch;
20
21pub use context::TaskContext;
22pub use id::{IDLE_PID, KernelStack, PidHandle, kstack_alloc, pid_alloc};
23pub use manager::{add_task, pid2process, remove_from_pid2process, remove_task, wakeup_task};
24pub use processor::{
25 current_kstack_top, current_process, current_task, current_trap_cx, current_trap_cx_user_va,
26 current_user_token, run_tasks, schedule, take_current_task,
27};
28pub use signal::SignalFlags;
29pub use task::{TaskControlBlock, TaskStatus};
30
31pub fn suspend_current_and_run_next() {
32 let task = take_current_task().unwrap();
34
35 let mut task_inner = task.inner_exclusive_access();
37 let task_cx_ptr = &mut task_inner.task_cx as *mut TaskContext;
38 task_inner.task_status = TaskStatus::Ready;
40 drop(task_inner);
41 add_task(task);
45 schedule(task_cx_ptr);
47}
48
49pub fn block_current_and_run_next() {
50 let task = take_current_task().unwrap();
51 let mut task_inner = task.inner_exclusive_access();
52 let task_cx_ptr = &mut task_inner.task_cx as *mut TaskContext;
53 task_inner.task_status = TaskStatus::Blocked;
54 drop(task_inner);
55 schedule(task_cx_ptr);
56}
57
58pub fn exit_current_and_run_next(exit_code: i32) {
60 let task = take_current_task().unwrap();
61 let mut task_inner = task.inner_exclusive_access();
62 let process = task.process.upgrade().unwrap();
63 let tid = task_inner.res.as_ref().unwrap().tid;
64 task_inner.exit_code = Some(exit_code);
66 task_inner.res = None;
67 drop(task_inner);
70 drop(task);
71 if tid == 0 {
74 let pid = process.getpid();
75 if pid == IDLE_PID {
76 println!(
77 "[kernel] Idle process exit with exit_code {} ...",
78 exit_code
79 );
80 if exit_code != 0 {
81 shutdown(true);
83 } else {
84 shutdown(false);
86 }
87 }
88 remove_from_pid2process(pid);
89 let mut process_inner = process.inner_exclusive_access();
90 process_inner.is_zombie = true;
92 process_inner.exit_code = exit_code;
94
95 {
96 let mut initproc_inner = INITPROC.inner_exclusive_access();
98 for child in process_inner.children.iter() {
99 child.inner_exclusive_access().parent = Some(Arc::downgrade(&INITPROC));
100 initproc_inner.children.push(child.clone());
101 }
102 }
103
104 let mut recycle_res = Vec::<TaskUserRes>::new();
108 for task in process_inner.tasks.iter().filter(|t| t.is_some()) {
109 let task = task.as_ref().unwrap();
110 remove_inactive_task(Arc::clone(&task));
117 let mut task_inner = task.inner_exclusive_access();
118 if let Some(res) = task_inner.res.take() {
119 recycle_res.push(res);
120 }
121 }
122 drop(process_inner);
126 recycle_res.clear();
127
128 let mut process_inner = process.inner_exclusive_access();
129 process_inner.children.clear();
130 process_inner.memory_set.recycle_data_pages();
132 process_inner.fd_table.clear();
134 while process_inner.tasks.len() > 1 {
139 process_inner.tasks.pop();
140 }
141 }
142 drop(process);
143 let mut _unused = TaskContext::zero_init();
145 schedule(&mut _unused as *mut _);
146}
147
148lazy_static! {
149 pub static ref INITPROC: Arc<ProcessControlBlock> = {
150 let inode = open_file("initproc", OpenFlags::RDONLY).unwrap();
151 let v = inode.read_all();
152 ProcessControlBlock::new(v.as_slice())
153 };
154}
155
156pub fn add_initproc() {
157 let _initproc = INITPROC.clone();
158}
159
160pub fn check_signals_of_current() -> Option<(i32, &'static str)> {
161 let process = current_process();
162 let process_inner = process.inner_exclusive_access();
163 process_inner.signals.check_error()
164}
165
166pub fn current_add_signal(signal: SignalFlags) {
167 let process = current_process();
168 let mut process_inner = process.inner_exclusive_access();
169 process_inner.signals |= signal;
170}
171
172pub fn remove_inactive_task(task: Arc<TaskControlBlock>) {
173 remove_task(Arc::clone(&task));
174 remove_timer(Arc::clone(&task));
175}