1/* Copyright (C) 1996-2022 Free Software Foundation, Inc.
2   This file is part of the GNU C Library.
3
4   The GNU C Library is free software; you can redistribute it and/or
5   modify it under the terms of the GNU Lesser General Public
6   License as published by the Free Software Foundation; either
7   version 2.1 of the License, or (at your option) any later version.
8
9   The GNU C Library is distributed in the hope that it will be useful,
10   but WITHOUT ANY WARRANTY; without even the implied warranty of
11   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12   Lesser General Public License for more details.
13
14   You should have received a copy of the GNU Lesser General Public
15   License along with the GNU C Library.  If not, see
16   <https://www.gnu.org/licenses/>.  */
17
18/* clone() is even more special than fork() as it mucks with stacks
19   and invokes a function in the right context after its all over.  */
20
21#include <sysdep.h>
22#include <tcb-offsets.h>
23#define _ERRNO_H	1
24#include <bits/errno.h>
25
26/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg,
27	     pid_t *ptid, struct user_desc *tls, pid_t *ctid); */
28
29        .text
30ENTRY(__clone)
31	@ sanity check args
32	cmp	r0, #0
33	@ align sp
34	and	r1, r1, #-8
35	ite	ne
36	cmpne	r1, #0
37	moveq	r0, #-EINVAL
38	beq	PLTJMP(syscall_error)
39
40	@ insert the args onto the new stack
41	str	r3, [r1, #-4]!
42	str	r0, [r1, #-4]!
43
44	@ do the system call
45	@ get flags
46	mov	r0, r2
47	mov	ip, r2
48	@ new sp is already in r1
49	push	{r4, r7}
50	cfi_adjust_cfa_offset (8)
51	cfi_rel_offset (r4, 0)
52	cfi_rel_offset (r7, 4)
53	ldr	r2, [sp, #8]
54	ldr	r3, [sp, #12]
55	ldr	r4, [sp, #16]
56	ldr	r7, =SYS_ify(clone)
57	swi	0x0
58	cfi_endproc
59	cmp	r0, #0
60	beq	1f
61	pop	{r4, r7}
62	blt	PLTJMP(C_SYMBOL_NAME(__syscall_error))
63	RETINSTR(, lr)
64
65	cfi_startproc
66PSEUDO_END (__clone)
67
681:
69	.fnstart
70	.cantunwind
71	@ pick the function arg and call address off the stack and execute
72	ldr	r0, [sp, #4]
73	ldr 	ip, [sp], #8
74	BLX (ip)
75
76	@ and we are done, passing the return value through r0
77	ldr	r7, =SYS_ify(exit)
78	swi	0x0
79
80	.fnend
81
82libc_hidden_def (__clone)
83weak_alias (__clone, clone)
84