Skip to content

Latest commit

 

History

History
186 lines (155 loc) · 4.81 KB

clone.S

File metadata and controls

186 lines (155 loc) · 4.81 KB
 
Apr 26, 2001
Apr 26, 2001
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
/* Taken with thanks from LinuxThreads 0.6 */
/* This is no longer necessary with glibc-2.1, which has it's own clone() */
#ifdef linux
/* Look to see if glibc is available, and if so, what version */
#include <features.h>
#if (__GLIBC__ > 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 1))
#define HAVE_CLONE
#endif /* glibc 2.1 or newer */
#endif /* linux */
#if defined(linux) && !defined(SDL_USE_PTHREADS) && !defined(HAVE_CLONE)
#if defined(__i386__)
/************************************************************************/
/* Copyright (C) 1996, 1997 Free Software Foundation, Inc.
Contributed by Richard Henderson (rth@tamu.edu)
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If
not, write to the Free Software Foundation, Inc., 675 Mass Ave,
#ifdef SAVE_RCSID
static char rcsid =
"@(#) $Id$";
#endif
Cambridge, MA 02139, USA. */
/* clone() is even more special than fork() as it mucks with stacks
and invokes a function in the right context after its all over. */
#include <asm/errno.h>
#include <asm/unistd.h>
/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg); */
.text
.align 4
.globl __clone
.type __clone,@function
.weak clone
clone = __clone
__clone:
/* Sanity check arguments. */
movl $-EINVAL,%eax
movl 4(%esp),%ecx /* no NULL function pointers */
testl %ecx,%ecx
jz syscall_error
movl 8(%esp),%ecx /* no NULL stack pointers */
testl %ecx,%ecx
jz syscall_error
/* Insert the argument onto the new stack. */
subl $8,%ecx
movl 16(%esp),%eax
movl %eax,4(%ecx)
/* Save the function pointer as the zeroth argument. */
/* It will be popped off in the child in the ebx frobbing below. */
movl 4(%esp),%eax
movl %eax,0(%ecx)
/* Do the system call */
pushl %ebx
movl 16(%esp),%ebx
movl $__NR_clone,%eax
int $0x80
popl %ebx
test %eax,%eax
jl syscall_error
jz thread_start
ret
syscall_error:
negl %eax
pushl %eax
#ifdef __PIC__
call __errno_location@PLT
#else
call __errno_location
#endif
popl 0(%eax)
movl $-1, %eax
ret
thread_start:
subl %ebp,%ebp /* terminate the stack frame */
call *%ebx
pushl %eax
#ifdef __PIC__
call _exit@PLT
#else
call _exit
#endif
/************************************************************************/
#elif defined(sparc)
/************************************************************************/
/* Copyright (C) 1996, 1997 Free Software Foundation, Inc.
Contributed by Miguel de Icaza (miguel@nuclecu.unam.mx)
Based on code written for the Intel by Richard
Henderson (rth@tamu.edu)
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If
not, write to the Free Software Foundation, Inc., 675 Mass Ave,
Cambridge, MA 02139, USA. */
/* clone() is even more special than fork() as it mucks with stacks
and invokes a function in the right context after its all over. */
#include <asm/errno.h>
#include <asm/unistd.h>
/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg); */
.text
.align 4
.globl __clone
.type __clone,@function
.weak clone
clone = __clone
__clone:
save %sp,-96,%sp
/* sanity check arguments */
tst %i0
be __clone_syscall_error
tst %i1
be __clone_syscall_error
nop
/* Do the system call */
mov %i1,%o1
mov %i2,%o0
set __NR_clone,%g1
ta 0x10
bcs __clone_syscall_error
tst %o1
bne __thread_start
nop
mov %o0,%i0
ret
restore
__clone_syscall_error:
call __errno_location
set EINVAL,%i0
st %i0,[%o0]
mov -1,%i0
ret
restore
__thread_start:
call %i0
mov %i3,%o0
call _exit,0
nop
/************************************************************************/
#else
#error "Unknown Linux architecture"
#endif
#endif /* Linux && ! SDL_USE_PTHREADS */