1/* Copyright (C) 1996-2000,02,03,04,2005 Free Software Foundation, Inc. 2 Contributed by Richard Henderson (rth@tamu.edu) 3 4 The GNU C Library is free software; you can redistribute it and/or 5 modify it under the terms of the GNU Lesser General Public 6 License as published by the Free Software Foundation; either 7 version 2.1 of the License, or (at your option) any later version. 8 9 The GNU C Library is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 Lesser General Public License for more details. 13 14 You should have received a copy of the GNU Lesser General Public 15 License along with the GNU C Library; if not, see 16 <http://www.gnu.org/licenses/>. */ 17 18/* clone() is even more special than fork() as it mucks with stacks 19 and invokes a function in the right context after its all over. 20 21 Hacked up for uClibc by Erik Andersen <andersen@codepoet.org> 22*/ 23 24#define _ERRNO_H 1 25#include <bits/errno.h> 26#include <sys/syscall.h> 27 28/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg, 29 pid_t *ptid, struct user_desc *tls, pid_t *ctid); */ 30 31#define LINKAGE 4 32#define PTR_SIZE 4 33#define PARMS LINKAGE /* no space for saved regs */ 34#define FUNC PARMS 35#define STACK FUNC+4 36#define FLAGS STACK+PTR_SIZE 37#define ARG FLAGS+4 38#define PTID ARG+PTR_SIZE 39#define TLS PTID+PTR_SIZE 40#define CTID TLS+PTR_SIZE 41 42.text 43.global clone 44.type clone,%function 45clone: 46 /* Sanity check arguments. */ 47 movl $-EINVAL,%eax 48 49 /* no NULL function pointers */ 50 movl FUNC(%esp),%ecx 51#ifdef __PIC__ 52 jecxz __error 53#else 54 testl %ecx,%ecx 55 jz __error 56#endif 57 58 /* no NULL stack pointers */ 59 movl STACK(%esp),%ecx 60#ifdef __PIC__ 61 jecxz __error 62#else 63 testl %ecx,%ecx 64 jz __error 65#endif 66 67 /* Insert the argument onto the new stack. Make sure the new 68 thread is started with an alignment of (mod 16). */ 69 andl $0xfffffff0, %ecx 70 subl $28,%ecx 71 movl ARG(%esp),%eax /* no negative argument counts */ 72 movl %eax,12(%ecx) 73 74 /* Save the function pointer as the zeroth argument. 75 It will be popped off in the child in the ebx frobbing below. */ 76 movl FUNC(%esp),%eax 77 movl %eax,8(%ecx) 78 /* Don't leak any information. */ 79 movl $0,4(%ecx) 80 81 /* Do the system call */ 82 pushl %ebx 83 pushl %esi 84 pushl %edi 85 movl TLS+12(%esp),%esi 86 movl PTID+12(%esp),%edx 87 movl FLAGS+12(%esp),%ebx 88 movl CTID+12(%esp),%edi 89 movl $__NR_clone,%eax 90 int $0x80 91 popl %edi 92 popl %esi 93 popl %ebx 94 95 test %eax,%eax 96 jl __error 97 jz .Lthread_start 98 ret 99 100.Lthread_start: 101 /* Note: %esi is zero. */ 102 movl %esi,%ebp /* terminate the stack frame */ 103 call *%ebx 104#ifdef __PIC__ 105 call .Lhere 106.Lhere: 107 popl %ebx 108 addl $_GLOBAL_OFFSET_TABLE_+[.-.Lhere], %ebx 109#endif 110 movl %eax, %ebx 111 movl $__NR_exit, %eax 112 int $0x80 113 114/* Need to indirect jump to syscall error 115 * or we end up with TEXTREL's 116 */ 117__error: 118 jmp __syscall_error 119 120.size clone,.-clone 121weak_alias(clone, __clone) 122