1mod action;
2mod context;
3mod manager;
4mod pid;
5mod processor;
6mod signal;
7mod switch;
8#[allow(clippy::module_inception)]
9mod task;
10
11use crate::fs::{OpenFlags, open_file};
12use crate::sbi::shutdown;
13use alloc::sync::Arc;
14pub use context::TaskContext;
15use lazy_static::*;
16use manager::fetch_task;
17use manager::remove_from_pid2task;
18use switch::__switch;
19use task::{TaskControlBlock, TaskStatus};
20
21pub use action::{SignalAction, SignalActions};
22pub use manager::{add_task, pid2task};
23pub use pid::{KernelStack, PidHandle, pid_alloc};
24pub use processor::{
25 current_task, current_trap_cx, current_user_token, run_tasks, schedule, take_current_task,
26};
27pub use signal::{MAX_SIG, SignalFlags};
28
29pub fn suspend_current_and_run_next() {
30 let task = take_current_task().unwrap();
32
33 let mut task_inner = task.inner_exclusive_access();
35 let task_cx_ptr = &mut task_inner.task_cx as *mut TaskContext;
36 task_inner.task_status = TaskStatus::Ready;
38 drop(task_inner);
39 add_task(task);
43 schedule(task_cx_ptr);
45}
46
47pub const IDLE_PID: usize = 1;
49
50pub fn exit_current_and_run_next(exit_code: i32) {
52 let task = take_current_task().unwrap();
54
55 let pid = task.getpid();
56 if pid == IDLE_PID {
57 println!(
58 "[kernel] Idle process exit with exit_code {} ...",
59 exit_code
60 );
61 if exit_code != 0 {
62 shutdown(true)
64 } else {
65 shutdown(false)
67 }
68 }
69
70 remove_from_pid2task(task.getpid());
72 let mut inner = task.inner_exclusive_access();
74 inner.task_status = TaskStatus::Zombie;
76 inner.exit_code = exit_code;
78 {
82 let mut initproc_inner = INITPROC.inner_exclusive_access();
83 for child in inner.children.iter() {
84 child.inner_exclusive_access().parent = Some(Arc::downgrade(&INITPROC));
85 initproc_inner.children.push(child.clone());
86 }
87 }
88 inner.children.clear();
91 inner.memory_set.recycle_data_pages();
93 inner.fd_table.clear();
95 drop(inner);
96 drop(task);
99 let mut _unused = TaskContext::zero_init();
101 schedule(&mut _unused as *mut _);
102}
103
104lazy_static! {
105 pub static ref INITPROC: Arc<TaskControlBlock> = Arc::new({
106 let inode = open_file("initproc", OpenFlags::RDONLY).unwrap();
107 let v = inode.read_all();
108 TaskControlBlock::new(v.as_slice())
109 });
110}
111
112pub fn add_initproc() {
113 add_task(INITPROC.clone());
114}
115
116pub fn check_signals_error_of_current() -> Option<(i32, &'static str)> {
117 let task = current_task().unwrap();
118 let task_inner = task.inner_exclusive_access();
119 task_inner.signals.check_error()
124}
125
126pub fn current_add_signal(signal: SignalFlags) {
127 let task = current_task().unwrap();
128 let mut task_inner = task.inner_exclusive_access();
129 task_inner.signals |= signal;
130 }
135
136fn call_kernel_signal_handler(signal: SignalFlags) {
137 let task = current_task().unwrap();
138 let mut task_inner = task.inner_exclusive_access();
139 match signal {
140 SignalFlags::SIGSTOP => {
141 task_inner.frozen = true;
142 task_inner.signals ^= SignalFlags::SIGSTOP;
143 }
144 SignalFlags::SIGCONT => {
145 if task_inner.signals.contains(SignalFlags::SIGCONT) {
146 task_inner.signals ^= SignalFlags::SIGCONT;
147 task_inner.frozen = false;
148 }
149 }
150 _ => {
151 task_inner.killed = true;
156 }
157 }
158}
159
160fn call_user_signal_handler(sig: usize, signal: SignalFlags) {
161 let task = current_task().unwrap();
162 let mut task_inner = task.inner_exclusive_access();
163
164 let handler = task_inner.signal_actions.table[sig].handler;
165 if handler != 0 {
166 task_inner.handling_sig = sig as isize;
170 task_inner.signals ^= signal;
171
172 let trap_ctx = task_inner.get_trap_cx();
174 task_inner.trap_ctx_backup = Some(*trap_ctx);
175
176 trap_ctx.sepc = handler;
178
179 trap_ctx.x[10] = sig;
181 } else {
182 println!("[K] task/call_user_signal_handler: default action: ignore it or kill process");
184 }
185}
186
187fn check_pending_signals() {
188 for sig in 0..(MAX_SIG + 1) {
189 let task = current_task().unwrap();
190 let task_inner = task.inner_exclusive_access();
191 let signal = SignalFlags::from_bits(1 << sig).unwrap();
192 if task_inner.signals.contains(signal) && (!task_inner.signal_mask.contains(signal)) {
193 let mut masked = true;
194 let handling_sig = task_inner.handling_sig;
195 if handling_sig == -1 {
196 masked = false;
197 } else {
198 let handling_sig = handling_sig as usize;
199 if !task_inner.signal_actions.table[handling_sig]
200 .mask
201 .contains(signal)
202 {
203 masked = false;
204 }
205 }
206 if !masked {
207 drop(task_inner);
208 drop(task);
209 if signal == SignalFlags::SIGKILL
210 || signal == SignalFlags::SIGSTOP
211 || signal == SignalFlags::SIGCONT
212 || signal == SignalFlags::SIGDEF
213 {
214 call_kernel_signal_handler(signal);
216 } else {
217 call_user_signal_handler(sig, signal);
219 return;
220 }
221 }
222 }
223 }
224}
225
226pub fn handle_signals() {
227 loop {
228 check_pending_signals();
229 let (frozen, killed) = {
230 let task = current_task().unwrap();
231 let task_inner = task.inner_exclusive_access();
232 (task_inner.frozen, task_inner.killed)
233 };
234 if !frozen || killed {
235 break;
236 }
237 suspend_current_and_run_next();
238 }
239}