OSDN Git Service

632cf59dfd4c052e6ba8ef4936fe395a6410224c
[uclinux-h8/uClibc.git] / libc / sysdeps / linux / i386 / clone.S
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)
4
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.
9
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.
14
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/>.  */
18
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.
21
22    Hacked up for uClibc by Erik Andersen <andersen@codepoet.org>
23 */
24
25 #define _ERRNO_H        1
26 #include <bits/errno.h>
27 #include <sys/syscall.h>
28
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); */
31
32 #define LINKAGE     4
33 #define PTR_SIZE    4
34 #define PARMS       LINKAGE        /* no space for saved regs */
35 #define FUNC        PARMS
36 #define STACK       FUNC+4
37 #define FLAGS       STACK+PTR_SIZE
38 #define ARG         FLAGS+4
39 #define PTID        ARG+PTR_SIZE
40 #define TLS         PTID+PTR_SIZE
41 #define CTID        TLS+PTR_SIZE
42
43 .text
44 .global clone
45 .type   clone,%function
46 clone:
47         /* Sanity check arguments.  */
48         movl    $-EINVAL,%eax
49
50         /* no NULL function pointers */
51         movl    FUNC(%esp),%ecx
52 #ifdef __PIC__
53         jecxz   __error
54 #else
55         testl   %ecx,%ecx
56         jz      __error
57 #endif
58
59         /* no NULL stack pointers */
60         movl    STACK(%esp),%ecx
61 #ifdef __PIC__
62         jecxz   __error
63 #else
64         testl   %ecx,%ecx
65         jz      __error
66 #endif
67
68         /* Insert the argument onto the new stack.  Make sure the new
69            thread is started with an alignment of (mod 16).  */
70         andl    $0xfffffff0, %ecx
71         subl    $28,%ecx
72         movl    ARG(%esp),%eax          /* no negative argument counts */
73         movl    %eax,12(%ecx)
74
75         /* Save the function pointer as the zeroth argument.
76            It will be popped off in the child in the ebx frobbing below.  */
77         movl    FUNC(%esp),%eax
78         movl    %eax,8(%ecx)
79         /* Don't leak any information.  */
80         movl    $0,4(%ecx)
81 #ifndef RESET_PID
82         movl    $0,(%ecx)
83 #endif
84
85
86         /* Do the system call */
87         pushl   %ebx
88         pushl   %esi
89         pushl   %edi
90         movl    TLS+12(%esp),%esi
91         movl    PTID+12(%esp),%edx
92         movl    FLAGS+12(%esp),%ebx
93         movl    CTID+12(%esp),%edi
94         movl    $__NR_clone,%eax
95 #ifdef RESET_PID
96         /* Remember the flag value.  */
97         movl    %ebx, (%ecx)
98 #endif
99         int     $0x80
100         popl    %edi
101         popl    %esi
102         popl    %ebx
103
104         test    %eax,%eax
105         jl      __error
106         jz      .Lthread_start
107         ret
108
109 .Lthread_start:
110         /* Note: %esi is zero.  */
111         movl    %esi,%ebp       /* terminate the stack frame */
112         call    *%ebx
113 #ifdef __PIC__
114         call    .Lhere
115 .Lhere:
116         popl    %ebx
117         addl    $_GLOBAL_OFFSET_TABLE_+[.-.Lhere], %ebx
118 #endif
119         movl    %eax, %ebx
120         movl    $__NR_exit, %eax
121         int     $0x80
122
123 /* Need to indirect jump to syscall error 
124  * or we end up with TEXTREL's
125  */
126 __error:
127         jmp __syscall_error
128
129 .size clone,.-clone
130 weak_alias(clone, __clone)