1use core::{
4 ffi::{c_int, c_uint, c_ulong},
5 sync::atomic::Ordering,
6};
7
8use alloc::{sync::Arc, vec::Vec};
9
10use crate::{
11 arch::{timer::clock_freq, trap::restore},
12 ipc::{create_siginfo_for_signal, do_sigpending},
13 kernel::{
14 SharedTask, TASK_MANAGER, TIMER_QUEUE, TaskManagerTrait, current_task,
15 sleep_task_with_guard_and_block, yield_task,
16 },
17 sync::SpinLock,
18 uapi::{
19 errno::{EAGAIN, EINTR, EINVAL, ENOMEM, ENOSYS, ESRCH},
20 signal::{
21 MINSIGSTKSZ, NSIG, SIG_BLOCK, SIG_SETMASK, SIG_UNBLOCK, SIGSET_SIZE, SS_AUTODISARM,
22 SS_DISABLE, SS_ONSTACK, SaFlags, SigInfoT, SignalAction, SignalFlags, UContextT,
23 },
24 time::TimeSpec,
25 types::{SigSetT, StackT},
26 },
27 util::user_buffer::{read_from_user, write_to_user},
28};
29
30pub fn rt_sigprocmask(
39 how: c_int,
40 set: *const SigSetT,
41 oset: *mut SigSetT,
42 sigsetsize: c_uint,
43) -> c_int {
44 if sigsetsize as usize != SIGSET_SIZE {
45 return -EINVAL;
46 }
47 let task = crate::kernel::current_task();
48 let mut t = task.lock();
49
50 if !oset.is_null() {
51 let old_set = t.blocked.bits() as c_ulong;
52 unsafe {
53 write_to_user(oset, old_set);
54 }
55 }
56
57 if !set.is_null() {
58 let new_set = unsafe { read_from_user(set) };
59 let new_flags = if let Some(flag) = SignalFlags::from_bits(new_set as usize) {
60 flag
61 } else {
62 return -EINVAL;
63 };
64
65 match how {
66 SIG_BLOCK => {
67 t.blocked |= new_flags;
68 }
69 SIG_UNBLOCK => {
70 t.blocked &= !new_flags;
71 }
72 SIG_SETMASK => {
73 t.blocked = new_flags;
74 }
75 _ => {
76 return -EINVAL;
77 }
78 }
79 }
80
81 0
82}
83
84pub fn rt_sigpending(uset: *mut SigSetT, sigsetsize: c_uint) -> c_int {
88 if sigsetsize as usize != SIGSET_SIZE {
89 return -EINVAL;
90 }
91 let pending = do_sigpending();
92 unsafe {
93 write_to_user(uset, pending.bits() as SigSetT);
94 }
95 0
96}
97
98pub fn rt_sigaction(signum: c_int, act: *const SignalAction, oldact: *mut SignalAction) -> c_int {
107 if signum <= 0 || signum as usize > NSIG {
108 return -EINVAL;
109 }
110
111 let task = crate::kernel::current_task();
112 let t = task.lock();
113
114 if !oldact.is_null() {
115 let current_action = t.signal_handlers.lock().actions[signum as usize].clone();
116 unsafe {
117 write_to_user(oldact, current_action);
118 }
119 }
120
121 if !act.is_null() {
122 let new_action = unsafe { read_from_user(act) };
123 let flag = if let Some(flag) = SaFlags::from_bits(new_action.sa_flags as u32) {
124 flag
125 } else {
126 return -EINVAL;
127 };
128 if !flag.is_known() {
129 return -EINVAL;
130 }
131 if !flag.is_supported() {
132 return -ENOSYS;
133 }
134 t.signal_handlers
135 .lock()
136 .set_action(signum as usize, new_action);
137 }
138
139 0
140}
141
142pub fn rt_sigtimedwait(
152 set: *const SigSetT,
153 info: *mut SigInfoT,
154 timeout: *const TimeSpec,
155 sigsetsize: c_uint,
156) -> c_int {
157 if sigsetsize as usize != SIGSET_SIZE {
158 return -EINVAL;
159 }
160
161 let wait_set_bits = unsafe { read_from_user(set) };
162 let wait_set = if let Some(flags) = SignalFlags::from_bits(wait_set_bits as usize) {
163 flags
164 } else {
165 return -EINVAL;
166 };
167
168 let timeout_opt = if !timeout.is_null() {
169 let ts = unsafe { read_from_user(timeout) };
170 Some(ts)
171 } else {
172 None
173 };
174
175 match wait_for_signal(current_task(), wait_set, timeout_opt) {
176 Ok((sig_num, sig_info)) => {
177 if !info.is_null() {
178 unsafe {
179 write_to_user(info, sig_info);
180 }
181 }
182 sig_num as c_int
183 }
184 Err(err_code) => err_code,
185 }
186}
187
188pub fn rt_sigsuspend(unewset: *const SigSetT, sigsetsize: c_uint) -> c_int {
200 if sigsetsize as usize != SIGSET_SIZE {
201 return -EINVAL;
202 }
203 let new_set_bits = unsafe { read_from_user(unewset) };
204 let new_set = if let Some(flags) = SignalFlags::from_bits(new_set_bits as usize) {
205 flags
206 } else {
207 return -EINVAL;
208 };
209 let task = current_task();
210 let old_set;
211 {
212 let mut t = task.lock();
213 old_set = t.blocked;
214 t.blocked = new_set;
215 sleep_task_with_guard_and_block(&mut t, task.clone(), true);
216 }
217 yield_task();
218 {
219 let mut t = task.lock();
220 t.blocked = old_set;
221 }
222 -EINTR
223}
224
225pub fn rt_sigreturn() -> ! {
230 let tfp = current_task().lock().trap_frame_ptr.load(Ordering::SeqCst);
231 let tf = unsafe { &mut *tfp };
232 let ucontext_addr = tf.get_sp();
233 let ucontext: UContextT = unsafe { read_from_user(ucontext_addr as *const UContextT) };
234 tf.restore_from_mcontext(&ucontext.uc_mcontext);
235 unsafe { restore(tf) }
236 unreachable!("rt_sigreturn should not return");
237}
238
239pub fn signal_stack(uss: *const StackT, uoss: *mut StackT) -> c_int {
247 let task = current_task();
248 let mut t = task.lock();
249
250 if !uoss.is_null() {
251 let old_ss = t.signal_stack.lock().clone();
252 unsafe {
253 write_to_user(uoss, old_ss);
254 }
255 }
256
257 if !uss.is_null() {
258 let new_ss = unsafe { read_from_user(uss) };
259 if new_ss.ss_size < MINSIGSTKSZ as u64 {
260 return -ENOMEM;
261 }
262 if new_ss.ss_flags as usize & SS_AUTODISARM & SS_DISABLE & SS_ONSTACK != 0 {
263 return -EINVAL;
264 }
265 t.signal_stack = Arc::new(SpinLock::new(new_ss));
266 }
267 0
268}
269
270pub fn kill(pid: c_int, sig: c_int) -> c_int {
283 if sig < 0 || sig as usize >= NSIG {
284 return -EINVAL;
285 }
286 let task_manager = TASK_MANAGER.lock();
287 let target_tasks: Vec<SharedTask> = match pid {
288 0 => {
289 let current_task = current_task();
290 let pgid = current_task.lock().pgid;
291 task_manager.get_task_cond(|t| {
292 t.lock().pgid == pgid && t.lock().pid != 1 && t.lock().is_process()
293 })
294 }
295 pid if pid > 0 => {
296 if let Some(task) = task_manager.get_task(pid as u32) {
297 if !task.lock().is_process() {
298 return -EINVAL;
299 }
300 alloc::vec![task]
301 } else {
302 return -ESRCH;
303 }
304 }
305 -1 => task_manager.get_task_cond(|t| t.lock().pid != 1 && t.lock().is_process()),
306 pid if pid < -1 => {
307 let pgid = (-pid) as u32;
308 task_manager.get_task_cond(|t| {
309 t.lock().pgid == pgid && t.lock().pid != 1 && t.lock().is_process()
310 })
311 }
312 _ => alloc::vec![],
313 };
314
315 if target_tasks.is_empty() {
316 return -ESRCH;
317 }
318
319 for task in target_tasks {
320 task_manager.send_signal(task, sig as usize);
321 }
322 0
323}
324
325pub fn tkill(tid: c_int, sig: c_int) -> c_int {
334 if sig < 0 || sig as usize >= NSIG {
335 return -EINVAL;
336 }
337 let task_manager = TASK_MANAGER.lock();
338 let task = if let Some(task) = task_manager.get_task(tid as u32) {
339 task
340 } else {
341 return -ESRCH;
342 };
343 if task.lock().pid != current_task().lock().pid {
344 return -EINVAL;
345 }
346 task_manager.send_signal(task, sig as usize);
347 0
348}
349
350pub fn tgkill(tgid: c_int, tid: c_int, sig: c_int) -> c_int {
359 if sig < 0 || sig as usize >= NSIG {
360 return -EINVAL;
361 }
362 let task_manager = TASK_MANAGER.lock();
363 let task = if let Some(task) = task_manager.get_task(tid as u32) {
364 task
365 } else {
366 return -ESRCH;
367 };
368 if task.lock().pid != tgid as u32 {
369 return -EINVAL;
370 }
371 task_manager.send_signal(task, sig as usize);
372 0
373}
374
375fn wait_for_signal(
384 task: SharedTask,
385 signal: SignalFlags,
386 timeout: Option<TimeSpec>,
387) -> Result<(usize, SigInfoT), i32> {
388 let mut t = task.lock();
389 if let Some(timeout) = timeout {
390 if timeout.tv_sec < 0 || timeout.tv_nsec < 0 || timeout.tv_nsec >= 1_000_000_000 {
391 return Err(-EINVAL);
392 }
393 if timeout.tv_sec == 0 && timeout.tv_nsec == 0 {
394 if t.pending.has_deliverable_signal(signal)
396 || t.shared_pending.lock().has_deliverable_signal(signal)
397 {
398 let flag = t
399 .pending
400 .first_deliverable_signal(signal)
401 .or_else(|| t.shared_pending.lock().first_deliverable_signal(signal))
402 .unwrap();
403 let sig_num = flag.to_signal_number();
404 t.pending.signals.remove(flag);
405 return Ok((sig_num, create_siginfo_for_signal(flag)));
406 } else {
407 Err(-EAGAIN)
408 }
409 } else {
410 let start = TimeSpec::now();
412 while !t.pending.has_deliverable_signal(signal)
413 && !t.shared_pending.lock().has_deliverable_signal(signal)
414 {
415 let now = TimeSpec::now();
416 if now - start > timeout {
417 return Err(-EAGAIN); }
419 TIMER_QUEUE
420 .lock()
421 .push(timeout.into_freq(clock_freq()), task.clone());
422 sleep_task_with_guard_and_block(&mut t, task.clone(), true);
423 drop(t);
424 yield_task();
425 t = task.lock();
426 }
427 TIMER_QUEUE.lock().remove_task(&task);
428 let flag = t
429 .pending
430 .first_deliverable_signal(signal)
431 .or_else(|| t.shared_pending.lock().first_deliverable_signal(signal))
432 .unwrap();
433 let sig_num = flag.to_signal_number();
434 t.pending.signals.remove(flag);
435 return Ok((sig_num, create_siginfo_for_signal(flag)));
436 }
437 } else {
438 while t
440 .pending
441 .first_target_signal(signal)
442 .or_else(|| t.shared_pending.lock().first_target_signal(signal))
443 .is_none()
444 {
445 sleep_task_with_guard_and_block(&mut t, task.clone(), true);
446 drop(t);
447 yield_task();
448 t = task.lock();
449 }
450 let flag = t
451 .pending
452 .first_target_signal(signal)
453 .or_else(|| t.shared_pending.lock().first_target_signal(signal))
454 .unwrap();
455 let sig_num = flag.to_signal_number();
456 t.pending.signals.remove(flag);
457 return Ok((sig_num, create_siginfo_for_signal(flag)));
458 }
459}