|
@@ -17,6 +17,7 @@
|
|
|
|
|
|
#include <asm/ptrace.h>
|
|
#include <asm/ptrace.h>
|
|
#include <asm/uaccess.h>
|
|
#include <asm/uaccess.h>
|
|
|
|
+#include <asm/unistd.h>
|
|
|
|
|
|
#undef DEBUG_SIG
|
|
#undef DEBUG_SIG
|
|
|
|
|
|
@@ -172,11 +173,12 @@ static inline int handle_signal(unsigned long sig, siginfo_t *info,
|
|
return ret;
|
|
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;
|
|
struct k_sigaction ka;
|
|
siginfo_t info;
|
|
siginfo_t info;
|
|
int signr;
|
|
int signr;
|
|
|
|
+ sigset_t *oldset;
|
|
|
|
|
|
/*
|
|
/*
|
|
* We want the common case to go fast, which is why we may in certain
|
|
* 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)
|
|
* if so.
|
|
* if so.
|
|
*/
|
|
*/
|
|
if (!user_mode(regs))
|
|
if (!user_mode(regs))
|
|
- return 1;
|
|
|
|
|
|
+ return;
|
|
|
|
|
|
- if (!oldset)
|
|
|
|
|
|
+ if (test_thread_flag(TIF_RESTORE_SIGMASK))
|
|
|
|
+ oldset = ¤t->saved_sigmask;
|
|
|
|
+ else
|
|
oldset = ¤t->blocked;
|
|
oldset = ¤t->blocked;
|
|
|
|
|
|
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
|
|
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;
|
|
|
|
+ }
|
|
|
|
|
|
/*
|
|
/*
|
|
* Who's code doesn't conform to the restartable syscall convention
|
|
* 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)
|
|
regs->regs[2] == ERESTARTNOINTR) {
|
|
regs->regs[2] == ERESTARTNOINTR) {
|
|
regs->cp0_epc -= 8;
|
|
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;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * 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
|
|
asmlinkage void
|
|
@@ -409,7 +437,7 @@ asmlinkage int irix_sigprocmask(int how, irix_sigset_t __user *new,
|
|
|
|
|
|
asmlinkage int irix_sigsuspend(struct pt_regs *regs)
|
|
asmlinkage int irix_sigsuspend(struct pt_regs *regs)
|
|
{
|
|
{
|
|
- sigset_t saveset, newset;
|
|
|
|
|
|
+ sigset_t newset;
|
|
sigset_t __user *uset;
|
|
sigset_t __user *uset;
|
|
|
|
|
|
uset = (sigset_t __user *) regs->regs[4];
|
|
uset = (sigset_t __user *) regs->regs[4];
|
|
@@ -418,18 +446,15 @@ asmlinkage int irix_sigsuspend(struct pt_regs *regs)
|
|
sigdelsetmask(&newset, ~_BLOCKABLE);
|
|
sigdelsetmask(&newset, ~_BLOCKABLE);
|
|
|
|
|
|
spin_lock_irq(¤t->sighand->siglock);
|
|
spin_lock_irq(¤t->sighand->siglock);
|
|
- saveset = current->blocked;
|
|
|
|
|
|
+ current->saved_sigmask = current->blocked;
|
|
current->blocked = newset;
|
|
current->blocked = newset;
|
|
recalc_sigpending();
|
|
recalc_sigpending();
|
|
spin_unlock_irq(¤t->sighand->siglock);
|
|
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... */
|
|
/* hate hate hate... */
|