in kernel/signal.c [232:297]
static int do_signal(struct pt_regs *regs)
{
unsigned int retval = 0, continue_addr = 0, restart_addr = 0;
int restart = 0;
struct ksignal ksig;
current->thread.kregs = regs;
/*
* If we were from a system call, check for system call restarting...
*/
if (regs->orig_r2 >= 0) {
continue_addr = regs->ea;
restart_addr = continue_addr - 4;
retval = regs->r2;
/*
* Prepare for system call restart. We do this here so that a
* debugger will see the already changed PC.
*/
switch (retval) {
case ERESTART_RESTARTBLOCK:
restart = -2;
fallthrough;
case ERESTARTNOHAND:
case ERESTARTSYS:
case ERESTARTNOINTR:
restart++;
regs->r2 = regs->orig_r2;
regs->r7 = regs->orig_r7;
regs->ea = restart_addr;
break;
}
}
if (get_signal(&ksig)) {
/* handler */
if (unlikely(restart && regs->ea == restart_addr)) {
if (retval == ERESTARTNOHAND ||
retval == ERESTART_RESTARTBLOCK ||
(retval == ERESTARTSYS
&& !(ksig.ka.sa.sa_flags & SA_RESTART))) {
regs->r2 = EINTR;
regs->r7 = 1;
regs->ea = continue_addr;
}
}
handle_signal(&ksig, regs);
return 0;
}
/*
* No handler present
*/
if (unlikely(restart) && regs->ea == restart_addr) {
regs->ea = continue_addr;
regs->r2 = __NR_restart_syscall;
}
/*
* If there's no signal to deliver, we just put the saved sigmask back.
*/
restore_saved_sigmask();
return restart;
}