clone.S revision 9f878c2fcab4e497d8b59f69dab74f092ad04deb
1/* 2 * Copyright (C) 2008-2010 The Android Open Source Project 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 */ 28 29#include <machine/asm.h> 30#include <sys/linux-syscalls.h> 31 32// int __pthread_clone(int (*fn)(void*), void* child_stack, int flags, void* arg); 33ENTRY(__pthread_clone) 34 # Copy the args onto the new stack. 35 stmdb r1!, {r0, r3} 36 37 # The sys_clone system call only takes two arguments: 'flags' and 'child_stack'. 38 # 'child_stack' is already in r1, but we need to move 'flags' into position. 39 mov r0, r2 40 stmfd sp!, {r4, r7} 41 42 # System call. 43 ldr r7, =__NR_clone 44 swi #0 45 movs r0, r0 46 beq 1f 47 48 # In parent, reload saved registers then either exit or set errno. 49 ldmfd sp!, {r4, r7} 50 bxpl lr 51 b __set_syscall_errno 52 531: # The child. 54 # pick the function arg and call address off the stack and jump 55 # to the C __thread_entry function which does some setup and then 56 # calls the thread's start function 57 pop {r0, r1} 58 # __thread_entry needs the TLS pointer 59 mov r2, sp 60 b __thread_entry 61END(__pthread_clone) 62 63 64 # 65 # This function is defined as: 66 # 67 # pid_t __bionic_clone( int flags, void *child_stack, 68 # pid_t *pid, void *tls, pid_t *ctid, 69 # int (*fn)(void *), void* arg ); 70 # 71 # NOTE: This is not the same signature as the glibc 72 # __clone function. Placing 'fn' and 'arg' 73 # at the end of the parameter list makes the 74 # implementation much simpler. 75 # 76 77ENTRY(__bionic_clone) 78 mov ip, sp 79 .save {r4, r5, r6, r7} 80 81 # save registers to parent stack 82 stmfd sp!, {r4, r5, r6, r7} 83 84 # load extra parameters 85 ldmfd ip, {r4, r5, r6} 86 87 # store 'fn' and 'arg' to the child stack 88 str r5, [r1, #-4] 89 str r6, [r1, #-8] 90 91 # System call 92 ldr r7, =__NR_clone 93 swi #0 94 movs r0, r0 95 beq 1f 96 97 # In the parent, reload saved registers then either exit or set errno. 98 ldmfd sp!, {r4, r5, r6, r7} 99 bxpl lr 100 b __set_syscall_errno 101 1021: # The child. 103 ldr r0, [sp, #-4] 104 ldr r1, [sp, #-8] 105 b __bionic_clone_entry 106END(__bionic_clone) 107