diff options
Diffstat (limited to 'arch/sh64/kernel/signal.c')
-rw-r--r-- | arch/sh64/kernel/signal.c | 35 |
1 files changed, 30 insertions, 5 deletions
diff --git a/arch/sh64/kernel/signal.c b/arch/sh64/kernel/signal.c index 1666d3efb52..0bb4a8f9427 100644 --- a/arch/sh64/kernel/signal.c +++ b/arch/sh64/kernel/signal.c @@ -16,7 +16,6 @@ #include <linux/sched.h> #include <linux/mm.h> #include <linux/smp.h> -#include <linux/smp_lock.h> #include <linux/kernel.h> #include <linux/signal.h> #include <linux/errno.h> @@ -641,6 +640,7 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, if (regs->syscall_nr >= 0) { /* If so, check system call restarting.. */ switch (regs->regs[REG_RET]) { + case -ERESTART_RESTARTBLOCK: case -ERESTARTNOHAND: regs->regs[REG_RET] = -EINTR; break; @@ -699,7 +699,9 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset) if (try_to_freeze()) goto no_signal; - if (!oldset) + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + oldset = ¤t->saved_sigmask; + else if (!oldset) oldset = ¤t->blocked; signr = get_signal_to_deliver(&info, &ka, regs, 0); @@ -707,6 +709,15 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset) if (signr > 0) { /* Whee! Actually deliver the signal. */ handle_signal(signr, &info, &ka, oldset, regs); + + /* + * If a signal was successfully delivered, the saved sigmask + * is in its frame, and we can clear the TIF_RESTORE_SIGMASK + * flag. + */ + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + clear_thread_flag(TIF_RESTORE_SIGMASK); + return 1; } @@ -714,13 +725,27 @@ no_signal: /* Did we come from a system call? */ if (regs->syscall_nr >= 0) { /* Restart the system call - no handlers present */ - if (regs->regs[REG_RET] == -ERESTARTNOHAND || - regs->regs[REG_RET] == -ERESTARTSYS || - regs->regs[REG_RET] == -ERESTARTNOINTR) { + switch (regs->regs[REG_RET]) { + case -ERESTARTNOHAND: + case -ERESTARTSYS: + case -ERESTARTNOINTR: /* Decode Syscall # */ regs->regs[REG_RET] = regs->syscall_nr; regs->pc -= 4; + break; + + case -ERESTART_RESTARTBLOCK: + regs->regs[REG_RET] = __NR_restart_syscall; + regs->pc -= 4; + break; } } + + /* No signal to deliver -- put the saved sigmask back */ + if (test_thread_flag(TIF_RESTORE_SIGMASK)) { + clear_thread_flag(TIF_RESTORE_SIGMASK); + sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); + } + return 0; } |