Update copyright dates with scripts/update-copyrights.
[glibc.git] / sysdeps / unix / sysv / linux / aarch64 / clone.S
blob1f5e1dcd7d272b640b0a2ccc1e32a30a1281b476
1 /* Copyright (C) 1996-2015 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
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.
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.
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    <http://www.gnu.org/licenses/>.  */
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.  */
22 #include <sysdep.h>
23 #define _ERRNO_H        1
24 #include <bits/errno.h>
26 #define CLONE_VM_BIT      8
27 #define CLONE_VM          (1 << CLONE_VM_BIT)
29 #define CLONE_THREAD_BIT  16
30 #define CLONE_THREAD      (1 << CLONE_THREAD_BIT)
32 /* int clone(int (*fn)(void *arg),            x0
33              void *child_stack,               x1
34              int flags,                       x2
35              void *arg,                       x3
36              pid_t *ptid,                     x4
37              struct user_desc *tls,           x5
38              pid_t *ctid);                    x6
39  */
40         .text
41 ENTRY(__clone)
42         /* Save args for the child.  */
43         mov     x10, x0
44         mov     x11, x2
45         mov     x12, x3
47         /* Sanity check args.  */
48         mov     x0, #-EINVAL
49         cbz     x10, .Lsyscall_error
50         cbz     x1, .Lsyscall_error
52         /* Do the system call.  */
53         /* X0:flags, x1:newsp, x2:parenttidptr, x3:newtls, x4:childtid.  */
54         mov     x0, x2                  /* flags  */
55         /* New sp is already in x1.  */
56         mov     x2, x4                  /* ptid  */
57         mov     x3, x5                  /* tls  */
58         mov     x4, x6                  /* ctid  */
59         mov     x8, #SYS_ify(clone)
60         svc     0x0
62         cmp     x0, #0
63         beq     thread_start
64         blt     .Lsyscall_error
65         RET
66 PSEUDO_END (__clone)
68         .align 4
69         .type thread_start, %function
70 thread_start:
71         cfi_startproc
72         cfi_undefined (x30)
73         mov     x29, 0
75         tbnz    x11, #CLONE_THREAD_BIT, 3f
76         mov     x0, #-1
77         tbnz    x11, #CLONE_VM_BIT, 2f
78         mov     x8, #SYS_ify(getpid)
79         svc     0x0
81         mrs     x1, tpidr_el0
82         sub     x1, x1, #PTHREAD_SIZEOF
83         str     w0, [x1, #PTHREAD_PID_OFFSET]
84         str     w0, [x1, #PTHREAD_TID_OFFSET]
87         /* Pick the function arg and execute.  */
88         mov     x0, x12
89         blr     x10
91         /* We are done, pass the return value through x0.  */
92         b       HIDDEN_JUMPTARGET(_exit)
93         cfi_endproc
94         .size thread_start, .-thread_start
96 weak_alias (__clone, clone)