|
|
|
@ -4,11 +4,13 @@ mod pid;
|
|
|
|
|
mod processor;
|
|
|
|
|
mod signal;
|
|
|
|
|
mod switch;
|
|
|
|
|
mod sigret;
|
|
|
|
|
mod action;
|
|
|
|
|
#[allow(clippy::module_inception)]
|
|
|
|
|
mod task;
|
|
|
|
|
|
|
|
|
|
use crate::fs::{open_file, OpenFlags};
|
|
|
|
|
use crate::mm::translated_refmut;
|
|
|
|
|
use alloc::sync::Arc;
|
|
|
|
|
pub use context::TaskContext;
|
|
|
|
|
use lazy_static::*;
|
|
|
|
@ -25,6 +27,9 @@ pub use processor::{
|
|
|
|
|
pub use signal::{SignalFlags, MAX_SIG};
|
|
|
|
|
pub use action::{SignalAction, SignalActions};
|
|
|
|
|
|
|
|
|
|
use self::sigret::end_sigret;
|
|
|
|
|
use self::sigret::start_sigret;
|
|
|
|
|
|
|
|
|
|
pub fn suspend_current_and_run_next() {
|
|
|
|
|
// There must be an application running.
|
|
|
|
|
let task = take_current_task().unwrap();
|
|
|
|
@ -92,7 +97,7 @@ pub fn add_initproc() {
|
|
|
|
|
add_task(INITPROC.clone());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn check_signals_of_current() -> Option<(i32, &'static str)> {
|
|
|
|
|
pub fn check_signals_error_of_current() -> Option<(i32, &'static str)> {
|
|
|
|
|
let task = current_task().unwrap();
|
|
|
|
|
let task_inner = task.inner_exclusive_access();
|
|
|
|
|
task_inner.signals.check_error()
|
|
|
|
@ -103,3 +108,110 @@ pub fn current_add_signal(signal: SignalFlags) {
|
|
|
|
|
let mut task_inner = task.inner_exclusive_access();
|
|
|
|
|
task_inner.signals |= signal;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn call_kernel_signal_handler(signal: SignalFlags) {
|
|
|
|
|
let task = current_task().unwrap();
|
|
|
|
|
let mut task_inner = task.inner_exclusive_access();
|
|
|
|
|
match signal {
|
|
|
|
|
SignalFlags::SIGSTOP => {
|
|
|
|
|
task_inner.frozen = true;
|
|
|
|
|
task_inner.signals ^= SignalFlags::SIGSTOP;
|
|
|
|
|
}
|
|
|
|
|
SignalFlags::SIGCONT => {
|
|
|
|
|
if task_inner.signals.contains(SignalFlags::SIGCONT) {
|
|
|
|
|
task_inner.signals ^= SignalFlags::SIGCONT;
|
|
|
|
|
task_inner.frozen = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
_ => {
|
|
|
|
|
task_inner.killed = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn call_user_signal_handler(sig: usize, signal: SignalFlags) {
|
|
|
|
|
let task = current_task().unwrap();
|
|
|
|
|
let mut task_inner = task.inner_exclusive_access();
|
|
|
|
|
let token = current_user_token();
|
|
|
|
|
|
|
|
|
|
let handler = task_inner.signal_actions.table[sig].handler;
|
|
|
|
|
// change current mask
|
|
|
|
|
task_inner.signal_mask = task_inner.signal_actions.table[sig].mask;
|
|
|
|
|
// handle flag
|
|
|
|
|
task_inner.handling_sig = sig as isize;
|
|
|
|
|
task_inner.signals ^= signal;
|
|
|
|
|
|
|
|
|
|
// backup trapframe
|
|
|
|
|
let mut trap_ctx = task_inner.get_trap_cx();
|
|
|
|
|
task_inner.trap_ctx_backup = Some(*trap_ctx);
|
|
|
|
|
|
|
|
|
|
// modify trapframe
|
|
|
|
|
trap_ctx.sepc = handler;
|
|
|
|
|
|
|
|
|
|
// inject sigret
|
|
|
|
|
let sigret_size = end_sigret as usize - start_sigret as usize;
|
|
|
|
|
trap_ctx.x[2] -= sigret_size;
|
|
|
|
|
let cur_sp = trap_ctx.x[2];
|
|
|
|
|
unsafe {
|
|
|
|
|
let target_sigret_ptr = translated_refmut(token, cur_sp as *mut u8);
|
|
|
|
|
let target_sigret_ptr = core::slice::from_raw_parts_mut(target_sigret_ptr as *mut u8, sigret_size);
|
|
|
|
|
let source_sigret_ptr = core::slice::from_raw_parts(start_sigret as usize as *mut u8, sigret_size);
|
|
|
|
|
target_sigret_ptr.copy_from_slice(source_sigret_ptr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// put args (a0)
|
|
|
|
|
trap_ctx.x[10] = sig;
|
|
|
|
|
// return addr
|
|
|
|
|
trap_ctx.x[1] = cur_sp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn check_pending_signals() {
|
|
|
|
|
for sig in 0..(MAX_SIG + 1) {
|
|
|
|
|
let task = current_task().unwrap();
|
|
|
|
|
let task_inner = task.inner_exclusive_access();
|
|
|
|
|
let signal = SignalFlags::from_bits(1 << sig).unwrap();
|
|
|
|
|
if task_inner.signals.contains(signal) && (!task_inner.signal_mask.contains(signal)) {
|
|
|
|
|
if task_inner.handling_sig == -1 {
|
|
|
|
|
drop(task_inner);
|
|
|
|
|
if signal == SignalFlags::SIGKILL || signal == SignalFlags::SIGSTOP ||
|
|
|
|
|
signal == SignalFlags::SIGCONT || signal == SignalFlags::SIGDEF {
|
|
|
|
|
// signal is a kernel signal
|
|
|
|
|
call_kernel_signal_handler(signal);
|
|
|
|
|
} else {
|
|
|
|
|
// signal is a user signal
|
|
|
|
|
call_user_signal_handler(sig, signal);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
if !task_inner.signal_actions.table[task_inner.handling_sig as usize].mask.contains(signal) {
|
|
|
|
|
drop(task_inner);
|
|
|
|
|
if signal == SignalFlags::SIGKILL || signal == SignalFlags::SIGSTOP ||
|
|
|
|
|
signal == SignalFlags::SIGCONT || signal == SignalFlags::SIGDEF {
|
|
|
|
|
// signal is a kernel signal
|
|
|
|
|
call_kernel_signal_handler(signal);
|
|
|
|
|
} else {
|
|
|
|
|
// signal is a user signal
|
|
|
|
|
call_user_signal_handler(sig, signal);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn handle_signals() {
|
|
|
|
|
check_pending_signals();
|
|
|
|
|
loop {
|
|
|
|
|
let task = current_task().unwrap();
|
|
|
|
|
let task_inner = task.inner_exclusive_access();
|
|
|
|
|
let frozen_flag = task_inner.frozen;
|
|
|
|
|
let killed_flag = task_inner.killed;
|
|
|
|
|
drop(task_inner);
|
|
|
|
|
if (!frozen_flag) || killed_flag {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
check_pending_signals();
|
|
|
|
|
suspend_current_and_run_next()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|