Ejemplo n.º 1
0
static void
handle_signal(unsigned long sig, struct k_sigaction *ka,
	      siginfo_t *info, sigset_t *oldset, struct pt_regs * regs)
{
	/* Are we from a system call? */
	if (PT_REGS_SYSCALL (regs)) {
		/* If so, check system call restarting.. */
		switch (regs->gpr[GPR_RVAL]) {
			case -ERESTARTNOHAND:
				regs->gpr[GPR_RVAL] = -EINTR;
				break;

			case -ERESTARTSYS:
				if (!(ka->sa.sa_flags & SA_RESTART)) {
					regs->gpr[GPR_RVAL] = -EINTR;
					break;
				}
			/* fallthrough */
			case -ERESTARTNOINTR:
				regs->gpr[12] = PT_REGS_SYSCALL (regs);
				/* offset of 8 bytes required = 4 for rtbd
				   offset, plus 4 for size of 
					"brki r14,8"
				   instruction. */
				regs->pc -= 8; 
		}

		PT_REGS_SET_SYSCALL (regs, 0);
	}

	/* Set up the stack frame */
	if (ka->sa.sa_flags & SA_SIGINFO)
		setup_rt_frame(sig, ka, info, oldset, regs);
	else
		setup_frame(sig, ka, oldset, regs);

	if (ka->sa.sa_flags & SA_ONESHOT)
		ka->sa.sa_handler = SIG_DFL;

	if (!(ka->sa.sa_flags & SA_NODEFER)) {
		spin_lock_irq(&current->sigmask_lock);
		sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
		sigaddset(&current->blocked,sig);
		recalc_sigpending(current);
		spin_unlock_irq(&current->sigmask_lock);
	}
}
Ejemplo n.º 2
0
Archivo: signal.c Proyecto: 274914765/C
/*
 * Note that 'init' is a special process: it doesn't get signals it doesn't
 * want to handle. Thus you cannot kill init even with a SIGKILL even by
 * mistake.
 *
 * Note that we go through the signals twice: once to check the signals that
 * 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)
{
    siginfo_t info;
    int signr;
    struct k_sigaction ka;

    /*
     * We want the common case to go fast, which
     * is why we may in certain cases get here from
     * kernel mode. Just return without doing anything
     * if so.
     */
    if (!user_mode(regs))
        return 1;

    if (!oldset)
        oldset = &current->blocked;

    signr = get_signal_to_deliver(&info, &ka, regs, NULL);
    if (signr > 0) {
        /* Whee!  Actually deliver the signal.  */
        handle_signal(signr, &info, &ka, oldset, regs);
        return 1;
    }

    /* Did we come from a system call? */
    if (PT_REGS_SYSCALL (regs)) {
        int rval = (int)regs->gpr[GPR_RVAL];
        /* Restart the system call - no handlers present */
        if (rval == -ERESTARTNOHAND
            || rval == -ERESTARTSYS
            || rval == -ERESTARTNOINTR)
        {
            regs->gpr[12] = PT_REGS_SYSCALL (regs);
            regs->pc -= 4; /* Size of `trap 0' insn.  */
        }
        else if (rval == -ERESTART_RESTARTBLOCK) {
            regs->gpr[12] = __NR_restart_syscall;
            regs->pc -= 4; /* Size of `trap 0' insn.  */
        }
    }
    return 0;
}
Ejemplo n.º 3
0
Archivo: signal.c Proyecto: 274914765/C
static void
handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
          sigset_t *oldset,    struct pt_regs * regs)
{
    /* Are we from a system call? */
    if (PT_REGS_SYSCALL (regs)) {
        /* If so, check system call restarting.. */
        switch (regs->gpr[GPR_RVAL]) {
        case -ERESTART_RESTARTBLOCK:
            current_thread_info()->restart_block.fn =
                do_no_restart_syscall;
            /* fall through */
        case -ERESTARTNOHAND:
            regs->gpr[GPR_RVAL] = -EINTR;
            break;

        case -ERESTARTSYS:
            if (!(ka->sa.sa_flags & SA_RESTART)) {
                regs->gpr[GPR_RVAL] = -EINTR;
                break;
            }
            /* fallthrough */
        case -ERESTARTNOINTR:
            regs->gpr[12] = PT_REGS_SYSCALL (regs);
            regs->pc -= 4; /* Size of `trap 0' insn.  */
        }

        PT_REGS_SET_SYSCALL (regs, 0);
    }

    /* Set up the stack frame */
    if (ka->sa.sa_flags & SA_SIGINFO)
        setup_rt_frame(sig, ka, info, oldset, regs);
    else
        setup_frame(sig, ka, oldset, regs);

    spin_lock_irq(&current->sighand->siglock);
    sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
    if (!(ka->sa.sa_flags & SA_NODEFER))
        sigaddset(&current->blocked,sig);
    recalc_sigpending();
    spin_unlock_irq(&current->sighand->siglock);
}
Ejemplo n.º 4
0
/*
 * Note that 'init' is a special process: it doesn't get signals it doesn't
 * want to handle. Thus you cannot kill init even with a SIGKILL even by
 * mistake.
 *
 * Note that we go through the signals twice: once to check the signals that
 * 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)
{
	siginfo_t info;
	struct k_sigaction *ka;

	/*
	 * We want the common case to go fast, which
	 * is why we may in certain cases get here from
	 * kernel mode. Just return without doing anything
	 * if so.
	 */
	if (!user_mode(regs))
		return 1;

	if (!oldset)
		oldset = &current->blocked;

	for (;;) {
		unsigned long signr;

		spin_lock_irq(&current->sigmask_lock);
		signr = dequeue_signal(&current->blocked, &info);
		spin_unlock_irq(&current->sigmask_lock);

		if (!signr)
			break;

		if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) {
			/* Let the debugger run.  */
			current->exit_code = signr;
			current->state = TASK_STOPPED;
			notify_parent(current, SIGCHLD);
			schedule();

			/* We're back.  Did the debugger cancel the sig?  */
			if (!(signr = current->exit_code))
				continue;
			current->exit_code = 0;

			/* The debugger continued.  Ignore SIGSTOP.  */
			if (signr == SIGSTOP)
				continue;

			/* Update the siginfo structure.  Is this good?  */
			if (signr != info.si_signo) {
				info.si_signo = signr;
				info.si_errno = 0;
				info.si_code = SI_USER;
				info.si_pid = current->p_pptr->pid;
				info.si_uid = current->p_pptr->uid;
			}

			/* If the (new) signal is now blocked, requeue it.  */
			if (sigismember(&current->blocked, signr)) {
				send_sig_info(signr, &info, current);
				continue;
			}
		}

		ka = &current->sig->action[signr-1];
		if (ka->sa.sa_handler == SIG_IGN) {
			if (signr != SIGCHLD)
				continue;
			/* Check for SIGCHLD: it's special.  */
			while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0)
				/* nothing */;
			continue;
		}

		if (ka->sa.sa_handler == SIG_DFL) {
			int exit_code = signr;

			/* Init gets no signals it doesn't want.  */
			if (current->pid == 1)
				continue;

			switch (signr) {
			case SIGCONT: case SIGCHLD: case SIGWINCH:
				continue;

			case SIGTSTP: case SIGTTIN: case SIGTTOU:
				if (is_orphaned_pgrp(current->pgrp))
				{
					continue;
				}
				/* FALLTHRU */

			case SIGSTOP:
				current->state = TASK_STOPPED;
				current->exit_code = signr;
				if (!(current->p_pptr->sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP))
					notify_parent(current, SIGCHLD);
				schedule();
				continue;

			case SIGQUIT: case SIGILL: case SIGTRAP:
			case SIGABRT: case SIGFPE: case SIGSEGV:
			case SIGBUS: case SIGSYS: case SIGXCPU: case SIGXFSZ:
				if (do_coredump(signr, regs))
					exit_code |= 0x80;
				/* FALLTHRU */

			default:
				sigaddset(&current->pending.signal, signr);
				recalc_sigpending(current);
				current->flags |= PF_SIGNALED;
				do_exit(exit_code);
				/* NOTREACHED */
			}
		}

		/* Whee!  Actually deliver the signal.  */
		handle_signal(signr, ka, &info, oldset, regs);
		return 1;
	}

	/* Did we come from a system call? */
	if (PT_REGS_SYSCALL (regs)) {
		/* Restart the system call - no handlers present */
		if (regs->gpr[GPR_RVAL] == -ERESTARTNOHAND ||
		    regs->gpr[GPR_RVAL] == -ERESTARTSYS ||
		    regs->gpr[GPR_RVAL] == -ERESTARTNOINTR) {
			regs->gpr[12] = PT_REGS_SYSCALL (regs);
			regs->pc -= 8; /* 4 + 8 for microblaze return offset wierdness */
		}
	}
	return 0;
}