chiark / gitweb /
eglibc (2.11.3-4+deb6u3) squeeze-lts; urgency=medium
[eglibc.git] / ports / sysdeps / unix / sysv / linux / hppa / clone.S
1 /* Copyright (C) 1996, 1997, 2000 Free Software Foundation, Inc.
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
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.
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
14    Lesser General Public License for more details.
15
16    You should have received a copy of the GNU Lesser General Public
17    License along with the GNU C Library; if not, write to the Free
18    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19    02111-1307 USA.  */
20
21 /* clone() is even more special than fork() as it mucks with stacks
22    and invokes a function in the right context after its all over.  */
23
24 #include <asm/unistd.h>
25 #include <sysdep.h>
26 #define _ERRNO_H        1
27 #include <bits/errno.h>
28
29 /* Non-thread code calls __clone with the following parameters:
30    int clone(int (*fn)(void *arg), 
31              void *child_stack, 
32              int flags, 
33              void *arg)
34    
35    NPTL Code will call __clone with the following parameters:
36    int clone(int (*fn)(void *arg), 
37              void *child_stack, 
38              int flags, 
39              void *arg,
40              int *parent_tidptr, 
41              struct user_desc *newtls, 
42              int *child_pidptr)
43         
44    The code should not mangle the extra input registers.
45    Syscall expects:                             Input to __clone:
46         4(r25) - function pointer               (r26, arg0) 
47         0(r25) - argument                       (r23, arg3)
48         r26 - clone flags.                      (r24, arg2)
49         r25+64 - user stack pointer.            (r25, arg1)
50         r24 - parent tid pointer.               (stack - 52)
51         r23 - struct user_desc newtls pointer.  (stack - 56)
52         r22 - child tid pointer.                (stack - 60)
53         r20 - clone syscall number              (constant)
54
55    Return:
56
57         On success the thread ID of the child process is returend in 
58         the callers context.
59         On error return -1, and set errno to the value returned by 
60         the syscall.
61  */
62
63         .text
64 ENTRY(__clone)
65         /* Prologue */
66         stwm    %r4, 64(%sp)
67         stw     %sp, -4(%sp)
68 #ifdef PIC
69         stw     %r19, -32(%sp)
70 #endif
71
72         /* Sanity check arguments.  */
73         comib,=,n  0, %arg0, .LerrorSanity        /* no NULL function pointers */
74         comib,=,n  0, %arg1, .LerrorSanity        /* no NULL stack pointers */
75
76         /* Save the function pointer, arg, and flags on the new stack.  */
77         stwm    %r26, 64(%r25)
78         stw     %r23, -60(%r25)
79         stw     %r24, -56(%r25)
80         /* Clone arguments are (int flags, void * child_stack) */
81         copy    %r24, %r26              /* flags are first */
82         /* User stack pointer is in the correct register already */
83
84         /* Load args from stack... */
85         ldw     -116(%sp), %r24         /* Load parent_tidptr */
86         ldw     -120(%sp), %r23         /* Load newtls */
87         ldw     -124(%sp), %r22         /* Load child_tidptr */
88
89         /* Save the PIC register. */
90 #ifdef PIC
91         copy    %r19, %r4               /* parent */
92 #endif
93
94         /* Do the system call */
95         ble     0x100(%sr2, %r0)
96         ldi     __NR_clone, %r20
97
98         ldi     -4096, %r1
99         comclr,>>= %r1, %ret0, %r0      /* Note: unsigned compare. */
100         b,n     .LerrorRest
101
102         /* Restore the PIC register.  */
103 #ifdef PIC
104         copy    %r4, %r19               /* parent */ 
105 #endif
106
107         comib,=,n 0, %ret0, .LthreadStart
108
109         /* Successful return from the parent
110            No need to restore the PIC register, 
111            since we return immediately. */
112
113         ldw     -84(%sp), %rp
114         bv      %r0(%rp)
115         ldwm    -64(%sp), %r4
116
117 .LerrorRest:
118         /* Something bad happened -- no child created */
119         bl      __syscall_error, %rp
120         sub     %r0, %ret0, %arg0
121         ldw     -84(%sp), %rp
122         /* Return after setting errno, ret0 is set to -1 by __syscall_error. */
123         bv      %r0(%rp)
124         ldwm    -64(%sp), %r4
125
126 .LerrorSanity:
127         /* Sanity checks failed, return -1, and set errno to EINVAL. */
128         bl      __syscall_error, %rp
129         ldi     EINVAL, %arg0
130         ldw     -84(%sp), %rp
131         bv      %r0(%rp)
132         ldwm    -64(%sp), %r4
133
134 .LthreadStart:
135 #ifdef RESET_PID
136 # define CLONE_VM_BIT           23      /* 0x00000100  */
137 # define CLONE_THREAD_BIT       15      /* 0x00010000  */
138         /* Load original clone flags. 
139            If CLONE_THREAD was passed, don't reset the PID/TID.
140            If CLONE_VM was passed, we need to store -1 to PID/TID.
141            If CLONE_VM and CLONE_THREAD were not set store the result
142            of getpid to PID/TID.  */
143         ldw     -56(%sp), %r26
144         bb,<,n  %r26, CLONE_THREAD_BIT, 1f
145         bb,<    %r26, CLONE_VM_BIT, 2f 
146         ldi     -1, %ret0
147         ble     0x100(%sr2, %r0)
148         ldi     __NR_getpid, %r20
149 2:
150         mfctl   %cr27, %r26
151         stw     %ret0, PID_THREAD_OFFSET(%r26)
152         stw     %ret0, TID_THREAD_OFFSET(%r26)
153 1:
154 #endif
155         /* Load up the arguments.  */
156         ldw     -60(%sp), %arg0
157         ldw     -64(%sp), %r22
158
159         /* $$dyncall fixes childs PIC register */
160
161         /* Call the user's function */
162 #ifdef PIC
163         copy    %r19, %r4
164 #endif
165         bl      $$dyncall, %r31
166         copy    %r31, %rp
167 #ifdef PIC
168         copy    %r4, %r19
169 #endif
170         /* The call to _exit needs saved r19.  */
171         bl      _exit, %rp
172         copy    %ret0, %arg0
173
174         /* We should not return from _exit.
175            We do not restore r4, or the stack state.  */
176         iitlbp  %r0, (%sr0, %r0)
177
178 PSEUDO_END(__clone)
179
180 weak_alias (__clone, clone)