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>
16 extern struct scheduler sched_ctx; /* kernel/sched.c */
18 #define UNMASKABLE (sigset(SIGKILL) | sigset(SIGTERM) | sigset(SIGILL))
19 #define TERMSIG (sigset(SIGSEGV) | sigset(SIGINT) | UNMASKABLE)
20 #define CORE (sigset(SIGSEGV))
21 #define within_kstack(addr) \
22 (KSTACK_AREA <= (addr) && (addr) <= KSTACK_AREA_END)
25 signal_terminate(int caused_by)
27 terminate_current(caused_by | PEXITSIG);
30 // Referenced in kernel/asm/x86/interrupt.S
34 if (kernel_process(__current)) {
35 // signal is undefined under 'kernel process'
39 if (!pending_sigs(current_thread)) {
44 struct sigregistry* sigreg = __current->sigreg;
45 struct sigctx* psig = ¤t_thread->sigctx;
46 struct sigact* prev_working = active_signal(current_thread);
47 sigset_t mask = psig->sig_mask | (prev_working ? prev_working->sa_mask : 0);
49 int sig_selected = 31 - clz(psig->sig_pending & ~mask);
50 sigset_clear(psig->sig_pending, sig_selected);
57 struct sigact* action = sigreg->signals[sig_selected];
58 if (!action || !action->sa_actor) {
59 if (sigset_test(TERMSIG, sig_selected)) {
60 signal_terminate(sig_selected);
67 ptr_t ustack = current_thread->ustack_top;
68 ptr_t ustack_start = current_thread->ustack->start;
69 if ((int)(ustack - ustack_start) < (int)sizeof(struct proc_sig)) {
74 struct proc_sig* sigframe =
75 (struct proc_sig*)((ustack - sizeof(struct proc_sig)) & ~0xf);
77 sigframe->sig_num = sig_selected;
78 sigframe->sigact = action->sa_actor;
79 sigframe->sighand = action->sa_handler;
81 sigframe->saved_hstate = current_thread->hstate;
83 sigactive_push(current_thread, sig_selected);
88 static inline void must_inline
89 __set_signal(struct thread* thread, signum_t signum)
91 raise_signal(thread, signum);
93 // for these mutually exclusive signal
94 if (signum == SIGCONT || signum == SIGSTOP) {
95 sigset_clear(thread->sigctx.sig_pending, signum ^ 1);
98 struct sigact* sig = sigact_of(thread->process, signum);
100 sig->sender = __current->pid;
104 static inline void must_inline
105 __set_signal_all_threads(struct proc_info* proc, signum_t signum)
107 struct thread *pos, *n;
108 llist_for_each(pos, n, &proc->threads, proc_sibs) {
109 __set_signal(pos, signum);
114 thread_setsignal(struct thread* thread, signum_t signum)
116 if (unlikely(kernel_process(thread->process))) {
120 __set_signal(thread, signum);
124 proc_setsignal(struct proc_info* proc, signum_t signum)
126 if (unlikely(kernel_process(proc))) {
130 // FIXME handle signal delivery at process level.
134 signal_terminate(signum);
138 __set_signal_all_threads(proc, signum);
143 __set_signal(proc->th_active, signum);
147 signal_send(pid_t pid, signum_t signum)
149 if (signum >= _SIG_NUM) {
150 syscall_result(EINVAL);
154 pid_t sender_pid = __current->pid;
155 struct proc_info* proc;
158 proc = get_process(pid);
163 } else if (pid < 0) {
164 proc = get_process(-pid);
167 // TODO: send to all process.
168 // But I don't want to support it yet.
169 syscall_result(EINVAL);
174 struct proc_info *pos, *n;
175 llist_for_each(pos, n, &proc->grp_member, grp_member)
177 proc_setsignal(pos, signum);
181 if (proc_terminated(proc)) {
182 syscall_result(EINVAL);
186 proc_setsignal(proc, signum);
192 signal_dup_context(struct sigctx* dest_ctx)
194 struct sigctx* old_ctx = ¤t_thread->sigctx;
195 memcpy(dest_ctx, old_ctx, sizeof(struct sigctx));
199 signal_dup_registry(struct sigregistry* dest_reg)
201 struct sigregistry* oldreg = __current->sigreg;
202 for (int i = 0; i < _SIG_NUM; i++) {
203 struct sigact* oldact = oldreg->signals[i];
208 struct sigact* newact = valloc(sizeof(struct sigact));
209 memcpy(newact, oldact, sizeof(struct sigact));
211 dest_reg->signals[i] = newact;
216 signal_reset_context(struct sigctx* sigctx) {
217 memset(sigctx, 0, sizeof(struct sigctx));
221 signal_reset_registry(struct sigregistry* sigreg) {
222 for (int i = 0; i < _SIG_NUM; i++) {
223 struct sigact* act = sigreg->signals[i];
226 sigreg->signals[i] = NULL;
232 signal_free_registry(struct sigregistry* sigreg) {
233 signal_reset_registry(sigreg);
238 signal_set_sigmask(struct thread* thread, int how, sigset_t* oldset, sigset_t* set)
240 struct sigctx* sh = ¤t_thread->sigctx;
241 *oldset = sh->sig_mask;
243 if (how == _SIG_BLOCK) {
244 sigset_union(sh->sig_mask, *set);
245 } else if (how == _SIG_UNBLOCK) {
246 sigset_intersect(sh->sig_mask, ~(*set));
247 } else if (how == _SIG_SETMASK) {
253 sigset_intersect(sh->sig_mask, ~UNMASKABLE);
257 __DEFINE_LXSYSCALL1(int, sigreturn, struct proc_sig, *sig_ctx)
259 struct sigctx* sigctx = ¤t_thread->sigctx;
260 struct sigact* active = active_signal(current_thread);
262 /* We choose signal#0 as our base case, that is sig#0 means no signal.
263 Therefore, it is an ill situation to return from such sigctx.
266 signal_terminate(SIGSEGV);
270 current_thread->hstate = sig_ctx->saved_hstate;
271 if (proc_terminated(__current)) {
272 __current->exit_code |= PEXITSIG;
273 } else if (sigset_test(CORE, sig_ctx->sig_num)) {
274 signal_terminate(sig_ctx->sig_num);
277 ptr_t ictx = (ptr_t)current_thread->hstate;
280 Ensure our restored context is within kernel stack
282 This prevent user to forge their own context such that arbitrary code
283 can be executed as supervisor level
285 if (!within_kstack(ictx)) {
286 signal_terminate(SIGSEGV);
289 sigactive_pop(current_thread);
298 int, sigprocmask, int, how, const sigset_t, *set, sigset_t, *oldset)
300 // TODO maybe it is a good opportunity to introduce a process-wide
303 if (signal_set_sigmask(current_thread, how, oldset, set)) {
307 syscall_result(EINVAL);
312 int, th_sigmask, int, how, const sigset_t, *set, sigset_t, *oldset)
314 if (signal_set_sigmask(current_thread, how, oldset, set)) {
321 __DEFINE_LXSYSCALL2(int, sys_sigaction, int, signum, struct sigaction*, action)
323 if (signum <= 0 || signum >= _SIG_NUM) {
327 if (sigset_test(UNMASKABLE, signum)) {
331 struct sigctx* sigctx = ¤t_thread->sigctx;
332 if (signum == sigctx->sig_active) {
336 struct sigact* sa = sigact_of(__current, signum);
339 sa = vzalloc(sizeof(struct sigact));
340 set_sigact(__current, signum, sa);
343 sa->sa_actor = (void*)action->sa_sigaction;
344 sa->sa_handler = (void*)action->sa_handler;
345 sigset_union(sa->sa_mask, sigset(signum));
350 __DEFINE_LXSYSCALL(int, pause)
352 pause_current_thread();
355 syscall_result(EINTR);
359 __DEFINE_LXSYSCALL2(int, kill, pid_t, pid, int, signum)
361 return signal_send(pid, signum);
364 __DEFINE_LXSYSCALL1(int, sigpending, sigset_t, *sigset)
366 *sigset = pending_sigs(current_thread);
370 __DEFINE_LXSYSCALL1(int, sigsuspend, sigset_t, *mask)
372 struct sigctx* sigctx = ¤t_thread->sigctx;
373 sigset_t tmp = current_thread->sigctx.sig_mask;
374 sigctx->sig_mask = (*mask) & ~UNMASKABLE;
376 pause_current_thread();
379 sigctx->sig_mask = tmp;