⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 signal.c

📁 优龙2410linux2.6.8内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	err |= __put_user(regs->er0, &gregs[0]);	err |= __put_user(regs->er1, &gregs[1]);	err |= __put_user(regs->er2, &gregs[2]);	err |= __put_user(regs->er3, &gregs[3]);	err |= __put_user(regs->er4, &gregs[4]);	err |= __put_user(regs->er5, &gregs[5]);	err |= __put_user(regs->er6, &gregs[6]);	err |= __put_user(rdusp(), &gregs[7]);	err |= __put_user(regs->pc, &gregs[8]);	err |= __put_user(regs->ccr, &gregs[9]);	return err;}static inline void *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size){	unsigned long usp;	/* Default to using normal stack.  */	usp = rdusp();	/* This is the X/Open sanctioned signal stack switching.  */	if (ka->sa.sa_flags & SA_ONSTACK) {		if (!on_sig_stack(usp))			usp = current->sas_ss_sp + current->sas_ss_size;	}	return (void *)((usp - frame_size) & -8UL);}static void setup_frame (int sig, struct k_sigaction *ka,			 sigset_t *set, struct pt_regs *regs){	struct sigframe *frame;	struct sigcontext context;	int err = 0;	frame = get_sigframe(ka, regs, sizeof(*frame));	if (_NSIG_WORDS > 1)		err |= copy_to_user(frame->extramask, &set->sig[1],				    sizeof(frame->extramask));	setup_sigcontext(&context, regs, set->sig[0]);	err |= copy_to_user (&frame->sc, &context, sizeof(context));	/* Set up to return from userspace.  */	err |= __put_user(frame->retcode, &frame->pretcode);	/* sub.l er0,er0; mov.b #__NR_sigreturn,r0l; trapa #0 */	err != __put_user(0x1a80f800 + (__NR_sigreturn & 0xff),			(unsigned long *)(frame->retcode + 0));	err |= __put_user(0x5700, (unsigned short *)(frame->retcode + 4));	if (err)		goto give_sigsegv;	/* Set up registers for signal handler */	wrusp ((unsigned long) frame);	regs->pc = (unsigned long) ka->sa.sa_handler;	regs->er0 = (current_thread_info()->exec_domain			   && current_thread_info()->exec_domain->signal_invmap			   && sig < 32			   ? current_thread_info()->exec_domain->signal_invmap[sig]		          : sig);	regs->er1 = (unsigned long)&(frame->sc);	regs->er5 = current->mm->start_data;	/* GOT base */	return;give_sigsegv:	if (sig == SIGSEGV)		ka->sa.sa_handler = SIG_DFL;	force_sig(SIGSEGV, current);}static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,			    sigset_t *set, struct pt_regs *regs){	struct rt_sigframe *frame;	int err = 0;	frame = get_sigframe(ka, regs, sizeof(*frame));	err |= copy_siginfo_to_user(&frame->info, info);	/* Create the ucontext.  */	err |= __put_user(0, &frame->uc.uc_flags);	err |= __put_user(0, &frame->uc.uc_link);	err |= __put_user((void *)current->sas_ss_sp,			  &frame->uc.uc_stack.ss_sp);	err |= __put_user(sas_ss_flags(rdusp()),			  &frame->uc.uc_stack.ss_flags);	err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);	err |= rt_setup_ucontext(&frame->uc, regs);	err |= copy_to_user (&frame->uc.uc_sigmask, set, sizeof(*set));	/* Set up to return from userspace.  */	err |= __put_user(frame->retcode, &frame->pretcode);	/* sub.l er0,er0; mov.b #__NR_rt_sigreturn,r0l; trapa #0 */	err != __put_user(0x1a80f800 + (__NR_rt_sigreturn & 0xff),			(long *)(frame->retcode + 0));	err |= __put_user(0x5700, (short *)(frame->retcode + 4));	if (err)		goto give_sigsegv;	/* Set up registers for signal handler */	wrusp ((unsigned long) frame);	regs->pc  = (unsigned long) ka->sa.sa_handler;	regs->er0 = (current_thread_info()->exec_domain		     && current_thread_info()->exec_domain->signal_invmap		     && sig < 32		     ? current_thread_info()->exec_domain->signal_invmap[sig]		     : sig);	regs->er1 = (unsigned long)&(frame->info);	regs->er2 = (unsigned long)&frame->uc;	regs->er5 = current->mm->start_data;	/* GOT base */	return;give_sigsegv:	if (sig == SIGSEGV)		ka->sa.sa_handler = SIG_DFL;	force_sig(SIGSEGV, current);}static inline voidhandle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler){	switch (regs->er0) {	case -ERESTARTNOHAND:		if (!has_handler)			goto do_restart;		regs->er0 = -EINTR;		break;	case -ERESTARTSYS:		if (has_handler && !(ka->sa.sa_flags & SA_RESTART)) {			regs->er0 = -EINTR;			break;		}	/* fallthrough */	case -ERESTARTNOINTR:	do_restart:		regs->er0 = regs->orig_er0;		regs->pc -= 2;		break;	}}/* * OK, we're invoking a handler */static voidhandle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,	      sigset_t *oldset, struct pt_regs *regs){	/* are we from a system call? */	if (regs->orig_er0 >= 0)		/* If so, check system call restarting.. */		handle_restart(regs, ka, 1);	/* 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->sighand->siglock);		sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);		sigaddset(&current->blocked,sig);		recalc_sigpending();		spin_unlock_irq(&current->sighand->siglock);	}}/* * 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. */asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs){	siginfo_t info;	struct k_sigaction *ka;	current->thread.esp0 = (unsigned long) regs;	if (!oldset)		oldset = &current->blocked;	for (;;) {		int signr;		signr = get_signal_to_deliver(&info, regs, NULL);		if (!signr)			break;		if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) {			current->exit_code = signr;			current->state = TASK_STOPPED;			/* Did we come from a system call? */			if (regs->orig_er0 >= 0) {				/* Restart the system call the same way as				   if the process were not traced.  */				struct k_sigaction *ka =					&current->sighand->action[signr-1];				int has_handler =					(ka->sa.sa_handler != SIG_IGN &&					 ka->sa.sa_handler != SIG_DFL);				handle_restart(regs, ka, has_handler);			}			notify_parent(current, SIGCHLD);			schedule();			/* We're back.  Did the debugger cancel the sig?  */			if (!(signr = current->exit_code)) {			discard_frame:			    continue;			}			current->exit_code = 0;			/* The debugger continued.  Ignore SIGSTOP.  */			if (signr == SIGSTOP)				goto discard_frame;			/* 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->parent->pid;				info.si_uid = current->parent->uid;			}			/* If the (new) signal is now blocked, requeue it.  */			if (sigismember(&current->blocked, signr)) {				send_sig_info(signr, &info, current);				continue;			}		}		ka = &current->sighand->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;			if (current->pid == 1)				continue;			switch (signr) {			case SIGCONT: case SIGCHLD:			case SIGWINCH: case SIGURG:				continue;			case SIGTSTP: case SIGTTIN: case SIGTTOU:				if (is_orphaned_pgrp(process_group(current)))					continue;				/* FALLTHRU */			case SIGSTOP: {				struct sighand_struct *sig;				current->state = TASK_STOPPED;				current->exit_code = signr;                                sig = current->parent->sighand;                                if (sig && !(sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP))                                        notify_parent(current, SIGCHLD);				schedule();				continue;			}			case SIGQUIT: case SIGILL: case SIGTRAP:			case SIGIOT: case SIGFPE: case SIGSEGV:			case SIGBUS: case SIGSYS: case SIGXCPU: case SIGXFSZ:				if (do_coredump(signr, exit_code, regs))					exit_code |= 0x80;				/* FALLTHRU */			default:				sigaddset(&current->pending.signal, signr);				recalc_sigpending();				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 (regs->orig_er0 >= 0)		/* Restart the system call - no handlers present */		handle_restart(regs, NULL, 0);	return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -