static int do_signal()

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;
}