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

📄 process.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
				break;			case SIGTRAP:				relay_signal(SIGTRAP, regs);				break;			case SIGIO:			case SIGVTALRM:			case SIGILL:			case SIGBUS:			case SIGFPE:			case SIGWINCH:                                user_signal(WSTOPSIG(status), regs, pid);				break;			default:			        printk("userspace - child stopped with signal "				       "%d\n", WSTOPSIG(status));			}			pid = userspace_pid[0];			interrupt_end();			/* Avoid -ERESTARTSYS handling in host */			PT_SYSCALL_NR(regs->skas.regs) = -1;		}	}}#define INIT_JMP_NEW_THREAD 0#define INIT_JMP_REMOVE_SIGSTACK 1#define INIT_JMP_CALLBACK 2#define INIT_JMP_HALT 3#define INIT_JMP_REBOOT 4int copy_context_skas0(unsigned long new_stack, int pid){	int err;	unsigned long regs[MAX_REG_NR];	unsigned long current_stack = current_stub_stack();	struct stub_data *data = (struct stub_data *) current_stack;	struct stub_data *child_data = (struct stub_data *) new_stack;	__u64 new_offset;	int new_fd = phys_mapping(to_phys((void *)new_stack), &new_offset);	/* prepare offset and fd of child's stack as argument for parent's	 * and child's mmap2 calls	 */	*data = ((struct stub_data) { .offset	= MMAP_OFFSET(new_offset),				      .fd	= new_fd,				      .timer	= ((struct itimerval)					           { { 0, 1000000 / hz() },						     { 0, 1000000 / hz() }})});	get_safe_registers(regs);	/* Set parent's instruction pointer to start of clone-stub */	regs[REGS_IP_INDEX] = UML_CONFIG_STUB_CODE +				(unsigned long) stub_clone_handler -				(unsigned long) &__syscall_stub_start;	regs[REGS_SP_INDEX] = UML_CONFIG_STUB_DATA + PAGE_SIZE -		sizeof(void *);	err = ptrace_setregs(pid, regs);	if(err < 0)		panic("copy_context_skas0 : PTRACE_SETREGS failed, "		      "pid = %d, errno = %d\n", pid, errno);	/* set a well known return code for detection of child write failure */	child_data->err = 12345678;	/* Wait, until parent has finished its work: read child's pid from	 * parent's stack, and check, if bad result.	 */	wait_stub_done(pid, 0, "copy_context_skas0");	pid = data->err;	if(pid < 0)		panic("copy_context_skas0 - stub-parent reports error %d\n",		      pid);	/* Wait, until child has finished too: read child's result from	 * child's stack and check it.	 */	wait_stub_done(pid, -1, "copy_context_skas0");	if (child_data->err != UML_CONFIG_STUB_DATA)		panic("copy_context_skas0 - stub-child reports error %d\n",		      child_data->err);	if (ptrace(PTRACE_OLDSETOPTIONS, pid, NULL,		   (void *)PTRACE_O_TRACESYSGOOD) < 0)		panic("copy_context_skas0 : PTRACE_SETOPTIONS failed, "		      "errno = %d\n", errno);	return pid;}/* * This is used only, if stub pages are needed, while proc_mm is * availabl. Opening /proc/mm creates a new mm_context, which lacks * the stub-pages. Thus, we map them using /proc/mm-fd */void map_stub_pages(int fd, unsigned long code,		    unsigned long data, unsigned long stack){	struct proc_mm_op mmop;	int n;	mmop = ((struct proc_mm_op) { .op        = MM_MMAP,				      .u         =				      { .mmap    =					{ .addr    = code,					  .len     = PAGE_SIZE,					  .prot    = PROT_EXEC,					  .flags   = MAP_FIXED | MAP_PRIVATE,					  .fd      = stub_code_fd,					  .offset  = stub_code_offset	} } });	n = os_write_file(fd, &mmop, sizeof(mmop));	if(n != sizeof(mmop))		panic("map_stub_pages : /proc/mm map for code failed, "		      "err = %d\n", -n);	if ( stack ) {		__u64 map_offset;		int map_fd = phys_mapping(to_phys((void *)stack), &map_offset);		mmop = ((struct proc_mm_op)				{ .op        = MM_MMAP,				  .u         =				  { .mmap    =				    { .addr    = data,				      .len     = PAGE_SIZE,				      .prot    = PROT_READ | PROT_WRITE,				      .flags   = MAP_FIXED | MAP_SHARED,				      .fd      = map_fd,				      .offset  = map_offset		} } });		n = os_write_file(fd, &mmop, sizeof(mmop));		if(n != sizeof(mmop))			panic("map_stub_pages : /proc/mm map for data failed, "			      "err = %d\n", -n);	}}void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr,		void (*handler)(int)){	unsigned long flags;	sigjmp_buf switch_buf, fork_buf;	*switch_buf_ptr = &switch_buf;	*fork_buf_ptr = &fork_buf;	/* Somewhat subtle - siglongjmp restores the signal mask before doing	 * the longjmp.  This means that when jumping from one stack to another	 * when the target stack has interrupts enabled, an interrupt may occur	 * on the source stack.  This is bad when starting up a process because	 * it's not supposed to get timer ticks until it has been scheduled.	 * So, we disable interrupts around the sigsetjmp to ensure that	 * they can't happen until we get back here where they are safe.	 */	flags = get_signals();	block_signals();	if(sigsetjmp(fork_buf, 1) == 0)		new_thread_proc(stack, handler);	remove_sigstack();	set_signals(flags);}void thread_wait(void *sw, void *fb){	sigjmp_buf buf, **switch_buf = sw, *fork_buf;	*switch_buf = &buf;	fork_buf = fb;	if(sigsetjmp(buf, 1) == 0)		siglongjmp(*fork_buf, INIT_JMP_REMOVE_SIGSTACK);}void switch_threads(void *me, void *next){	sigjmp_buf my_buf, **me_ptr = me, *next_buf = next;		*me_ptr = &my_buf;	if(sigsetjmp(my_buf, 1) == 0)		siglongjmp(*next_buf, 1);}static sigjmp_buf initial_jmpbuf;/* XXX Make these percpu */static void (*cb_proc)(void *arg);static void *cb_arg;static sigjmp_buf *cb_back;int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr){	sigjmp_buf **switch_buf = switch_buf_ptr;	int n;	set_handler(SIGWINCH, (__sighandler_t) sig_handler,		    SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGALRM,		    SIGVTALRM, -1);	*fork_buf_ptr = &initial_jmpbuf;	n = sigsetjmp(initial_jmpbuf, 1);        switch(n){        case INIT_JMP_NEW_THREAD:                new_thread_proc((void *) stack, new_thread_handler);                break;        case INIT_JMP_REMOVE_SIGSTACK:                remove_sigstack();                break;        case INIT_JMP_CALLBACK:		(*cb_proc)(cb_arg);		siglongjmp(*cb_back, 1);                break;        case INIT_JMP_HALT:		kmalloc_ok = 0;		return(0);        case INIT_JMP_REBOOT:		kmalloc_ok = 0;		return(1);        default:                panic("Bad sigsetjmp return in start_idle_thread - %d\n", n);	}	siglongjmp(**switch_buf, 1);}void remove_sigstack(void){	stack_t stack = ((stack_t) { .ss_flags	= SS_DISABLE,				     .ss_sp	= NULL,				     .ss_size	= 0 });	if(sigaltstack(&stack, NULL) != 0)		panic("disabling signal stack failed, errno = %d\n", errno);}void initial_thread_cb_skas(void (*proc)(void *), void *arg){	sigjmp_buf here;	cb_proc = proc;	cb_arg = arg;	cb_back = &here;	block_signals();	if(sigsetjmp(here, 1) == 0)		siglongjmp(initial_jmpbuf, INIT_JMP_CALLBACK);	unblock_signals();	cb_proc = NULL;	cb_arg = NULL;	cb_back = NULL;}void halt_skas(void){	block_signals();	siglongjmp(initial_jmpbuf, INIT_JMP_HALT);}void reboot_skas(void){	block_signals();	siglongjmp(initial_jmpbuf, INIT_JMP_REBOOT);}void switch_mm_skas(struct mm_id *mm_idp){	int err;#warning need cpu pid in switch_mm_skas	if(proc_mm){		err = ptrace(PTRACE_SWITCH_MM, userspace_pid[0], 0,			     mm_idp->u.mm_fd);		if(err)			panic("switch_mm_skas - PTRACE_SWITCH_MM failed, "			      "errno = %d\n", errno);	}	else userspace_pid[0] = mm_idp->u.pid;}/* * Overrides for Emacs so that we follow Linus's tabbing style. * Emacs will notice this stuff at the end of the file and automatically * adjust the settings for this buffer only.  This must remain at the end * of the file. * --------------------------------------------------------------------------- * Local variables: * c-file-style: "linux" * End: */

⌨️ 快捷键说明

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