alpha: fix crash if pthread_create races with signal delivery
[pandora-kernel.git] / arch / alpha / kernel / process.c
index 89bbe5b..42c2481 100644 (file)
@@ -279,7 +279,7 @@ copy_thread(unsigned long clone_flags, unsigned long usp,
        struct thread_info *childti = task_thread_info(p);
        struct pt_regs * childregs;
        struct switch_stack * childstack, *stack;
-       unsigned long stack_offset, settls;
+       unsigned long stack_offset;
 
        stack_offset = PAGE_SIZE - sizeof(struct pt_regs);
        if (!(regs->ps & 8))
@@ -288,11 +288,9 @@ copy_thread(unsigned long clone_flags, unsigned long usp,
          (stack_offset + PAGE_SIZE + task_stack_page(p));
                
        *childregs = *regs;
-       settls = regs->r20;
        childregs->r0 = 0;
        childregs->r19 = 0;
        childregs->r20 = 1;     /* OSF/1 has some strange fork() semantics.  */
-       regs->r20 = 0;
        stack = ((struct switch_stack *) regs) - 1;
        childstack = ((struct switch_stack *) childregs) - 1;
        *childstack = *stack;
@@ -302,16 +300,16 @@ copy_thread(unsigned long clone_flags, unsigned long usp,
        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.  */
+          syscall arguments that we saved on syscall entry. */
        /* 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;
+               childti->pcb.unique = regs->r20;
+       else
+               regs->r20 = 0;  /* OSF/1 has some strange fork() semantics.  */
 
        return 0;
 }