Update copyright notices with scripts/update-copyrights
[glibc.git] / ports / sysdeps / unix / sysv / linux / alpha / clone.S
blobc5c3300c472911dc84fac25173f2664b9d082195
1 /* Copyright (C) 1996-2014 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3    Contributed by Richard Henderson <rth@tamu.edu>, 1996.
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        0x00000100
27 #define CLONE_THREAD    0x00010000
29 /* int clone(int (*fn)(void *arg), void *child_stack, int flags,
30              void *arg, pid_t *ptid, void *tls, pid_t *ctid);
32    Note that everything past ARG is technically optional, based
33    on FLAGS, and that CTID is arg 7, and thus is on the stack.
34    However, since a load from top-of-stack better be legal always,
35    we don't bother checking FLAGS.  */
37         .text
38         .align  4
39         .globl  __clone
40         .ent    __clone
41         .usepv  __clone, USEPV_PROF
43         cfi_startproc
44 __clone:
45 #ifdef PROF
46         ldgp    gp,0(pv)
47         lda     AT, _mcount
48         jsr     AT, (AT), _mcount
49 #endif
51         /* Sanity check arguments.  */
52         ldiq    v0, EINVAL
53         beq     a0, SYSCALL_ERROR_LABEL /* no NULL function pointers */
54         beq     a1, SYSCALL_ERROR_LABEL /* no NULL stack pointers */
56         /* Save the fn ptr and arg on the new stack.  */
57         subq    a1, 32, a1
58         stq     a0, 0(a1)
59         stq     a3, 8(a1)
60 #ifdef RESET_PID
61         stq     a2, 16(a1)
62 #endif
64         /* The syscall is of the form clone(flags, usp, ptid, ctid, tls).
65            Shift the flags, ptid, ctid, tls arguments into place; the
66            child_stack argument is already correct.  */
67         mov     a2, a0
68         mov     a4, a2
69         ldq     a3, 0(sp)
70         mov     a5, a4
72         /* Do the system call.  */
73         ldiq    v0, __NR_clone
74         call_pal PAL_callsys
76         bne     a3, SYSCALL_ERROR_LABEL
77         beq     v0, thread_start
79         /* Successful return from the parent.  */
80         ret
82 PSEUDO_END(__clone)
83         cfi_endproc
85 /* Load up the arguments to the function.  Put this block of code in
86    its own function so that we can terminate the stack trace with our
87    debug info.  */
89         .ent thread_start
90         cfi_startproc
91 thread_start:
92         mov     0, fp
93         cfi_def_cfa_register(fp)
94         cfi_undefined(ra)
96 #ifdef RESET_PID
97         /* Check and see if we need to reset the PID.  */
98         ldq     t0, 16(sp)
99         lda     t1, CLONE_THREAD
100         and     t0, t1, t2
101         beq     t2, 2f
103 #endif
105         /* Load up the arguments.  */
106         ldq     pv, 0(sp)
107         ldq     a0, 8(sp)
108         addq    sp, 32, sp
110         /* Call the user's function.  */
111         jsr     ra, (pv)
112         ldgp    gp, 0(ra)
114         /* Call _exit rather than doing it inline for breakpoint purposes.  */
115         mov     v0, a0
116 #ifdef PIC
117         bsr     ra, HIDDEN_JUMPTARGET(_exit)    !samegp
118 #else
119         jsr     ra, HIDDEN_JUMPTARGET(_exit)
120 #endif
122         /* Die horribly.  */
123         halt
125 #ifdef RESET_PID
127         rduniq
128         lda     t1, CLONE_VM
129         mov     v0, s0
130         lda     v0, -1
131         and     t0, t1, t2
132         bne     t2, 3f
133         lda     v0, __NR_getxpid
134         callsys
136         stl     v0, PID_OFFSET(s0)
137         stl     v0, TID_OFFSET(s0)
138         br      1b
139 #endif
140         cfi_endproc
141         .end thread_start
143 weak_alias (__clone, clone)