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

📄 signal.c

📁 这个linux源代码是很全面的~基本完整了~使用c编译的~由于时间问题我没有亲自测试~但就算用来做参考资料也是非常好的
💻 C
📖 第 1 页 / 共 2 页
字号:
		asm ("mfsp %%sr3,%0" : "=r" (sid));		DBG(("flushing 64 bytes at space %#x offset %p\n",		       sid, frame->tramp));	}#endif#if CACHE_FLUSHING_IS_NOT_BROKEN	flush_icache_range((unsigned long) &frame->tramp[0],			   (unsigned long) &frame->tramp[4]);#else	/* It should *always* be cache line-aligned, but the compiler           sometimes screws up. */	asm volatile("fdc 0(%%sr3,%0)\n\t"		     "fdc %1(%%sr3,%0)\n\t"		     "sync\n\t"		     "fic 0(%%sr3,%0)\n\t"		     "fic %1(%%sr3,%0)\n\t"		     "sync\n\t"		     : : "r" (frame->tramp), "r" (L1_CACHE_BYTES));#endif	rp = (unsigned long) frame->tramp;	if (err)		goto give_sigsegv;#ifdef __LP64__/* Much more has to happen with signals than this -- but it'll at least *//* provide a pointer to some places which definitely need a look. */#define HACK unsigned int#else#define HACK unsigned long#endif	haddr = (HACK) ka->sa.sa_handler;	/* ARGH!  Fucking brain damage.  You don't want to know. */	if (haddr & 2) {		HACK *plabel;		HACK ltp;		plabel = (HACK *) (haddr & ~3);		err |= __get_user(haddr, plabel);		err |= __get_user(ltp, plabel + 1);		if (err)			goto give_sigsegv;		regs->gr[19] = ltp;	}	/* The syscall return path will create IAOQ values from r31.	 */	if (in_syscall)		regs->gr[31] = (HACK) haddr;	else {		regs->gr[0] = USER_PSW;		regs->iaoq[0] = (HACK) haddr | 3;		regs->iaoq[1] = regs->iaoq[0] + 4;	}	regs->gr[2]  = rp;                /* userland return pointer */	regs->gr[26] = sig;               /* signal number */	regs->gr[25] = (HACK) &frame->info; /* siginfo pointer */	regs->gr[24] = (HACK) &frame->uc;   /* ucontext pointer */	DBG(("making sigreturn frame: %#lx + %#x = %#lx\n",	       regs->gr[30], PARISC_RT_SIGFRAME_SIZE,	       regs->gr[30] + PARISC_RT_SIGFRAME_SIZE));	/* Raise the user stack pointer to make a proper call frame. */	regs->gr[30] = ((HACK) frame + PARISC_RT_SIGFRAME_SIZE);	DBG(("SIG deliver (%s:%d): frame=0x%p sp=%#lx iaoq=%#lx/%#lx rp=%#lx\n",	       current->comm, current->pid, frame, regs->gr[30],	       regs->iaoq[0], regs->iaoq[1], rp));	return 1;give_sigsegv:	DBG(("setup_rt_frame sending SIGSEGV\n"));	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;}/* * OK, we're invoking a handler. */	static longhandle_signal(unsigned long sig, struct k_sigaction *ka,	      siginfo_t *info, sigset_t *oldset,	      struct pt_regs *regs, int in_syscall){	DBG(("handle_signal(sig=%ld, ka=%p, info=%p, oldset=%p, regs=%p)\n",	       sig, ka, info, oldset, regs));		/* Set up the stack frame */	if (!setup_rt_frame(sig, ka, info, oldset, regs, in_syscall))		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(&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);	}	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. * * We need to be able to restore the syscall arguments (r21-r26) to * restart syscalls.  Thus, the syscall path should save them in the * pt_regs structure (it's okay to do so since they are caller-save * registers).  As noted below, the syscall number gets restored for * us due to the magic of delayed branching. */asmlinkage intdo_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall){	siginfo_t info;	struct k_sigaction *ka;	DBG(("do_signal(oldset=0x%p, regs=0x%p, sr7 %#lx, pending %d, in_syscall=%d\n",	       oldset, regs, regs->sr[7], current->sigpending, in_syscall));	/* Everyone else checks to see if they are in kernel mode at	   this point and exits if that's the case.  I'm not sure why	   we would be called in that case, but for some reason we	   are. */	if (!oldset)		oldset = &current->blocked;	DBG(("do_signal: oldset %08lx:%08lx\n", 		oldset->sig[0], oldset->sig[1]));	for (;;) {		unsigned long signr;		spin_lock_irq(&current->sigmask_lock);		signr = dequeue_signal(&current->blocked, &info);		spin_unlock_irq(&current->sigmask_lock);		DBG(("do_signal: signr=%ld, pid=%d\n", signr, current->pid));		if (!signr)			break;		if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) {			/* Let the debugger run.  */			current->exit_code = signr;			set_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];		DBG(("sa_handler is %x\n", 			(unsigned int) ka->sa.sa_handler));		if (ka->sa.sa_handler == SIG_IGN) {			if (signr != SIGCHLD)				continue;			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:				set_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 (signr == SIGQUIT) /* Userspace debugging */					show_regs(regs);				if (do_coredump(signr, regs))					exit_code |= 0x80;				/* FALLTHRU */			default:				sig_exit(signr, exit_code, &info);				/* NOTREACHED */			}		}		/* Restart a system call if necessary. */		if (in_syscall) {			/* Check the return code */			switch (regs->gr[28]) {			case -ERESTARTNOHAND:				DBG(("ERESTARTNOHAND: returning -EINTR\n"));				regs->gr[28] = -EINTR;				break;			case -ERESTARTSYS:				if (!(ka->sa.sa_flags & SA_RESTART)) {					DBG(("ERESTARTSYS: putting -EINTR\n"));					regs->gr[28] = -EINTR;					break;				}			/* fallthrough */			case -ERESTARTNOINTR:				/* A syscall is just a branch, so all                                   we have to do is fiddle the return                                   pointer. */				regs->gr[31] -= 8; /* delayed branching */				/* Preserve original r28. */				regs->gr[28] = regs->orig_r28;				break;			}		}		/* 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, regs, in_syscall)) {			DBG((KERN_DEBUG				"Exiting do_signal (success), regs->gr[28] = %ld\n",				regs->gr[28]));			return 1;		}	}	/* Did we come from a system call? */	if (in_syscall) {		/* Restart the system call - no handlers present */		if (regs->gr[28] == -ERESTARTNOHAND ||		    regs->gr[28] == -ERESTARTSYS ||		    regs->gr[28] == -ERESTARTNOINTR) {			/* Hooray for delayed branching.  We don't                           have to restore %r20 (the system call                           number) because it gets loaded in the delay                           slot of the branch external instruction. */			regs->gr[31] -= 8;			/* Preserve original r28. */			regs->gr[28] = regs->orig_r28;		}	}		DBG(("Exiting do_signal (not delivered), regs->gr[28] = %ld\n", 		regs->gr[28]));	return 0;}

⌨️ 快捷键说明

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