1use bitflags::bitflags;
13
14use crate::{
15 arch::{
16 kernel::cpu,
17 trap::{TrapFrame, sigreturn_trampoline_address},
18 },
19 kernel::{
20 SharedTask, TASK_MANAGER, TaskManagerTrait, TaskState, current_cpu, current_task,
21 exit_process, exit_task_with_block, sleep_task_with_block, wake_up_with_block, yield_task,
22 },
23 pr_err,
24 uapi::signal::*,
25 util::{address::align_down, user_buffer::write_to_user},
26};
27
28#[derive(Debug, Clone)]
36pub struct SignalHandlerTable {
37 pub actions: [SignalAction; NSIG + 1],
39}
40
41unsafe impl Send for SignalHandlerTable {}
42unsafe impl Sync for SignalHandlerTable {}
43
44impl SignalHandlerTable {
45 pub fn new() -> Self {
47 Self {
48 actions: core::array::from_fn(|_| SignalAction::default()),
49 }
50 }
51
52 pub fn set_action(&mut self, sig: usize, action: SignalAction) {
54 if sig == 0 || sig > NSIG {
55 return;
56 }
57 self.actions[sig] = action;
58 }
59}
60
61pub fn first_deliverable_signal(
63 pending_flags: SignalFlags,
64 blocked_mask: SignalFlags,
65) -> Option<SignalFlags> {
66 let deliverable_signals = pending_flags.difference(blocked_mask);
67
68 if deliverable_signals.is_empty() {
69 return None;
70 }
71
72 let signal_bit_index = deliverable_signals.bits().trailing_zeros();
73 if signal_bit_index < NSIG as u32 {
74 let first_sig = SignalFlags::from_bits(1 << signal_bit_index).unwrap();
75 return Some(first_sig);
76 }
77
78 None
79}
80
81#[inline]
82fn handle_one_signal(sig_flag: SignalFlags, action: SignalAction, task: &SharedTask) {
83 let sig_num = signal_from_flag(sig_flag).unwrap();
84
85 match unsafe { action.sa_handler() } as isize {
86 SIG_DFL => match sig_num {
87 NUM_SIGQUIT | NUM_SIGILL | NUM_SIGABRT | NUM_SIGBUS | NUM_SIGFPE | NUM_SIGSEGV
88 | NUM_SIGSYS | NUM_SIGXCPU | NUM_SIGXFSZ => sig_dump(sig_num), NUM_SIGHUP | NUM_SIGINT | NUM_SIGPIPE | NUM_SIGALRM | NUM_SIGTERM | NUM_SIGUSR1
91 | NUM_SIGUSR2 | NUM_SIGSTKFLT | NUM_SIGPROF | NUM_SIGPWR => sig_terminate(sig_num), NUM_SIGKILL => sig_terminate(sig_num), NUM_SIGSTOP | NUM_SIGTSTP | NUM_SIGTTIN | NUM_SIGTTOU => sig_stop(sig_num),
94 NUM_SIGCONT => sig_continue(sig_num),
95 NUM_SIGCHLD | NUM_SIGURG | NUM_SIGWINCH | NUM_SIGIO => sig_ignore(sig_num),
96 _ => panic!("Unhandled signal"),
97 },
98 SIG_IGN => sig_ignore(sig_num),
99 handler_addr => {
100 install_user_signal_trap_frame(
103 task,
104 sig_num,
105 handler_addr,
106 SignalFlags::from_sigset_t(action.sa_mask),
107 );
108 }
109 }
110}
111
112pub fn check_signal() {
118 let task = current_task();
119 let (sig_flag, action) = {
120 let mut t = task.lock();
121 let pending_copy = t.pending.clone();
122 let shared_pending_copy = t.shared_pending.lock().clone();
123 let blocked_copy = t.blocked.clone();
124 if let Some(flag) = first_deliverable_signal(pending_copy.signals, blocked_copy) {
125 let num = signal_from_flag(flag).unwrap();
126 let action = {
127 let handlers = t.signal_handlers.lock();
128 handlers.actions[num]
129 };
130 t.pending.signals.remove(flag);
131 (flag, action)
132 } else if let Some(flag) =
133 first_deliverable_signal(shared_pending_copy.signals, blocked_copy)
134 {
135 let num = signal_from_flag(flag).unwrap();
136 let action = {
137 let handlers = t.signal_handlers.lock();
138 handlers.actions[num]
139 };
140 t.shared_pending.lock().signals.remove(flag);
141 (flag, action)
142 } else {
143 return;
144 }
145 };
146
147 handle_one_signal(sig_flag, action, &task);
148}
149
150pub fn create_siginfo_for_signal(flag: SignalFlags) -> SigInfoT {
155 let sig_num = flag.to_signal_number();
156 let mut sig_info = SigInfoT::new();
157 sig_info.si_signo = sig_num as i32;
158 sig_info.si_code = 0;
159 sig_info.si_errno = 0;
160 sig_info
161}
162
163fn install_user_signal_trap_frame(
177 task: &SharedTask,
178 sig_num: usize,
179 entry: isize,
180 action_mask: SignalFlags,
181) {
182 let mut t = task.lock();
183 let tp = t.trap_frame_ptr.load(core::sync::atomic::Ordering::SeqCst);
184 unsafe {
185 let tf = &mut *tp;
186 let siginfo = create_siginfo_for_signal(SignalFlags::from_signal_num(sig_num).unwrap());
187 let uc = UContextT::new(
188 0, 0 as *mut _, t.signal_stack.lock().clone(),
191 t.blocked.to_sigset_t(),
192 MContextT::from_trap_frame(tf),
193 );
194 let mut current_sp = tf.get_sp();
201
202 current_sp = align_down(current_sp, align_of::<SigInfoT>());
203 let sig_info_addr = current_sp - size_of::<SigInfoT>();
204 current_sp = sig_info_addr;
205
206 current_sp = align_down(current_sp, align_of::<UContextT>());
207 let ucontext_addr = current_sp - size_of::<UContextT>();
208 current_sp = ucontext_addr;
209
210 current_sp = align_down(current_sp, align_of::<usize>()) - size_of::<usize>();
211 let return_addr_slot = current_sp;
212
213 let ucontext_addr = current_sp + size_of::<usize>();
216
217 let final_sp = current_sp;
218
219 write_to_user(sig_info_addr as *mut SigInfoT, siginfo);
220 write_to_user(ucontext_addr as *mut UContextT, uc);
221 write_to_user(
222 return_addr_slot as *mut usize,
223 sigreturn_trampoline_address(),
224 );
225
226 if sig_num != NUM_SIGKILL && sig_num != NUM_SIGSTOP {
228 let self_flag = SignalFlags::from_bits(1 << (sig_num - 1)).unwrap();
229 t.blocked |= action_mask | self_flag;
230 }
231
232 tf.set_sepc(entry as usize);
234 tf.set_a0(sig_num);
235 tf.set_sp(final_sp);
236 }
237}
238
239fn signal_from_flag(flag: SignalFlags) -> Option<usize> {
240 let bit_index = flag.bits().trailing_zeros() as usize;
241
242 if bit_index >= NSIG {
243 return None;
244 }
245
246 Some(bit_index + 1)
247}
248
249fn sig_terminate(sig_num: usize) {
252 let tasks = TASK_MANAGER.lock().get_process_threads(current_task());
253 for task in tasks {
254 exit_process(task, (128 + sig_num) as i32);
255 }
256}
257
258fn sig_dump(sig_num: usize) {
261 pr_err!("signal {}: generating core (stub)", sig_num);
262 sig_terminate(sig_num);
263}
264
265fn sig_stop(sig_num: usize) {
267 let pid = current_cpu()
268 .lock()
269 .current_task
270 .clone()
271 .unwrap()
272 .lock()
273 .pid;
274 let tasks = TASK_MANAGER.lock().get_process_threads(current_task());
275 for task in tasks {
276 {
277 let mut t = task.lock();
278 if t.state == TaskState::Zombie {
279 continue;
280 }
281 t.state = TaskState::Stopped;
282 }
283
284 sleep_task_with_block(task, false);
286 }
287 yield_task();
288}
289
290fn sig_continue(sig_num: usize) {
292 let pid = current_cpu()
293 .lock()
294 .current_task
295 .clone()
296 .unwrap()
297 .lock()
298 .pid;
299 let tasks = TASK_MANAGER.lock().get_process_threads(current_task());
300 for task in tasks {
301 let mut resume = false;
302 {
303 let mut t = task.lock();
304 if t.state == TaskState::Stopped {
305 t.state = TaskState::Running;
306 resume = true;
307 }
308 }
309 if resume {
310 wake_up_with_block(task);
311 }
312 }
313}
314
315fn sig_ignore(sig_num: usize) {}
317
318#[derive(Debug, Clone)]
320pub struct SignalPending {
321 pub signals: SignalFlags,
323 }
326
327impl SignalPending {
328 pub fn empty() -> Self {
330 Self {
331 signals: SignalFlags::empty(),
332 }
334 }
335
336 pub fn has_deliverable_signal(&self, blocked: SignalFlags) -> bool {
340 !first_deliverable_signal(self.signals, blocked).is_none()
341 }
342
343 pub fn first_deliverable_signal(&self, blocked: SignalFlags) -> Option<SignalFlags> {
347 first_deliverable_signal(self.signals, blocked)
348 }
349
350 pub fn first_target_signal(&self, target: SignalFlags) -> Option<SignalFlags> {
354 let intersect = self.signals & target;
355 if intersect.is_empty() {
356 return None;
357 }
358
359 let signal_bit_index = intersect.bits().trailing_zeros();
360 if signal_bit_index < NSIG as u32 {
361 let first_sig = SignalFlags::from_bits(1 << signal_bit_index).unwrap();
362 return Some(first_sig);
363 }
364
365 None
366 }
367}
368
369pub fn do_sigpending() -> SignalFlags {
371 let task = current_task();
372 let t = task.lock();
373 t.pending.signals | t.shared_pending.lock().signals
374}
375
376pub fn signal_pending(task: &SharedTask) -> bool {
380 let t = task.lock();
381 t.pending.has_deliverable_signal(t.blocked)
382 || t.shared_pending.lock().has_deliverable_signal(t.blocked)
383}