Code-base clean-up and refactoring (#47)
[lunaix-os.git] / lunaix-os / kernel / process / signal.c
index a132de8b1e4f76b5acd1daad7a945b558454779f..0389a4a1ba0938c47f345bc0375ebec62185e517 100644 (file)
@@ -6,12 +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>
-
-// FIXME issues with signal
+#include <asm/mempart.h>
 
 LOG_MODULE("SIG")
 
@@ -29,48 +29,55 @@ 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 sigregister* sigreg = __current->sigreg;
+    struct sigregistry* sigreg = __current->sigreg;
     struct sigctx* psig = &current_thread->sigctx;
     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 =
@@ -80,11 +87,11 @@ signal_dispatch()
     sigframe->sigact = action->sa_actor;
     sigframe->sighand = action->sa_handler;
 
-    sigframe->saved_ictx = current_thread->intr_ctx;
+    sigframe->saved_hstate = current_thread->hstate;
 
     sigactive_push(current_thread, sig_selected);
 
-    return sigframe;
+    redirect_switch(result, __ptr(sigframe));
 }
 
 static inline void must_inline
@@ -133,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:
@@ -145,12 +152,25 @@ 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)
 {
     if (signum >= _SIG_NUM) {
-        syscall_result(EINVAL);
-        return -1;
+        return EINVAL;
     }
 
     pid_t sender_pid = __current->pid;
@@ -158,31 +178,19 @@ 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.
-        syscall_result(EINVAL);
-        return -1;
+        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)) {
-        syscall_result(EINVAL);
-        return -1;
+        return EINVAL;
     }
 
     proc_setsignal(proc, signum);
@@ -198,9 +206,9 @@ signal_dup_context(struct sigctx* dest_ctx)
 }
 
 void
-signal_dup_registers(struct sigregister* dest_reg)
+signal_dup_registry(struct sigregistry* dest_reg)
 {
-    struct sigregister* oldreg = __current->sigreg;
+    struct sigregistry* oldreg = __current->sigreg;
     for (int i = 0; i < _SIG_NUM; i++) {
         struct sigact* oldact = oldreg->signals[i];
         if (!oldact) {
@@ -220,7 +228,7 @@ signal_reset_context(struct sigctx* sigctx) {
 }
 
 void
-signal_reset_register(struct sigregister* sigreg) {
+signal_reset_registry(struct sigregistry* sigreg) {
     for (int i = 0; i < _SIG_NUM; i++) {
         struct sigact* act = sigreg->signals[i];
         if (act) {
@@ -231,8 +239,8 @@ signal_reset_register(struct sigregister* sigreg) {
 }
 
 void
-signal_free_registers(struct sigregister* sigreg) {
-    signal_reset_register(sigreg);
+signal_free_registry(struct sigregistry* sigreg) {
+    signal_reset_registry(sigreg);
     vfree(sigreg);
 }
 
@@ -269,14 +277,14 @@ __DEFINE_LXSYSCALL1(int, sigreturn, struct proc_sig, *sig_ctx)
         schedule();
     }
 
-    current_thread->intr_ctx = sig_ctx->saved_ictx;
+    current_thread->hstate = sig_ctx->saved_hstate;
     if (proc_terminated(__current)) {
         __current->exit_code |= PEXITSIG;
     } else if (sigset_test(CORE, sig_ctx->sig_num)) {
         signal_terminate(sig_ctx->sig_num);
     }
 
-    ptr_t ictx = (ptr_t)current_thread->intr_ctx;
+    ptr_t ictx = (ptr_t)current_thread->hstate;
 
     /*
         Ensure our restored context is within kernel stack
@@ -352,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;
@@ -360,7 +368,7 @@ __DEFINE_LXSYSCALL(int, pause)
 
 __DEFINE_LXSYSCALL2(int, kill, pid_t, pid, int, signum)
 {
-    return signal_send(pid, signum);
+    return syscall_result(signal_send(pid, signum));
 }
 
 __DEFINE_LXSYSCALL1(int, sigpending, sigset_t, *sigset)
@@ -376,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;