Elliott Hughes | 851e68a | 2014-02-19 16:53:20 -0800 | [diff] [blame] | 1 | #include <private/bionic_asm.h> |
The Android Open Source Project | 1dc9e47 | 2009-03-03 19:28:35 -0800 | [diff] [blame] | 2 | |
Elliott Hughes | 70b24b1 | 2013-11-15 11:51:07 -0800 | [diff] [blame] | 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); |
Elliott Hughes | bdff26d | 2013-02-11 17:08:16 -0800 | [diff] [blame] | 4 | ENTRY(__bionic_clone) |
Jin Wei | 22d366c | 2012-08-08 15:15:16 +0800 | [diff] [blame] | 5 | pushl %ebx |
| 6 | pushl %esi |
| 7 | pushl %edi |
| 8 | |
Elliott Hughes | 0d236aa | 2014-05-09 14:42:16 -0700 | [diff] [blame] | 9 | # Load system call arguments into registers. |
| 10 | movl 16(%esp), %ebx # flags |
| 11 | movl 20(%esp), %ecx # child_stack |
| 12 | movl 24(%esp), %edx # parent_tid |
| 13 | movl 28(%esp), %esi # tls |
| 14 | movl 32(%esp), %edi # child_tid |
Jin Wei | 22d366c | 2012-08-08 15:15:16 +0800 | [diff] [blame] | 15 | |
Elliott Hughes | 99c393d | 2013-11-26 16:20:50 -0800 | [diff] [blame] | 16 | # Copy 'fn' and 'arg' onto the child stack |
| 17 | movl 36(%esp), %eax # Read 'fn'. |
| 18 | movl %eax, -16(%ecx) # Write 'fn'. |
| 19 | movl 40(%esp), %eax # Read 'arg'. |
| 20 | movl %eax, -12(%ecx) # Write 'arg'. |
Jin Wei | 22d366c | 2012-08-08 15:15:16 +0800 | [diff] [blame] | 21 | subl $16, %ecx |
Elliott Hughes | b603251 | 2013-02-12 23:02:33 -0800 | [diff] [blame] | 22 | |
Elliott Hughes | 99c393d | 2013-11-26 16:20:50 -0800 | [diff] [blame] | 23 | # Make the system call. |
Jin Wei | 22d366c | 2012-08-08 15:15:16 +0800 | [diff] [blame] | 24 | movl $__NR_clone, %eax |
| 25 | int $0x80 |
Elliott Hughes | b603251 | 2013-02-12 23:02:33 -0800 | [diff] [blame] | 26 | |
Elliott Hughes | 99c393d | 2013-11-26 16:20:50 -0800 | [diff] [blame] | 27 | # Check result. |
Elliott Hughes | aeb3016 | 2014-06-05 12:28:14 -0700 | [diff] [blame] | 28 | testl %eax, %eax |
| 29 | jz .L_bc_child |
Elliott Hughes | fff3c0f | 2014-05-09 12:16:20 -0700 | [diff] [blame] | 30 | jg .L_bc_parent |
Jin Wei | 22d366c | 2012-08-08 15:15:16 +0800 | [diff] [blame] | 31 | |
Elliott Hughes | 99c393d | 2013-11-26 16:20:50 -0800 | [diff] [blame] | 32 | # An error occurred, so set errno and return -1. |
Jin Wei | 22d366c | 2012-08-08 15:15:16 +0800 | [diff] [blame] | 33 | negl %eax |
Elliott Hughes | b603251 | 2013-02-12 23:02:33 -0800 | [diff] [blame] | 34 | pushl %eax |
Dan Albert | 3726f9c | 2014-08-08 15:15:29 -0700 | [diff] [blame^] | 35 | call __set_errno |
Elliott Hughes | b603251 | 2013-02-12 23:02:33 -0800 | [diff] [blame] | 36 | addl $4, %esp |
Elliott Hughes | fff3c0f | 2014-05-09 12:16:20 -0700 | [diff] [blame] | 37 | jmp .L_bc_return |
Jin Wei | 22d366c | 2012-08-08 15:15:16 +0800 | [diff] [blame] | 38 | |
Elliott Hughes | fff3c0f | 2014-05-09 12:16:20 -0700 | [diff] [blame] | 39 | .L_bc_child: |
Elliott Hughes | ee9d5bd | 2014-05-30 11:15:32 -0700 | [diff] [blame] | 40 | # We don't want anyone to unwind past this point. |
| 41 | .cfi_undefined %eip |
Elliott Hughes | ebc8cd1 | 2014-06-06 15:18:54 -0700 | [diff] [blame] | 42 | call __start_thread |
Jin Wei | 22d366c | 2012-08-08 15:15:16 +0800 | [diff] [blame] | 43 | hlt |
| 44 | |
Elliott Hughes | fff3c0f | 2014-05-09 12:16:20 -0700 | [diff] [blame] | 45 | .L_bc_parent: |
Elliott Hughes | aeb3016 | 2014-06-05 12:28:14 -0700 | [diff] [blame] | 46 | # We're the parent; nothing to do. |
Elliott Hughes | fff3c0f | 2014-05-09 12:16:20 -0700 | [diff] [blame] | 47 | .L_bc_return: |
Jin Wei | 22d366c | 2012-08-08 15:15:16 +0800 | [diff] [blame] | 48 | popl %edi |
| 49 | popl %esi |
| 50 | popl %ebx |
| 51 | ret |
Elliott Hughes | bdff26d | 2013-02-11 17:08:16 -0800 | [diff] [blame] | 52 | END(__bionic_clone) |
Elliott Hughes | 954cf0d | 2014-05-08 19:00:23 -0700 | [diff] [blame] | 53 | .hidden __bionic_clone |