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

📄 signal.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*  $Id: signal.c,v 1.54 2000/09/05 21:44:54 davem Exp $ *  arch/sparc64/kernel/signal.c * *  Copyright (C) 1991, 1992  Linus Torvalds *  Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) *  Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx) *  Copyright (C) 1997 Eddie C. Dost   (ecd@skynet.be) *  Copyright (C) 1997,1998 Jakub Jelinek   (jj@sunsite.mff.cuni.cz) */#include <linux/config.h>#include <linux/sched.h>#include <linux/kernel.h>#include <linux/signal.h>#include <linux/errno.h>#include <linux/wait.h>#include <linux/ptrace.h>#include <linux/unistd.h>#include <linux/mm.h>#include <linux/smp_lock.h>#include <asm/uaccess.h>#include <asm/bitops.h>#include <asm/ptrace.h>#include <asm/svr4.h>#include <asm/pgtable.h>#include <asm/fpumacro.h>#include <asm/uctx.h>#include <asm/siginfo.h>#include <asm/visasm.h>#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))asmlinkage int sys_wait4(pid_t pid, unsigned long *stat_addr,			 int options, unsigned long *ru);asmlinkage int do_signal(sigset_t *oldset, struct pt_regs * regs,			 unsigned long orig_o0, int ret_from_syscall);/* This turned off for production... *//* #define DEBUG_SIGNALS 1 *//* #define DEBUG_SIGNALS_TRACE 1 *//* #define DEBUG_SIGNALS_MAPS 1 */int copy_siginfo_to_user(siginfo_t *to, siginfo_t *from){	if (!access_ok (VERIFY_WRITE, to, sizeof(siginfo_t)))		return -EFAULT;	if (from->si_code < 0)		return __copy_to_user(to, from, sizeof(siginfo_t));	else {		int err;		/* If you change siginfo_t structure, please be sure		   this code is fixed accordingly.		   It should never copy any pad contained in the structure		   to avoid security leaks, but must copy the generic		   3 ints plus the relevant union member.  */		err = __put_user(*(long *)&from->si_signo, (long *)&to->si_signo);		err |= __put_user((short)from->si_code, &to->si_code);		switch (from->si_code >> 16) {		case __SI_CHLD >> 16:			err |= __put_user(from->si_utime, &to->si_utime);			err |= __put_user(from->si_stime, &to->si_stime);		case __SI_FAULT >> 16:		case __SI_POLL >> 16:			err |= __put_user(from->si_trapno, &to->si_trapno);		default:			err |= __put_user(from->si_addr, &to->si_addr);			break;		/* case __SI_RT: This is not generated by the kernel as of now.  */		}		return err;	}}/* {set, get}context() needed for 64-bit SparcLinux userland. */asmlinkage void sparc64_set_context(struct pt_regs *regs){	struct ucontext *ucp = (struct ucontext *) regs->u_regs[UREG_I0];	struct thread_struct *tp = &current->thread;	mc_gregset_t *grp;	unsigned long pc, npc, tstate;	unsigned long fp, i7;	unsigned char fenab;	int err;	flush_user_windows();	if(tp->w_saved						||	   (((unsigned long)ucp) & (sizeof(unsigned long)-1))	||	   (!__access_ok((unsigned long)ucp, sizeof(*ucp))))		goto do_sigsegv;	grp  = &ucp->uc_mcontext.mc_gregs;	err  = __get_user(pc, &((*grp)[MC_PC]));	err |= __get_user(npc, &((*grp)[MC_NPC]));	if(err || ((pc | npc) & 3))		goto do_sigsegv;	if(regs->u_regs[UREG_I1]) {		sigset_t set;		if (_NSIG_WORDS == 1) {			if (__get_user(set.sig[0], &ucp->uc_sigmask.sig[0]))				goto do_sigsegv;		} else {			if (__copy_from_user(&set, &ucp->uc_sigmask, sizeof(sigset_t)))				goto do_sigsegv;		}		sigdelsetmask(&set, ~_BLOCKABLE);		spin_lock_irq(&current->sigmask_lock);		current->blocked = set;		recalc_sigpending(current);		spin_unlock_irq(&current->sigmask_lock);	}	regs->tpc = pc;	regs->tnpc = npc;	err |= __get_user(regs->y, &((*grp)[MC_Y]));	err |= __get_user(tstate, &((*grp)[MC_TSTATE]));	regs->tstate &= ~(TSTATE_ICC | TSTATE_XCC);	regs->tstate |= (tstate & (TSTATE_ICC | TSTATE_XCC));	err |= __get_user(regs->u_regs[UREG_G1], (&(*grp)[MC_G1]));	err |= __get_user(regs->u_regs[UREG_G2], (&(*grp)[MC_G2]));	err |= __get_user(regs->u_regs[UREG_G3], (&(*grp)[MC_G3]));	err |= __get_user(regs->u_regs[UREG_G4], (&(*grp)[MC_G4]));	err |= __get_user(regs->u_regs[UREG_G5], (&(*grp)[MC_G5]));	err |= __get_user(regs->u_regs[UREG_G6], (&(*grp)[MC_G6]));	err |= __get_user(regs->u_regs[UREG_G7], (&(*grp)[MC_G7]));	err |= __get_user(regs->u_regs[UREG_I0], (&(*grp)[MC_O0]));	err |= __get_user(regs->u_regs[UREG_I1], (&(*grp)[MC_O1]));	err |= __get_user(regs->u_regs[UREG_I2], (&(*grp)[MC_O2]));	err |= __get_user(regs->u_regs[UREG_I3], (&(*grp)[MC_O3]));	err |= __get_user(regs->u_regs[UREG_I4], (&(*grp)[MC_O4]));	err |= __get_user(regs->u_regs[UREG_I5], (&(*grp)[MC_O5]));	err |= __get_user(regs->u_regs[UREG_I6], (&(*grp)[MC_O6]));	err |= __get_user(regs->u_regs[UREG_I7], (&(*grp)[MC_O7]));	err |= __get_user(fp, &(ucp->uc_mcontext.mc_fp));	err |= __get_user(i7, &(ucp->uc_mcontext.mc_i7));	err |= __put_user(fp,	      (&(((struct reg_window *)(STACK_BIAS+regs->u_regs[UREG_I6]))->ins[6])));	err |= __put_user(i7,	      (&(((struct reg_window *)(STACK_BIAS+regs->u_regs[UREG_I6]))->ins[7])));	err |= __get_user(fenab, &(ucp->uc_mcontext.mc_fpregs.mcfpu_enab));	if(fenab) {		unsigned long *fpregs = (unsigned long *)(((char *)current) + AOFF_task_fpregs);		unsigned long fprs;				fprs_write(0);		err |= __get_user(fprs, &(ucp->uc_mcontext.mc_fpregs.mcfpu_fprs));		if (fprs & FPRS_DL)			err |= copy_from_user(fpregs,					      &(ucp->uc_mcontext.mc_fpregs.mcfpu_fregs),					      (sizeof(unsigned int) * 32));		if (fprs & FPRS_DU)			err |= copy_from_user(fpregs+16,			 ((unsigned long *)&(ucp->uc_mcontext.mc_fpregs.mcfpu_fregs))+16,			 (sizeof(unsigned int) * 32));		err |= __get_user(current->thread.xfsr[0],				  &(ucp->uc_mcontext.mc_fpregs.mcfpu_fsr));		err |= __get_user(current->thread.gsr[0],				  &(ucp->uc_mcontext.mc_fpregs.mcfpu_gsr));		regs->tstate &= ~TSTATE_PEF;	}	if (err)		goto do_sigsegv;	return;do_sigsegv:	do_exit(SIGSEGV);}asmlinkage void sparc64_get_context(struct pt_regs *regs){	struct ucontext *ucp = (struct ucontext *) regs->u_regs[UREG_I0];	struct thread_struct *tp = &current->thread;	mc_gregset_t *grp;	mcontext_t *mcp;	unsigned long fp, i7;	unsigned char fenab;	int err;	synchronize_user_stack();	if(tp->w_saved || clear_user(ucp, sizeof(*ucp)))		goto do_sigsegv;#if 1	fenab = 0; /* IMO get_context is like any other system call, thus modifies FPU state -jj */#else	fenab = (current->thread.fpsaved[0] & FPRS_FEF);#endif			mcp = &ucp->uc_mcontext;	grp = &mcp->mc_gregs;	/* Skip over the trap instruction, first. */	regs->tpc   = regs->tnpc;	regs->tnpc += 4;	err = 0;	if (_NSIG_WORDS == 1)		err |= __put_user(current->blocked.sig[0],				  (unsigned long *)&ucp->uc_sigmask);	else		err |= __copy_to_user(&ucp->uc_sigmask, &current->blocked,				      sizeof(sigset_t));	err |= __put_user(regs->tstate, &((*grp)[MC_TSTATE]));	err |= __put_user(regs->tpc, &((*grp)[MC_PC]));	err |= __put_user(regs->tnpc, &((*grp)[MC_NPC]));	err |= __put_user(regs->y, &((*grp)[MC_Y]));	err |= __put_user(regs->u_regs[UREG_G1], &((*grp)[MC_G1]));	err |= __put_user(regs->u_regs[UREG_G2], &((*grp)[MC_G2]));	err |= __put_user(regs->u_regs[UREG_G3], &((*grp)[MC_G3]));	err |= __put_user(regs->u_regs[UREG_G4], &((*grp)[MC_G4]));	err |= __put_user(regs->u_regs[UREG_G5], &((*grp)[MC_G5]));	err |= __put_user(regs->u_regs[UREG_G6], &((*grp)[MC_G6]));	err |= __put_user(regs->u_regs[UREG_G6], &((*grp)[MC_G7]));	err |= __put_user(regs->u_regs[UREG_I0], &((*grp)[MC_O0]));	err |= __put_user(regs->u_regs[UREG_I1], &((*grp)[MC_O1]));	err |= __put_user(regs->u_regs[UREG_I2], &((*grp)[MC_O2]));	err |= __put_user(regs->u_regs[UREG_I3], &((*grp)[MC_O3]));	err |= __put_user(regs->u_regs[UREG_I4], &((*grp)[MC_O4]));	err |= __put_user(regs->u_regs[UREG_I5], &((*grp)[MC_O5]));	err |= __put_user(regs->u_regs[UREG_I6], &((*grp)[MC_O6]));	err |= __put_user(regs->u_regs[UREG_I7], &((*grp)[MC_O7]));	err |= __get_user(fp,		 (&(((struct reg_window *)(STACK_BIAS+regs->u_regs[UREG_I6]))->ins[6])));	err |= __get_user(i7,		 (&(((struct reg_window *)(STACK_BIAS+regs->u_regs[UREG_I6]))->ins[7])));	err |= __put_user(fp, &(mcp->mc_fp));	err |= __put_user(i7, &(mcp->mc_i7));	err |= __put_user(fenab, &(mcp->mc_fpregs.mcfpu_enab));	if(fenab) {		unsigned long *fpregs = (unsigned long *)(((char *)current) + AOFF_task_fpregs);		unsigned long fprs;				fprs = current->thread.fpsaved[0];		if (fprs & FPRS_DL)			err |= copy_to_user(&(mcp->mc_fpregs.mcfpu_fregs), fpregs,					    (sizeof(unsigned int) * 32));		if (fprs & FPRS_DU)			err |= copy_to_user(                          ((unsigned long *)&(mcp->mc_fpregs.mcfpu_fregs))+16, fpregs+16,			  (sizeof(unsigned int) * 32));		err |= __put_user(current->thread.xfsr[0], &(mcp->mc_fpregs.mcfpu_fsr));		err |= __put_user(current->thread.gsr[0], &(mcp->mc_fpregs.mcfpu_gsr));		err |= __put_user(fprs, &(mcp->mc_fpregs.mcfpu_fprs));	}	if (err)		goto do_sigsegv;	return;do_sigsegv:	do_exit(SIGSEGV);}struct rt_signal_frame {	struct sparc_stackf	ss;	siginfo_t		info;	struct pt_regs		regs;	__siginfo_fpu_t *	fpu_save;	stack_t			stack;	sigset_t		mask;	__siginfo_fpu_t		fpu_state;};/* Align macros */#define RT_ALIGNEDSZ  (((sizeof(struct rt_signal_frame) + 7) & (~7)))/* * atomically swap in the new signal mask, and wait for a signal. * This is really tricky on the Sparc, watch out... */asmlinkage void _sigpause_common(old_sigset_t set, struct pt_regs *regs){	sigset_t saveset;#ifdef CONFIG_SPARC32_COMPAT	if (current->thread.flags & SPARC_FLAG_32BIT) {		extern asmlinkage void _sigpause32_common(old_sigset_t32,							  struct pt_regs *);		_sigpause32_common(set, regs);		return;	}#endif	set &= _BLOCKABLE;	spin_lock_irq(&current->sigmask_lock);	saveset = current->blocked;	siginitset(&current->blocked, set);	recalc_sigpending(current);	spin_unlock_irq(&current->sigmask_lock);		regs->tpc = regs->tnpc;	regs->tnpc += 4;	/* Condition codes and return value where set here for sigpause,	 * and so got used by setup_frame, which again causes sigreturn()	 * to return -EINTR.	 */	while (1) {		current->state = TASK_INTERRUPTIBLE;		schedule();		/*		 * Return -EINTR and set condition code here,		 * so the interrupted system call actually returns		 * these.		 */		regs->tstate |= (TSTATE_ICARRY|TSTATE_XCARRY);		regs->u_regs[UREG_I0] = EINTR;		if (do_signal(&saveset, regs, 0, 0))			return;	}}asmlinkage void do_sigpause(unsigned int set, struct pt_regs *regs){	_sigpause_common(set, regs);}asmlinkage void do_sigsuspend(struct pt_regs *regs){	_sigpause_common(regs->u_regs[UREG_I0], regs);}asmlinkage void do_rt_sigsuspend(sigset_t *uset, size_t sigsetsize, struct pt_regs *regs){	sigset_t oldset, set;        	/* XXX: Don't preclude handling different sized sigset_t's.  */	if (sigsetsize != sizeof(sigset_t)) {		regs->tstate |= (TSTATE_ICARRY|TSTATE_XCARRY);		regs->u_regs[UREG_I0] = EINVAL;		return;	}	if (copy_from_user(&set, uset, sizeof(set))) {		regs->tstate |= (TSTATE_ICARRY|TSTATE_XCARRY);		regs->u_regs[UREG_I0] = EFAULT;		return;	}                                                                	sigdelsetmask(&set, ~_BLOCKABLE);	spin_lock_irq(&current->sigmask_lock);	oldset = current->blocked;	current->blocked = set;	recalc_sigpending(current);	spin_unlock_irq(&current->sigmask_lock);		regs->tpc = regs->tnpc;	regs->tnpc += 4;	/* Condition codes and return value where set here for sigpause,	 * and so got used by setup_frame, which again causes sigreturn()	 * to return -EINTR.	 */	while (1) {		current->state = TASK_INTERRUPTIBLE;		schedule();		/*		 * Return -EINTR and set condition code here,		 * so the interrupted system call actually returns		 * these.		 */		regs->tstate |= (TSTATE_ICARRY|TSTATE_XCARRY);		regs->u_regs[UREG_I0] = EINTR;		if (do_signal(&oldset, regs, 0, 0))			return;	}}static inline intrestore_fpu_state(struct pt_regs *regs, __siginfo_fpu_t *fpu){	unsigned long *fpregs = (unsigned long *)(((char *)current) + AOFF_task_fpregs);	unsigned long fprs;	int err;	err = __get_user(fprs, &fpu->si_fprs);	fprs_write(0);	regs->tstate &= ~TSTATE_PEF;	if (fprs & FPRS_DL)		err |= copy_from_user(fpregs, &fpu->si_float_regs[0],		       	       (sizeof(unsigned int) * 32));	if (fprs & FPRS_DU)		err |= copy_from_user(fpregs+16, &fpu->si_float_regs[32],		       	       (sizeof(unsigned int) * 32));	err |= __get_user(current->thread.xfsr[0], &fpu->si_fsr);	err |= __get_user(current->thread.gsr[0], &fpu->si_gsr);	current->thread.fpsaved[0] |= fprs;	return err;}void do_rt_sigreturn(struct pt_regs *regs){	struct rt_signal_frame *sf;	unsigned long tpc, tnpc, tstate;	__siginfo_fpu_t *fpu_save;	sigset_t set;	stack_t st;	int err;	synchronize_user_stack ();	sf = (struct rt_signal_frame *)		(regs->u_regs [UREG_FP] + STACK_BIAS);

⌨️ 快捷键说明

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