]>
Commit | Line | Data |
---|---|---|
b5ce64ef | 1 | /* Copyright (C) 1996, 1997 Free Software Foundation, Inc. |
3c7b2587 UD |
2 | This file is part of the GNU C Library. |
3 | Contributed by Richard Henderson <rth@tamu.edu>, 1996. | |
3b0174d0 | 4 | |
3c7b2587 | 5 | The GNU C Library is free software; you can redistribute it and/or |
3214b89b AJ |
6 | modify it under the terms of the GNU Lesser General Public |
7 | License as published by the Free Software Foundation; either | |
8 | version 2.1 of the License, or (at your option) any later version. | |
3b0174d0 | 9 | |
3c7b2587 UD |
10 | The GNU C Library is distributed in the hope that it will be useful, |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
3214b89b | 13 | Lesser General Public License for more details. |
3b0174d0 | 14 | |
3214b89b AJ |
15 | You should have received a copy of the GNU Lesser General Public |
16 | License along with the GNU C Library; if not, write to the Free | |
17 | Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA | |
18 | 02111-1307 USA. */ | |
3b0174d0 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 <sysdep.h> | |
81e25b60 | 24 | #define _ERRNO_H 1 |
405916ef | 25 | #include <bits/errno.h> |
3b0174d0 | 26 | |
b5ce64ef | 27 | /* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg) */ |
3b0174d0 UD |
28 | |
29 | .text | |
30 | ENTRY(__clone) | |
dd4b8913 | 31 | #ifdef PROF |
18a702a8 | 32 | ldgp gp,0(pv) |
3c7b2587 | 33 | .set noat |
dd4b8913 UD |
34 | lda AT, _mcount |
35 | jsr AT, (AT), _mcount | |
3c7b2587 | 36 | .set at |
3b0174d0 | 37 | .prologue 1 |
18a702a8 RH |
38 | #else |
39 | .prologue 0 | |
40 | #endif | |
3b0174d0 UD |
41 | |
42 | /* Sanity check arguments. */ | |
3b0174d0 UD |
43 | ldiq v0,EINVAL |
44 | beq a0,$error /* no NULL function pointers */ | |
45 | beq a1,$error /* no NULL stack pointers */ | |
3b0174d0 | 46 | |
0f85544d UD |
47 | /* Save the fn ptr and arg on the new stack. */ |
48 | subq a1,16,a1 | |
49 | stq a0,0(a1) | |
50 | stq a3,8(a1) | |
51 | ||
3b0174d0 | 52 | /* Do the system call */ |
3b0174d0 UD |
53 | mov a2,a0 |
54 | ldiq v0,__NR_clone | |
55 | call_pal PAL_callsys | |
56 | ||
57 | bne a3,$error | |
58 | beq v0,thread_start | |
59 | ||
60 | /* Successful return from the parent */ | |
3b0174d0 UD |
61 | ret |
62 | ||
63 | /* Something bad happened -- no child created */ | |
64 | $error: | |
73bc8117 | 65 | #ifndef PROF |
3b0174d0 UD |
66 | br gp,1f |
67 | 1: ldgp gp,0(gp) | |
73bc8117 | 68 | #endif |
3b0174d0 UD |
69 | jmp zero,__syscall_error |
70 | ||
71 | END(__clone) | |
72 | ||
73 | /* Load up the arguments to the function. Put this block of code in | |
74 | its own function so that we can terminate the stack trace with our | |
b5ce64ef | 75 | debug info. */ |
3b0174d0 UD |
76 | |
77 | .ent thread_start | |
78 | thread_start: | |
79 | .frame fp,0,zero,0 | |
80 | mov zero,fp | |
81 | .prologue 0 | |
82 | ||
0f85544d UD |
83 | /* Load up the arguments. */ |
84 | ldq pv,0(sp) | |
85 | ldq a0,8(sp) | |
86 | addq sp,16,sp | |
87 | ||
3b0174d0 UD |
88 | /* Call the user's function */ |
89 | jsr ra,(pv) | |
90 | ldgp gp,0(ra) | |
91 | ||
92 | /* Call _exit rather than doing it inline for breakpoint purposes */ | |
93 | mov v0,a0 | |
94 | jsr ra,_exit | |
95 | ||
b5ce64ef UD |
96 | /* Die horribly. */ |
97 | halt | |
98 | ||
3b0174d0 UD |
99 | .end thread_start |
100 | ||
101 | weak_alias(__clone, clone) |