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
|
.file "clone.S"
#include <sys/syscall.h>
#if __FreeBSD__ >= 5
#include <machine/asm.h>
#else
#include "DEFS.h"
#endif
#include "SYS.h"
#define KERNEL
#define _KERNEL
#include <sys/errno.h>
#undef _KERNEL
#undef KERNEL
#undef DEBUG
/*
* 8 12 16 20
* _clone (__fn, __childstack, __flags, __arg);
*
* Here's the idea:
* __childstack is the TOS for the new rforked thread
* __flags are the rfork flags
* __fn is the userland function go be started for the new thread
* as in:
*
* int __fn (void * __arg)
*
*/
.stabs "clone.S",100,0,0,Ltext0
.text
Ltext0:
.type CNAME(_clone),@function
.stabd 68,0,1
ENTRY(_clone)
pushl %ebp
movl %esp, %ebp
pushl %esi
PIC_PROLOGUE
/*
* Push thread info onto the new thread's stack
*/
movl 12(%ebp), %esi /* get stack addr */
subl $4, %esi
movl 20(%ebp), %eax /* get __arg */
movl %eax, (%esi)
subl $4, %esi
movl 8(%ebp), %eax /* get __fn */
movl %eax, (%esi)
.stabd 68,0,2
/*
* Prepare and execute rfork
*/
pushl 16(%ebp)
pushl $0 /* fake return address */
leal SYS_rfork, %eax
KERNCALL
jb 2f
.stabd 68,0,3
/*
* Check to see if we are in the parent or child
*/
cmpl $0, %edx
jnz 1f
addl $8, %esp
PIC_EPILOGUE
popl %esi
movl %ebp, %esp
popl %ebp
ret
.p2align 2
/*
* If we are in the child (new thread), then
* set-up the call to the internal subroutine. If it
* returns, then call _exit.
*/
.stabd 68,0,4
1:
movl %esi,%esp
#ifdef DEBUG
movl %esp, _stackaddr
movl (%esp), %eax
movl %eax, _stack
movl 4(%esp), %eax
movl %eax,_stack+4
movl 8(%esp), %eax
movl %eax,_stack+8
#endif
popl %eax
#ifdef DEBUG
movl %eax,_fcn
#endif
movl $0, %ebp
call *%eax
addl $8, %esp
/*
* Exit system call
*/
call PIC_PLT(_exit)
.stabd 68,0,5
2: addl $8, %esp
PIC_EPILOGUE
popl %esi
movl %ebp, %esp
popl %ebp
PIC_PROLOGUE
/* Copy of libc .cerror since libc .cerror must be called from libc */
pushl %eax
/* The caller must execute the PIC prologue before jumping to cerror. */
call PIC_PLT(CNAME(__error))
popl %ecx
PIC_EPILOGUE
movl %ecx,(%eax)
movl $-1,%eax
movl $-1,%edx
ret
.stabs "_clone:f67",36,0,6,CNAME(_clone)
Lfe1:
.size CNAME(_clone),Lfe1-CNAME(_clone)
#ifdef DEBUG
.data
.globl _stack
_stack: .long 0
.long 0
.long 0
.long 0
.globl _stackaddr
_stackaddr: .long 0
.globl _fcn
_fcn: .long 0
#endif
|