signal: interrupt_syscall is called by the core executing the thread that recieved the signal.

refs #999
This commit is contained in:
Tomoki Shirasawa
2018-01-23 14:31:04 +09:00
parent 1e9f9d9809
commit 2f2b3cdc6f
3 changed files with 85 additions and 24 deletions

View File

@ -849,6 +849,7 @@ void setup_x86_ap(void (*next_func)(void))
void arch_show_interrupt_context(const void *reg); void arch_show_interrupt_context(const void *reg);
void set_signal(int sig, void *regs, struct siginfo *info); void set_signal(int sig, void *regs, struct siginfo *info);
void check_signal(unsigned long, void *, int); void check_signal(unsigned long, void *, int);
void check_sig_pending();
extern void tlb_flush_handler(int vector); extern void tlb_flush_handler(int vector);
void __show_stack(uintptr_t *sp) { void __show_stack(uintptr_t *sp) {
@ -870,6 +871,18 @@ void show_context_stack(uintptr_t *rbp) {
return; 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) void handle_interrupt(int vector, struct x86_user_context *regs)
{ {
struct ihk_mc_interrupt_handler *h; 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)){ interrupt_exit(regs);
cpu_enable_interrupt();
check_signal(0, regs, 0);
check_need_resched();
}
set_cputime(0); set_cputime(0);
--v->in_interrupt; --v->in_interrupt;
@ -1012,11 +1021,7 @@ void gpe_handler(struct x86_user_context *regs)
panic("gpe_handler"); panic("gpe_handler");
} }
set_signal(SIGSEGV, regs, NULL); set_signal(SIGSEGV, regs, NULL);
if(interrupt_from_user(regs)){ interrupt_exit(regs);
cpu_enable_interrupt();
check_signal(0, regs, 0);
check_need_resched();
}
set_cputime(0); set_cputime(0);
panic("GPF"); panic("GPF");
} }
@ -1045,11 +1050,7 @@ void debug_handler(struct x86_user_context *regs)
memset(&info, '\0', sizeof info); memset(&info, '\0', sizeof info);
info.si_code = si_code; info.si_code = si_code;
set_signal(SIGTRAP, regs, &info); set_signal(SIGTRAP, regs, &info);
if(interrupt_from_user(regs)){ interrupt_exit(regs);
cpu_enable_interrupt();
check_signal(0, regs, 0);
check_need_resched();
}
set_cputime(0); set_cputime(0);
} }
@ -1067,11 +1068,7 @@ void int3_handler(struct x86_user_context *regs)
memset(&info, '\0', sizeof info); memset(&info, '\0', sizeof info);
info.si_code = TRAP_BRKPT; info.si_code = TRAP_BRKPT;
set_signal(SIGTRAP, regs, &info); set_signal(SIGTRAP, regs, &info);
if(interrupt_from_user(regs)){ interrupt_exit(regs);
cpu_enable_interrupt();
check_signal(0, regs, 0);
check_need_resched();
}
set_cputime(0); set_cputime(0);
} }

View File

@ -32,7 +32,6 @@
#include <limits.h> #include <limits.h>
#include <syscall.h> #include <syscall.h>
void terminate(int, int);
extern long do_sigaction(int sig, struct k_sigaction *act, struct k_sigaction *oact); extern long do_sigaction(int sig, struct k_sigaction *act, struct k_sigaction *oact);
long syscall(int num, ihk_mc_user_context_t *ctx); long syscall(int num, ihk_mc_user_context_t *ctx);
void set_signal(int sig, void *regs0, siginfo_t *info); 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 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 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 interrupt_syscall(struct thread *, int sig);
extern void terminate(int, int);
extern int num_processors; extern int num_processors;
#define RFLAGS_MASK (RFLAGS_CF | RFLAGS_PF | RFLAGS_AF | RFLAGS_ZF | \ #define RFLAGS_MASK (RFLAGS_CF | RFLAGS_PF | RFLAGS_AF | RFLAGS_ZF | \
@ -1054,6 +1054,72 @@ out:
return; 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 unsigned long
do_kill(struct thread *thread, int pid, int tid, int sig, siginfo_t *info, do_kill(struct thread *thread, int pid, int tid, int sig, siginfo_t *info,
int ptracecont) int ptracecont)
@ -1308,9 +1374,6 @@ done:
ihk_mc_interrupt_cpu(get_x86_cpu_local_variable(tthread->cpu_id)->apic_id, 0xd0); 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 (status != PS_RUNNING) {
if(sig == SIGKILL){ if(sig == SIGKILL){
/* Wake up the target only when stopped by ptrace-reporting */ /* Wake up the target only when stopped by ptrace-reporting */

View File

@ -437,6 +437,7 @@ struct sig_pending {
sigset_t sigmask; sigset_t sigmask;
siginfo_t info; siginfo_t info;
int ptracecont; int ptracecont;
int interrupted;
}; };
typedef void pgio_func_t(void *arg); typedef void pgio_func_t(void *arg);