aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2006-08-07 22:47:01 -0400
committerRalf Baechle <ralf@linux-mips.org>2006-09-27 08:37:33 -0400
commit13fdd31abec5f48cf97693bd14d2e11e0779b4ca (patch)
tree66eff81e11545ef5259812a1a83dd75a8d520567
parent847b9dfccad7dd34b2e44b1c6ceeb1c4cb88084a (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>
-rw-r--r--arch/mips/kernel/irixsig.c1
-rw-r--r--arch/mips/kernel/signal.c2
-rw-r--r--arch/mips/kernel/signal32.c1
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 = &current->blocked; 430 oldset = &current->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 /*