feat: signal support (tested!)
[lunaix-os.git] / lunaix-os / kernel / signal.c
1 #include <lunaix/process.h>
2 #include <lunaix/sched.h>
3 #include <lunaix/signal.h>
4 #include <lunaix/syscall.h>
5
6 extern struct scheduler sched_ctx; /* kernel/sched.c */
7
8 void* default_handlers[_SIG_NUM] = {
9     // TODO: 添加默认handler
10 };
11
12 // Referenced in kernel/asm/x86/interrupt.S
13 void*
14 signal_dispatch()
15 {
16     // if (!(SEL_RPL(__current->intr_ctx.cs))) {
17     //     // 同特权级间调度不进行信号处理
18     //     return 0;
19     // }
20
21     if (!__current->sig_pending) {
22         // 没有待处理信号
23         return 0;
24     }
25
26     int sig_selected =
27       31 - __builtin_clz(__current->sig_pending & ~__current->sig_mask);
28
29     __current->sig_pending = __current->sig_pending & ~__SIGNAL(sig_selected);
30
31     if (!__current->sig_handler[sig_selected] &&
32         !default_handlers[sig_selected]) {
33         // 如果该信号没有handler,则忽略
34         return 0;
35     }
36
37     uintptr_t ustack = __current->ustack_top & ~0xf;
38
39     if ((int)(ustack - USTACK_END) < (int)sizeof(struct proc_sig)) {
40         // 用户栈没有空间存放信号上下文
41         return 0;
42     }
43
44     struct proc_sig* sig_ctx =
45       (struct proc_sig*)(ustack - sizeof(struct proc_sig));
46
47     sig_ctx->prev_context = __current->intr_ctx;
48     sig_ctx->sig_num = sig_selected;
49     sig_ctx->signal_handler = __current->sig_handler[sig_selected];
50
51     if (!sig_ctx->signal_handler) {
52         // 如果没有用户自定义的Handler,则使用系统默认Handler。
53         sig_ctx->signal_handler = default_handlers[sig_selected];
54     }
55
56     __current->sig_mask |= __SIGNAL(sig_selected);
57
58     return sig_ctx;
59 }
60
61 __DEFINE_LXSYSCALL1(int, sigreturn, struct proc_sig, *sig_ctx)
62 {
63     __current->intr_ctx = sig_ctx->prev_context;
64     __current->sig_mask &= ~__SIGNAL(sig_ctx->sig_num);
65     schedule();
66 }
67
68 __DEFINE_LXSYSCALL3(int,
69                     sigprocmask,
70                     int,
71                     how,
72                     const sigset_t,
73                     *set,
74                     sigset_t,
75                     *oldset)
76 {
77     *oldset = __current->sig_mask;
78     if (how == _SIG_BLOCK) {
79         __current->sig_mask |= *set;
80     } else if (how == _SIG_UNBLOCK) {
81         __current->sig_mask &= ~(*set);
82     } else if (how == _SIG_SETMASK) {
83         __current->sig_mask = *set;
84     } else {
85         return 0;
86     }
87     __current->sig_mask &= ~_SIGNAL_UNMASKABLE;
88     return 1;
89 }
90
91 __DEFINE_LXSYSCALL2(int, signal, int, signum, sighandler_t, handler)
92 {
93     if (signum < 0 || signum >= _SIG_NUM) {
94         return -1;
95     }
96
97     if (((1 << signum) & _SIGNAL_UNMASKABLE)) {
98         return -1;
99     }
100
101     __current->sig_handler[signum] = (void*)handler;
102
103     return 0;
104 }