alpha: reorganize copy_process(), prepare to saner fork_idle()
[cascardo/linux.git] / arch / alpha / kernel / process.c
index 51987dc..a4dc79b 100644 (file)
@@ -246,19 +246,17 @@ release_thread(struct task_struct *dead_task)
 int
 alpha_clone(unsigned long clone_flags, unsigned long usp,
            int __user *parent_tid, int __user *child_tid,
-           unsigned long tls_value, struct pt_regs *regs)
+           unsigned long tls_value)
 {
-       if (!usp)
-               usp = rdusp();
-
-       return do_fork(clone_flags, usp, regs, 0, parent_tid, child_tid);
+       return do_fork(clone_flags, usp, current_pt_regs(), 0,
+                       parent_tid, child_tid);
 }
 
 int
-alpha_vfork(struct pt_regs *regs)
+alpha_vfork(void)
 {
-       return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(),
-                      regs, 0, NULL, NULL);
+       return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, 0,
+                      current_pt_regs(), 0, NULL, NULL);
 }
 
 /*
@@ -268,18 +266,22 @@ alpha_vfork(struct pt_regs *regs)
 int
 copy_thread(unsigned long clone_flags, unsigned long usp,
            unsigned long arg,
-           struct task_struct * p, struct pt_regs * regs)
+           struct task_struct *p, struct pt_regs *wontuse)
 {
        extern void ret_from_fork(void);
        extern void ret_from_kernel_thread(void);
 
        struct thread_info *childti = task_thread_info(p);
        struct pt_regs *childregs = task_pt_regs(p);
+       struct pt_regs *regs = current_pt_regs();
        struct switch_stack *childstack, *stack;
        unsigned long settls;
 
        childstack = ((struct switch_stack *) childregs) - 1;
-       if (unlikely(!regs)) {
+       childti->pcb.ksp = (unsigned long) childstack;
+       childti->pcb.flags = 1; /* set FEN, clear everything else */
+
+       if (unlikely(p->flags & PF_KTHREAD)) {
                /* kernel thread */
                memset(childstack, 0,
                        sizeof(struct switch_stack) + sizeof(struct pt_regs));
@@ -288,12 +290,17 @@ copy_thread(unsigned long clone_flags, unsigned long usp,
                childstack->r10 = arg;
                childregs->hae = alpha_mv.hae_cache,
                childti->pcb.usp = 0;
-               childti->pcb.ksp = (unsigned long) childstack;
-               childti->pcb.flags = 1; /* set FEN, clear everything else */
                return 0;
        }
+       /* Note: if CLONE_SETTLS is not set, then we must inherit the
+          value from the parent, which will have been set by the block
+          copy in dup_task_struct.  This is non-intuitive, but is
+          required for proper operation in the case of a threaded
+          application calling fork.  */
+       if (clone_flags & CLONE_SETTLS)
+               childti->pcb.unique = regs->r20;
+       childti->pcb.usp = usp ?: rdusp();
        *childregs = *regs;
-       settls = regs->r20;
        childregs->r0 = 0;
        childregs->r19 = 0;
        childregs->r20 = 1;     /* OSF/1 has some strange fork() semantics.  */
@@ -301,22 +308,6 @@ copy_thread(unsigned long clone_flags, unsigned long usp,
        stack = ((struct switch_stack *) regs) - 1;
        *childstack = *stack;
        childstack->r26 = (unsigned long) ret_from_fork;
-       childti->pcb.usp = usp;
-       childti->pcb.ksp = (unsigned long) childstack;
-       childti->pcb.flags = 1; /* set FEN, clear everything else */
-
-       /* Set a new TLS for the child thread?  Peek back into the
-          syscall arguments that we saved on syscall entry.  Oops,
-          except we'd have clobbered it with the parent/child set
-          of r20.  Read the saved copy.  */
-       /* Note: if CLONE_SETTLS is not set, then we must inherit the
-          value from the parent, which will have been set by the block
-          copy in dup_task_struct.  This is non-intuitive, but is
-          required for proper operation in the case of a threaded
-          application calling fork.  */
-       if (clone_flags & CLONE_SETTLS)
-               childti->pcb.unique = settls;
-
        return 0;
 }