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