diff --git a/arch/x86_64/kernel/syscall.c b/arch/x86_64/kernel/syscall.c index a3ff105e..bd55b34f 100644 --- a/arch/x86_64/kernel/syscall.c +++ b/arch/x86_64/kernel/syscall.c @@ -32,6 +32,7 @@ #include #include +void terminate_mcexec(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); @@ -1116,7 +1117,15 @@ check_sig_pending() } if (found) { - interrupt_syscall(thread, 0); + if (sig != SIGCHLD && sig != SIGURG && + thread->sigcommon->action[sig - 1].sa.sa_handler == NULL) { + terminate_mcexec(0, sig); + } + else if (thread->sigcommon->action[sig - 1].sa.sa_handler && + thread->sigcommon->action[sig - 1].sa.sa_handler != + (void *)1) { + interrupt_syscall(thread, 0); + } } } diff --git a/kernel/include/process.h b/kernel/include/process.h index 210745f0..65474044 100644 --- a/kernel/include/process.h +++ b/kernel/include/process.h @@ -488,7 +488,7 @@ struct process { // V +---- | // PS_STOPPED -----+ // (PS_TRACED) - int exit_status; // only for zombie + unsigned long exit_status; // only for zombie /* Store exit_status for a group of threads when stopped by SIGSTOP. exit_status can't be used because values of exit_status of threads diff --git a/kernel/syscall.c b/kernel/syscall.c index d3c0f6f4..e1f6e3b8 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -957,6 +957,28 @@ SYSCALL_DECLARE(waitid) return 0; } +void terminate_mcexec(int rc, int sig) +{ + unsigned long old_exit_status; + unsigned long exit_status; + struct thread *mythread = cpu_local_var(current); + struct process *proc = mythread->proc; + struct syscall_request request IHK_DMA_ALIGN; + + if ((old_exit_status = proc->exit_status) & 0x0000000100000000L) + return; + exit_status = 0x0000000100000000L | ((rc & 0x00ff) << 8) | (sig & 0xff); + if (!__sync_bool_compare_and_swap(&proc->exit_status, + old_exit_status, exit_status)) + return; + if (!proc->nohost) { + request.number = __NR_exit_group; + request.args[0] = proc->exit_status; + proc->nohost = 1; + do_syscall(&request, ihk_mc_get_processor_id(), proc->pid); + } +} + void terminate(int rc, int sig) { struct resource_set *resource_set = cpu_local_var(resource_set); @@ -974,7 +996,6 @@ void terminate(int rc, int sig) int i; int n; int *ids = NULL; - struct syscall_request request IHK_DMA_ALIGN; int exit_status; // sync perf info @@ -996,8 +1017,11 @@ void terminate(int rc, int sig) return; } - exit_status = mythread->exit_status = ((rc & 0x00ff) << 8) | (sig & 0xff); + exit_status = ((rc & 0x00ff) << 8) | (sig & 0xff); + mythread->exit_status = exit_status; proc->status = PS_EXITED; + terminate_mcexec(rc, sig); + mcs_rwlock_writer_unlock_noirq(&proc->update_lock, &updatelock); mcs_rwlock_reader_unlock(&proc->threads_lock, &lock); @@ -1145,19 +1169,7 @@ void terminate(int rc, int sig) #endif // clean up memory - if (!proc->nohost) { - request.number = __NR_exit_group; - request.args[0] = exit_status; -#ifdef POSTK_DEBUG_TEMP_FIX_48 /* nohost flag missed fix */ - proc->nohost = 1; - do_syscall(&request, ihk_mc_get_processor_id(), proc->pid); -#else /* POSTK_DEBUG_TEMP_FIX_48 */ - do_syscall(&request, ihk_mc_get_processor_id(), proc->pid); - proc->nohost = 1; -#endif /* POSTK_DEBUG_TEMP_FIX_48 */ - } - proc->exit_status = exit_status; finalize_process(proc); preempt_disable();