]> git.ipfire.org Git - thirdparty/glibc.git/blob - sysdeps/unix/sysv/linux/mips/clone.S
Prefer https to http for gnu.org and fsf.org URLs
[thirdparty/glibc.git] / sysdeps / unix / sysv / linux / mips / clone.S
1 /* Copyright (C) 1996-2019 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Contributed by Ralf Bächle <ralf@linux-mips.org>, 1996.
4
5 The GNU C Library is free software; you can redistribute it and/or
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.
9
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
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library. If not, see
17 <https://www.gnu.org/licenses/>. */
18
19 /* clone() is even more special than fork() as it mucks with stacks
20 and invokes a function in the right context after its all over. */
21
22 #include <sys/asm.h>
23 #include <sysdep.h>
24 #define _ERRNO_H 1
25 #include <bits/errno.h>
26 #include <tls.h>
27
28 /* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg,
29 void *parent_tidptr, void *tls, void *child_tidptr) */
30
31 .text
32 .set nomips16
33 #if _MIPS_SIM == _ABIO32
34 # define EXTRA_LOCALS 1
35 #else
36 # define EXTRA_LOCALS 0
37 #endif
38 LOCALSZ= 4
39 FRAMESZ= (((NARGSAVE+LOCALSZ)*SZREG)+ALSZ)&ALMASK
40 GPOFF= FRAMESZ-(1*SZREG)
41 NESTED(__clone,4*SZREG,sp)
42 #ifdef __PIC__
43 SETUP_GP
44 #endif
45 PTR_SUBU sp, FRAMESZ
46 cfi_adjust_cfa_offset (FRAMESZ)
47 SETUP_GP64_STACK (GPOFF, __clone)
48 #ifdef __PIC__
49 SAVE_GP (GPOFF)
50 #endif
51 #ifdef PROF
52 .set noat
53 move $1,ra
54 jal _mcount
55 .set at
56 #endif
57
58
59 /* Sanity check arguments. */
60 li v0,EINVAL
61 beqz a0,L(error) /* No NULL function pointers. */
62 beqz a1,L(error) /* No NULL stack pointers. */
63
64 PTR_SUBU a1,32 /* Reserve argument save space. */
65 PTR_S a0,0(a1) /* Save function pointer. */
66 PTR_S a3,PTRSIZE(a1) /* Save argument pointer. */
67 LONG_S a2,(PTRSIZE*2)(a1) /* Save clone flags. */
68
69 move a0,a2
70
71 /* Shuffle in the last three arguments - arguments 5, 6, and 7 to
72 this function, but arguments 3, 4, and 5 to the syscall. */
73 #if _MIPS_SIM == _ABIO32
74 PTR_L a2,(FRAMESZ+PTRSIZE+PTRSIZE+16)(sp)
75 PTR_S a2,16(sp)
76 PTR_L a2,(FRAMESZ+16)(sp)
77 PTR_L a3,(FRAMESZ+PTRSIZE+16)(sp)
78 #else
79 move a2,a4
80 move a3,a5
81 move a4,a6
82 #endif
83
84 /* Do the system call */
85 li v0,__NR_clone
86 cfi_endproc
87 syscall
88
89 bnez a3,L(error)
90 beqz v0,L(thread_start)
91
92 /* Successful return from the parent */
93 cfi_startproc
94 cfi_adjust_cfa_offset (FRAMESZ)
95 SETUP_GP64_STACK_CFI (GPOFF)
96 cfi_remember_state
97 RESTORE_GP64_STACK
98 PTR_ADDU sp, FRAMESZ
99 cfi_adjust_cfa_offset (-FRAMESZ)
100 ret
101
102 /* Something bad happened -- no child created */
103 L(error):
104 cfi_restore_state
105 #ifdef __PIC__
106 PTR_LA t9,__syscall_error
107 RESTORE_GP64_STACK
108 PTR_ADDU sp, FRAMESZ
109 cfi_adjust_cfa_offset (-FRAMESZ)
110 jr t9
111 #else
112 RESTORE_GP64_STACK
113 PTR_ADDU sp, FRAMESZ
114 cfi_adjust_cfa_offset (-FRAMESZ)
115 j __syscall_error
116 #endif
117 END(__clone)
118
119 /* Load up the arguments to the function. Put this block of code in
120 its own function so that we can terminate the stack trace with our
121 debug info. */
122
123 ENTRY(__thread_start)
124 L(thread_start):
125 cfi_undefined ($31)
126 /* cp is already loaded. */
127 SAVE_GP (GPOFF)
128 /* The stackframe has been created on entry of clone(). */
129
130 /* Restore the arg for user's function. */
131 PTR_L t9,0(sp) /* Function pointer. */
132 PTR_L a0,PTRSIZE(sp) /* Argument pointer. */
133
134 /* Call the user's function. */
135 jal t9
136
137 move a0,v0
138 li v0,__NR_exit
139 syscall
140
141 END(__thread_start)
142
143 libc_hidden_def (__clone)
144 weak_alias (__clone, clone)