diff options
Diffstat (limited to 'arch/m32r/kernel/process.c')
| -rw-r--r-- | arch/m32r/kernel/process.c | 126 | 
1 files changed, 17 insertions, 109 deletions
diff --git a/arch/m32r/kernel/process.c b/arch/m32r/kernel/process.c index e7366276ef30..765d0f57c787 100644 --- a/arch/m32r/kernel/process.c +++ b/arch/m32r/kernel/process.c @@ -165,41 +165,6 @@ void show_regs(struct pt_regs * regs)  }  /* - * Create a kernel thread - */ - -/* - * This is the mechanism for creating a new kernel thread. - * - * NOTE! Only a kernel-only process(ie the swapper or direct descendants - * who haven't done an "execve()") should use this: it will work within - * a system call from a "real" process, but the process memory space will - * not be free'd until both the parent and the child have exited. - */ -static void kernel_thread_helper(void *nouse, int (*fn)(void *), void *arg) -{ -	fn(arg); -	do_exit(-1); -} - -int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) -{ -	struct pt_regs regs; - -	memset(®s, 0, sizeof (regs)); -	regs.r1 = (unsigned long)fn; -	regs.r2 = (unsigned long)arg; - -	regs.bpc = (unsigned long)kernel_thread_helper; - -	regs.psw = M32R_PSW_BIE; - -	/* Ok, create the new process. */ -	return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, 0, NULL, -		NULL); -} - -/*   * Free current thread data structures etc..   */  void exit_thread(void) @@ -227,88 +192,31 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu)  }  int copy_thread(unsigned long clone_flags, unsigned long spu, -	unsigned long unused, struct task_struct *tsk, struct pt_regs *regs) +	unsigned long arg, struct task_struct *tsk)  {  	struct pt_regs *childregs = task_pt_regs(tsk);  	extern void ret_from_fork(void); - -	/* Copy registers */ -	*childregs = *regs; - -	childregs->spu = spu; -	childregs->r0 = 0;	/* Child gets zero as return value */ -	regs->r0 = tsk->pid; +	extern void ret_from_kernel_thread(void); + +	if (unlikely(tsk->flags & PF_KTHREAD)) { +		memset(childregs, 0, sizeof(struct pt_regs)); +		childregs->psw = M32R_PSW_BIE; +		childregs->r1 = spu;	/* fn */ +		childregs->r0 = arg; +		tsk->thread.lr = (unsigned long)ret_from_kernel_thread; +	} else { +		/* Copy registers */ +		*childregs = *current_pt_regs(); +		if (spu) +			childregs->spu = spu; +		childregs->r0 = 0;	/* Child gets zero as return value */ +		tsk->thread.lr = (unsigned long)ret_from_fork; +	}  	tsk->thread.sp = (unsigned long)childregs; -	tsk->thread.lr = (unsigned long)ret_from_fork;  	return 0;  } -asmlinkage int sys_fork(unsigned long r0, unsigned long r1, unsigned long r2, -	unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6, -	struct pt_regs regs) -{ -#ifdef CONFIG_MMU -	return do_fork(SIGCHLD, regs.spu, ®s, 0, NULL, NULL); -#else -	return -EINVAL; -#endif /* CONFIG_MMU */ -} - -asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp, -			 unsigned long parent_tidptr, -			 unsigned long child_tidptr, -			 unsigned long r4, unsigned long r5, unsigned long r6, -			 struct pt_regs regs) -{ -	if (!newsp) -		newsp = regs.spu; - -	return do_fork(clone_flags, newsp, ®s, 0, -		       (int __user *)parent_tidptr, (int __user *)child_tidptr); -} - -/* - * This is trivial, and on the face of it looks like it - * could equally well be done in user mode. - * - * Not so, for quite unobvious reasons - register pressure. - * In user mode vfork() cannot have a stack frame, and if - * done by calling the "clone()" system call directly, you - * do not have enough call-clobbered registers to hold all - * the information you need. - */ -asmlinkage int sys_vfork(unsigned long r0, unsigned long r1, unsigned long r2, -	unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6, -	struct pt_regs regs) -{ -	return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.spu, ®s, 0, -			NULL, NULL); -} - -/* - * sys_execve() executes a new program. - */ -asmlinkage int sys_execve(const char __user *ufilename, -			  const char __user *const __user *uargv, -			  const char __user *const __user *uenvp, -			  unsigned long r3, unsigned long r4, unsigned long r5, -			  unsigned long r6, struct pt_regs regs) -{ -	int error; -	struct filename *filename; - -	filename = getname(ufilename); -	error = PTR_ERR(filename); -	if (IS_ERR(filename)) -		goto out; - -	error = do_execve(filename->name, uargv, uenvp, ®s); -	putname(filename); -out: -	return error; -} -  /*   * These bracket the sleeping functions..   */  |