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) {
153 pid_t sender_pid = __current->pid;
154 struct proc_info* proc;
157 proc = get_process(pid);
162 } else if (pid < 0) {
163 proc = get_process(-pid);
166 // TODO: send to all process.
167 // But I don't want to support it yet.
172 struct proc_info *pos, *n;
173 llist_for_each(pos, n, &proc->grp_member, grp_member)
175 proc_setsignal(pos, signum);
179 if (proc_terminated(proc)) {
183 proc_setsignal(proc, signum);
189 signal_dup_context(struct sigctx* dest_ctx)
191 struct sigctx* old_ctx = ¤t_thread->sigctx;
192 memcpy(dest_ctx, old_ctx, sizeof(struct sigctx));
196 signal_dup_registry(struct sigregistry* dest_reg)
198 struct sigregistry* oldreg = __current->sigreg;
199 for (int i = 0; i < _SIG_NUM; i++) {
200 struct sigact* oldact = oldreg->signals[i];
205 struct sigact* newact = valloc(sizeof(struct sigact));
206 memcpy(newact, oldact, sizeof(struct sigact));
208 dest_reg->signals[i] = newact;
213 signal_reset_context(struct sigctx* sigctx) {
214 memset(sigctx, 0, sizeof(struct sigctx));
218 signal_reset_registry(struct sigregistry* sigreg) {
219 for (int i = 0; i < _SIG_NUM; i++) {
220 struct sigact* act = sigreg->signals[i];
223 sigreg->signals[i] = NULL;
229 signal_free_registry(struct sigregistry* sigreg) {
230 signal_reset_registry(sigreg);
235 signal_set_sigmask(struct thread* thread, int how, sigset_t* oldset, sigset_t* set)
237 struct sigctx* sh = ¤t_thread->sigctx;
238 *oldset = sh->sig_mask;
240 if (how == _SIG_BLOCK) {
241 sigset_union(sh->sig_mask, *set);
242 } else if (how == _SIG_UNBLOCK) {
243 sigset_intersect(sh->sig_mask, ~(*set));
244 } else if (how == _SIG_SETMASK) {
250 sigset_intersect(sh->sig_mask, ~UNMASKABLE);
254 __DEFINE_LXSYSCALL1(int, sigreturn, struct proc_sig, *sig_ctx)
256 struct sigctx* sigctx = ¤t_thread->sigctx;
257 struct sigact* active = active_signal(current_thread);
259 /* We choose signal#0 as our base case, that is sig#0 means no signal.
260 Therefore, it is an ill situation to return from such sigctx.
263 signal_terminate(SIGSEGV);
267 current_thread->hstate = sig_ctx->saved_hstate;
268 if (proc_terminated(__current)) {
269 __current->exit_code |= PEXITSIG;
270 } else if (sigset_test(CORE, sig_ctx->sig_num)) {
271 signal_terminate(sig_ctx->sig_num);
274 ptr_t ictx = (ptr_t)current_thread->hstate;
277 Ensure our restored context is within kernel stack
279 This prevent user to forge their own context such that arbitrary code
280 can be executed as supervisor level
282 if (!within_kstack(ictx)) {
283 signal_terminate(SIGSEGV);
286 sigactive_pop(current_thread);
295 int, sigprocmask, int, how, const sigset_t, *set, sigset_t, *oldset)
297 // TODO maybe it is a good opportunity to introduce a process-wide
300 if (signal_set_sigmask(current_thread, how, oldset, set)) {
304 syscall_result(EINVAL);
309 int, th_sigmask, int, how, const sigset_t, *set, sigset_t, *oldset)
311 if (signal_set_sigmask(current_thread, how, oldset, set)) {
318 __DEFINE_LXSYSCALL2(int, sys_sigaction, int, signum, struct sigaction*, action)
320 if (signum <= 0 || signum >= _SIG_NUM) {
324 if (sigset_test(UNMASKABLE, signum)) {
328 struct sigctx* sigctx = ¤t_thread->sigctx;
329 if (signum == sigctx->sig_active) {
333 struct sigact* sa = sigact_of(__current, signum);
336 sa = vzalloc(sizeof(struct sigact));
337 set_sigact(__current, signum, sa);
340 sa->sa_actor = (void*)action->sa_sigaction;
341 sa->sa_handler = (void*)action->sa_handler;
342 sigset_union(sa->sa_mask, sigset(signum));
347 __DEFINE_LXSYSCALL(int, pause)
349 pause_current_thread();
352 syscall_result(EINTR);
356 __DEFINE_LXSYSCALL2(int, kill, pid_t, pid, int, signum)
358 return syscall_result(signal_send(pid, signum));
361 __DEFINE_LXSYSCALL1(int, sigpending, sigset_t, *sigset)
363 *sigset = pending_sigs(current_thread);
367 __DEFINE_LXSYSCALL1(int, sigsuspend, sigset_t, *mask)
369 struct sigctx* sigctx = ¤t_thread->sigctx;
370 sigset_t tmp = current_thread->sigctx.sig_mask;
371 sigctx->sig_mask = (*mask) & ~UNMASKABLE;
373 pause_current_thread();
376 sigctx->sig_mask = tmp;