| #include <private/bionic_asm.h> |
| |
| // pid_t __bionic_clone(int flags, void* child_stack, pid_t* parent_tid, void* tls, pid_t* child_tid, int (*fn)(void*), void* arg); |
| ENTRY(__bionic_clone) |
| pushl %ebx |
| pushl %esi |
| pushl %edi |
| |
| # Load system call arguments into registers. |
| movl 16(%esp), %ebx # flags |
| movl 20(%esp), %ecx # child_stack |
| movl 24(%esp), %edx # parent_tid |
| movl 28(%esp), %esi # tls |
| movl 32(%esp), %edi # child_tid |
| |
| # Copy 'fn' and 'arg' onto the child stack |
| movl 36(%esp), %eax # Read 'fn'. |
| movl %eax, -16(%ecx) # Write 'fn'. |
| movl 40(%esp), %eax # Read 'arg'. |
| movl %eax, -12(%ecx) # Write 'arg'. |
| subl $16, %ecx |
| |
| # Make the system call. |
| movl $__NR_clone, %eax |
| int $0x80 |
| |
| # Check result. |
| testl %eax, %eax |
| jz .L_bc_child |
| jg .L_bc_parent |
| |
| # An error occurred, so set errno and return -1. |
| negl %eax |
| pushl %eax |
| call __set_errno |
| addl $4, %esp |
| jmp .L_bc_return |
| |
| .L_bc_child: |
| # We don't want anyone to unwind past this point. |
| .cfi_undefined %eip |
| call __start_thread |
| hlt |
| |
| .L_bc_parent: |
| # We're the parent; nothing to do. |
| .L_bc_return: |
| popl %edi |
| popl %esi |
| popl %ebx |
| ret |
| END(__bionic_clone) |
| .hidden __bionic_clone |