Code-base clean-up and refactoring (#47)
[lunaix-os.git] / lunaix-os / kernel / process / signal.c
index eef5c7ba4f72b3a57d08d5059f1067fa01622872..0389a4a1ba0938c47f345bc0375ebec62185e517 100644 (file)
@@ -6,10 +6,12 @@
 #include <lunaix/syscall.h>
 #include <lunaix/syslog.h>
 #include <lunaix/mm/valloc.h>
+#include <lunaix/switch.h>
+#include <lunaix/kpreempt.h>
 
 #include <klibc/string.h>
 
-#include <sys/mm/mempart.h>
+#include <asm/mempart.h>
 
 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;