support SA_RESTART flag and restart syscall

This commit is contained in:
Tomoki Shirasawa
2015-07-16 16:33:14 +09:00
parent 1bc84d3feb
commit 1ff4cf68c2
5 changed files with 85 additions and 22 deletions

View File

@ -604,7 +604,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 rc, void *regs);
void check_signal(unsigned long, void *, int);
extern void tlb_flush_handler(int vector);
void handle_interrupt(int vector, struct x86_user_context *regs)
@ -678,7 +678,7 @@ void handle_interrupt(int vector, struct x86_user_context *regs)
}
}
check_signal(0, regs);
check_signal(0, regs, 0);
check_need_resched();
}
@ -691,7 +691,7 @@ void gpe_handler(struct x86_user_context *regs)
panic("gpe_handler");
}
set_signal(SIGSEGV, regs, NULL);
check_signal(0, regs);
check_signal(0, regs, 0);
check_need_resched();
// panic("GPF");
}
@ -719,7 +719,7 @@ void debug_handler(struct x86_user_context *regs)
memset(&info, '\0', sizeof info);
info.si_code = si_code;
set_signal(SIGTRAP, regs, &info);
check_signal(0, regs);
check_signal(0, regs, 0);
check_need_resched();
}
@ -736,7 +736,7 @@ void int3_handler(struct x86_user_context *regs)
memset(&info, '\0', sizeof info);
info.si_code = TRAP_BRKPT;
set_signal(SIGTRAP, regs, &info);
check_signal(0, regs);
check_signal(0, regs, 0);
check_need_resched();
}

View File

@ -26,6 +26,7 @@ SYSCALL_DELEGATED(2, open)
SYSCALL_HANDLED(3, close)
SYSCALL_DELEGATED(4, stat)
SYSCALL_DELEGATED(5, fstat)
SYSCALL_DELEGATED(7, poll)
SYSCALL_DELEGATED(8, lseek)
SYSCALL_HANDLED(9, mmap)
SYSCALL_HANDLED(10, mprotect)
@ -39,6 +40,7 @@ SYSCALL_DELEGATED(17, pread64)
SYSCALL_DELEGATED(18, pwrite64)
SYSCALL_DELEGATED(20, writev)
SYSCALL_DELEGATED(21, access)
SYSCALL_DELEGATED(23, select)
SYSCALL_HANDLED(24, sched_yield)
SYSCALL_HANDLED(25, mremap)
SYSCALL_HANDLED(26, msync)
@ -48,6 +50,7 @@ SYSCALL_HANDLED(29, shmget)
SYSCALL_HANDLED(30, shmat)
SYSCALL_HANDLED(31, shmctl)
SYSCALL_HANDLED(34, pause)
SYSCALL_DELEGATED(35, nanosleep)
SYSCALL_HANDLED(39, getpid)
SYSCALL_HANDLED(56, clone)
SYSCALL_DELEGATED(57, fork)
@ -57,7 +60,10 @@ SYSCALL_HANDLED(60, exit)
SYSCALL_HANDLED(61, wait4)
SYSCALL_HANDLED(62, kill)
SYSCALL_DELEGATED(63, uname)
SYSCALL_DELEGATED(65, semop)
SYSCALL_HANDLED(67, shmdt)
SYSCALL_DELEGATED(69, msgsnd)
SYSCALL_DELEGATED(70, msgrcv)
SYSCALL_DELEGATED(72, fcntl)
SYSCALL_DELEGATED(79, getcwd)
SYSCALL_DELEGATED(89, readlink)
@ -104,18 +110,25 @@ SYSCALL_DELEGATED(201, time)
SYSCALL_HANDLED(202, futex)
SYSCALL_HANDLED(203, sched_setaffinity)
SYSCALL_HANDLED(204, sched_getaffinity)
SYSCALL_DELEGATED(208, io_getevents)
SYSCALL_HANDLED(216, remap_file_pages)
SYSCALL_DELEGATED(217, getdents64)
SYSCALL_HANDLED(218, set_tid_address)
SYSCALL_DELEGATED(220, semtimedop)
SYSCALL_DELEGATED(230, clock_nanosleep)
SYSCALL_HANDLED(231, exit_group)
SYSCALL_DELEGATED(232, epoll_wait)
SYSCALL_HANDLED(234, tgkill)
SYSCALL_HANDLED(237, mbind)
SYSCALL_HANDLED(238, set_mempolicy)
SYSCALL_HANDLED(239, get_mempolicy)
SYSCALL_HANDLED(247, waitid)
SYSCALL_HANDLED(256, migrate_pages)
SYSCALL_DELEGATED(270, pselect6)
SYSCALL_DELEGATED(271, ppoll)
SYSCALL_HANDLED(273, set_robust_list)
SYSCALL_HANDLED(279, move_pages)
SYSCALL_DELEGATED(281, epoll_pwait)
SYSCALL_HANDLED(282, signalfd)
SYSCALL_HANDLED(289, signalfd4)
#ifdef DCFA_KMOD

View File

@ -30,6 +30,7 @@ int copy_from_user(void *dst, const void *src, size_t siz);
int copy_to_user(void *dst, const void *src, size_t siz);
int write_process_vm(struct process_vm *vm, void *dst, const void *src, size_t siz);
long do_sigaction(int sig, struct k_sigaction *act, struct k_sigaction *oact);
long syscall(int num, ihk_mc_user_context_t *ctx);
extern void save_fp_regs(struct process *proc);
//#define DEBUG_PRINT_SC
@ -152,6 +153,8 @@ struct sigsp {
unsigned long sigrc;
unsigned long sigmask;
int ssflags;
int num;
int restart;
siginfo_t info;
};
@ -160,18 +163,19 @@ SYSCALL_DECLARE(rt_sigreturn)
struct process *proc = cpu_local_var(current);
struct x86_user_context *regs;
struct sigsp *sigsp;
long rc = -EFAULT;
asm("movq %%gs:132, %0" : "=r" (regs));
--regs;
sigsp = (struct sigsp *)regs->gpr.rsp;
if(copy_from_user(regs, &sigsp->regs, sizeof(struct x86_user_context)))
return -EFAULT;
proc->sigmask.__val[0] = sigsp->sigmask;
proc->sigstack.ss_flags = sigsp->ssflags;
if(copy_from_user(regs, &sigsp->regs, sizeof(struct x86_user_context)))
return rc;
copy_from_user(&rc, &sigsp->sigrc, sizeof(long));
return rc;
if(sigsp->restart){
return syscall(sigsp->num, (ihk_mc_user_context_t *)regs);
}
return sigsp->sigrc;
}
extern struct cpu_local_var *clv;
@ -495,9 +499,41 @@ void ptrace_report_signal(struct process *proc, int sig)
schedule();
dkprintf("ptrace_report_signal,wake up\n");
}
static int
isrestart(int num, unsigned long rc, int sig, int restart)
{
if(num == 0 || rc != -EINTR)
return 0;
switch(num){
case __NR_pause:
case __NR_rt_sigsuspend:
case __NR_rt_sigtimedwait:
// case __NR_rt_sigwaitinfo:
case __NR_epoll_wait:
case __NR_epoll_pwait:
case __NR_poll:
case __NR_ppoll:
case __NR_select:
case __NR_pselect6:
case __NR_msgrcv:
case __NR_msgsnd:
case __NR_semop:
case __NR_semtimedop:
case __NR_clock_nanosleep:
case __NR_nanosleep:
// case __NR_usleep:
case __NR_io_getevents:
return 0;
}
if(sig == SIGCHLD)
return 1;
if(restart)
return 1;
return 0;
}
void
do_signal(unsigned long rc, void *regs0, struct process *proc, struct sig_pending *pending)
do_signal(unsigned long rc, void *regs0, struct process *proc, struct sig_pending *pending, int num)
{
struct x86_user_context *regs = regs0;
struct k_sigaction *k;
@ -564,6 +600,10 @@ do_signal(unsigned long rc, void *regs0, struct process *proc, struct sig_pendin
}
sigsp->sigmask = mask;
sigsp->ssflags = ssflags;
sigsp->num = num;
sigsp->restart = isrestart(num, rc, sig, k->sa.sa_flags & SA_RESTART);
if(num != 0 && rc == -EINTR && sig == SIGCHLD)
sigsp->restart = 1;
memcpy(&sigsp->info, &pending->info, sizeof(siginfo_t));
usp = (unsigned long *)sigsp;
@ -697,6 +737,9 @@ getsigpending(struct process *proc, int delflag){
struct sig_pending *pending;
__sigset_t w;
int irqstate;
__sigset_t x;
int sig;
struct k_sigaction *k;
w = proc->sigmask.__val[0];
@ -705,11 +748,18 @@ getsigpending(struct process *proc, int delflag){
for(;;){
irqstate = ihk_mc_spinlock_lock(lock);
list_for_each_entry_safe(pending, next, head, list){
if(!(pending->sigmask.__val[0] & w)){
if(delflag)
list_del(&pending->list);
ihk_mc_spinlock_unlock(lock, irqstate);
return pending;
for(x = pending->sigmask.__val[0], sig = 0; x; sig++, x >>= 1);
k = proc->sighandler->action + sig - 1;
if(delflag ||
(sig != SIGCHLD && sig != SIGURG) ||
(k->sa.sa_handler != (void *)1 &&
k->sa.sa_handler != NULL)){
if(!(pending->sigmask.__val[0] & w)){
if(delflag)
list_del(&pending->list);
ihk_mc_spinlock_unlock(lock, irqstate);
return pending;
}
}
}
ihk_mc_spinlock_unlock(lock, irqstate);
@ -730,7 +780,7 @@ hassigpending(struct process *proc)
}
void
check_signal(unsigned long rc, void *regs0)
check_signal(unsigned long rc, void *regs0, int num)
{
struct x86_user_context *regs = regs0;
struct process *proc;
@ -770,7 +820,7 @@ check_signal(unsigned long rc, void *regs0)
return;
}
do_signal(rc, regs, proc, pending);
do_signal(rc, regs, proc, pending, num);
}
}

View File

@ -171,7 +171,7 @@ static struct ihk_mc_interrupt_handler query_free_mem_handler = {
};
void set_signal(int sig, void *regs, struct siginfo *info);
void check_signal(unsigned long rc, void *regs);
void check_signal(unsigned long, void *, int);
int gencore(struct process *, void *, struct coretable **, int *);
void freecore(struct coretable **);
@ -416,7 +416,7 @@ static void page_fault_handler(void *fault_addr, uint64_t reason, void *regs)
info._sifields._sigfault.si_addr = fault_addr;
set_signal(SIGSEGV, regs, &info);
}
check_signal(0, regs);
check_signal(0, regs, 0);
goto out;
}

View File

@ -94,7 +94,7 @@ static char *syscall_name[] MCKERNEL_UNUSED = {
#undef SYSCALL_DELEGATED
};
void check_signal(unsigned long rc, void *regs);
void check_signal(unsigned long, void *, int);
void do_signal(long rc, void *regs, struct process *proc, struct sig_pending *pending);
extern unsigned long do_kill(int pid, int tid, int sig, struct siginfo *info, int ptracecont);
extern struct sigpending *hassigpending(struct process *proc);
@ -6059,7 +6059,7 @@ long syscall(int num, ihk_mc_user_context_t *ctx)
l = syscall_generic_forwarding(num, ctx);
}
check_signal(l, NULL);
check_signal(l, NULL, num);
check_need_resched();
if (cpu_local_var(current)->ftn->ptrace) {