| The Android Open Source Project | 1dc9e47 | 2009-03-03 19:28:35 -0800 | [diff] [blame] | 1 | /* | 
| Elliott Hughes | dd57029 | 2015-05-12 10:10:01 -0700 | [diff] [blame] | 2 |  * Copyright (C) 2008 The Android Open Source Project | 
| The Android Open Source Project | 1dc9e47 | 2009-03-03 19:28:35 -0800 | [diff] [blame] | 3 |  * All rights reserved. | 
 | 4 |  * | 
 | 5 |  * Redistribution and use in source and binary forms, with or without | 
 | 6 |  * modification, are permitted provided that the following conditions | 
 | 7 |  * are met: | 
 | 8 |  *  * Redistributions of source code must retain the above copyright | 
 | 9 |  *    notice, this list of conditions and the following disclaimer. | 
 | 10 |  *  * Redistributions in binary form must reproduce the above copyright | 
 | 11 |  *    notice, this list of conditions and the following disclaimer in | 
 | 12 |  *    the documentation and/or other materials provided with the | 
 | 13 |  *    distribution. | 
 | 14 |  * | 
 | 15 |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 
 | 16 |  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 
 | 17 |  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | 
 | 18 |  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | 
 | 19 |  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | 
 | 20 |  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | 
 | 21 |  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS | 
 | 22 |  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | 
 | 23 |  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | 
 | 24 |  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT | 
 | 25 |  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | 
 | 26 |  * SUCH DAMAGE. | 
 | 27 |  */ | 
| Elliott Hughes | f94fd3c | 2013-02-11 15:36:59 -0800 | [diff] [blame] | 28 |  | 
| Elliott Hughes | ed74484 | 2013-11-07 10:31:05 -0800 | [diff] [blame] | 29 | #include <private/bionic_asm.h> | 
| The Android Open Source Project | 1dc9e47 | 2009-03-03 19:28:35 -0800 | [diff] [blame] | 30 |  | 
| Elliott Hughes | 70b24b1 | 2013-11-15 11:51:07 -0800 | [diff] [blame] | 31 | // pid_t __bionic_clone(int flags, void* child_stack, pid_t* parent_tid, void* tls, pid_t* child_tid, int (*fn)(void*), void* arg); | 
| Kenny Root | 420878c | 2011-02-16 11:55:58 -0800 | [diff] [blame] | 32 | ENTRY(__bionic_clone) | 
| David 'Digit' Turner | 97cf7f3 | 2010-01-22 18:59:05 -0800 | [diff] [blame] | 33 |     mov     ip, sp | 
| David 'Digit' Turner | 97cf7f3 | 2010-01-22 18:59:05 -0800 | [diff] [blame] | 34 |     # save registers to parent stack | 
 | 35 |     stmfd   sp!, {r4, r5, r6, r7} | 
| Christopher Ferris | ed45970 | 2013-12-02 17:44:53 -0800 | [diff] [blame] | 36 |     .cfi_def_cfa_offset 16 | 
 | 37 |     .cfi_rel_offset r4, 0 | 
 | 38 |     .cfi_rel_offset r5, 4 | 
 | 39 |     .cfi_rel_offset r6, 8 | 
 | 40 |     .cfi_rel_offset r7, 12 | 
| David 'Digit' Turner | 97cf7f3 | 2010-01-22 18:59:05 -0800 | [diff] [blame] | 41 |  | 
 | 42 |     # load extra parameters | 
 | 43 |     ldmfd   ip, {r4, r5, r6} | 
 | 44 |  | 
| Elliott Hughes | 51f5d83 | 2014-12-10 11:08:47 -0800 | [diff] [blame] | 45 |     # Push 'fn' and 'arg' onto the child stack. | 
| Jiangli Yuan | c3d1728 | 2014-12-09 17:02:59 -0800 | [diff] [blame] | 46 |     stmdb   r1!, {r5, r6} | 
| David 'Digit' Turner | 97cf7f3 | 2010-01-22 18:59:05 -0800 | [diff] [blame] | 47 |  | 
| Elliott Hughes | 51f5d83 | 2014-12-10 11:08:47 -0800 | [diff] [blame] | 48 |     # Make the system call. | 
| David 'Digit' Turner | 97cf7f3 | 2010-01-22 18:59:05 -0800 | [diff] [blame] | 49 |     ldr     r7, =__NR_clone | 
 | 50 |     swi     #0 | 
| Elliott Hughes | 51f5d83 | 2014-12-10 11:08:47 -0800 | [diff] [blame] | 51 |  | 
 | 52 |     # Are we the child? | 
| David 'Digit' Turner | 97cf7f3 | 2010-01-22 18:59:05 -0800 | [diff] [blame] | 53 |     movs    r0, r0 | 
| Elliott Hughes | 2fc14a9 | 2016-09-08 14:11:28 -0700 | [diff] [blame] | 54 |     beq     .L_bc_child | 
| David 'Digit' Turner | 97cf7f3 | 2010-01-22 18:59:05 -0800 | [diff] [blame] | 55 |  | 
| Elliott Hughes | 9aceab5 | 2013-03-12 14:57:30 -0700 | [diff] [blame] | 56 |     # In the parent, reload saved registers then either return or set errno. | 
| David 'Digit' Turner | 97cf7f3 | 2010-01-22 18:59:05 -0800 | [diff] [blame] | 57 |     ldmfd   sp!, {r4, r5, r6, r7} | 
| Elliott Hughes | 9aceab5 | 2013-03-12 14:57:30 -0700 | [diff] [blame] | 58 |     cmn     r0, #(MAX_ERRNO + 1) | 
 | 59 |     bxls    lr | 
 | 60 |     neg     r0, r0 | 
| Elliott Hughes | 011e111 | 2014-09-08 15:25:01 -0700 | [diff] [blame] | 61 |     b       __set_errno_internal | 
| David 'Digit' Turner | 97cf7f3 | 2010-01-22 18:59:05 -0800 | [diff] [blame] | 62 |  | 
| Elliott Hughes | 2fc14a9 | 2016-09-08 14:11:28 -0700 | [diff] [blame] | 63 | .L_bc_child: | 
 | 64 |     # Setting lr to 0 will make the unwinder stop at __start_thread. | 
 | 65 |     mov    lr, #0 | 
| Elliott Hughes | 51f5d83 | 2014-12-10 11:08:47 -0800 | [diff] [blame] | 66 |     # Call __start_thread with the 'fn' and 'arg' we stored on the child stack. | 
| Jiangli Yuan | c3d1728 | 2014-12-09 17:02:59 -0800 | [diff] [blame] | 67 |     pop    {r0, r1} | 
| Elliott Hughes | ebc8cd1 | 2014-06-06 15:18:54 -0700 | [diff] [blame] | 68 |     b      __start_thread | 
| Kenny Root | 420878c | 2011-02-16 11:55:58 -0800 | [diff] [blame] | 69 | END(__bionic_clone) | 
| Elliott Hughes | 954cf0d | 2014-05-08 19:00:23 -0700 | [diff] [blame] | 70 | .hidden __bionic_clone |