1 #include <lunaix/process.h>
2 #include <lunaix/sched.h>
3 #include <lunaix/signal.h>
4 #include <lunaix/status.h>
5 #include <lunaix/syscall.h>
7 extern struct scheduler sched_ctx; /* kernel/sched.c */
9 void* default_handlers[_SIG_NUM] = {
13 // Referenced in kernel/asm/x86/interrupt.S
17 // if (!(SEL_RPL(__current->intr_ctx.cs))) {
22 if (!__current->sig_pending) {
28 31 - __builtin_clz(__current->sig_pending & ~__current->sig_mask);
30 __current->sig_pending = __current->sig_pending & ~__SIGNAL(sig_selected);
32 if (!__current->sig_handler[sig_selected] &&
33 !default_handlers[sig_selected]) {
38 uintptr_t ustack = __current->ustack_top & ~0xf;
40 if ((int)(ustack - USTACK_END) < (int)sizeof(struct proc_sig)) {
45 struct proc_sig* sig_ctx =
46 (struct proc_sig*)(ustack - sizeof(struct proc_sig));
48 sig_ctx->prev_context = __current->intr_ctx;
49 sig_ctx->sig_num = sig_selected;
50 sig_ctx->signal_handler = __current->sig_handler[sig_selected];
52 if (!sig_ctx->signal_handler) {
53 // 如果没有用户自定义的Handler,则使用系统默认Handler。
54 sig_ctx->signal_handler = default_handlers[sig_selected];
57 __current->sig_mask |= __SIGNAL(sig_selected);
62 __DEFINE_LXSYSCALL1(int, sigreturn, struct proc_sig, *sig_ctx)
64 __current->intr_ctx = sig_ctx->prev_context;
65 __current->sig_mask &= ~__SIGNAL(sig_ctx->sig_num);
66 __current->flags &= ~PROC_FINPAUSE;
70 __DEFINE_LXSYSCALL3(int,
79 *oldset = __current->sig_mask;
80 if (how == _SIG_BLOCK) {
81 __current->sig_mask |= *set;
82 } else if (how == _SIG_UNBLOCK) {
83 __current->sig_mask &= ~(*set);
84 } else if (how == _SIG_SETMASK) {
85 __current->sig_mask = *set;
89 __current->sig_mask &= ~_SIGNAL_UNMASKABLE;
93 __DEFINE_LXSYSCALL2(int, signal, int, signum, sighandler_t, handler)
95 if (signum < 0 || signum >= _SIG_NUM) {
99 if (((1 << signum) & _SIGNAL_UNMASKABLE)) {
103 __current->sig_handler[signum] = (void*)handler;
108 __DEFINE_LXSYSCALL(int, pause)
110 __current->flags |= PROC_FINPAUSE;
112 __SYSCALL_INTERRUPTIBLE({
113 while ((__current->flags & PROC_FINPAUSE)) {
117 __current->k_status = EINTR;