1 #include <lunaix/process.h>
2 #include <lunaix/sched.h>
3 #include <lunaix/signal.h>
4 #include <lunaix/spike.h>
5 #include <lunaix/status.h>
6 #include <lunaix/syscall.h>
7 #include <lunaix/syslog.h>
8 #include <lunaix/mm/valloc.h>
9 #include <lunaix/switch.h>
10 #include <lunaix/kpreempt.h>
12 #include <klibc/string.h>
14 #include <asm/mempart.h>
18 extern struct scheduler sched_ctx; /* kernel/sched.c */
20 #define UNMASKABLE (sigset(SIGKILL) | sigset(SIGTERM) | sigset(SIGILL))
21 #define TERMSIG (sigset(SIGSEGV) | sigset(SIGINT) | UNMASKABLE)
22 #define CORE (sigset(SIGSEGV))
23 #define within_kstack(addr) \
24 (KSTACK_AREA <= (addr) && (addr) <= KSTACK_AREA_END)
27 signal_terminate(int caused_by)
29 terminate_current(caused_by | PEXITSIG);
33 signal_terminate_proc(struct proc_info* pcb, int caused_by)
35 terminate_proccess(pcb, caused_by | PEXITSIG);
38 // Referenced in kernel/asm/x86/interrupt.S
40 signal_dispatch(struct signpost_result* result)
42 continue_switch(result);
44 if (kernel_process(__current)) {
45 // signal is undefined under 'kernel process'
49 if (!pending_sigs(current_thread)) {
54 struct sigregistry* sigreg = __current->sigreg;
55 struct sigctx* psig = ¤t_thread->sigctx;
56 struct sigact* prev_working = active_signal(current_thread);
57 sigset_t mask = psig->sig_mask | (prev_working ? prev_working->sa_mask : 0);
59 int sig_selected = msbiti - clz(psig->sig_pending & ~mask);
60 sigset_clear(psig->sig_pending, sig_selected);
67 struct sigact* action = sigreg->signals[sig_selected];
68 if (!action || !action->sa_actor) {
69 if (sigset_test(TERMSIG, sig_selected)) {
70 signal_terminate(sig_selected);
71 giveup_switch(result);
76 ptr_t ustack = current_thread->ustack_top;
77 ptr_t ustack_start = current_thread->ustack->start;
78 if ((int)(ustack - ustack_start) < (int)sizeof(struct proc_sig)) {
83 struct proc_sig* sigframe =
84 (struct proc_sig*)((ustack - sizeof(struct proc_sig)) & ~0xf);
86 sigframe->sig_num = sig_selected;
87 sigframe->sigact = action->sa_actor;
88 sigframe->sighand = action->sa_handler;
90 sigframe->saved_hstate = current_thread->hstate;
92 sigactive_push(current_thread, sig_selected);
94 redirect_switch(result, __ptr(sigframe));
97 static inline void must_inline
98 __set_signal(struct thread* thread, signum_t signum)
100 raise_signal(thread, signum);
102 // for these mutually exclusive signal
103 if (signum == SIGCONT || signum == SIGSTOP) {
104 sigset_clear(thread->sigctx.sig_pending, signum ^ 1);
107 struct sigact* sig = sigact_of(thread->process, signum);
109 sig->sender = __current->pid;
113 static inline void must_inline
114 __set_signal_all_threads(struct proc_info* proc, signum_t signum)
116 struct thread *pos, *n;
117 llist_for_each(pos, n, &proc->threads, proc_sibs) {
118 __set_signal(pos, signum);
123 thread_setsignal(struct thread* thread, signum_t signum)
125 if (unlikely(kernel_process(thread->process))) {
129 __set_signal(thread, signum);
133 proc_setsignal(struct proc_info* proc, signum_t signum)
135 if (unlikely(kernel_process(proc))) {
139 // FIXME handle signal delivery at process level.
143 signal_terminate_proc(proc, signum);
147 __set_signal_all_threads(proc, signum);
152 __set_signal(proc->th_active, signum);
156 __broadcast_group(struct proc_info* proc, signum_t signum)
158 if (proc_terminated(proc)) {
162 struct proc_info *pos, *n;
163 llist_for_each(pos, n, &proc->grp_member, grp_member)
165 proc_setsignal(pos, signum);
170 signal_send(pid_t pid, signum_t signum)
172 if (signum >= _SIG_NUM) {
176 pid_t sender_pid = __current->pid;
177 struct proc_info* proc;
180 proc = get_process(pid);
183 } else if (pid < 0) {
184 proc = get_process(-pid);
185 __broadcast_group(proc, signum);
187 // TODO: send to all process.
188 // But I don't want to support it yet.
192 if (proc_terminated(proc)) {
196 proc_setsignal(proc, signum);
202 signal_dup_context(struct sigctx* dest_ctx)
204 struct sigctx* old_ctx = ¤t_thread->sigctx;
205 memcpy(dest_ctx, old_ctx, sizeof(struct sigctx));
209 signal_dup_registry(struct sigregistry* dest_reg)
211 struct sigregistry* oldreg = __current->sigreg;
212 for (int i = 0; i < _SIG_NUM; i++) {
213 struct sigact* oldact = oldreg->signals[i];
218 struct sigact* newact = valloc(sizeof(struct sigact));
219 memcpy(newact, oldact, sizeof(struct sigact));
221 dest_reg->signals[i] = newact;
226 signal_reset_context(struct sigctx* sigctx) {
227 memset(sigctx, 0, sizeof(struct sigctx));
231 signal_reset_registry(struct sigregistry* sigreg) {
232 for (int i = 0; i < _SIG_NUM; i++) {
233 struct sigact* act = sigreg->signals[i];
236 sigreg->signals[i] = NULL;
242 signal_free_registry(struct sigregistry* sigreg) {
243 signal_reset_registry(sigreg);
248 signal_set_sigmask(struct thread* thread, int how, sigset_t* oldset, sigset_t* set)
250 struct sigctx* sh = ¤t_thread->sigctx;
251 *oldset = sh->sig_mask;
253 if (how == _SIG_BLOCK) {
254 sigset_union(sh->sig_mask, *set);
255 } else if (how == _SIG_UNBLOCK) {
256 sigset_intersect(sh->sig_mask, ~(*set));
257 } else if (how == _SIG_SETMASK) {
263 sigset_intersect(sh->sig_mask, ~UNMASKABLE);
267 __DEFINE_LXSYSCALL1(int, sigreturn, struct proc_sig, *sig_ctx)
269 struct sigctx* sigctx = ¤t_thread->sigctx;
270 struct sigact* active = active_signal(current_thread);
272 /* We choose signal#0 as our base case, that is sig#0 means no signal.
273 Therefore, it is an ill situation to return from such sigctx.
276 signal_terminate(SIGSEGV);
280 current_thread->hstate = sig_ctx->saved_hstate;
281 if (proc_terminated(__current)) {
282 __current->exit_code |= PEXITSIG;
283 } else if (sigset_test(CORE, sig_ctx->sig_num)) {
284 signal_terminate(sig_ctx->sig_num);
287 ptr_t ictx = (ptr_t)current_thread->hstate;
290 Ensure our restored context is within kernel stack
292 This prevent user to forge their own context such that arbitrary code
293 can be executed as supervisor level
295 if (!within_kstack(ictx)) {
296 signal_terminate(SIGSEGV);
299 sigactive_pop(current_thread);
308 int, sigprocmask, int, how, const sigset_t, *set, sigset_t, *oldset)
310 // TODO maybe it is a good opportunity to introduce a process-wide
313 if (signal_set_sigmask(current_thread, how, oldset, set)) {
317 syscall_result(EINVAL);
322 int, th_sigmask, int, how, const sigset_t, *set, sigset_t, *oldset)
324 if (signal_set_sigmask(current_thread, how, oldset, set)) {
331 __DEFINE_LXSYSCALL2(int, sys_sigaction, int, signum, struct sigaction*, action)
333 if (signum <= 0 || signum >= _SIG_NUM) {
337 if (sigset_test(UNMASKABLE, signum)) {
341 struct sigctx* sigctx = ¤t_thread->sigctx;
342 if (signum == sigctx->sig_active) {
346 struct sigact* sa = sigact_of(__current, signum);
349 sa = vzalloc(sizeof(struct sigact));
350 set_sigact(__current, signum, sa);
353 sa->sa_actor = (void*)action->sa_sigaction;
354 sa->sa_handler = (void*)action->sa_handler;
355 sigset_union(sa->sa_mask, sigset(signum));
360 __DEFINE_LXSYSCALL(int, pause)
362 pause_current_thread();
365 syscall_result(EINTR);
369 __DEFINE_LXSYSCALL2(int, kill, pid_t, pid, int, signum)
371 return syscall_result(signal_send(pid, signum));
374 __DEFINE_LXSYSCALL1(int, sigpending, sigset_t, *sigset)
376 *sigset = pending_sigs(current_thread);
380 __DEFINE_LXSYSCALL1(int, sigsuspend, sigset_t, *mask)
382 struct sigctx* sigctx = ¤t_thread->sigctx;
383 sigset_t tmp = current_thread->sigctx.sig_mask;
384 sigctx->sig_mask = (*mask) & ~UNMASKABLE;
386 pause_current_thread();
389 sigctx->sig_mask = tmp;