1851e68a2402fa414544e66650e09dfdaac813e51Elliott Hughes#include <private/bionic_asm.h>
21dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project
370b24b1cc2a1a4436b1fea3f8b76616fdcb27224Elliott Hughes// pid_t __bionic_clone(int flags, void* child_stack, pid_t* parent_tid, void* tls, pid_t* child_tid, int (*fn)(void*), void* arg);
4bdff26df2749d8d66e5d4eb5a2ecf4a9ff50fad2Elliott HughesENTRY(__bionic_clone)
522d366cc09383956dc264ed4641572e609392eeeJin Wei        pushl   %ebx
6605ee81b0660760dd191f2e2de4c4c92dca5192fChristopher Ferris        .cfi_adjust_cfa_offset 4
7605ee81b0660760dd191f2e2de4c4c92dca5192fChristopher Ferris        .cfi_rel_offset ebx, 0
822d366cc09383956dc264ed4641572e609392eeeJin Wei        pushl   %esi
9605ee81b0660760dd191f2e2de4c4c92dca5192fChristopher Ferris        .cfi_adjust_cfa_offset 4
10605ee81b0660760dd191f2e2de4c4c92dca5192fChristopher Ferris        .cfi_rel_offset esi, 0
1122d366cc09383956dc264ed4641572e609392eeeJin Wei        pushl   %edi
12605ee81b0660760dd191f2e2de4c4c92dca5192fChristopher Ferris        .cfi_adjust_cfa_offset 4
13605ee81b0660760dd191f2e2de4c4c92dca5192fChristopher Ferris        .cfi_rel_offset edi, 0
1422d366cc09383956dc264ed4641572e609392eeeJin Wei
150d236aa3f1e6d31b0c729448ae9d3ed1cad23fb4Elliott Hughes        # Load system call arguments into registers.
160d236aa3f1e6d31b0c729448ae9d3ed1cad23fb4Elliott Hughes        movl    16(%esp), %ebx   # flags
170d236aa3f1e6d31b0c729448ae9d3ed1cad23fb4Elliott Hughes        movl    20(%esp), %ecx   # child_stack
180d236aa3f1e6d31b0c729448ae9d3ed1cad23fb4Elliott Hughes        movl    24(%esp), %edx   # parent_tid
190d236aa3f1e6d31b0c729448ae9d3ed1cad23fb4Elliott Hughes        movl    28(%esp), %esi   # tls
200d236aa3f1e6d31b0c729448ae9d3ed1cad23fb4Elliott Hughes        movl    32(%esp), %edi   # child_tid
2122d366cc09383956dc264ed4641572e609392eeeJin Wei
2299c393dff33e0a5d3838c16dc7878f32ac3da971Elliott Hughes        # Copy 'fn' and 'arg' onto the child stack
2399c393dff33e0a5d3838c16dc7878f32ac3da971Elliott Hughes        movl    36(%esp), %eax   # Read 'fn'.
2499c393dff33e0a5d3838c16dc7878f32ac3da971Elliott Hughes        movl    %eax, -16(%ecx)  # Write 'fn'.
2599c393dff33e0a5d3838c16dc7878f32ac3da971Elliott Hughes        movl    40(%esp), %eax   # Read 'arg'.
2699c393dff33e0a5d3838c16dc7878f32ac3da971Elliott Hughes        movl    %eax, -12(%ecx)  # Write 'arg'.
2722d366cc09383956dc264ed4641572e609392eeeJin Wei        subl    $16, %ecx
28b6032515a058fb02c8c4152c9f055bb3bd462ae2Elliott Hughes
2999c393dff33e0a5d3838c16dc7878f32ac3da971Elliott Hughes        # Make the system call.
3022d366cc09383956dc264ed4641572e609392eeeJin Wei        movl    $__NR_clone, %eax
3122d366cc09383956dc264ed4641572e609392eeeJin Wei        int     $0x80
32b6032515a058fb02c8c4152c9f055bb3bd462ae2Elliott Hughes
3399c393dff33e0a5d3838c16dc7878f32ac3da971Elliott Hughes        # Check result.
34aeb3016f8132689d1b49d30056005b667e3d2d0eElliott Hughes        testl    %eax, %eax
35aeb3016f8132689d1b49d30056005b667e3d2d0eElliott Hughes        jz      .L_bc_child
36fff3c0fdcf2a6f4301a238628fbf8182780a1612Elliott Hughes        jg      .L_bc_parent
3722d366cc09383956dc264ed4641572e609392eeeJin Wei
3899c393dff33e0a5d3838c16dc7878f32ac3da971Elliott Hughes        # An error occurred, so set errno and return -1.
3922d366cc09383956dc264ed4641572e609392eeeJin Wei        negl    %eax
40b6032515a058fb02c8c4152c9f055bb3bd462ae2Elliott Hughes        pushl   %eax
41011e111d299284b65af07add523a9dccac356244Elliott Hughes        call    __set_errno_internal
42b6032515a058fb02c8c4152c9f055bb3bd462ae2Elliott Hughes        addl    $4, %esp
43fff3c0fdcf2a6f4301a238628fbf8182780a1612Elliott Hughes        jmp     .L_bc_return
4422d366cc09383956dc264ed4641572e609392eeeJin Wei
45fff3c0fdcf2a6f4301a238628fbf8182780a1612Elliott Hughes.L_bc_child:
46ee9d5bdd950bb05549bddc614c3c5ce9d10a5b08Elliott Hughes        # We don't want anyone to unwind past this point.
47ee9d5bdd950bb05549bddc614c3c5ce9d10a5b08Elliott Hughes        .cfi_undefined %eip
48ebc8cd117a562f387c52ed4e1aeba0fb21f33194Elliott Hughes        call    __start_thread
4922d366cc09383956dc264ed4641572e609392eeeJin Wei        hlt
5022d366cc09383956dc264ed4641572e609392eeeJin Wei
51fff3c0fdcf2a6f4301a238628fbf8182780a1612Elliott Hughes.L_bc_parent:
52aeb3016f8132689d1b49d30056005b667e3d2d0eElliott Hughes        # We're the parent; nothing to do.
53fff3c0fdcf2a6f4301a238628fbf8182780a1612Elliott Hughes.L_bc_return:
5422d366cc09383956dc264ed4641572e609392eeeJin Wei        popl    %edi
55605ee81b0660760dd191f2e2de4c4c92dca5192fChristopher Ferris        .cfi_adjust_cfa_offset -4
56605ee81b0660760dd191f2e2de4c4c92dca5192fChristopher Ferris        .cfi_restore edi
5722d366cc09383956dc264ed4641572e609392eeeJin Wei        popl    %esi
58605ee81b0660760dd191f2e2de4c4c92dca5192fChristopher Ferris        .cfi_adjust_cfa_offset -4
59605ee81b0660760dd191f2e2de4c4c92dca5192fChristopher Ferris        .cfi_restore esi
6022d366cc09383956dc264ed4641572e609392eeeJin Wei        popl    %ebx
61605ee81b0660760dd191f2e2de4c4c92dca5192fChristopher Ferris        .cfi_adjust_cfa_offset -4
62605ee81b0660760dd191f2e2de4c4c92dca5192fChristopher Ferris        .cfi_restore ebx
6322d366cc09383956dc264ed4641572e609392eeeJin Wei        ret
64bdff26df2749d8d66e5d4eb5a2ecf4a9ff50fad2Elliott HughesEND(__bionic_clone)
65954cf0d4e2669f91194b45f484152e47efa4f6c7Elliott Hughes.hidden __bionic_clone
66