Home | History | Annotate | Download | only in bionic
      1 #include <asm/unistd.h>
      2 #include <machine/asm.h>
      3 
      4 // int  __pthread_clone(void* (*fn)(void*), void* tls, int flags, void* arg);
      5 ENTRY(__pthread_clone)
      6         pushl   %ebx
      7         pushl   %ecx
      8         movl    16(%esp), %ecx
      9 
     10         # save tls
     11         movl    %ecx, %ebx
     12         # 16-byte alignment on child stack
     13         andl    $~15, %ecx
     14 
     15         # insert arguments onto the child stack
     16         movl    12(%esp), %eax
     17         movl    %eax, -16(%ecx)
     18         movl    24(%esp), %eax
     19         movl    %eax, -12(%ecx)
     20         movl    %ebx, -8(%ecx)
     21 
     22         subl    $16, %ecx
     23         movl    20(%esp), %ebx
     24 
     25         # make system call
     26         movl    $__NR_clone, %eax
     27         int     $0x80
     28 
     29         cmpl    $0, %eax
     30         je      pc_child
     31         jg      pc_parent
     32 
     33         # an error occurred, set errno and return -1
     34         negl    %eax
     35         pushl   %eax
     36         call    __set_errno
     37         addl    $4, %esp
     38         orl     $-1, %eax
     39         jmp     pc_return
     40 
     41 pc_child:
     42         # we're in the child thread now, call __thread_entry
     43         # with the appropriate arguments on the child stack
     44         # we already placed most of them
     45         call    __thread_entry
     46         hlt
     47 
     48 pc_parent:
     49         # we're the parent; nothing to do.
     50 pc_return:
     51         popl    %ecx
     52         popl    %ebx
     53         ret
     54 END(__pthread_clone)
     55 
     56 
     57 /*
     58  * int  __bionic_clone(unsigned long clone_flags,
     59  *                     void*         newsp,
     60  *                     int           *parent_tidptr,
     61  *                     void          *new_tls,
     62  *                     int           *child_tidptr,
     63  *                     int           (*fn)(void *),
     64  *                     void          *arg);
     65  */
     66 ENTRY(__bionic_clone)
     67         pushl   %ebx
     68         pushl   %esi
     69         pushl   %edi
     70 
     71         # insert arguments onto the child stack
     72         movl    20(%esp), %ecx
     73         andl    $~15, %ecx
     74         movl    36(%esp), %eax
     75         movl    %eax, -16(%ecx)
     76         movl    40(%esp), %eax
     77         movl    %eax, -12(%ecx)
     78 
     79         subl    $16, %ecx
     80         movl    16(%esp), %ebx
     81         movl    24(%esp), %edx
     82         movl    32(%esp), %esi
     83         movl    28(%esp), %edi
     84 
     85         # make system call
     86         movl    $__NR_clone, %eax
     87         int     $0x80
     88 
     89         cmpl    $0, %eax
     90         je      bc_child
     91         jg      bc_parent
     92 
     93         # an error occurred, set errno and return -1
     94         negl    %eax
     95         pushl   %eax
     96         call    __set_errno
     97         addl    $4, %esp
     98         orl     $-1, %eax
     99         jmp     bc_return
    100 
    101 bc_child:
    102         # we're in the child now, call __bionic_clone_entry
    103         # with the appropriate arguments on the child stack
    104         # we already placed most of them
    105         call    __bionic_clone_entry
    106         hlt
    107 
    108 bc_parent:
    109         # we're the parent; nothing to do.
    110 bc_return:
    111         popl    %edi
    112         popl    %esi
    113         popl    %ebx
    114         ret
    115 END(__bionic_clone)
    116