]>
Commit | Line | Data |
---|---|---|
568035b7 | 1 | /* Copyright (C) 1996-2013 Free Software Foundation, Inc. |
b35e2407 UD |
2 | This file is part of the GNU C Library. |
3 | Contributed by David Huggins-Daines <dhd@debian.org>, 2000. | |
4 | Based on the Alpha version by Richard Henderson <rth@tamu.edu>, 1996. | |
5 | ||
6 | The GNU C Library is free software; you can redistribute it and/or | |
3214b89b AJ |
7 | modify it under the terms of the GNU Lesser General Public |
8 | License as published by the Free Software Foundation; either | |
9 | version 2.1 of the License, or (at your option) any later version. | |
b35e2407 UD |
10 | |
11 | The GNU C Library is distributed in the hope that it will be useful, | |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
3214b89b | 14 | Lesser General Public License for more details. |
b35e2407 | 15 | |
3214b89b | 16 | You should have received a copy of the GNU Lesser General Public |
ab84e3ff PE |
17 | License along with the GNU C Library. If not, see |
18 | <http://www.gnu.org/licenses/>. */ | |
b35e2407 UD |
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 | #include <asm/unistd.h> | |
24 | #include <sysdep.h> | |
25 | #define _ERRNO_H 1 | |
26 | #include <bits/errno.h> | |
27 | ||
a29e6e84 | 28 | /* Non-thread code calls __clone with the following parameters: |
5556231d JM |
29 | int clone(int (*fn)(void *arg), |
30 | void *child_stack, | |
31 | int flags, | |
0daa0500 | 32 | void *arg) |
5556231d | 33 | |
a29e6e84 | 34 | NPTL Code will call __clone with the following parameters: |
5556231d JM |
35 | int clone(int (*fn)(void *arg), |
36 | void *child_stack, | |
37 | int flags, | |
0daa0500 | 38 | void *arg, |
5556231d JM |
39 | int *parent_tidptr, |
40 | struct user_desc *newtls, | |
0daa0500 | 41 | int *child_pidptr) |
5556231d | 42 | |
a29e6e84 CD |
43 | The code should not mangle the extra input registers. |
44 | Syscall expects: Input to __clone: | |
5556231d | 45 | 4(r25) - function pointer (r26, arg0) |
a29e6e84 CD |
46 | 0(r25) - argument (r23, arg3) |
47 | r26 - clone flags. (r24, arg2) | |
48 | r25+64 - user stack pointer. (r25, arg1) | |
49 | r24 - parent tid pointer. (stack - 52) | |
50 | r23 - struct user_desc newtls pointer. (stack - 56) | |
51 | r22 - child tid pointer. (stack - 60) | |
52 | r20 - clone syscall number (constant) | |
0daa0500 CD |
53 | |
54 | Return: | |
55 | ||
5556231d | 56 | On success the thread ID of the child process is returend in |
0daa0500 | 57 | the callers context. |
5556231d | 58 | On error return -1, and set errno to the value returned by |
0daa0500 | 59 | the syscall. |
a29e6e84 | 60 | */ |
b35e2407 UD |
61 | |
62 | .text | |
63 | ENTRY(__clone) | |
0daa0500 | 64 | /* Prologue */ |
7cad09f9 | 65 | stwm %r4, 64(%sp) |
0daa0500 | 66 | stw %sp, -4(%sp) |
7cad09f9 | 67 | #ifdef PIC |
0daa0500 | 68 | stw %r19, -32(%sp) |
7cad09f9 | 69 | #endif |
b35e2407 UD |
70 | |
71 | /* Sanity check arguments. */ | |
0daa0500 CD |
72 | comib,=,n 0, %arg0, .LerrorSanity /* no NULL function pointers */ |
73 | comib,=,n 0, %arg1, .LerrorSanity /* no NULL stack pointers */ | |
b35e2407 | 74 | |
7cad09f9 | 75 | /* Save the function pointer, arg, and flags on the new stack. */ |
0daa0500 CD |
76 | stwm %r26, 64(%r25) |
77 | stw %r23, -60(%r25) | |
7cad09f9 | 78 | stw %r24, -56(%r25) |
a29e6e84 | 79 | /* Clone arguments are (int flags, void * child_stack) */ |
0daa0500 | 80 | copy %r24, %r26 /* flags are first */ |
a29e6e84 CD |
81 | /* User stack pointer is in the correct register already */ |
82 | ||
83 | /* Load args from stack... */ | |
0daa0500 CD |
84 | ldw -116(%sp), %r24 /* Load parent_tidptr */ |
85 | ldw -120(%sp), %r23 /* Load newtls */ | |
86 | ldw -124(%sp), %r22 /* Load child_tidptr */ | |
b35e2407 | 87 | |
46bf1d81 UD |
88 | /* Save the PIC register. */ |
89 | #ifdef PIC | |
7cad09f9 | 90 | copy %r19, %r4 /* parent */ |
46bf1d81 UD |
91 | #endif |
92 | ||
b35e2407 | 93 | /* Do the system call */ |
0daa0500 CD |
94 | ble 0x100(%sr2, %r0) |
95 | ldi __NR_clone, %r20 | |
b35e2407 | 96 | |
0daa0500 CD |
97 | ldi -4096, %r1 |
98 | comclr,>>= %r1, %ret0, %r0 /* Note: unsigned compare. */ | |
a29e6e84 | 99 | b,n .LerrorRest |
b35e2407 | 100 | |
7cad09f9 CD |
101 | /* Restore the PIC register. */ |
102 | #ifdef PIC | |
5556231d | 103 | copy %r4, %r19 /* parent */ |
7cad09f9 CD |
104 | #endif |
105 | ||
0daa0500 | 106 | comib,=,n 0, %ret0, .LthreadStart |
b35e2407 | 107 | |
46bf1d81 | 108 | /* Successful return from the parent |
5556231d | 109 | No need to restore the PIC register, |
46bf1d81 UD |
110 | since we return immediately. */ |
111 | ||
0daa0500 | 112 | ldw -84(%sp), %rp |
b35e2407 | 113 | bv %r0(%rp) |
7cad09f9 | 114 | ldwm -64(%sp), %r4 |
46bf1d81 | 115 | |
31e69e34 | 116 | .LerrorRest: |
a29e6e84 | 117 | /* Something bad happened -- no child created */ |
0daa0500 CD |
118 | bl __syscall_error, %rp |
119 | sub %r0, %ret0, %arg0 | |
120 | ldw -84(%sp), %rp | |
121 | /* Return after setting errno, ret0 is set to -1 by __syscall_error. */ | |
122 | bv %r0(%rp) | |
7cad09f9 | 123 | ldwm -64(%sp), %r4 |
0daa0500 CD |
124 | |
125 | .LerrorSanity: | |
126 | /* Sanity checks failed, return -1, and set errno to EINVAL. */ | |
127 | bl __syscall_error, %rp | |
128 | ldi EINVAL, %arg0 | |
0daa0500 | 129 | ldw -84(%sp), %rp |
a29e6e84 | 130 | bv %r0(%rp) |
7cad09f9 | 131 | ldwm -64(%sp), %r4 |
b35e2407 | 132 | |
0daa0500 | 133 | .LthreadStart: |
7cad09f9 CD |
134 | #ifdef RESET_PID |
135 | # define CLONE_VM_BIT 23 /* 0x00000100 */ | |
136 | # define CLONE_THREAD_BIT 15 /* 0x00010000 */ | |
5556231d | 137 | /* Load original clone flags. |
7cad09f9 CD |
138 | If CLONE_THREAD was passed, don't reset the PID/TID. |
139 | If CLONE_VM was passed, we need to store -1 to PID/TID. | |
140 | If CLONE_VM and CLONE_THREAD were not set store the result | |
141 | of getpid to PID/TID. */ | |
142 | ldw -56(%sp), %r26 | |
143 | bb,<,n %r26, CLONE_THREAD_BIT, 1f | |
5556231d | 144 | bb,< %r26, CLONE_VM_BIT, 2f |
7cad09f9 CD |
145 | ldi -1, %ret0 |
146 | ble 0x100(%sr2, %r0) | |
147 | ldi __NR_getpid, %r20 | |
148 | 2: | |
149 | mfctl %cr27, %r26 | |
150 | stw %ret0, PID_THREAD_OFFSET(%r26) | |
151 | stw %ret0, TID_THREAD_OFFSET(%r26) | |
152 | 1: | |
153 | #endif | |
b35e2407 | 154 | /* Load up the arguments. */ |
0daa0500 CD |
155 | ldw -60(%sp), %arg0 |
156 | ldw -64(%sp), %r22 | |
46bf1d81 | 157 | |
382466e0 | 158 | /* $$dyncall fixes child's PIC register */ |
b35e2407 UD |
159 | |
160 | /* Call the user's function */ | |
7cad09f9 CD |
161 | #ifdef PIC |
162 | copy %r19, %r4 | |
163 | #endif | |
0daa0500 CD |
164 | bl $$dyncall, %r31 |
165 | copy %r31, %rp | |
7cad09f9 CD |
166 | #ifdef PIC |
167 | copy %r4, %r19 | |
168 | #endif | |
169 | /* The call to _exit needs saved r19. */ | |
0daa0500 CD |
170 | bl _exit, %rp |
171 | copy %ret0, %arg0 | |
b35e2407 | 172 | |
7cad09f9 CD |
173 | /* We should not return from _exit. |
174 | We do not restore r4, or the stack state. */ | |
0daa0500 | 175 | iitlbp %r0, (%sr0, %r0) |
b35e2407 UD |
176 | |
177 | PSEUDO_END(__clone) | |
178 | ||
8796ce21 | 179 | weak_alias (__clone, clone) |