1/* Copyright (C) 1999, 2000, 2003, 2004, 2007 Free Software Foundation, Inc. 2 3 The GNU C Library is free software; you can redistribute it and/or 4 modify it under the terms of the GNU Lesser General Public 5 License as published by the Free Software Foundation; either 6 version 2.1 of the License, or (at your option) any later version. 7 8 The GNU C Library is distributed in the hope that it will be useful, 9 but WITHOUT ANY WARRANTY; without even the implied warranty of 10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 11 Lesser General Public License for more details. 12 13 You should have received a copy of the GNU Lesser General Public 14 License along with the GNU C Library; if not, see 15 <http://www.gnu.org/licenses/>. */ 16 17/* clone() is even more special than fork() as it mucks with stacks 18 and invokes a function in the right context after its all over. */ 19 20#include <features.h> 21#include <asm/unistd.h> 22#include <sysdep.h> 23#define _ERRNO_H 1 24#include <bits/errno.h> 25 26/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg, 27 pid_t *ptid, void *tls, pid_t *ctid); */ 28 29 .text 30ENTRY(__clone) 31 /* sanity check arguments. */ 32 tst r4, r4 33 bt/s 0f 34 tst r5, r5 35 bf 1f 360: 37 bra .Lsyscall_error 38 mov #-EINVAL,r0 391: 40 /* insert the args onto the new stack */ 41 mov.l r7, @-r5 42 /* save the function pointer as the 0th element */ 43 mov.l r4, @-r5 44 45 /* do the system call */ 46 mov r6, r4 47 mov.l @r15, r6 48 mov.l @(8,r15), r7 49 mov.l @(4,r15), r0 50 mov #+SYS_ify(clone), r3 51 trapa #0x15 52 mov r0, r1 53#ifdef __sh2__ 54/* 12 arithmetic shifts for the sh2, because shad doesn't exist! */ 55 shar r1 56 shar r1 57 shar r1 58 shar r1 59 shar r1 60 shar r1 61 shar r1 62 shar r1 63 shar r1 64 shar r1 65 shar r1 66 shar r1 67#else 68 mov #-12, r2 69 shad r2, r1 70#endif 71 not r1, r1 // r1=0 means r0 = -1 to -4095 72 tst r1, r1 // i.e. error in linux 73 bf .Lclone_end 74.Lsyscall_error: 75 SYSCALL_ERROR_HANDLER 76.Lclone_end: 77 tst r0, r0 78 bt 2f 79.Lpseudo_end: 80 rts 81 nop 822: 83 /* terminate the stack frame */ 84 mov #0, r14 85 86 /* thread starts */ 87 mov.l @r15, r1 88 jsr @r1 89 mov.l @(4,r15), r4 90 91 /* we are done, passing the return value through r0 */ 92 mov.l .L3, r1 93#ifdef SHARED 94 mov.l r12, @-r15 95 sts.l pr, @-r15 96 mov r0, r4 97 mova .LG, r0 98 mov.l .LG, r12 99 add r0, r12 100 mova .L3, r0 101 add r0, r1 102 jsr @r1 103 nop 104 lds.l @r15+, pr 105 rts 106 mov.l @r15+, r12 107#else 108 jmp @r1 109 mov r0, r4 110#endif 111 .align 2 112.LG: 113 .long _GLOBAL_OFFSET_TABLE_ 114.L3: 115 .long PLTJMP(C_SYMBOL_NAME(_exit)) 116 117PSEUDO_END (__clone) 118weak_alias (__clone, clone) 119