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 <sys/mm/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);
32 // Referenced in kernel/asm/x86/interrupt.S
34 signal_dispatch(struct signpost_result* result)
36 continue_switch(result);
38 if (kernel_process(__current)) {
39 // signal is undefined under 'kernel process'
43 if (!pending_sigs(current_thread)) {
48 struct sigregistry* sigreg = __current->sigreg;
49 struct sigctx* psig = ¤t_thread->sigctx;
50 struct sigact* prev_working = active_signal(current_thread);
51 sigset_t mask = psig->sig_mask | (prev_working ? prev_working->sa_mask : 0);
53 int sig_selected = msbiti - clz(psig->sig_pending & ~mask);
54 sigset_clear(psig->sig_pending, sig_selected);
61 struct sigact* action = sigreg->signals[sig_selected];
62 if (!action || !action->sa_actor) {
63 if (sigset_test(TERMSIG, sig_selected)) {
64 signal_terminate(sig_selected);
65 giveup_switch(result);
70 ptr_t ustack = current_thread->ustack_top;
71 ptr_t ustack_start = current_thread->ustack->start;
72 if ((int)(ustack - ustack_start) < (int)sizeof(struct proc_sig)) {
77 struct proc_sig* sigframe =
78 (struct proc_sig*)((ustack - sizeof(struct proc_sig)) & ~0xf);
80 sigframe->sig_num = sig_selected;
81 sigframe->sigact = action->sa_actor;
82 sigframe->sighand = action->sa_handler;
84 sigframe->saved_hstate = current_thread->hstate;
86 sigactive_push(current_thread, sig_selected);
88 redirect_switch(result, __ptr(sigframe));
91 static inline void must_inline
92 __set_signal(struct thread* thread, signum_t signum)
94 raise_signal(thread, signum);
96 // for these mutually exclusive signal
97 if (signum == SIGCONT || signum == SIGSTOP) {
98 sigset_clear(thread->sigctx.sig_pending, signum ^ 1);
101 struct sigact* sig = sigact_of(thread->process, signum);
103 sig->sender = __current->pid;
107 static inline void must_inline
108 __set_signal_all_threads(struct proc_info* proc, signum_t signum)
110 struct thread *pos, *n;
111 llist_for_each(pos, n, &proc->threads, proc_sibs) {
112 __set_signal(pos, signum);
117 thread_setsignal(struct thread* thread, signum_t signum)
119 if (unlikely(kernel_process(thread->process))) {
123 __set_signal(thread, signum);
127 proc_setsignal(struct proc_info* proc, signum_t signum)
129 if (unlikely(kernel_process(proc))) {
133 // FIXME handle signal delivery at process level.
137 signal_terminate(signum);
141 __set_signal_all_threads(proc, signum);
146 __set_signal(proc->th_active, signum);
150 signal_send(pid_t pid, signum_t signum)
152 if (signum >= _SIG_NUM) {
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.
175 struct proc_info *pos, *n;
176 llist_for_each(pos, n, &proc->grp_member, grp_member)
178 proc_setsignal(pos, signum);
182 if (proc_terminated(proc)) {
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 syscall_result(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;