bt/s restore_all
mov r15, r4
mov #0, r5
+ mov r12, r6 ! set arg2(save_r0)
mov.l 2f, r1
mova restore_all, r0
jmp @r1
mov.l @r9, r8
jsr @r8 ! jump to specific syscall handler
nop
+ mov.l @(OFF_R0,r15), r12 ! save r0
mov.l r0, @(OFF_R0,r15) ! save the return value
!
syscall_exit:
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
-asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset);
+asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset,
+ unsigned int save_r0);
/*
* Atomically swap in the new signal mask, and wait for a signal.
while (1) {
current->state = TASK_INTERRUPTIBLE;
schedule();
- if (do_signal(®s, &saveset))
+ if (do_signal(®s, &saveset, regs.regs[0]))
return -EINTR;
}
}
while (1) {
current->state = TASK_INTERRUPTIBLE;
schedule();
- if (do_signal(®s, &saveset))
+ if (do_signal(®s, &saveset, regs.regs[0]))
return -EINTR;
}
}
* the kernel can handle, and then we build all the user-level signal handling
* stack-frames in one go after that.
*/
-int do_signal(struct pt_regs *regs, sigset_t *oldset)
+int do_signal(struct pt_regs *regs, sigset_t *oldset, unsigned int save_r0)
{
siginfo_t info;
int signr;
/* Restart the system call - no handlers present */
if (regs->regs[0] == -ERESTARTNOHAND ||
regs->regs[0] == -ERESTARTSYS ||
- regs->regs[0] == -ERESTARTNOINTR ||
- regs->regs[0] == -ERESTART_RESTARTBLOCK) {
+ regs->regs[0] == -ERESTARTNOINTR) {
+ regs->regs[0] = save_r0;
regs->pc -= 2;
+ } else if (regs->regs[0] == -ERESTART_RESTARTBLOCK) {
+ regs->pc -= 2;
+ regs->regs[3] = __NR_restart_syscall;
}
}
return 0;