]> git.neil.brown.name Git - history.git/commitdiff
PPC32: Add a thread-pointer argument to the clone syscall, make a prepare_to_copy().
authorPaul Mackerras <paulus@samba.org>
Thu, 13 Mar 2003 09:28:56 +0000 (20:28 +1100)
committerPaul Mackerras <paulus@samba.org>
Thu, 13 Mar 2003 09:28:56 +0000 (20:28 +1100)
The thread-pointer argument gets copied to R2 in the child in copy_thread() if
the CLONE_SETTLS flag is set.  Adding a prepare_to_copy simplifies the copy_thread
logic since we don't have to do the extra copy of fpu/altivec state to the child.

arch/ppc/kernel/process.c
include/asm-ppc/processor.h

index 803c73301b9de10d676aa91ef04b017ee943a3f7..a821de2750806b92f74ee64adf00778e1415a893 100644 (file)
@@ -320,6 +320,24 @@ release_thread(struct task_struct *t)
 {
 }
 
+/*
+ * This gets called before we allocate a new thread and copy
+ * the current task into it.
+ */
+void prepare_to_copy(struct task_struct *tsk)
+{
+       struct pt_regs *regs = tsk->thread.regs;
+
+       if (regs == NULL)
+               return;
+       if (regs->msr & MSR_FP)
+               giveup_fpu(current);
+#ifdef CONFIG_ALTIVEC
+       if (regs->msr & MSR_VEC)
+               giveup_altivec(current);
+#endif /* CONFIG_ALTIVEC */
+}
+
 /*
  * Copy a thread..
  */
@@ -348,6 +366,8 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
        } else {
                childregs->gpr[1] = usp;
                p->thread.regs = childregs;
+               if (clone_flags & CLONE_SETTLS)
+                       childregs->gpr[2] = childregs->gpr[6];
        }
        childregs->gpr[3] = 0;  /* Result from fork() */
        sp -= STACK_FRAME_OVERHEAD;
@@ -367,29 +387,6 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
        p->thread.ksp = sp;
        kregs->nip = (unsigned long)ret_from_fork;
 
-       /*
-        * copy fpu info - assume lazy fpu switch now always
-        *  -- Cort
-        */
-       if (regs->msr & MSR_FP) {
-               giveup_fpu(current);
-               childregs->msr &= ~(MSR_FP | MSR_FE0 | MSR_FE1);
-       }
-       memcpy(&p->thread.fpr, &current->thread.fpr, sizeof(p->thread.fpr));
-       p->thread.fpscr = current->thread.fpscr;
-
-#ifdef CONFIG_ALTIVEC
-       /*
-        * copy altiVec info - assume lazy altiVec switch
-        * - kumar
-        */
-       if (regs->msr & MSR_VEC)
-               giveup_altivec(current);
-       memcpy(&p->thread.vr, &current->thread.vr, sizeof(p->thread.vr));
-       p->thread.vscr = current->thread.vscr;
-       childregs->msr &= ~MSR_VEC;
-#endif /* CONFIG_ALTIVEC */
-
        p->thread.last_syscall = -1;
 
        return 0;
@@ -444,15 +441,17 @@ int get_fpexc_mode(struct task_struct *tsk, unsigned long adr)
        return put_user(val, (unsigned int *) adr);
 }
 
-int sys_clone(int p1, int p2, int p3, int p4, int p5, int p6,
+int sys_clone(unsigned long clone_flags, unsigned long usp, int *parent_tidp,
+             void *child_threadptr, int *child_tidp, int p6,
              struct pt_regs *regs)
 {
        struct task_struct *p;
 
        CHECK_FULL_REGS(regs);
-       if (p2 == 0)
-               p2 = regs->gpr[1];      /* stack pointer for child */
-       p = do_fork(p1 & ~CLONE_IDLETASK, p2, regs, 0, (int *)p3, (int *)p4);
+       if (usp == 0)
+               usp = regs->gpr[1];     /* stack pointer for child */
+       p = do_fork(clone_flags & ~CLONE_IDLETASK, usp, regs, 0,
+                   parent_tidp, child_tidp);
        return IS_ERR(p) ? PTR_ERR(p) : p->pid;
 }
 
index 18d3995bc586ad4202f22d62492beccb38c9a803..a61bf98d0843831bb8bd0afd4a2274d497b5b07c 100644 (file)
@@ -609,7 +609,7 @@ void start_thread(struct pt_regs *regs, unsigned long nip, unsigned long sp);
 void release_thread(struct task_struct *);
 
 /* Prepare to copy thread state - unlazy all lazy status */
-#define prepare_to_copy(tsk)   do { } while (0)
+extern void prepare_to_copy(struct task_struct *tsk);
 
 /*
  * Create a new kernel thread.