]>
Commit | Line | Data |
---|---|---|
b35e2407 UD |
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 Library General Public License as | |
8 | published by the Free Software Foundation; either version 2 of the | |
9 | 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 | Library General Public License for more details. | |
15 | ||
16 | You should have received a copy of the GNU Library General Public | |
17 | License along with the GNU C Library; see the file COPYING.LIB. If not, | |
18 | write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
19 | Boston, MA 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 | /* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg) */ | |
30 | ||
31 | .text | |
32 | ENTRY(__clone) | |
33 | /* FIXME: I have no idea how profiling works on hppa. */ | |
34 | ||
35 | /* Sanity check arguments. */ | |
36 | comib,<> 0,%arg0,.Lerror /* no NULL function pointers */ | |
37 | ldi EINVAL,%ret0 | |
38 | comib,<> 0,%arg1,.Lerror /* no NULL stack pointers */ | |
39 | nop | |
40 | ||
41 | /* Save the fn ptr and arg on the new stack. */ | |
42 | stwm %arg3,64(%arg1) | |
43 | stw %arg3,-60(%arg1) | |
44 | ||
45 | /* Do the system call */ | |
46 | copy %arg2,%arg0 | |
47 | ble 0x100(%sr7,%r0) | |
48 | ldi __NR_clone,%r20 | |
49 | ||
50 | ldi -4096,%r1 | |
51 | comclr,>>= %r1,%ret0,%r0 /* Note: unsigned compare. */ | |
52 | b,n .Lerror | |
53 | ||
54 | comib,=,n 0,%ret0,thread_start | |
55 | ||
56 | /* Successful return from the parent */ | |
57 | bv %r0(%rp) | |
58 | nop | |
59 | ||
60 | /* Something bad happened -- no child created */ | |
61 | .Lerror: | |
62 | b __syscall_error | |
63 | nop | |
64 | ||
65 | thread_start: | |
66 | /* Load up the arguments. */ | |
67 | ldw -60(%sp),%arg0 | |
68 | ldwm -64(%sp),%r22 | |
69 | ||
70 | /* Call the user's function */ | |
71 | bl $$dyncall,%r31 | |
72 | copy %r31,%rp | |
73 | ||
74 | bl _exit,%rp | |
75 | copy %ret0,%arg0 | |
76 | ||
77 | /* Die horribly. */ | |
78 | iitlbp %r0,(%r0) | |
79 | ||
80 | PSEUDO_END(__clone) | |
81 | ||
82 | weak_alias(__clone, clone) |