Home | History | Annotate | Download | only in bionic
      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