X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Fmips%2Fkernel%2Firixsig.c;h=2132485caa744bbeddca7b4af11070b2e8c8591f;hb=refs%2Fheads%2Fvserver;hp=08273a2a501d5ca1b837a80bbf1826d269b90113;hpb=76828883507a47dae78837ab5dec5a5b4513c667;p=linux-2.6.git diff --git a/arch/mips/kernel/irixsig.c b/arch/mips/kernel/irixsig.c index 08273a2a5..2132485ca 100644 --- a/arch/mips/kernel/irixsig.c +++ b/arch/mips/kernel/irixsig.c @@ -13,9 +13,11 @@ #include #include #include +#include #include #include +#include #undef DEBUG_SIG @@ -171,11 +173,12 @@ static inline int handle_signal(unsigned long sig, siginfo_t *info, return ret; } -asmlinkage int do_irix_signal(sigset_t *oldset, struct pt_regs *regs) +void do_irix_signal(struct pt_regs *regs) { struct k_sigaction ka; siginfo_t info; int signr; + sigset_t *oldset; /* * We want the common case to go fast, which is why we may in certain @@ -183,19 +186,28 @@ asmlinkage int do_irix_signal(sigset_t *oldset, struct pt_regs *regs) * if so. */ if (!user_mode(regs)) - return 1; + return; - if (try_to_freeze()) - goto no_signal; - - if (!oldset) + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + oldset = ¤t->saved_sigmask; + else oldset = ¤t->blocked; signr = get_signal_to_deliver(&info, &ka, regs, NULL); - if (signr > 0) - return handle_signal(signr, &info, &ka, oldset, regs); + if (signr > 0) { + /* Whee! Actually deliver the signal. */ + if (handle_signal(signr, &info, &ka, oldset, regs) == 0) { + /* a signal was successfully delivered; the saved + * sigmask will have been stored in the signal frame, + * and will be restored by sigreturn, so we can simply + * clear the TIF_RESTORE_SIGMASK flag */ + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + clear_thread_flag(TIF_RESTORE_SIGMASK); + } + + return; + } -no_signal: /* * Who's code doesn't conform to the restartable syscall convention * dies here!!! The li instruction, a single machine instruction, @@ -207,8 +219,22 @@ no_signal: regs->regs[2] == ERESTARTNOINTR) { regs->cp0_epc -= 8; } + if (regs->regs[2] == ERESTART_RESTARTBLOCK) { + regs->regs[2] = __NR_restart_syscall; + regs->regs[7] = regs->regs[26]; + regs->cp0_epc -= 4; + } + regs->regs[0] = 0; /* Don't deal with this again. */ + } + + /* + * If there's no signal to deliver, we just put the saved sigmask + * back + */ + if (test_thread_flag(TIF_RESTORE_SIGMASK)) { + clear_thread_flag(TIF_RESTORE_SIGMASK); + sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); } - return 0; } asmlinkage void @@ -260,7 +286,7 @@ irix_sigreturn(struct pt_regs *regs) for(i = 0; i < 32; i++) error |= __get_user(fregs[i], &context->fpregs[i]); - error |= __get_user(current->thread.fpu.hard.fcr31, &context->fpcsr); + error |= __get_user(current->thread.fpu.fcr31, &context->fpcsr); } /* XXX do sigstack crapola here... XXX */ @@ -297,6 +323,9 @@ struct sigact_irix5 { int _unused0[2]; }; +#define SIG_SETMASK32 256 /* Goodie from SGI for BSD compatibility: + set only the low 32 bit of the sigset. */ + #ifdef DEBUG_SIG static inline void dump_sigact_irix5(struct sigact_irix5 *p) { @@ -412,7 +441,7 @@ asmlinkage int irix_sigprocmask(int how, irix_sigset_t __user *new, asmlinkage int irix_sigsuspend(struct pt_regs *regs) { - sigset_t saveset, newset; + sigset_t newset; sigset_t __user *uset; uset = (sigset_t __user *) regs->regs[4]; @@ -421,18 +450,15 @@ asmlinkage int irix_sigsuspend(struct pt_regs *regs) sigdelsetmask(&newset, ~_BLOCKABLE); spin_lock_irq(¤t->sighand->siglock); - saveset = current->blocked; + current->saved_sigmask = current->blocked; current->blocked = newset; recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); - regs->regs[2] = -EINTR; - while (1) { - current->state = TASK_INTERRUPTIBLE; - schedule(); - if (do_irix_signal(&saveset, regs)) - return -EINTR; - } + current->state = TASK_INTERRUPTIBLE; + schedule(); + set_thread_flag(TIF_RESTORE_SIGMASK); + return -ERESTARTNOHAND; } /* hate hate hate... */ @@ -540,8 +566,6 @@ out: #define IRIX_P_PGID 2 #define IRIX_P_ALL 7 -extern int getrusage(struct task_struct *, int, struct rusage __user *); - #define W_EXITED 1 #define W_TRAPPED 2 #define W_STOPPED 4 @@ -603,7 +627,7 @@ repeat: /* move to end of parent's list to avoid starvation */ write_lock_irq(&tasklist_lock); remove_parent(p); - add_parent(p, p->parent); + add_parent(p); write_unlock_irq(&tasklist_lock); retval = ru ? getrusage(p, RUSAGE_BOTH, ru) : 0; if (retval) @@ -643,7 +667,7 @@ repeat: write_lock_irq(&tasklist_lock); remove_parent(p); p->parent = p->real_parent; - add_parent(p, p->parent); + add_parent(p); do_notify_parent(p, SIGCHLD); write_unlock_irq(&tasklist_lock); } else