remove PID caching
[uclibc-ng.git] / libc / sysdeps / linux / arc / clone.S
blobc2ce906c921686adf8a9bcf13a351de2113a2734
1 /*
2  * Copyright (C) 2013 Synopsys, Inc. (www.synopsys.com)
3  *
4  * Licensed under the LGPL v2.1 or later, see the file COPYING.LIB in this tarball.
5  */
7 #include <asm/errno.h>
8 #include <sys/syscall.h>
9 #include <sysdep.h>
11 ; Per man, libc clone( ) is as follows
13 ; int clone(int (*fn)(void *), void *child_stack,
14 ;           int flags, void *arg, ...
15 ;           /* pid_t *ptid, struct user_desc *tls, pid_t *ctid */);
17 ; NOTE: I'm assuming that the last 3 args are NOT var-args and in case all
18 ;       3 are not relevant, caller will nevertheless pass those as NULL.
19 ;       Current (Jul 2012) upstream powerpc/clone.S assumes similarly.
20 ;       Our LTP (from 2007) doesn't seem to have tests to prove otherwise
22 ; clone syscall in kernel (ABI: CONFIG_CLONE_BACKWARDS)
24 ; int sys_clone(unsigned long clone_flags,
25 ;               unsigned long newsp,
26 ;               int __user *parent_tidptr,
27 ;               void *tls,
28 ;               int __user *child_tidptr)
30 #define CLONE_SETTLS            0x00080000
32 ENTRY(clone)
33         cmp     r0, 0           ; @fn can't be NULL
34         cmp.ne  r1, 0           ; @child_stack can't be NULL
35         bz      .L__sys_err
37         ; save some of the orig args
38         ; r0 containg @fn will be clobbered AFTER syscall (with ret val)
39         ; rest are clobbered BEFORE syscall due to different arg ordering
40         mov     r10, r0         ; @fn
41         mov     r11, r3         ; @args
42         mov     r12, r2         ; @clone_flags
43         mov     r9,  r5         ; @tls
45         ; adjust libc args for syscall
47         mov     r0, r2          ; libc @flags is 1st syscall arg
48         mov     r2, r4          ; libc @ptid
49         mov     r3, r5          ; libc @tls
50         mov     r4, r6          ; libc @ctid
51         mov     r8, __NR_clone
52         ARC_TRAP_INSN
54         cmp     r0, 0           ; return code : 0 new process, !0 parent
55         blt     .L__sys_err2    ; < 0 (signed) error
56         jnz     [blink]         ; Parent returns
58         ; ----- child starts here ---------
60 #if defined(__UCLIBC_HAS_TLS__)
61         ; Setup TP register (since kernel doesn't do that)
62         and.f   0, r12, CLONE_SETTLS
63         bz      .Lnext_clone_quirk
64         mov     r25, r9
66 .Lnext_clone_quirk:
67 #endif
68         ; child jumps off to @fn with @arg as argument, and returns here
69         jl.d    [r10]
70         mov     r0, r11
72         ; falls thru to _exit() with result from @fn (already in r0)
73         b       HIDDEN_JUMPTARGET(_exit)
75 .L__sys_err:
76         mov     r0, -EINVAL
77 .L__sys_err2:
78         ; (1) No need to make -ve kernel error code as positive errno
79         ;   __syscall_error expects the -ve error code returned by kernel
80         ; (2) r0 still had orig -ve kernel error code
81         ; (3) Tail call to __syscall_error so we dont have to come back
82         ;     here hence instead of jmp-n-link (reg push/pop) we do jmp
83         ; (4) No need to route __syscall_error via PLT, B is inherently
84         ;     position independent
85         b   __syscall_error
86 END(clone)
87 libc_hidden_def(clone)