aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips')
-rw-r--r--arch/mips/kernel/irixsig.c55
1 files changed, 40 insertions, 15 deletions
diff --git a/arch/mips/kernel/irixsig.c b/arch/mips/kernel/irixsig.c
index e6f40609ba6a..052ea15f1e80 100644
--- a/arch/mips/kernel/irixsig.c
+++ b/arch/mips/kernel/irixsig.c
@@ -17,6 +17,7 @@
17 17
18#include <asm/ptrace.h> 18#include <asm/ptrace.h>
19#include <asm/uaccess.h> 19#include <asm/uaccess.h>
20#include <asm/unistd.h>
20 21
21#undef DEBUG_SIG 22#undef DEBUG_SIG
22 23
@@ -172,11 +173,12 @@ static inline int handle_signal(unsigned long sig, siginfo_t *info,
172 return ret; 173 return ret;
173} 174}
174 175
175asmlinkage int do_irix_signal(sigset_t *oldset, struct pt_regs *regs) 176void do_irix_signal(struct pt_regs *regs)
176{ 177{
177 struct k_sigaction ka; 178 struct k_sigaction ka;
178 siginfo_t info; 179 siginfo_t info;
179 int signr; 180 int signr;
181 sigset_t *oldset;
180 182
181 /* 183 /*
182 * We want the common case to go fast, which is why we may in certain 184 * We want the common case to go fast, which is why we may in certain
@@ -184,14 +186,27 @@ asmlinkage int do_irix_signal(sigset_t *oldset, struct pt_regs *regs)
184 * if so. 186 * if so.
185 */ 187 */
186 if (!user_mode(regs)) 188 if (!user_mode(regs))
187 return 1; 189 return;
188 190
189 if (!oldset) 191 if (test_thread_flag(TIF_RESTORE_SIGMASK))
192 oldset = &current->saved_sigmask;
193 else
190 oldset = &current->blocked; 194 oldset = &current->blocked;
191 195
192 signr = get_signal_to_deliver(&info, &ka, regs, NULL); 196 signr = get_signal_to_deliver(&info, &ka, regs, NULL);
193 if (signr > 0) 197 if (signr > 0) {
194 return handle_signal(signr, &info, &ka, oldset, regs); 198 /* Whee! Actually deliver the signal. */
199 if (handle_signal(signr, &info, &ka, oldset, regs) == 0) {
200 /* a signal was successfully delivered; the saved
201 * sigmask will have been stored in the signal frame,
202 * and will be restored by sigreturn, so we can simply
203 * clear the TIF_RESTORE_SIGMASK flag */
204 if (test_thread_flag(TIF_RESTORE_SIGMASK))
205 clear_thread_flag(TIF_RESTORE_SIGMASK);
206 }
207
208 return;
209 }
195 210
196 /* 211 /*
197 * Who's code doesn't conform to the restartable syscall convention 212 * Who's code doesn't conform to the restartable syscall convention
@@ -204,8 +219,21 @@ asmlinkage int do_irix_signal(sigset_t *oldset, struct pt_regs *regs)
204 regs->regs[2] == ERESTARTNOINTR) { 219 regs->regs[2] == ERESTARTNOINTR) {
205 regs->cp0_epc -= 8; 220 regs->cp0_epc -= 8;
206 } 221 }
222 if (regs->regs[2] == ERESTART_RESTARTBLOCK) {
223 regs->regs[2] = __NR_restart_syscall;
224 regs->regs[7] = regs->regs[26];
225 regs->cp0_epc -= 4;
226 }
227 }
228
229 /*
230 * If there's no signal to deliver, we just put the saved sigmask
231 * back
232 */
233 if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
234 clear_thread_flag(TIF_RESTORE_SIGMASK);
235 sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
207 } 236 }
208 return 0;
209} 237}
210 238
211asmlinkage void 239asmlinkage void
@@ -409,7 +437,7 @@ asmlinkage int irix_sigprocmask(int how, irix_sigset_t __user *new,
409 437
410asmlinkage int irix_sigsuspend(struct pt_regs *regs) 438asmlinkage int irix_sigsuspend(struct pt_regs *regs)
411{ 439{
412 sigset_t saveset, newset; 440 sigset_t newset;
413 sigset_t __user *uset; 441 sigset_t __user *uset;
414 442
415 uset = (sigset_t __user *) regs->regs[4]; 443 uset = (sigset_t __user *) regs->regs[4];
@@ -418,18 +446,15 @@ asmlinkage int irix_sigsuspend(struct pt_regs *regs)
418 sigdelsetmask(&newset, ~_BLOCKABLE); 446 sigdelsetmask(&newset, ~_BLOCKABLE);
419 447
420 spin_lock_irq(&current->sighand->siglock); 448 spin_lock_irq(&current->sighand->siglock);
421 saveset = current->blocked; 449 current->saved_sigmask = current->blocked;
422 current->blocked = newset; 450 current->blocked = newset;
423 recalc_sigpending(); 451 recalc_sigpending();
424 spin_unlock_irq(&current->sighand->siglock); 452 spin_unlock_irq(&current->sighand->siglock);
425 453
426 regs->regs[2] = -EINTR; 454 current->state = TASK_INTERRUPTIBLE;
427 while (1) { 455 schedule();
428 current->state = TASK_INTERRUPTIBLE; 456 set_thread_flag(TIF_RESTORE_SIGMASK);
429 schedule(); 457 return -ERESTARTNOHAND;
430 if (do_irix_signal(&saveset, regs))
431 return -EINTR;
432 }
433} 458}
434 459
435/* hate hate hate... */ 460/* hate hate hate... */