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>
10 #include <klibc/string.h>
12 #include <sys/mm/mempart.h>
14 // FIXME issues with signal
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);
32 // Referenced in kernel/asm/x86/interrupt.S
36 if (kernel_process(__current)) {
37 // signal is undefined under 'kernel process'
41 if (!pending_sigs(current_thread)) {
46 struct sigregister* sigreg = __current->sigreg;
47 struct sigctx* psig = ¤t_thread->sigctx;
48 struct sigact* prev_working = active_signal(current_thread);
49 sigset_t mask = psig->sig_mask | (prev_working ? prev_working->sa_mask : 0);
51 int sig_selected = 31 - clz(psig->sig_pending & ~mask);
52 sigset_clear(psig->sig_pending, sig_selected);
59 struct sigact* action = sigreg->signals[sig_selected];
60 if (!action || !action->sa_actor) {
61 if (sigset_test(TERMSIG, sig_selected)) {
62 signal_terminate(sig_selected);
69 ptr_t ustack = current_thread->ustack_top;
70 ptr_t ustack_start = current_thread->ustack->start;
71 if ((int)(ustack - ustack_start) < (int)sizeof(struct proc_sig)) {
76 struct proc_sig* sigframe =
77 (struct proc_sig*)((ustack - sizeof(struct proc_sig)) & ~0xf);
79 sigframe->sig_num = sig_selected;
80 sigframe->sigact = action->sa_actor;
81 sigframe->sighand = action->sa_handler;
83 sigframe->saved_ictx = current_thread->intr_ctx;
85 sigactive_push(current_thread, sig_selected);
90 static inline void must_inline
91 __set_signal(struct thread* thread, signum_t signum)
93 raise_signal(thread, signum);
95 // for these mutually exclusive signal
96 if (signum == SIGCONT || signum == SIGSTOP) {
97 sigset_clear(thread->sigctx.sig_pending, signum ^ 1);
100 struct sigact* sig = sigact_of(thread->process, signum);
102 sig->sender = __current->pid;
106 static inline void must_inline
107 __set_signal_all_threads(struct proc_info* proc, signum_t signum)
109 struct thread *pos, *n;
110 llist_for_each(pos, n, &proc->threads, proc_sibs) {
111 __set_signal(pos, signum);
116 thread_setsignal(struct thread* thread, signum_t signum)
118 if (unlikely(kernel_process(thread->process))) {
122 __set_signal(thread, signum);
126 proc_setsignal(struct proc_info* proc, signum_t signum)
128 if (unlikely(kernel_process(proc))) {
132 // FIXME handle signal delivery at process level.
136 signal_terminate(signum);
140 __set_signal_all_threads(proc, signum);
145 __set_signal(proc->th_active, signum);
149 signal_send(pid_t pid, signum_t signum)
151 if (signum >= _SIG_NUM) {
152 syscall_result(EINVAL);
156 pid_t sender_pid = __current->pid;
157 struct proc_info* proc;
160 proc = get_process(pid);
165 } else if (pid < 0) {
166 proc = get_process(-pid);
169 // TODO: send to all process.
170 // But I don't want to support it yet.
171 syscall_result(EINVAL);
176 struct proc_info *pos, *n;
177 llist_for_each(pos, n, &proc->grp_member, grp_member)
179 proc_setsignal(pos, signum);
183 if (proc_terminated(proc)) {
184 syscall_result(EINVAL);
188 proc_setsignal(proc, signum);
194 signal_dup_context(struct sigctx* dest_ctx)
196 struct sigctx* old_ctx = ¤t_thread->sigctx;
197 memcpy(dest_ctx, old_ctx, sizeof(struct sigctx));
201 signal_dup_registers(struct sigregister* dest_reg)
203 struct sigregister* oldreg = __current->sigreg;
204 for (int i = 0; i < _SIG_NUM; i++) {
205 struct sigact* oldact = oldreg->signals[i];
210 struct sigact* newact = valloc(sizeof(struct sigact));
211 memcpy(newact, oldact, sizeof(struct sigact));
213 dest_reg->signals[i] = newact;
218 signal_reset_context(struct sigctx* sigctx) {
219 memset(sigctx, 0, sizeof(struct sigctx));
223 signal_reset_register(struct sigregister* sigreg) {
224 for (int i = 0; i < _SIG_NUM; i++) {
225 struct sigact* act = sigreg->signals[i];
228 sigreg->signals[i] = NULL;
234 signal_free_registers(struct sigregister* sigreg) {
235 signal_reset_register(sigreg);
240 signal_set_sigmask(struct thread* thread, int how, sigset_t* oldset, sigset_t* set)
242 struct sigctx* sh = ¤t_thread->sigctx;
243 *oldset = sh->sig_mask;
245 if (how == _SIG_BLOCK) {
246 sigset_union(sh->sig_mask, *set);
247 } else if (how == _SIG_UNBLOCK) {
248 sigset_intersect(sh->sig_mask, ~(*set));
249 } else if (how == _SIG_SETMASK) {
255 sigset_intersect(sh->sig_mask, ~UNMASKABLE);
259 __DEFINE_LXSYSCALL1(int, sigreturn, struct proc_sig, *sig_ctx)
261 struct sigctx* sigctx = ¤t_thread->sigctx;
262 struct sigact* active = active_signal(current_thread);
264 /* We choose signal#0 as our base case, that is sig#0 means no signal.
265 Therefore, it is an ill situation to return from such sigctx.
268 signal_terminate(SIGSEGV);
272 current_thread->intr_ctx = sig_ctx->saved_ictx;
273 if (proc_terminated(__current)) {
274 __current->exit_code |= PEXITSIG;
275 } else if (sigset_test(CORE, sig_ctx->sig_num)) {
276 signal_terminate(sig_ctx->sig_num);
279 ptr_t ictx = (ptr_t)current_thread->intr_ctx;
282 Ensure our restored context is within kernel stack
284 This prevent user to forge their own context such that arbitrary code
285 can be executed as supervisor level
287 if (!within_kstack(ictx)) {
288 signal_terminate(SIGSEGV);
291 sigactive_pop(current_thread);
300 int, sigprocmask, int, how, const sigset_t, *set, sigset_t, *oldset)
302 // TODO maybe it is a good opportunity to introduce a process-wide
305 if (signal_set_sigmask(current_thread, how, oldset, set)) {
309 syscall_result(EINVAL);
314 int, th_sigmask, int, how, const sigset_t, *set, sigset_t, *oldset)
316 if (signal_set_sigmask(current_thread, how, oldset, set)) {
323 __DEFINE_LXSYSCALL2(int, sys_sigaction, int, signum, struct sigaction*, action)
325 if (signum <= 0 || signum >= _SIG_NUM) {
329 if (sigset_test(UNMASKABLE, signum)) {
333 struct sigctx* sigctx = ¤t_thread->sigctx;
334 if (signum == sigctx->sig_active) {
338 struct sigact* sa = sigact_of(__current, signum);
341 sa = vzalloc(sizeof(struct sigact));
342 set_sigact(__current, signum, sa);
345 sa->sa_actor = (void*)action->sa_sigaction;
346 sa->sa_handler = (void*)action->sa_handler;
347 sigset_union(sa->sa_mask, sigset(signum));
352 __DEFINE_LXSYSCALL(int, pause)
354 pause_current_thread();
357 syscall_result(EINTR);
361 __DEFINE_LXSYSCALL2(int, kill, pid_t, pid, int, signum)
363 return signal_send(pid, signum);
366 __DEFINE_LXSYSCALL1(int, sigpending, sigset_t, *sigset)
368 *sigset = pending_sigs(current_thread);
372 __DEFINE_LXSYSCALL1(int, sigsuspend, sigset_t, *mask)
374 struct sigctx* sigctx = ¤t_thread->sigctx;
375 sigset_t tmp = current_thread->sigctx.sig_mask;
376 sigctx->sig_mask = (*mask) & ~UNMASKABLE;
378 pause_current_thread();
381 sigctx->sig_mask = tmp;