diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2006-08-07 22:47:01 -0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2006-09-27 08:37:33 -0400 |
commit | 13fdd31abec5f48cf97693bd14d2e11e0779b4ca (patch) | |
tree | 66eff81e11545ef5259812a1a83dd75a8d520567 /arch/mips/kernel | |
parent | 847b9dfccad7dd34b2e44b1c6ceeb1c4cb88084a (diff) |
[MIPS] Avoid double signal restarting.
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>
Diffstat (limited to 'arch/mips/kernel')
-rw-r--r-- | arch/mips/kernel/irixsig.c | 1 | ||||
-rw-r--r-- | arch/mips/kernel/signal.c | 2 | ||||
-rw-r--r-- | arch/mips/kernel/signal32.c | 1 |
3 files changed, 3 insertions, 1 deletions
diff --git a/arch/mips/kernel/irixsig.c b/arch/mips/kernel/irixsig.c index 052ea15f1e80..719364752e77 100644 --- a/arch/mips/kernel/irixsig.c +++ b/arch/mips/kernel/irixsig.c | |||
@@ -224,6 +224,7 @@ void do_irix_signal(struct pt_regs *regs) | |||
224 | regs->regs[7] = regs->regs[26]; | 224 | regs->regs[7] = regs->regs[26]; |
225 | regs->cp0_epc -= 4; | 225 | regs->cp0_epc -= 4; |
226 | } | 226 | } |
227 | regs->regs[0] = 0; /* Don't deal with this again. */ | ||
227 | } | 228 | } |
228 | 229 | ||
229 | /* | 230 | /* |
diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c index 56bf42911336..b9d358e05214 100644 --- a/arch/mips/kernel/signal.c +++ b/arch/mips/kernel/signal.c | |||
@@ -429,7 +429,6 @@ void do_signal(struct pt_regs *regs) | |||
429 | else | 429 | else |
430 | oldset = ¤t->blocked; | 430 | oldset = ¤t->blocked; |
431 | 431 | ||
432 | |||
433 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); | 432 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); |
434 | if (signr > 0) { | 433 | if (signr > 0) { |
435 | /* Whee! Actually deliver the signal. */ | 434 | /* Whee! Actually deliver the signal. */ |
@@ -464,6 +463,7 @@ void do_signal(struct pt_regs *regs) | |||
464 | regs->regs[7] = regs->regs[26]; | 463 | regs->regs[7] = regs->regs[26]; |
465 | regs->cp0_epc -= 4; | 464 | regs->cp0_epc -= 4; |
466 | } | 465 | } |
466 | regs->regs[0] = 0; /* Don't deal with this again. */ | ||
467 | } | 467 | } |
468 | 468 | ||
469 | /* | 469 | /* |
diff --git a/arch/mips/kernel/signal32.c b/arch/mips/kernel/signal32.c index 282e85a7bae1..c86a5ddff050 100644 --- a/arch/mips/kernel/signal32.c +++ b/arch/mips/kernel/signal32.c | |||
@@ -854,6 +854,7 @@ void do_signal32(struct pt_regs *regs) | |||
854 | regs->regs[7] = regs->regs[26]; | 854 | regs->regs[7] = regs->regs[26]; |
855 | regs->cp0_epc -= 4; | 855 | regs->cp0_epc -= 4; |
856 | } | 856 | } |
857 | regs->regs[0] = 0; /* Don't deal with this again. */ | ||
857 | } | 858 | } |
858 | 859 | ||
859 | /* | 860 | /* |