Replace FSF snail mail address with URLs.
[glibc.git] / sysdeps / unix / sysv / linux / i386 / clone.S
blob0603218acdc07aff265e6a20af4c863a01f4bbd7
1 /* Copyright (C) 1996-2000,02,03,04,2005 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3    Contributed by Richard Henderson (rth@tamu.edu)
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, see
17    <http://www.gnu.org/licenses/>.  */
19 /* clone() is even more special than fork() as it mucks with stacks
20    and invokes a function in the right context after its all over.  */
22 #include <sysdep.h>
23 #define _ERRNO_H        1
24 #include <bits/errno.h>
25 #include <asm-syntax.h>
26 #include <bp-sym.h>
27 #include <bp-asm.h>
29 /* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg,
30              pid_t *ptid, struct user_desc *tls, pid_t *ctid); */
32 #define PARMS   LINKAGE         /* no space for saved regs */
33 #define FUNC    PARMS
34 #define STACK   FUNC+4
35 #define FLAGS   STACK+PTR_SIZE
36 #define ARG     FLAGS+4
37 #define PTID    ARG+PTR_SIZE
38 #define TLS     PTID+PTR_SIZE
39 #define CTID    TLS+PTR_SIZE
41 #define __NR_clone 120
42 #define SYS_clone 120
44 #define CLONE_VM        0x00000100
45 #define CLONE_THREAD    0x00010000
47         .text
48 ENTRY (BP_SYM (__clone))
49         /* Sanity check arguments.  */
50         movl    $-EINVAL,%eax
51         movl    FUNC(%esp),%ecx         /* no NULL function pointers */
52 #ifdef PIC
53         jecxz   SYSCALL_ERROR_LABEL
54 #else
55         testl   %ecx,%ecx
56         jz      SYSCALL_ERROR_LABEL
57 #endif
58         movl    STACK(%esp),%ecx        /* no NULL stack pointers */
59 #ifdef PIC
60         jecxz   SYSCALL_ERROR_LABEL
61 #else
62         testl   %ecx,%ecx
63         jz      SYSCALL_ERROR_LABEL
64 #endif
66         /* Insert the argument onto the new stack.  Make sure the new
67            thread is started with an alignment of (mod 16).  */
68         andl    $0xfffffff0, %ecx
69         subl    $28,%ecx
70         movl    ARG(%esp),%eax          /* no negative argument counts */
71         movl    %eax,12(%ecx)
73         /* Save the function pointer as the zeroth argument.
74            It will be popped off in the child in the ebx frobbing below.  */
75         movl    FUNC(%esp),%eax
76         movl    %eax,8(%ecx)
77         /* Don't leak any information.  */
78         movl    $0,4(%ecx)
79 #ifndef RESET_PID
80         movl    $0,(%ecx)
81 #endif
83         /* Do the system call */
84         pushl   %ebx
85         cfi_adjust_cfa_offset (4)
86         pushl   %esi
87         cfi_adjust_cfa_offset (4)
88         pushl   %edi
89         cfi_adjust_cfa_offset (4)
91         movl    TLS+12(%esp),%esi
92         cfi_rel_offset (esi, 4)
93         movl    PTID+12(%esp),%edx
94         movl    FLAGS+12(%esp),%ebx
95         cfi_rel_offset (ebx, 8)
96         movl    CTID+12(%esp),%edi
97         cfi_rel_offset (edi, 0)
98         movl    $SYS_ify(clone),%eax
100 #ifdef RESET_PID
101         /* Remember the flag value.  */
102         movl    %ebx, (%ecx)
103 #endif
105         /* End FDE now, because in the child the unwind info will be
106            wrong.  */
107         cfi_endproc
109         int     $0x80
110         popl    %edi
111         popl    %esi
112         popl    %ebx
114         test    %eax,%eax
115         jl      SYSCALL_ERROR_LABEL
116         jz      L(thread_start)
118 L(pseudo_end):
119         ret
121 L(thread_start):
122         cfi_startproc;
123         /* Clearing frame pointer is insufficient, use CFI.  */
124         cfi_undefined (eip);
125         /* Note: %esi is zero.  */
126         movl    %esi,%ebp       /* terminate the stack frame */
127 #ifdef RESET_PID
128         testl   $CLONE_THREAD, %edi
129         je      L(newpid)
130 L(haspid):
131 #endif
132         call    *%ebx
133 #ifdef PIC
134         call    L(here)
135 L(here):
136         popl    %ebx
137         addl    $_GLOBAL_OFFSET_TABLE_+[.-L(here)], %ebx
138 #endif
139         movl    %eax, %ebx
140         movl    $SYS_ify(exit), %eax
141         ENTER_KERNEL
143 #ifdef RESET_PID
144         .subsection 2
145 L(newpid):
146         testl   $CLONE_VM, %edi
147         movl    $-1, %eax
148         jne     L(nomoregetpid)
149         movl    $SYS_ify(getpid), %eax
150         ENTER_KERNEL
151 L(nomoregetpid):
152         movl    %eax, %gs:PID
153         movl    %eax, %gs:TID
154         jmp     L(haspid)
155         .previous
156 #endif
157         cfi_endproc;
159         cfi_startproc
160 PSEUDO_END (BP_SYM (__clone))
162 weak_alias (BP_SYM (__clone), BP_SYM (clone))