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

📄 signal.c

📁 优龙2410linux2.6.8内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	unsigned long sp = regs->ARM_sp;	/*	 * This is the X/Open sanctioned signal stack switching.	 */	if ((ka->sa.sa_flags & SA_ONSTACK) && !sas_ss_flags(sp))		sp = current->sas_ss_sp + current->sas_ss_size;	/*	 * ATPCS B01 mandates 8-byte alignment	 */	return (void __user *)((sp - framesize) & ~7);}static intsetup_return(struct pt_regs *regs, struct k_sigaction *ka,	     unsigned long __user *rc, void __user *frame, int usig){	unsigned long handler = (unsigned long)ka->sa.sa_handler;	unsigned long retcode;	int thumb = 0;	unsigned long cpsr = regs->ARM_cpsr & ~PSR_f;	/*	 * Maybe we need to deliver a 32-bit signal to a 26-bit task.	 */	if (ka->sa.sa_flags & SA_THIRTYTWO)		cpsr = (cpsr & ~MODE_MASK) | USR_MODE;#ifdef CONFIG_ARM_THUMB	if (elf_hwcap & HWCAP_THUMB) {		/*		 * The LSB of the handler determines if we're going to		 * be using THUMB or ARM mode for this signal handler.		 */		thumb = handler & 1;		if (thumb)			cpsr |= PSR_T_BIT;		else			cpsr &= ~PSR_T_BIT;	}#endif	if (ka->sa.sa_flags & SA_RESTORER) {		retcode = (unsigned long)ka->sa.sa_restorer;	} else {		unsigned int idx = thumb;		if (ka->sa.sa_flags & SA_SIGINFO)			idx += 2;		if (__put_user(retcodes[idx], rc))			return 1;		/*		 * Ensure that the instruction cache sees		 * the return code written onto the stack.		 */		flush_icache_range((unsigned long)rc,				   (unsigned long)(rc + 1));		retcode = ((unsigned long)rc) + thumb;	}	regs->ARM_r0 = usig;	regs->ARM_sp = (unsigned long)frame;	regs->ARM_lr = retcode;	regs->ARM_pc = handler;	regs->ARM_cpsr = cpsr;	return 0;}static intsetup_frame(int usig, struct k_sigaction *ka, sigset_t *set, struct pt_regs *regs){	struct sigframe __user *frame = get_sigframe(ka, regs, sizeof(*frame));	int err = 0;	if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))		return 1;	err |= setup_sigcontext(&frame->sc, /*&frame->fpstate,*/ regs, set->sig[0]);	if (_NSIG_WORDS > 1) {		err |= __copy_to_user(frame->extramask, &set->sig[1],				      sizeof(frame->extramask));	}	if (err == 0)		err = setup_return(regs, ka, &frame->retcode, frame, usig);	return err;}static intsetup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info,	       sigset_t *set, struct pt_regs *regs){	struct rt_sigframe __user *frame = get_sigframe(ka, regs, sizeof(*frame));	stack_t stack;	int err = 0;	if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))		return 1;	__put_user_error(&frame->info, &frame->pinfo, err);	__put_user_error(&frame->uc, &frame->puc, err);	err |= copy_siginfo_to_user(&frame->info, info);	__put_user_error(0, &frame->uc.uc_flags, err);	__put_user_error(NULL, &frame->uc.uc_link, err);	memset(&stack, 0, sizeof(stack));	stack.ss_sp = (void __user *)current->sas_ss_sp;	stack.ss_flags = sas_ss_flags(regs->ARM_sp);	stack.ss_size = current->sas_ss_size;	err |= __copy_to_user(&frame->uc.uc_stack, &stack, sizeof(stack));	err |= setup_sigcontext(&frame->uc.uc_mcontext, /*&frame->fpstate,*/				regs, set->sig[0]);	err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));	if (err == 0)		err = setup_return(regs, ka, &frame->retcode, frame, usig);	if (err == 0) {		/*		 * For realtime signals we must also set the second and third		 * arguments for the signal handler.		 *   -- Peter Maydell <pmaydell@chiark.greenend.org.uk> 2000-12-06		 */		regs->ARM_r1 = (unsigned long)&frame->info;		regs->ARM_r2 = (unsigned long)&frame->uc;	}	return err;}static inline void restart_syscall(struct pt_regs *regs){	regs->ARM_r0 = regs->ARM_ORIG_r0;	regs->ARM_pc -= thumb_mode(regs) ? 2 : 4;}/* * OK, we're invoking a handler */	static voidhandle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset,	      struct pt_regs * regs, int syscall){	struct thread_info *thread = current_thread_info();	struct task_struct *tsk = current;	struct k_sigaction *ka = &tsk->sighand->action[sig-1];	int usig = sig;	int ret;	/*	 * If we were from a system call, check for system call restarting...	 */	if (syscall) {		switch (regs->ARM_r0) {		case -ERESTART_RESTARTBLOCK:		case -ERESTARTNOHAND:			regs->ARM_r0 = -EINTR;			break;		case -ERESTARTSYS:			if (!(ka->sa.sa_flags & SA_RESTART)) {				regs->ARM_r0 = -EINTR;				break;			}			/* fallthrough */		case -ERESTARTNOINTR:			restart_syscall(regs);		}	}	/*	 * translate the signal	 */	if (usig < 32 && thread->exec_domain && thread->exec_domain->signal_invmap)		usig = thread->exec_domain->signal_invmap[usig];	/*	 * Set up the stack frame	 */	if (ka->sa.sa_flags & SA_SIGINFO)		ret = setup_rt_frame(usig, ka, info, oldset, regs);	else		ret = setup_frame(usig, ka, oldset, regs);	/*	 * Check that the resulting registers are actually sane.	 */	ret |= !valid_user_regs(regs);	/*	 * Block the signal if we were unsuccessful.	 */	if (ret != 0 || !(ka->sa.sa_flags & SA_NODEFER)) {		spin_lock_irq(&tsk->sighand->siglock);		sigorsets(&tsk->blocked, &tsk->blocked,			  &ka->sa.sa_mask);		sigaddset(&tsk->blocked, sig);		recalc_sigpending();		spin_unlock_irq(&tsk->sighand->siglock);	}	if (ret == 0) {		if (ka->sa.sa_flags & SA_ONESHOT)			ka->sa.sa_handler = SIG_DFL;		return;	}	if (sig == SIGSEGV)		ka->sa.sa_handler = SIG_DFL;	force_sig(SIGSEGV, tsk);}/* * 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. */static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall){	siginfo_t info;	int signr;	/*	 * 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 0;	if (current->flags & PF_FREEZE) {		refrigerator(0);		goto no_signal;	}	if (current->ptrace & PT_SINGLESTEP)		ptrace_cancel_bpt(current);	signr = get_signal_to_deliver(&info, regs, NULL);	if (signr > 0) {		handle_signal(signr, &info, oldset, regs, syscall);		if (current->ptrace & PT_SINGLESTEP)			ptrace_set_bpt(current);		return 1;	} no_signal:	/*	 * No signal to deliver to the process - restart the syscall.	 */	if (syscall) {		if (regs->ARM_r0 == -ERESTART_RESTARTBLOCK) {			if (thumb_mode(regs)) {				regs->ARM_r7 = __NR_restart_syscall;				regs->ARM_pc -= 2;			} else {				u32 __user *usp;				regs->ARM_sp -= 12;				usp = (u32 __user *)regs->ARM_sp;				put_user(regs->ARM_pc, &usp[0]);				/* swi __NR_restart_syscall */				put_user(0xef000000 | __NR_restart_syscall, &usp[1]);				/* ldr	pc, [sp], #12 */				put_user(0xe49df00c, &usp[2]);				flush_icache_range((unsigned long)usp,						   (unsigned long)(usp + 3));				regs->ARM_pc = regs->ARM_sp + 4;			}		}		if (regs->ARM_r0 == -ERESTARTNOHAND ||		    regs->ARM_r0 == -ERESTARTSYS ||		    regs->ARM_r0 == -ERESTARTNOINTR) {			restart_syscall(regs);		}	}	if (current->ptrace & PT_SINGLESTEP)		ptrace_set_bpt(current);	return 0;}asmlinkage voiddo_notify_resume(struct pt_regs *regs, unsigned int thread_flags, int syscall){	if (thread_flags & _TIF_SIGPENDING)		do_signal(&current->blocked, regs, syscall);}

⌨️ 快捷键说明

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