* Atomically swap in the new signal mask, and wait for a signal.
*/
asmlinkage int
-do_sigsuspend(old_sigset_t mask, struct pt_regs *reg, struct switch_stack *sw)
+do_sigsuspend(old_sigset_t mask, struct pt_regs *regs, struct switch_stack *sw)
{
sigset_t oldset;
recalc_sigpending();
spin_unlock_irq(¤t->sighand->siglock);
+ /* Indicate EINTR on return from any possible signal handler,
+ which will not come back through here, but via sigreturn. */
+ regs->r0 = EINTR;
+ regs->r19 = 1;
+
while (1) {
current->state = TASK_INTERRUPTIBLE;
schedule();
- if (do_signal(&oldset, reg, sw, 0, 0))
+ if (do_signal(&oldset, regs, sw, 0, 0))
return -EINTR;
}
}
asmlinkage int
do_rt_sigsuspend(sigset_t __user *uset, size_t sigsetsize,
- struct pt_regs *reg, struct switch_stack *sw)
+ struct pt_regs *regs, struct switch_stack *sw)
{
sigset_t oldset, set;
recalc_sigpending();
spin_unlock_irq(¤t->sighand->siglock);
+ /* Indicate EINTR on return from any possible signal handler,
+ which will not come back through here, but via sigreturn. */
+ regs->r0 = EINTR;
+ regs->r19 = 1;
+
while (1) {
current->state = TASK_INTERRUPTIBLE;
schedule();
- if (do_signal(&oldset, reg, sw, 0, 0))
+ if (do_signal(&oldset, regs, sw, 0, 0))
return -EINTR;
}
}
unsigned int retcode[3];
};
+/* If this changes, userland unwinders that Know Things about our signal
+ frame will break. Do not undertake lightly. It also implies an ABI
+ change wrt the size of siginfo_t, which may cause some pain. */
+extern char compile_time_assert
+ [offsetof(struct rt_sigframe, uc.uc_mcontext) == 176 ? 1 : -1];
+
#define INSN_MOV_R30_R16 0x47fe0410
#define INSN_LDI_R0 0x201f0000
#define INSN_CALLSYS 0x00000083
return;
give_sigsegv:
- if (sig == SIGSEGV)
- ka->sa.sa_handler = SIG_DFL;
- force_sig(SIGSEGV, current);
+ force_sigsegv(sig, current);
}
static void
return;
give_sigsegv:
- if (sig == SIGSEGV)
- ka->sa.sa_handler = SIG_DFL;
- force_sig(SIGSEGV, current);
+ force_sigsegv(sig, current);
}
siginfo_t info;
int signr;
unsigned long single_stepping = ptrace_cancel_bpt(current);
+ struct k_sigaction ka;
if (!oldset)
oldset = ¤t->blocked;
/* This lets the debugger run, ... */
- signr = get_signal_to_deliver(&info, regs, NULL);
+ signr = get_signal_to_deliver(&info, &ka, regs, NULL);
/* ... so re-check the single stepping. */
single_stepping |= ptrace_cancel_bpt(current);
if (signr > 0) {
/* Whee! Actually deliver the signal. */
- struct k_sigaction *ka = ¤t->sighand->action[signr-1];
-
- if (r0) syscall_restart(r0, r19, regs, ka);
- handle_signal(signr, ka, &info, oldset, regs, sw);
+ if (r0) syscall_restart(r0, r19, regs, &ka);
+ handle_signal(signr, &ka, &info, oldset, regs, sw);
if (single_stepping)
ptrace_set_bpt(current); /* re-set bpt */
return 1;