]> rtime.felk.cvut.cz Git - l4.git/blobdiff - l4/pkg/uclibc/lib/contrib/uclibc/libc/sysdeps/linux/powerpc/clone.S
update
[l4.git] / l4 / pkg / uclibc / lib / contrib / uclibc / libc / sysdeps / linux / powerpc / clone.S
index 15d03f6790d0343a6a72e78c704784ac0816e891..307053fe50b69fb8f321a63af61f90d66603a5f3 100644 (file)
    02111-1307 USA.  */
 
 #include <features.h>
-#include "ppc_asm.h"
 #define _ERRNO_H       1
 #include <bits/errno.h>
-#include <sys/syscall.h>
+#include <sysdep.h>
+
+#define CLONE_VM       0x00000100
+#define CLONE_THREAD   0x00010000
 
 /* This is the only really unusual system call in PPC linux, but not
    because of any weirdness in the system call itself; because of
    all the freaky stuff we have to do to make the call useful.  */
 
 /* int [r3] clone(int (*fn)(void *arg) [r3], void *child_stack [r4],
-                 int flags [r5], void *arg [r6]); */
+                 int flags [r5], void *arg [r6], void *parent_tid [r7],
+                 void *tls [r8], void *child_tid [r9]); */
 
 #ifdef __NR_clone
-       .globl clone
-       .type clone,@function
+       .globl __clone
+       .type __clone,@function
        .align 2
 
-clone:
+__clone:
        /* Check for child_stack == NULL || fn == NULL.  */
        cmpwi   cr0,r4,0
        cmpwi   cr1,r3,0
@@ -44,22 +47,44 @@ clone:
 
        /* Set up stack frame for parent.  */
        stwu    r1,-32(r1)
+       cfi_adjust_cfa_offset (32)
+#ifdef RESET_PID
+       stmw    r28,16(r1)
+#else
+# ifdef __ASSUME_FIXED_CLONE_SYSCALL
        stmw    r29,16(r1)
-       
+# else
+       stmw    r30,16(r1)
+# endif
+#endif
+
        /* Set up stack frame for child.  */
        clrrwi  r4,r4,4
        li      r0,0
        stwu    r0,-16(r4)
 
        /* Save fn, args, stack across syscall.  */
-       mr      r29,r3                  /* Function in r29.  */
-       mr      r30,r4                  /* Stack pointer in r30.  */
+       mr      r30,r3                  /* Function in r30.  */
+#ifndef __ASSUME_FIXED_CLONE_SYSCALL
+       mr      r29,r4                  /* Stack pointer in r29.  */
+#endif
+#ifdef RESET_PID
+       mr      r28,r5
+#endif
        mr      r31,r6                  /* Argument in r31.  */
 
        /* 'flags' argument is first parameter to clone syscall. (The other
           argument is the stack pointer, already in r4.)  */
        mr      r3,r5
 
+       /* Move the parent_tid, child_tid and tls arguments. */
+       mr      r5,r7
+       mr      r6,r8
+       mr      r7,r9
+
+       /* End FDE now, because in the child the unwind info will be wrong.  */
+       cfi_endproc
+
        /* Do the call.  */
        li 0, __NR_clone
        sc
@@ -69,13 +94,27 @@ clone:
        crandc  cr1*4+eq,cr1*4+eq,cr0*4+so
        bne-    cr1,.Lparent            /* The '-' is to minimise the race.  */
 
+#ifndef __ASSUME_FIXED_CLONE_SYSCALL
        /* On at least mklinux DR3a5, clone() doesn't actually change
           the stack pointer.  I'm pretty sure this is a bug, because
           it adds a race condition if a signal is sent to a thread
           just after it is created (in the previous three instructions).  */
-       mr      r1,r30
+       mr      r1,r29
+#endif
+
+#ifdef RESET_PID
+       andis.  r0,r28,CLONE_THREAD>>16
+       bne+    r0,.Loldpid
+       andi.   r0,r28,CLONE_VM
+       li      r3,-1
+       bne-    r0,.Lnomoregetpid
+.Lnomoregetpid:
+       stw     r3,TID(r2)
+       stw     r3,PID(r2)
+.Loldpid:
+#endif
        /* Call procedure.  */
-       mtctr   r29
+       mtctr   r30
        mr      r3,r31
        bctrl
        /* Call _exit with result from procedure.  */
@@ -83,16 +122,24 @@ clone:
 
 .Lparent:
        /* Parent.  Restore registers & return.  */
+#ifdef RESET_PID
+       lmw     r28,16(r1)
+#else
+# ifndef __ASSUME_FIXED_CLONE_SYSCALL
        lmw     r29,16(r1)
+# else
+       lmw     r30,16(r1)
+# endif
+#endif
        addi    r1,r1,32
        bnslr+
-
        b       __syscall_error
 
 .Lbadargs:
        li      r3,EINVAL
-
        b       __syscall_error
 
-       .size clone,.-clone
+       cfi_startproc
+       .size __clone,.-__clone
+weak_alias(__clone, clone)
 #endif