feat: pause(2) support
[lunaix-os.git] / lunaix-os / kernel / signal.c
index 4c0bb56ad27b307c1e1b44641d47e28db1b88799..80a709831627f014aac41320b972e17b6b09b038 100644 (file)
@@ -1,6 +1,7 @@
 #include <lunaix/process.h>
 #include <lunaix/sched.h>
 #include <lunaix/signal.h>
+#include <lunaix/status.h>
 #include <lunaix/syscall.h>
 
 extern struct scheduler sched_ctx; /* kernel/sched.c */
@@ -26,7 +27,7 @@ signal_dispatch()
     int sig_selected =
       31 - __builtin_clz(__current->sig_pending & ~__current->sig_mask);
 
-    __current->sig_pending = __current->sig_pending & ~(1 << sig_selected);
+    __current->sig_pending = __current->sig_pending & ~__SIGNAL(sig_selected);
 
     if (!__current->sig_handler[sig_selected] &&
         !default_handlers[sig_selected]) {
@@ -34,7 +35,7 @@ signal_dispatch()
         return 0;
     }
 
-    uintptr_t ustack = __current->ustack_top;
+    uintptr_t ustack = __current->ustack_top & ~0xf;
 
     if ((int)(ustack - USTACK_END) < (int)sizeof(struct proc_sig)) {
         // 用户栈没有空间存放信号上下文
@@ -53,12 +54,16 @@ signal_dispatch()
         sig_ctx->signal_handler = default_handlers[sig_selected];
     }
 
+    __current->sig_mask |= __SIGNAL(sig_selected);
+
     return sig_ctx;
 }
 
 __DEFINE_LXSYSCALL1(int, sigreturn, struct proc_sig, *sig_ctx)
 {
     __current->intr_ctx = sig_ctx->prev_context;
+    __current->sig_mask &= ~__SIGNAL(sig_ctx->sig_num);
+    __current->flags &= ~PROC_FINPAUSE;
     schedule();
 }
 
@@ -98,4 +103,17 @@ __DEFINE_LXSYSCALL2(int, signal, int, signum, sighandler_t, handler)
     __current->sig_handler[signum] = (void*)handler;
 
     return 0;
+}
+
+__DEFINE_LXSYSCALL(int, pause)
+{
+    __current->flags |= PROC_FINPAUSE;
+
+    __SYSCALL_INTERRUPTIBLE({
+        while ((__current->flags & PROC_FINPAUSE)) {
+            sched_yield();
+        }
+    })
+    __current->k_status = EINTR;
+    return -1;
 }
\ No newline at end of file