aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh
diff options
context:
space:
mode:
authorKaz Kojima <kkojima@rr.iij4u.or.jp>2007-06-17 21:08:20 -0400
committerPaul Mundt <lethal@linux-sh.org>2007-06-17 21:08:20 -0400
commit69a331470ff02561cf1898eeb152ccca9f22bf53 (patch)
treee097e9317f5c2e3e03125dfd1e232dfbcebd4a3a /arch/sh
parent188e1f81ba31af1b65a2f3611df4c670b092bbac (diff)
sh: Fix restartable syscall arg5 clobbering.
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>
Diffstat (limited to 'arch/sh')
-rw-r--r--arch/sh/kernel/signal.c6
1 files changed, 4 insertions, 2 deletions
diff --git a/arch/sh/kernel/signal.c b/arch/sh/kernel/signal.c
index b32c35a7c0a3..fdca038e4b91 100644
--- a/arch/sh/kernel/signal.c
+++ b/arch/sh/kernel/signal.c
@@ -481,7 +481,7 @@ give_sigsegv:
481 481
482static int 482static int
483handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, 483handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
484 sigset_t *oldset, struct pt_regs *regs) 484 sigset_t *oldset, struct pt_regs *regs, unsigned int save_r0)
485{ 485{
486 int ret; 486 int ret;
487 487
@@ -500,6 +500,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
500 } 500 }
501 /* fallthrough */ 501 /* fallthrough */
502 case -ERESTARTNOINTR: 502 case -ERESTARTNOINTR:
503 regs->regs[0] = save_r0;
503 regs->pc -= instruction_size( 504 regs->pc -= instruction_size(
504 ctrl_inw(regs->pc - 4)); 505 ctrl_inw(regs->pc - 4));
505 break; 506 break;
@@ -583,7 +584,8 @@ static void do_signal(struct pt_regs *regs, unsigned int save_r0)
583 signr = get_signal_to_deliver(&info, &ka, regs, NULL); 584 signr = get_signal_to_deliver(&info, &ka, regs, NULL);
584 if (signr > 0) { 585 if (signr > 0) {
585 /* Whee! Actually deliver the signal. */ 586 /* Whee! Actually deliver the signal. */
586 if (handle_signal(signr, &ka, &info, oldset, regs) == 0) { 587 if (handle_signal(signr, &ka, &info, oldset, regs, save_r0)
588 == 0) {
587 /* a signal was successfully delivered; the saved 589 /* a signal was successfully delivered; the saved
588 * sigmask will have been stored in the signal frame, 590 * sigmask will have been stored in the signal frame,
589 * and will be restored by sigreturn, so we can simply 591 * and will be restored by sigreturn, so we can simply