#include <lunaix/syscall.h>
#include <lunaix/syslog.h>
#include <lunaix/mm/valloc.h>
+#include <lunaix/switch.h>
+#include <lunaix/kpreempt.h>
#include <klibc/string.h>
-#include <sys/mm/mempart.h>
-
-// FIXME issues with signal
+#include <asm/mempart.h>
LOG_MODULE("SIG")
terminate_current(caused_by | PEXITSIG);
}
+static inline void
+signal_terminate_proc(struct proc_info* pcb, int caused_by)
+{
+ terminate_proccess(pcb, caused_by | PEXITSIG);
+}
+
// Referenced in kernel/asm/x86/interrupt.S
-void*
-signal_dispatch()
+void
+signal_dispatch(struct signpost_result* result)
{
+ continue_switch(result);
+
if (kernel_process(__current)) {
// signal is undefined under 'kernel process'
- return 0;
+ return;
}
if (!pending_sigs(current_thread)) {
// 没有待处理信号
- return 0;
+ return;
}
- struct sigregister* sigreg = __current->sigreg;
+ struct sigregistry* sigreg = __current->sigreg;
struct sigctx* psig = ¤t_thread->sigctx;
struct sigact* prev_working = active_signal(current_thread);
sigset_t mask = psig->sig_mask | (prev_working ? prev_working->sa_mask : 0);
- int sig_selected = 31 - clz(psig->sig_pending & ~mask);
+ int sig_selected = msbiti - clz(psig->sig_pending & ~mask);
sigset_clear(psig->sig_pending, sig_selected);
if (!sig_selected) {
// SIG0 is reserved
- return 0;
+ return;
}
struct sigact* action = sigreg->signals[sig_selected];
if (!action || !action->sa_actor) {
if (sigset_test(TERMSIG, sig_selected)) {
signal_terminate(sig_selected);
- schedule();
- // never return
+ giveup_switch(result);
}
- return 0;
+ return;
}
ptr_t ustack = current_thread->ustack_top;
ptr_t ustack_start = current_thread->ustack->start;
if ((int)(ustack - ustack_start) < (int)sizeof(struct proc_sig)) {
// 用户栈没有空间存放信号上下文
- return 0;
+ return;
}
struct proc_sig* sigframe =
sigframe->sigact = action->sa_actor;
sigframe->sighand = action->sa_handler;
- sigframe->saved_ictx = current_thread->intr_ctx;
+ sigframe->saved_hstate = current_thread->hstate;
sigactive_push(current_thread, sig_selected);
- return sigframe;
+ redirect_switch(result, __ptr(sigframe));
}
static inline void must_inline
switch (signum)
{
case SIGKILL:
- signal_terminate(signum);
+ signal_terminate_proc(proc, signum);
break;
case SIGCONT:
case SIGSTOP:
__set_signal(proc->th_active, signum);
}
+static inline void
+__broadcast_group(struct proc_info* proc, signum_t signum)
+{
+ if (proc_terminated(proc)) {
+ return;
+ }
+
+ struct proc_info *pos, *n;
+ llist_for_each(pos, n, &proc->grp_member, grp_member)
+ {
+ proc_setsignal(pos, signum);
+ }
+}
+
int
signal_send(pid_t pid, signum_t signum)
{
if (signum >= _SIG_NUM) {
- syscall_result(EINVAL);
- return -1;
+ return EINVAL;
}
pid_t sender_pid = __current->pid;
if (pid > 0) {
proc = get_process(pid);
- goto send_single;
} else if (!pid) {
proc = __current;
- goto send_grp;
} else if (pid < 0) {
proc = get_process(-pid);
- goto send_grp;
+ __broadcast_group(proc, signum);
} else {
// TODO: send to all process.
// But I don't want to support it yet.
- syscall_result(EINVAL);
- return -1;
+ return EINVAL;
}
-send_grp: ;
- struct proc_info *pos, *n;
- llist_for_each(pos, n, &proc->grp_member, grp_member)
- {
- proc_setsignal(pos, signum);
- }
-
-send_single:
if (proc_terminated(proc)) {
- syscall_result(EINVAL);
- return -1;
+ return EINVAL;
}
proc_setsignal(proc, signum);
}
void
-signal_dup_registers(struct sigregister* dest_reg)
+signal_dup_registry(struct sigregistry* dest_reg)
{
- struct sigregister* oldreg = __current->sigreg;
+ struct sigregistry* oldreg = __current->sigreg;
for (int i = 0; i < _SIG_NUM; i++) {
struct sigact* oldact = oldreg->signals[i];
if (!oldact) {
}
void
-signal_reset_register(struct sigregister* sigreg) {
+signal_reset_registry(struct sigregistry* sigreg) {
for (int i = 0; i < _SIG_NUM; i++) {
struct sigact* act = sigreg->signals[i];
if (act) {
}
void
-signal_free_registers(struct sigregister* sigreg) {
- signal_reset_register(sigreg);
+signal_free_registry(struct sigregistry* sigreg) {
+ signal_reset_registry(sigreg);
vfree(sigreg);
}
schedule();
}
- current_thread->intr_ctx = sig_ctx->saved_ictx;
+ current_thread->hstate = sig_ctx->saved_hstate;
if (proc_terminated(__current)) {
__current->exit_code |= PEXITSIG;
} else if (sigset_test(CORE, sig_ctx->sig_num)) {
signal_terminate(sig_ctx->sig_num);
}
- ptr_t ictx = (ptr_t)current_thread->intr_ctx;
+ ptr_t ictx = (ptr_t)current_thread->hstate;
/*
Ensure our restored context is within kernel stack
__DEFINE_LXSYSCALL(int, pause)
{
pause_current_thread();
- sched_pass();
+ yield_current();
syscall_result(EINTR);
return -1;
__DEFINE_LXSYSCALL2(int, kill, pid_t, pid, int, signum)
{
- return signal_send(pid, signum);
+ return syscall_result(signal_send(pid, signum));
}
__DEFINE_LXSYSCALL1(int, sigpending, sigset_t, *sigset)
sigctx->sig_mask = (*mask) & ~UNMASKABLE;
pause_current_thread();
- sched_pass();
+ yield_current();
sigctx->sig_mask = tmp;
return -1;