[MIPS] Avoid double signal restarting.
authorRalf Baechle <ralf@linux-mips.org>
Tue, 8 Aug 2006 02:47:01 +0000 (03:47 +0100)
committerRalf Baechle <ralf@linux-mips.org>
Wed, 27 Sep 2006 12:37:33 +0000 (13:37 +0100)
In entry.S resume_userspace ... jal do_notify_resume form a loop through
which the kernel will iterate as long as work is pending.  If we
iterate through this loop more than once with no signal pending for at
least one but the last iteration we will take do the syscall restarting
multiple times resulting in a syscall return prior to the the syscall
instruction in userspace.  This may happen when debugging a multithreaded
program.

Debugging and original fix by Maciej; extended to other ABIs by me.

Signed-off-by: Maciej W. Rozycki <macro@mips.com>
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
arch/mips/kernel/irixsig.c
arch/mips/kernel/signal.c
arch/mips/kernel/signal32.c

index 052ea15f1e800ac8627d6aa4f68ca965ed8232fb..719364752e7758c3b936203951d4dcd8b5e2f149 100644 (file)
@@ -224,6 +224,7 @@ void do_irix_signal(struct pt_regs *regs)
                        regs->regs[7] = regs->regs[26];
                        regs->cp0_epc -= 4;
                }
+               regs->regs[0] = 0;      /* Don't deal with this again.  */
        }
 
        /*
index 56bf42911336b696bb3da697741bb5be992224b6..b9d358e052144bb501956da1afca37553ab58394 100644 (file)
@@ -429,7 +429,6 @@ void do_signal(struct pt_regs *regs)
        else
                oldset = &current->blocked;
 
-
        signr = get_signal_to_deliver(&info, &ka, regs, NULL);
        if (signr > 0) {
                /* Whee!  Actually deliver the signal.  */
@@ -464,6 +463,7 @@ void do_signal(struct pt_regs *regs)
                        regs->regs[7] = regs->regs[26];
                        regs->cp0_epc -= 4;
                }
+               regs->regs[0] = 0;      /* Don't deal with this again.  */
        }
 
        /*
index 282e85a7bae17bb399c104b382ad3f6405cc3b06..c86a5ddff050a78661eced6ca74a68b5358b5187 100644 (file)
@@ -854,6 +854,7 @@ void do_signal32(struct pt_regs *regs)
                        regs->regs[7] = regs->regs[26];
                        regs->cp0_epc -= 4;
                }
+               regs->regs[0] = 0;      /* Don't deal with this again.  */
        }
 
        /*