OSDN Git Service

79ebd065ab858937f8b99842d85a5caf393dd21d
[uclinux-h8/uClibc.git] / libc / sysdeps / linux / arc / clone.S
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  */
6
7 #include <asm/errno.h>
8 #include <sys/syscall.h>
9 #include <sysdep.h>
10
11 ; Per man, libc clone( ) is as follows
12 ;
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 */);
16 ;
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
21
22 ; clone syscall in kernel
23 ;
24 ; int sys_clone(unsigned long clone_flags, unsigned long newsp,
25 ;               int __user *parent_tidptr, void *tls,
26 ;               int __user *child_tidptr)
27
28
29 ENTRY(clone)
30         cmp     r0, 0           ; @fn can't be NULL
31         cmp.ne  r1, 0           ; @child_stack can't be NULL
32         bz      .L__sys_err
33
34         ; @fn and @args needed after the syscall for child
35         ; However r3 containing @arg will be clobbered BEFORE syscall
36         ; r0 containg @fn will be clobbered AFTER syscall (with ret val)
37         mov     r10, r0
38         mov     r11, r3
39
40         ; adjust libc args for syscall
41         mov     r0, r2          ; libc @flags is 1st syscall arg
42         mov     r2, r4          ; libc @ptid
43         mov     r3, r5          ; libc @tls
44         mov     r4, r6          ; libc @ctid
45         mov     r8, __NR_clone
46         ARC_TRAP_INSN
47
48         cmp     r0, 0           ; return code : 0 new process, !0 parent
49         blt     .L__sys_err2    ; < 0 (signed) error
50         jnz     [blink]         ; Parent returns
51
52         ; child jumps off to @fn with @arg as argument
53         j.d     [r10]
54         mov     r0, r11
55
56         ; falls thru to _exit() with result from @fn (already in r0)
57         b       HIDDEN_JUMPTARGET(_exit)
58
59 .L__sys_err:
60         mov     r0, -EINVAL
61 .L__sys_err2:
62         ; (1) No need to make -ve kernel error code as positive errno
63         ;   __syscall_error expects the -ve error code returned by kernel
64         ; (2) r0 still had orig -ve kernel error code
65         ; (3) Tail call to __syscall_error so we dont have to come back
66         ;     here hence instead of jmp-n-link (reg push/pop) we do jmp
67         ; (4) No need to route __syscall_error via PLT, B is inherently
68         ;     position independent
69         b   __syscall_error
70 END(clone)
71 libc_hidden_def(clone)