c3a6c07ffa89982bce3932a31652b32096dcb79e
[lunaix-os.git] / lunaix-os / kernel / signal.c
1 #include <lunaix/lunistd.h>
2 #include <lunaix/lxsignal.h>
3 #include <lunaix/process.h>
4 #include <lunaix/sched.h>
5 #include <lunaix/signal.h>
6 #include <lunaix/spike.h>
7 #include <lunaix/status.h>
8 #include <lunaix/syscall.h>
9
10 extern struct scheduler sched_ctx; /* kernel/sched.c */
11
12 void __USER__
13 default_sighandler_term(int signum)
14 {
15     _exit(signum);
16 }
17
18 void* default_handlers[_SIG_NUM] = {
19     // TODO: 添加默认handler
20     [_SIGINT] = default_sighandler_term,
21     [_SIGTERM] = default_sighandler_term,
22 };
23
24 // Referenced in kernel/asm/x86/interrupt.S
25 void*
26 signal_dispatch()
27 {
28     if (!__current->sig_pending) {
29         // 没有待处理信号
30         return 0;
31     }
32
33     int sig_selected =
34       31 - __builtin_clz(__current->sig_pending &
35                          ~(__current->sig_mask | __current->sig_inprogress));
36
37     __SIGCLEAR(__current->sig_pending, sig_selected);
38
39     if (sig_selected == 0) {
40         // SIG0 is reserved
41         return 0;
42     }
43
44     if (!__current->sig_handler[sig_selected] &&
45         !default_handlers[sig_selected]) {
46         // 如果该信号没有handler,则忽略
47         return 0;
48     }
49
50     uintptr_t ustack = __current->ustack_top & ~0xf;
51
52     if ((int)(ustack - USTACK_END) < (int)sizeof(struct proc_sig)) {
53         // 用户栈没有空间存放信号上下文
54         return 0;
55     }
56
57     struct proc_sig* sig_ctx =
58       (struct proc_sig*)(ustack - sizeof(struct proc_sig));
59
60     sig_ctx->prev_context = __current->intr_ctx;
61     sig_ctx->sig_num = sig_selected;
62     sig_ctx->signal_handler = __current->sig_handler[sig_selected];
63
64     if (!sig_ctx->signal_handler) {
65         // 如果没有用户自定义的Handler,则使用系统默认Handler。
66         sig_ctx->signal_handler = default_handlers[sig_selected];
67     }
68
69     __SIGSET(__current->sig_inprogress, sig_selected);
70
71     return sig_ctx;
72 }
73
74 int
75 signal_send(pid_t pid, int signum)
76 {
77     if (signum < 0 || signum >= _SIG_NUM) {
78         __current->k_status = LXINVL;
79         return -1;
80     }
81
82     struct proc_info* proc;
83     if (pid > 0) {
84         proc = get_process(pid);
85         goto send_single;
86     } else if (!pid) {
87         proc = __current;
88         goto send_grp;
89     } else if (pid < -1) {
90         proc = get_process(-pid);
91         goto send_grp;
92     } else {
93         // TODO: send to all process.
94         //  But I don't want to support it yet.
95         __current->k_status = LXINVL;
96         return -1;
97     }
98
99 send_grp:
100     struct proc_info *pos, *n;
101     llist_for_each(pos, n, &proc->grp_member, grp_member)
102     {
103         __SIGSET(pos->sig_pending, signum);
104     }
105     return 0;
106
107 send_single:
108     if ((proc->state & PROC_TERMMASK)) {
109         __current->k_status = LXINVL;
110         return -1;
111     }
112     __SIGSET(proc->sig_pending, signum);
113     return 0;
114 }
115
116 __DEFINE_LXSYSCALL1(int, sigreturn, struct proc_sig, *sig_ctx)
117 {
118     __current->intr_ctx = sig_ctx->prev_context;
119     __current->flags &= ~PROC_FINPAUSE;
120     __SIGCLEAR(__current->sig_inprogress, sig_ctx->sig_num);
121     schedule();
122 }
123
124 __DEFINE_LXSYSCALL3(int,
125                     sigprocmask,
126                     int,
127                     how,
128                     const sigset_t,
129                     *set,
130                     sigset_t,
131                     *oldset)
132 {
133     *oldset = __current->sig_mask;
134     if (how == _SIG_BLOCK) {
135         __current->sig_mask |= *set;
136     } else if (how == _SIG_UNBLOCK) {
137         __current->sig_mask &= ~(*set);
138     } else if (how == _SIG_SETMASK) {
139         __current->sig_mask = *set;
140     } else {
141         return 0;
142     }
143     __current->sig_mask &= ~_SIGNAL_UNMASKABLE;
144     return 1;
145 }
146
147 __DEFINE_LXSYSCALL2(int, signal, int, signum, sighandler_t, handler)
148 {
149     if (signum <= 0 || signum >= _SIG_NUM) {
150         return -1;
151     }
152
153     if ((__SIGNAL(signum) & _SIGNAL_UNMASKABLE)) {
154         return -1;
155     }
156
157     __current->sig_handler[signum] = (void*)handler;
158
159     return 0;
160 }
161
162 __DEFINE_LXSYSCALL(int, pause)
163 {
164     __current->flags |= PROC_FINPAUSE;
165
166     __SYSCALL_INTERRUPTIBLE({
167         while ((__current->flags & PROC_FINPAUSE)) {
168             sched_yield();
169         }
170     })
171     __current->k_status = EINTR;
172     return -1;
173 }
174
175 __DEFINE_LXSYSCALL2(int, kill, pid_t, pid, int, signum)
176 {
177     return signal_send(pid, signum);
178 }