1#include <private/bionic_asm.h>
2
3// pid_t __bionic_clone(int flags, void* child_stack, pid_t* parent_tid, void* tls, pid_t* child_tid, int (*fn)(void*), void* arg);
4ENTRY_PRIVATE(__bionic_clone)
5        pushl   %ebx
6        .cfi_adjust_cfa_offset 4
7        .cfi_rel_offset ebx, 0
8        pushl   %esi
9        .cfi_adjust_cfa_offset 4
10        .cfi_rel_offset esi, 0
11        pushl   %edi
12        .cfi_adjust_cfa_offset 4
13        .cfi_rel_offset edi, 0
14
15        # Load system call arguments into registers.
16        movl    16(%esp), %ebx   # flags
17        movl    20(%esp), %ecx   # child_stack
18        movl    24(%esp), %edx   # parent_tid
19        movl    28(%esp), %esi   # tls
20        movl    32(%esp), %edi   # child_tid
21
22        # Copy 'fn' and 'arg' onto the child stack
23        movl    36(%esp), %eax   # Read 'fn'.
24        movl    %eax, -16(%ecx)  # Write 'fn'.
25        movl    40(%esp), %eax   # Read 'arg'.
26        movl    %eax, -12(%ecx)  # Write 'arg'.
27        subl    $16, %ecx
28
29        # Make the system call.
30        movl    $__NR_clone, %eax
31        int     $0x80
32
33        # Check result.
34        testl    %eax, %eax
35        jz      .L_bc_child
36        jg      .L_bc_parent
37
38        # An error occurred, so set errno and return -1.
39        negl    %eax
40        pushl   %eax
41        call    __set_errno_internal
42        addl    $4, %esp
43        jmp     .L_bc_return
44
45.L_bc_child:
46        # We don't want anyone to unwind past this point.
47        .cfi_undefined %eip
48        call    __start_thread
49        hlt
50
51.L_bc_parent:
52        # We're the parent; nothing to do.
53.L_bc_return:
54        popl    %edi
55        .cfi_adjust_cfa_offset -4
56        .cfi_restore edi
57        popl    %esi
58        .cfi_adjust_cfa_offset -4
59        .cfi_restore esi
60        popl    %ebx
61        .cfi_adjust_cfa_offset -4
62        .cfi_restore ebx
63        ret
64END(__bionic_clone)
65