1 /* 2 * Copyright (C) 2008 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 <asm/unistd.h> 30 #include <linux/errno.h> 31 #include <linux/sched.h> 32 33 .text 34 .type __pthread_clone, @function 35 .global __pthread_clone 36 .align 4 37 .ent __pthread_clone 38 39 /* 40 * int __pthread_clone(void* (*fn)(void*), void *child_stack, 41 * int flags, void *arg); 42 */ 43 44 __pthread_clone: 45 .set noreorder 46 .cpload $t9 47 .set reorder 48 49 # set up child stack 50 subu $a1,16 51 sw $a0,0($a1) # fn 52 sw $a3,4($a1) # arg 53 # sw $a1+16,8($a1) # tls 54 55 /* 56 * int sys_clone(int flags, void *child_stack, int *parent_tidptr, 57 * struct user_desc *newtls, int *child_tidptr); 58 */ 59 60 move $a0,$a2 # flags 61 # move $a1,$a1 # child_stack 62 move $a2,$0 # parent_tidptr 63 move $a3,$0 # user_desc 64 and $a0,~(CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID) 65 # make sure the kernel doesn't access child_tidptr 66 67 li $v0,__NR_clone 68 syscall 69 70 bnez $a3,.L__error 71 72 beqz $v0,.L__thread_start 73 74 j $ra 75 76 .L__thread_start: 77 lw $a0,0($sp) # fn 78 lw $a1,4($sp) # arg 79 addu $a2,$sp,16 # tls 80 81 # void __thread_entry(void* (*func)(void*), void *arg, void *tls) 82 la $t9, __thread_entry 83 j $t9 84 85 .L__error: 86 move $a0,$v0 87 la $t9,__set_errno 88 j $t9 89 90 .end __pthread_clone 91 92 93 # 94 # This function is defined as: 95 # 96 # pid_t __bionic_clone( int flags, void *child_stack, 97 # pid_t *pid, void *tls, pid_t *ctid, 98 # int (*fn)(void *), void* arg ); 99 # 100 # NOTE: This is not the same signature than the GLibc 101 # __clone function here !! Placing 'fn' and 'arg' 102 # at the end of the parameter list makes the 103 # implementation much simpler. 104 # 105 .text 106 .type __bionic_clone, @function 107 .global __bionic_clone 108 .align 4 109 .ent __bionic_clone 110 __bionic_clone: 111 .set noreorder 112 .cpload $t9 113 .set reorder 114 115 # set up child stack 116 subu $a1,16 117 lw $t0,20($sp) # fn 118 lw $t1,24($sp) # arg 119 sw $t0,0($a1) # fn 120 sw $t1,4($a1) # arg 121 122 # remainder of arguments are correct for clone system call 123 li $v0,__NR_clone 124 syscall 125 126 bnez $a3,.L__error_bc 127 128 beqz $v0,.L__thread_start_bc 129 130 j $ra 131 132 .L__thread_start_bc: 133 lw $a0,0($sp) # fn 134 lw $a1,4($sp) # arg 135 136 # void __bionic_clone_entry(int (*func)(void*), void *arg) 137 la $t9,__bionic_clone_entry 138 j $t9 139 140 .L__error_bc: 141 move $a0,$v0 142 la $t9,__set_errno 143 j $t9 144 145 .end __bionic_clone 146