Update copyright dates with scripts/update-copyrights.
[glibc.git] / sysdeps / unix / sysv / linux / i386 / clone.S
blob243dbfecc9b102266083000bd4696d7cdf7dae87
1 /* Copyright (C) 1996-2015 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>
27 /* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg,
28              pid_t *ptid, struct user_desc *tls, pid_t *ctid); */
30 #define PARMS   4               /* no space for saved regs */
31 #define FUNC    PARMS
32 #define STACK   FUNC+4
33 #define FLAGS   STACK+4
34 #define ARG     FLAGS+4
35 #define PTID    ARG+4
36 #define TLS     PTID+4
37 #define CTID    TLS+4
39 #define __NR_clone 120
40 #define SYS_clone 120
42 #define CLONE_VM        0x00000100
43 #define CLONE_THREAD    0x00010000
45         .text
46 ENTRY (__clone)
47         /* Sanity check arguments.  */
48         movl    $-EINVAL,%eax
49         movl    FUNC(%esp),%ecx         /* no NULL function pointers */
50 #ifdef PIC
51         jecxz   SYSCALL_ERROR_LABEL
52 #else
53         testl   %ecx,%ecx
54         jz      SYSCALL_ERROR_LABEL
55 #endif
56         movl    STACK(%esp),%ecx        /* no NULL stack pointers */
57 #ifdef PIC
58         jecxz   SYSCALL_ERROR_LABEL
59 #else
60         testl   %ecx,%ecx
61         jz      SYSCALL_ERROR_LABEL
62 #endif
64         /* Insert the argument onto the new stack.  Make sure the new
65            thread is started with an alignment of (mod 16).  */
66         andl    $0xfffffff0, %ecx
67         subl    $28,%ecx
68         movl    ARG(%esp),%eax          /* no negative argument counts */
69         movl    %eax,12(%ecx)
71         /* Save the function pointer as the zeroth argument.
72            It will be popped off in the child in the ebx frobbing below.  */
73         movl    FUNC(%esp),%eax
74         movl    %eax,8(%ecx)
75         /* Don't leak any information.  */
76         movl    $0,4(%ecx)
78         /* Do the system call */
79         pushl   %ebx
80         cfi_adjust_cfa_offset (4)
81         pushl   %esi
82         cfi_adjust_cfa_offset (4)
83         pushl   %edi
84         cfi_adjust_cfa_offset (4)
86         movl    TLS+12(%esp),%esi
87         cfi_rel_offset (esi, 4)
88         movl    PTID+12(%esp),%edx
89         movl    FLAGS+12(%esp),%ebx
90         cfi_rel_offset (ebx, 8)
91         movl    CTID+12(%esp),%edi
92         cfi_rel_offset (edi, 0)
93         movl    $SYS_ify(clone),%eax
95         /* Remember the flag value.  */
96         movl    %ebx, (%ecx)
98         /* End FDE now, because in the child the unwind info will be
99            wrong.  */
100         cfi_endproc
102         int     $0x80
103         popl    %edi
104         popl    %esi
105         popl    %ebx
107         test    %eax,%eax
108         jl      SYSCALL_ERROR_LABEL
109         jz      L(thread_start)
111         ret
113 L(thread_start):
114         cfi_startproc;
115         /* Clearing frame pointer is insufficient, use CFI.  */
116         cfi_undefined (eip);
117         /* Note: %esi is zero.  */
118         movl    %esi,%ebp       /* terminate the stack frame */
119         testl   $CLONE_THREAD, %edi
120         je      L(newpid)
121 L(haspid):
122         call    *%ebx
123 #ifdef PIC
124         call    L(here)
125 L(here):
126         popl    %ebx
127         addl    $_GLOBAL_OFFSET_TABLE_+[.-L(here)], %ebx
128 #endif
129         movl    %eax, %ebx
130         movl    $SYS_ify(exit), %eax
131         ENTER_KERNEL
133         .subsection 2
134 L(newpid):
135         testl   $CLONE_VM, %edi
136         movl    $-1, %eax
137         jne     L(nomoregetpid)
138         movl    $SYS_ify(getpid), %eax
139         ENTER_KERNEL
140 L(nomoregetpid):
141         movl    %eax, %gs:PID
142         movl    %eax, %gs:TID
143         jmp     L(haspid)
144         .previous
145         cfi_endproc;
147         cfi_startproc
148 PSEUDO_END (__clone)
150 weak_alias (__clone, clone)