]> err.no Git - linux-2.6/commitdiff
sh: Fix restartable syscall arg5 clobbering.
authorKaz Kojima <kkojima@rr.iij4u.or.jp>
Mon, 18 Jun 2007 01:08:20 +0000 (10:08 +0900)
committerPaul Mundt <lethal@linux-sh.org>
Mon, 18 Jun 2007 01:08:20 +0000 (10:08 +0900)
We use R0 as the 5th argument of syscall.  When the syscall restarts
after signal handling, we should restore the old value of R0.
The attached patch does it. Without this patch, I've experienced random
failures in the situation which signals are issued frequently.

Signed-off-by: Kaz Kojima <kkojima@rr.iij4u.or.jp>
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
arch/sh/kernel/signal.c

index b32c35a7c0a3e42512765962e8b71c0c1096a5c8..fdca038e4b912df928b3ec69410daab7f124e36b 100644 (file)
@@ -481,7 +481,7 @@ give_sigsegv:
 
 static int
 handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
-             sigset_t *oldset, struct pt_regs *regs)
+             sigset_t *oldset, struct pt_regs *regs, unsigned int save_r0)
 {
        int ret;
 
@@ -500,6 +500,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
                                }
                        /* fallthrough */
                        case -ERESTARTNOINTR:
+                               regs->regs[0] = save_r0;
                                regs->pc -= instruction_size(
                                                ctrl_inw(regs->pc - 4));
                                break;
@@ -583,7 +584,8 @@ static void do_signal(struct pt_regs *regs, unsigned int save_r0)
        signr = get_signal_to_deliver(&info, &ka, regs, NULL);
        if (signr > 0) {
                /* Whee!  Actually deliver the signal.  */
-               if (handle_signal(signr, &ka, &info, oldset, regs) == 0) {
+               if (handle_signal(signr, &ka, &info, oldset, regs, save_r0)
+                   == 0) {
                        /* a signal was successfully delivered; the saved
                         * sigmask will have been stored in the signal frame,
                         * and will be restored by sigreturn, so we can simply