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>
11 #include <klibc/string.h>
13 extern struct scheduler sched_ctx; /* kernel/sched.c */
15 #define UNMASKABLE (sigset(SIGKILL) | sigset(SIGTERM))
16 #define TERMSIG (sigset(SIGSEGV) | sigset(SIGINT) | UNMASKABLE)
17 #define CORE (sigset(SIGSEGV))
20 signal_terminate(int errcode)
22 terminate_proc(errcode | PEXITSIG);
25 // Referenced in kernel/asm/x86/interrupt.S
29 if (!__current->sigctx.sig_pending) {
34 struct sighail* psig = &__current->sigctx;
35 struct sigact* prev_working = psig->inprogress;
36 sigset_t mask = psig->sig_mask | (prev_working ? prev_working->sa_mask : 0);
38 int sig_selected = 31 - __builtin_clz(psig->sig_pending & ~mask);
40 sigset_clear(psig->sig_pending, sig_selected);
42 struct sigact* action = &psig->signals[sig_selected];
44 if (sig_selected == 0) {
49 if (!action->sa_actor) {
50 if (sigset_test(TERMSIG, sig_selected)) {
51 signal_terminate(sig_selected);
58 ptr_t ustack = __current->ustack_top;
60 if ((int)(ustack - USTACK_END) < (int)sizeof(struct proc_sig)) {
65 struct proc_sig* sigframe =
66 (struct proc_sig*)((ustack - sizeof(struct proc_sig)) & ~0xf);
68 sigframe->sig_num = sig_selected;
69 sigframe->sigact = action->sa_actor;
70 sigframe->sighand = action->sa_handler;
72 sigframe->saved_ictx = __current->intr_ctx;
74 action->prev = prev_working;
75 psig->inprogress = action;
81 proc_setsignal(struct proc_info* proc, int signum)
83 sigset_add(proc->sigctx.sig_pending, signum);
84 proc->sigctx.signals[signum].sender = __current->pid;
88 signal_send(pid_t pid, int signum)
90 if (signum < 0 || signum >= _SIG_NUM) {
91 __current->k_status = EINVAL;
95 pid_t sender_pid = __current->pid;
96 struct proc_info* proc;
99 proc = get_process(pid);
104 } else if (pid < -1) {
105 proc = get_process(-pid);
108 // TODO: send to all process.
109 // But I don't want to support it yet.
110 __current->k_status = EINVAL;
115 struct proc_info *pos, *n;
116 llist_for_each(pos, n, &proc->grp_member, grp_member)
118 struct sighail* sh = &pos->sigctx;
119 sigset_add(sh->sig_pending, signum);
120 sh->signals[signum].sender = sender_pid;
124 if (proc_terminated(proc)) {
125 __current->k_status = EINVAL;
129 sigset_add(proc->sigctx.sig_pending, signum);
130 proc->sigctx.signals[signum].sender = sender_pid;
135 __DEFINE_LXSYSCALL1(int, sigreturn, struct proc_sig, *sig_ctx)
137 __current->intr_ctx = sig_ctx->saved_ictx;
139 struct sigact* current = __current->sigctx.inprogress;
141 __current->sigctx.inprogress = current->prev;
142 current->prev = NULL;
144 __current->sigctx.inprogress = NULL;
147 if (proc_terminated(__current)) {
148 __current->exit_code |= PEXITSIG;
149 } else if (sigset_test(CORE, sig_ctx->sig_num)) {
150 signal_terminate(sig_ctx->sig_num);
153 ptr_t ictx = (ptr_t)__current->intr_ctx;
156 Ensure our restored context is within kernel stack
158 This prevent user to forge their own context such that arbitrary code
159 can be executed as supervisor level
161 if (!within_kstack(ictx)) {
162 signal_terminate(SIGSEGV);
171 __DEFINE_LXSYSCALL3(int,
180 struct sighail* sh = &__current->sigctx;
181 *oldset = sh->sig_mask;
183 if (how == _SIG_BLOCK) {
184 sigset_union(sh->sig_mask, *set);
185 } else if (how == _SIG_UNBLOCK) {
186 sigset_intersect(sh->sig_mask, ~(*set));
187 } else if (how == _SIG_SETMASK) {
193 sigset_intersect(sh->sig_mask, ~UNMASKABLE);
197 __DEFINE_LXSYSCALL2(int, sys_sigaction, int, signum, struct sigaction*, action)
199 if (signum <= 0 || signum >= _SIG_NUM) {
203 if (sigset_test(UNMASKABLE, signum)) {
207 struct sigact* sa = &__current->sigctx.signals[signum];
209 sa->sa_actor = (void*)action->sa_sigaction;
210 sa->sa_handler = (void*)action->sa_handler;
211 sigset_union(sa->sa_mask, sigset(signum));
216 __DEFINE_LXSYSCALL(int, pause)
221 __current->k_status = EINTR;
225 __DEFINE_LXSYSCALL2(int, kill, pid_t, pid, int, signum)
227 return signal_send(pid, signum);
230 __DEFINE_LXSYSCALL1(int, sigpending, sigset_t, *sigset)
232 *sigset = __current->sigctx.sig_pending;
236 __DEFINE_LXSYSCALL1(int, sigsuspend, sigset_t, *mask)
238 sigset_t tmp = __current->sigctx.sig_mask;
239 __current->sigctx.sig_mask = (*mask) & ~UNMASKABLE;
244 __current->sigctx.sig_mask = tmp;