aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/kernel/irixsig.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/kernel/irixsig.c')
-rw-r--r--arch/mips/kernel/irixsig.c63
1 files changed, 44 insertions, 19 deletions
diff --git a/arch/mips/kernel/irixsig.c b/arch/mips/kernel/irixsig.c
index 676e868d26fb..2132485caa74 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,19 +186,28 @@ 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 (try_to_freeze()) 191 if (test_thread_flag(TIF_RESTORE_SIGMASK))
190 goto no_signal; 192 oldset = &current->saved_sigmask;
191 193 else
192 if (!oldset)
193 oldset = &current->blocked; 194 oldset = &current->blocked;
194 195
195 signr = get_signal_to_deliver(&info, &ka, regs, NULL); 196 signr = get_signal_to_deliver(&info, &ka, regs, NULL);
196 if (signr > 0) 197 if (signr > 0) {
197 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 }
198 210
199no_signal:
200 /* 211 /*
201 * Who's code doesn't conform to the restartable syscall convention 212 * Who's code doesn't conform to the restartable syscall convention
202 * dies here!!! The li instruction, a single machine instruction, 213 * dies here!!! The li instruction, a single machine instruction,
@@ -208,8 +219,22 @@ no_signal:
208 regs->regs[2] == ERESTARTNOINTR) { 219 regs->regs[2] == ERESTARTNOINTR) {
209 regs->cp0_epc -= 8; 220 regs->cp0_epc -= 8;
210 } 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 regs->regs[0] = 0; /* Don't deal with this again. */
228 }
229
230 /*
231 * If there's no signal to deliver, we just put the saved sigmask
232 * back
233 */
234 if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
235 clear_thread_flag(TIF_RESTORE_SIGMASK);
236 sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
211 } 237 }
212 return 0;
213} 238}
214 239
215asmlinkage void 240asmlinkage void
@@ -298,6 +323,9 @@ struct sigact_irix5 {
298 int _unused0[2]; 323 int _unused0[2];
299}; 324};
300 325
326#define SIG_SETMASK32 256 /* Goodie from SGI for BSD compatibility:
327 set only the low 32 bit of the sigset. */
328
301#ifdef DEBUG_SIG 329#ifdef DEBUG_SIG
302static inline void dump_sigact_irix5(struct sigact_irix5 *p) 330static inline void dump_sigact_irix5(struct sigact_irix5 *p)
303{ 331{
@@ -413,7 +441,7 @@ asmlinkage int irix_sigprocmask(int how, irix_sigset_t __user *new,
413 441
414asmlinkage int irix_sigsuspend(struct pt_regs *regs) 442asmlinkage int irix_sigsuspend(struct pt_regs *regs)
415{ 443{
416 sigset_t saveset, newset; 444 sigset_t newset;
417 sigset_t __user *uset; 445 sigset_t __user *uset;
418 446
419 uset = (sigset_t __user *) regs->regs[4]; 447 uset = (sigset_t __user *) regs->regs[4];
@@ -422,18 +450,15 @@ asmlinkage int irix_sigsuspend(struct pt_regs *regs)
422 sigdelsetmask(&newset, ~_BLOCKABLE); 450 sigdelsetmask(&newset, ~_BLOCKABLE);
423 451
424 spin_lock_irq(&current->sighand->siglock); 452 spin_lock_irq(&current->sighand->siglock);
425 saveset = current->blocked; 453 current->saved_sigmask = current->blocked;
426 current->blocked = newset; 454 current->blocked = newset;
427 recalc_sigpending(); 455 recalc_sigpending();
428 spin_unlock_irq(&current->sighand->siglock); 456 spin_unlock_irq(&current->sighand->siglock);
429 457
430 regs->regs[2] = -EINTR; 458 current->state = TASK_INTERRUPTIBLE;
431 while (1) { 459 schedule();
432 current->state = TASK_INTERRUPTIBLE; 460 set_thread_flag(TIF_RESTORE_SIGMASK);
433 schedule(); 461 return -ERESTARTNOHAND;
434 if (do_irix_signal(&saveset, regs))
435 return -EINTR;
436 }
437} 462}
438 463
439/* hate hate hate... */ 464/* hate hate hate... */