📄 signal.c
字号:
err |= __put_user(scr->pt.pr, &sc->sc_pr); /* predicates */ err |= __put_user(scr->pt.b0, &sc->sc_br[0]); /* b0 (rp) */ err |= __put_user(scr->pt.b6, &sc->sc_br[6]); /* b6 */ err |= __put_user(scr->pt.b7, &sc->sc_br[7]); /* b7 */ err |= __copy_to_user(&sc->sc_gr[1], &scr->pt.r1, 3*8); /* r1-r3 */ err |= __copy_to_user(&sc->sc_gr[8], &scr->pt.r8, 4*8); /* r8-r11 */ err |= __copy_to_user(&sc->sc_gr[12], &scr->pt.r12, 4*8); /* r12-r15 */ err |= __copy_to_user(&sc->sc_gr[16], &scr->pt.r16, 16*8); /* r16-r31 */ err |= __put_user(scr->pt.cr_iip + ia64_psr(&scr->pt)->ri, &sc->sc_ip); return err;}static longsetup_frame (int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set, struct sigscratch *scr){ extern char ia64_sigtramp[], __start_gate_section[]; unsigned long tramp_addr, new_rbs = 0; struct sigframe *frame; struct siginfo si; long err; frame = (void *) scr->pt.r12; tramp_addr = GATE_ADDR + (ia64_sigtramp - __start_gate_section); if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && !on_sig_stack((unsigned long) frame)) { new_rbs = (current->sas_ss_sp + sizeof(long) - 1) & ~(sizeof(long) - 1); frame = (void *) ((current->sas_ss_sp + current->sas_ss_size) & ~(STACK_ALIGN - 1)); } frame = (void *) frame - ((sizeof(*frame) + STACK_ALIGN - 1) & ~(STACK_ALIGN - 1)); if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) goto give_sigsegv; err = copy_siginfo_to_user(&frame->info, info); err |= __put_user(current->sas_ss_sp, &frame->sc.sc_stack.ss_sp); err |= __put_user(current->sas_ss_size, &frame->sc.sc_stack.ss_size); err |= __put_user(sas_ss_flags(scr->pt.r12), &frame->sc.sc_stack.ss_flags); err |= setup_sigcontext(&frame->sc, set, scr); if (err) goto give_sigsegv; scr->pt.r12 = (unsigned long) frame - 16; /* new stack pointer */ scr->pt.r2 = sig; /* signal number */ scr->pt.r3 = (unsigned long) ka->sa.sa_handler; /* addr. of handler's proc desc */ scr->pt.r15 = new_rbs; scr->pt.ar_fpsr = FPSR_DEFAULT; /* reset fpsr for signal handler */ scr->pt.cr_iip = tramp_addr; ia64_psr(&scr->pt)->ri = 0; /* start executing in first slot */#ifdef CONFIG_IA64_NEW_UNWIND /* * Note: this affects only the NaT bits of the scratch regs * (the ones saved in pt_regs), which is exactly what we want. */ scr->scratch_unat = 0; /* ensure NaT bits of at least r2, r3, r12, and r15 are clear */#else /* * Note: this affects only the NaT bits of the scratch regs * (the ones saved in pt_regs), which is exactly what we want. * The NaT bits for the preserved regs (r4-r7) are in * sw->ar_unat iff this process is being PTRACED. */ scr->sw.caller_unat = 0; /* ensure NaT bits of at least r2, r3, r12, and r15 are clear */#endif#if DEBUG_SIG printk("SIG deliver (%s:%d): sig=%d sp=%lx ip=%lx handler=%lx\n", current->comm, current->pid, sig, scr->pt.r12, scr->pt.cr_iip, scr->pt.r3);#endif return 1; give_sigsegv: if (sig == SIGSEGV) ka->sa.sa_handler = SIG_DFL; si.si_signo = SIGSEGV; si.si_errno = 0; si.si_code = SI_KERNEL; si.si_pid = current->pid; si.si_uid = current->uid; si.si_addr = frame; force_sig_info(SIGSEGV, &si, current); return 0;}static longhandle_signal (unsigned long sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *oldset, struct sigscratch *scr){#ifdef CONFIG_IA32_SUPPORT if (IS_IA32_PROCESS(&scr->pt)) { /* send signal to IA-32 process */ if (!ia32_setup_frame1(sig, ka, info, oldset, &scr->pt)) return 0; } else#endif /* send signal to IA-64 process */ if (!setup_frame(sig, ka, info, oldset, scr)) return 0; if (ka->sa.sa_flags & SA_ONESHOT) ka->sa.sa_handler = SIG_DFL; if (!(ka->sa.sa_flags & SA_NODEFER)) { spin_lock_irq(¤t->sigmask_lock); { sigorsets(¤t->blocked, ¤t->blocked, &ka->sa.sa_mask); sigaddset(¤t->blocked, sig); recalc_sigpending(current); } spin_unlock_irq(¤t->sigmask_lock); } return 1;}/* * 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. */longia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall){ struct k_sigaction *ka; siginfo_t info; long restart = in_syscall; long errno = scr->pt.r8; /* * In the ia64_leave_kernel code path, 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(&scr->pt)) return 0; if (!oldset) oldset = ¤t->blocked;#ifdef CONFIG_IA32_SUPPORT if (IS_IA32_PROCESS(&scr->pt)) { if (in_syscall) { if (errno >= 0) restart = 0; else errno = -errno; } } else#endif if (scr->pt.r10 != -1) { /* * A system calls has to be restarted only if one of * the error codes ERESTARTNOHAND, ERESTARTSYS, or * ERESTARTNOINTR is returned. If r10 isn't -1 then * r8 doesn't hold an error code and we don't need to * restart the syscall, so we set in_syscall to zero. */ restart = 0; } for (;;) { unsigned long signr; spin_lock_irq(¤t->sigmask_lock); signr = dequeue_signal(¤t->blocked, &info); spin_unlock_irq(¤t->sigmask_lock); if (!signr) break; if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) { /* Let the debugger run. */ current->exit_code = signr; current->thread.siginfo = &info; current->state = TASK_STOPPED; notify_parent(current, SIGCHLD); schedule(); signr = current->exit_code; current->thread.siginfo = 0; /* We're back. Did the debugger cancel the sig? */ if (!signr) 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(¤t->blocked, signr)) { send_sig_info(signr, &info, current); continue; } } ka = ¤t->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, &scr->pt)) exit_code |= 0x80; /* FALLTHRU */ default: sigaddset(¤t->pending.signal, signr); recalc_sigpending(current); current->flags |= PF_SIGNALED; do_exit(exit_code); /* NOTREACHED */ } } if (restart) { switch (errno) { case ERESTARTSYS: if ((ka->sa.sa_flags & SA_RESTART) == 0) { case ERESTARTNOHAND:#ifdef CONFIG_IA32_SUPPORT if (IS_IA32_PROCESS(&scr->pt)) scr->pt.r8 = -EINTR; else#endif scr->pt.r8 = EINTR; /* note: scr->pt.r10 is already -1 */ break; } case ERESTARTNOINTR:#ifdef CONFIG_IA32_SUPPORT if (IS_IA32_PROCESS(&scr->pt)) { scr->pt.r8 = scr->pt.r1; scr->pt.cr_iip -= 2; } else#endif ia64_decrement_ip(&scr->pt); } } /* Whee! Actually deliver the signal. If the delivery failed, we need to continue to iterate in this loop so we can deliver the SIGSEGV... */ if (handle_signal(signr, ka, &info, oldset, scr)) return 1; } /* Did we come from a system call? */ if (restart) { /* Restart the system call - no handlers present */ if (errno == ERESTARTNOHAND || errno == ERESTARTSYS || errno == ERESTARTNOINTR) {#ifdef CONFIG_IA32_SUPPORT if (IS_IA32_PROCESS(&scr->pt)) { scr->pt.r8 = scr->pt.r1; scr->pt.cr_iip -= 2; } else#endif /* * Note: the syscall number is in r15 which is * saved in pt_regs so all we need to do here * is adjust ip so that the "break" * instruction gets re-executed. */ ia64_decrement_ip(&scr->pt); } } return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -