From 2f2b3cdc6facd20b4354a89223631c4713a16f06 Mon Sep 17 00:00:00 2001 From: Tomoki Shirasawa Date: Tue, 23 Jan 2018 14:31:04 +0900 Subject: [PATCH] signal: interrupt_syscall is called by the core executing the thread that recieved the signal. refs #999 --- arch/x86_64/kernel/cpu.c | 37 +++++++++---------- arch/x86_64/kernel/syscall.c | 71 ++++++++++++++++++++++++++++++++++-- kernel/include/process.h | 1 + 3 files changed, 85 insertions(+), 24 deletions(-) diff --git a/arch/x86_64/kernel/cpu.c b/arch/x86_64/kernel/cpu.c index 5bcad024..9903aa3d 100644 --- a/arch/x86_64/kernel/cpu.c +++ b/arch/x86_64/kernel/cpu.c @@ -849,6 +849,7 @@ void setup_x86_ap(void (*next_func)(void)) void arch_show_interrupt_context(const void *reg); void set_signal(int sig, void *regs, struct siginfo *info); void check_signal(unsigned long, void *, int); +void check_sig_pending(); extern void tlb_flush_handler(int vector); void __show_stack(uintptr_t *sp) { @@ -870,6 +871,18 @@ void show_context_stack(uintptr_t *rbp) { return; } +void interrupt_exit(struct x86_user_context *regs) +{ + if (interrupt_from_user(regs)) { + cpu_enable_interrupt(); + check_signal(0, regs, 0); + check_need_resched(); + } + else { + check_sig_pending(); + } +} + void handle_interrupt(int vector, struct x86_user_context *regs) { struct ihk_mc_interrupt_handler *h; @@ -992,11 +1005,7 @@ void handle_interrupt(int vector, struct x86_user_context *regs) } } - if(interrupt_from_user(regs)){ - cpu_enable_interrupt(); - check_signal(0, regs, 0); - check_need_resched(); - } + interrupt_exit(regs); set_cputime(0); --v->in_interrupt; @@ -1012,11 +1021,7 @@ void gpe_handler(struct x86_user_context *regs) panic("gpe_handler"); } set_signal(SIGSEGV, regs, NULL); - if(interrupt_from_user(regs)){ - cpu_enable_interrupt(); - check_signal(0, regs, 0); - check_need_resched(); - } + interrupt_exit(regs); set_cputime(0); panic("GPF"); } @@ -1045,11 +1050,7 @@ void debug_handler(struct x86_user_context *regs) memset(&info, '\0', sizeof info); info.si_code = si_code; set_signal(SIGTRAP, regs, &info); - if(interrupt_from_user(regs)){ - cpu_enable_interrupt(); - check_signal(0, regs, 0); - check_need_resched(); - } + interrupt_exit(regs); set_cputime(0); } @@ -1067,11 +1068,7 @@ void int3_handler(struct x86_user_context *regs) memset(&info, '\0', sizeof info); info.si_code = TRAP_BRKPT; set_signal(SIGTRAP, regs, &info); - if(interrupt_from_user(regs)){ - cpu_enable_interrupt(); - check_signal(0, regs, 0); - check_need_resched(); - } + interrupt_exit(regs); set_cputime(0); } diff --git a/arch/x86_64/kernel/syscall.c b/arch/x86_64/kernel/syscall.c index 1e0f6025..a3ff105e 100644 --- a/arch/x86_64/kernel/syscall.c +++ b/arch/x86_64/kernel/syscall.c @@ -32,7 +32,6 @@ #include #include -void terminate(int, int); extern long do_sigaction(int sig, struct k_sigaction *act, struct k_sigaction *oact); long syscall(int num, ihk_mc_user_context_t *ctx); void set_signal(int sig, void *regs0, siginfo_t *info); @@ -280,6 +279,7 @@ SYSCALL_DECLARE(rt_sigreturn) extern struct cpu_local_var *clv; extern unsigned long do_kill(struct thread *thread, int pid, int tid, int sig, struct siginfo *info, int ptracecont); extern void interrupt_syscall(struct thread *, int sig); +extern void terminate(int, int); extern int num_processors; #define RFLAGS_MASK (RFLAGS_CF | RFLAGS_PF | RFLAGS_AF | RFLAGS_ZF | \ @@ -1054,6 +1054,72 @@ out: return; } +void +check_sig_pending() +{ + struct thread *thread; + int found = 0; + struct list_head *head; + mcs_rwlock_lock_t *lock; + struct mcs_rwlock_node_irqsave mcs_rw_node; + struct sig_pending *next; + struct sig_pending *pending; + __sigset_t w; + __sigset_t x; + int sig; + struct k_sigaction *k; + + + if(clv == NULL) + return; + thread = cpu_local_var(current); + + if (thread == NULL || thread == &cpu_local_var(idle)) { + return; + } + + if (thread->in_syscall_offload == 0) { + return; + } + + w = thread->sigmask.__val[0]; + + lock = &thread->sigcommon->lock; + head = &thread->sigcommon->sigpending; + for (;;) { + mcs_rwlock_reader_lock(lock, &mcs_rw_node); + + list_for_each_entry_safe(pending, next, head, list){ + for (x = pending->sigmask.__val[0], sig = 0; x; + sig++, x >>= 1); + k = thread->sigcommon->action + sig - 1; + if ((sig != SIGCHLD && sig != SIGURG) || + (k->sa.sa_handler != (void *)1 && + k->sa.sa_handler != NULL)) { + if (!(pending->sigmask.__val[0] & w)) { + if (pending->interrupted == 0) { + pending->interrupted = 1; + found = 1; + } + } + } + } + + mcs_rwlock_reader_unlock(lock, &mcs_rw_node); + + if (lock == &thread->sigpendinglock) { + break; + } + + lock = &thread->sigpendinglock; + head = &thread->sigpending; + } + + if (found) { + interrupt_syscall(thread, 0); + } +} + unsigned long do_kill(struct thread *thread, int pid, int tid, int sig, siginfo_t *info, int ptracecont) @@ -1308,9 +1374,6 @@ done: ihk_mc_interrupt_cpu(get_x86_cpu_local_variable(tthread->cpu_id)->apic_id, 0xd0); } - if(!tthread->proc->nohost) - interrupt_syscall(tthread, 0); - if (status != PS_RUNNING) { if(sig == SIGKILL){ /* Wake up the target only when stopped by ptrace-reporting */ diff --git a/kernel/include/process.h b/kernel/include/process.h index 1bd70e17..210745f0 100644 --- a/kernel/include/process.h +++ b/kernel/include/process.h @@ -437,6 +437,7 @@ struct sig_pending { sigset_t sigmask; siginfo_t info; int ptracecont; + int interrupted; }; typedef void pgio_func_t(void *arg);