remove PID caching
[uclibc-ng.git] / libc / sysdeps / linux / ia64 / clone2.S
blob692ee3600b5a899732720a09fb66f137f5d86ee6
1 /* Copyright (C) 2000, 2001, 2003, 2004, 2006 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
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.
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.
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    <http://www.gnu.org/licenses/>.  */
18 #include "sysdep.h"
19 #include <asm/errno.h>
21 /* int  __clone2(int (*fn) (void *arg), void *child_stack_base,         */
22 /*               size_t child_stack_size, int flags, void *arg,         */
23 /*               pid_t *parent_tid, void *tls, pid_t *child_tid)        */
25 #define CHILD   p8
26 #define PARENT  p9
28 ENTRY(__clone2)
29         .prologue
30         alloc r2=ar.pfs,8,1,6,0
31         cmp.eq p6,p0=0,in0
32         cmp.eq p7,p0=0,in1
33         mov r8=EINVAL
34         mov out0=in3            /* Flags are first syscall argument.    */
35         mov out1=in1            /* Stack address.                       */
36 (p6)    br.cond.spnt.many __syscall_error       /* no NULL function pointers */
37 (p7)    br.cond.spnt.many __syscall_error       /* no NULL stack pointers */
38         ;;
39         mov out2=in2            /* Stack size.                          */
40         mov out3=in5            /* Parent TID Pointer                   */
41         mov out4=in7            /* Child TID Pointer                    */
42         mov out5=in6            /* TLS pointer                          */
43         /*
44          * clone2() is special: the child cannot execute br.ret right
45          * after the system call returns, because it starts out
46          * executing on an empty stack.  Because of this, we can't use
47          * the new (lightweight) syscall convention here.  Instead, we
48          * just fall back on always using "break".
49          *
50          * Furthermore, since the child starts with an empty stack, we
51          * need to avoid unwinding past invalid memory.  To that end,
52          * we'll pretend now that __clone2() is the end of the
53          * call-chain.  This is wrong for the parent, but only until
54          * it returns from clone2() but it's better than the
55          * alternative.
56          */
57         mov r15=SYS_ify (clone2)
58         .save rp, r0
59         break __BREAK_SYSCALL
60         .body
61         cmp.eq p6,p0=-1,r10
62         cmp.eq CHILD,PARENT=0,r8 /* Are we the child?   */
63 (p6)    br.cond.spnt.many __syscall_error
64         ;;
65 (CHILD) mov loc0=gp
66 (PARENT) ret
67         ;;
68 1:      ld8 out1=[in0],8        /* Retrieve code pointer.       */
69         mov out0=in4            /* Pass proper argument to fn */
70         ;;
71         ld8 gp=[in0]            /* Load function gp.            */
72         mov b6=out1
73         br.call.dptk.many rp=b6 /* Call fn(arg) in the child    */
74         ;;
75         mov out0=r8             /* Argument to _exit            */
76         mov gp=loc0
77         .globl HIDDEN_JUMPTARGET(_exit)
78         br.call.dpnt.many rp=HIDDEN_JUMPTARGET(_exit)
79                                 /* call _exit with result from fn.      */
80         ret                     /* Not reached.         */
81 PSEUDO_END(__clone2)
83 /* For now we leave __clone undefined.  This is unlikely to be a        */
84 /* problem, since at least the i386 __clone in glibc always failed      */
85 /* with a 0 sp (eventhough the kernel explicitly handled it).           */
86 /* Thus all such calls needed to pass an explicit sp, and as a result,  */
87 /* would be unlikely to work on ia64.                                   */