summaryrefslogtreecommitdiff
path: root/devel/linuxthreads/files/clone.S
blob: 51e7560446b0bd03fe1e9f9d3fdb0e60d7f570ed (plain) (blame)
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
	.file	"clone.S"
#include <sys/syscall.h>
#include "DEFS.h"
#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);	
 *
 * I'm pretty shakey on assembly language, so someone else better
 * check this!  I don't even know what half this stuff means, its
 * just copied from somewhere else (rf.S).
 *
 * It seems to work though.
 *	
 * 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

	/*
	 * 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	%esi

	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
	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
	call	%eax
	addl	$8, %esp

	/*
	 * Exit system call
	 */
	call	PIC_PLT(_exit)

	.stabd 68,0,5
2:	addl	$8, %esp
	popl	%esi
	movl	%ebp, %esp
	popl	%ebp
	jmp	PIC_PLT(HIDENAME(cerror))

.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