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