X-Git-Url: https://scm.lunaixsky.com/lunaix-os.git/blobdiff_plain/bdc143a7aa3f51a46eceec62b0b364599533fa21..34f6af4f61e0eec9c96113e07f140b609b4113c8:/lunaix-os/kernel/process/signal.c diff --git a/lunaix-os/kernel/process/signal.c b/lunaix-os/kernel/process/signal.c index eef5c7b..0389a4a 100644 --- a/lunaix-os/kernel/process/signal.c +++ b/lunaix-os/kernel/process/signal.c @@ -6,10 +6,12 @@ #include #include #include +#include +#include #include -#include +#include LOG_MODULE("SIG") @@ -27,18 +29,26 @@ signal_terminate(int caused_by) terminate_current(caused_by | PEXITSIG); } +static inline void +signal_terminate_proc(struct proc_info* pcb, int caused_by) +{ + terminate_proccess(pcb, caused_by | PEXITSIG); +} + // Referenced in kernel/asm/x86/interrupt.S -void* -signal_dispatch() +void +signal_dispatch(struct signpost_result* result) { + continue_switch(result); + if (kernel_process(__current)) { // signal is undefined under 'kernel process' - return 0; + return; } if (!pending_sigs(current_thread)) { // 没有待处理信号 - return 0; + return; } struct sigregistry* sigreg = __current->sigreg; @@ -46,29 +56,28 @@ signal_dispatch() struct sigact* prev_working = active_signal(current_thread); sigset_t mask = psig->sig_mask | (prev_working ? prev_working->sa_mask : 0); - int sig_selected = 31 - clz(psig->sig_pending & ~mask); + int sig_selected = msbiti - clz(psig->sig_pending & ~mask); sigset_clear(psig->sig_pending, sig_selected); if (!sig_selected) { // SIG0 is reserved - return 0; + return; } struct sigact* action = sigreg->signals[sig_selected]; if (!action || !action->sa_actor) { if (sigset_test(TERMSIG, sig_selected)) { signal_terminate(sig_selected); - schedule(); - // never return + giveup_switch(result); } - return 0; + return; } ptr_t ustack = current_thread->ustack_top; ptr_t ustack_start = current_thread->ustack->start; if ((int)(ustack - ustack_start) < (int)sizeof(struct proc_sig)) { // 用户栈没有空间存放信号上下文 - return 0; + return; } struct proc_sig* sigframe = @@ -82,7 +91,7 @@ signal_dispatch() sigactive_push(current_thread, sig_selected); - return sigframe; + redirect_switch(result, __ptr(sigframe)); } static inline void must_inline @@ -131,7 +140,7 @@ proc_setsignal(struct proc_info* proc, signum_t signum) switch (signum) { case SIGKILL: - signal_terminate(signum); + signal_terminate_proc(proc, signum); break; case SIGCONT: case SIGSTOP: @@ -143,6 +152,20 @@ proc_setsignal(struct proc_info* proc, signum_t signum) __set_signal(proc->th_active, signum); } +static inline void +__broadcast_group(struct proc_info* proc, signum_t signum) +{ + if (proc_terminated(proc)) { + return; + } + + struct proc_info *pos, *n; + llist_for_each(pos, n, &proc->grp_member, grp_member) + { + proc_setsignal(pos, signum); + } +} + int signal_send(pid_t pid, signum_t signum) { @@ -155,27 +178,17 @@ signal_send(pid_t pid, signum_t signum) if (pid > 0) { proc = get_process(pid); - goto send_single; } else if (!pid) { proc = __current; - goto send_grp; } else if (pid < 0) { proc = get_process(-pid); - goto send_grp; + __broadcast_group(proc, signum); } else { // TODO: send to all process. // But I don't want to support it yet. return EINVAL; } -send_grp: ; - struct proc_info *pos, *n; - llist_for_each(pos, n, &proc->grp_member, grp_member) - { - proc_setsignal(pos, signum); - } - -send_single: if (proc_terminated(proc)) { return EINVAL; } @@ -347,7 +360,7 @@ __DEFINE_LXSYSCALL2(int, sys_sigaction, int, signum, struct sigaction*, action) __DEFINE_LXSYSCALL(int, pause) { pause_current_thread(); - sched_pass(); + yield_current(); syscall_result(EINTR); return -1; @@ -371,7 +384,7 @@ __DEFINE_LXSYSCALL1(int, sigsuspend, sigset_t, *mask) sigctx->sig_mask = (*mask) & ~UNMASKABLE; pause_current_thread(); - sched_pass(); + yield_current(); sigctx->sig_mask = tmp; return -1;