| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162 | /* Copyright (C) 1996-2018 Free Software Foundation, Inc.   Contributed by David Huggins-Daines <dhd@debian.org>, 2000.   Based on the Alpha version by Richard Henderson <rth@tamu.edu>, 1996.   The GNU C Library is free software; you can redistribute it and/or   modify it under the terms of the GNU Lesser General Public   License as published by the Free Software Foundation; either   version 2.1 of the License, or (at your option) any later version.   The GNU C Library is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU   Lesser General Public License for more details.   You should have received a copy of the GNU Lesser General Public   License along with the GNU C Library.  If not, see   <http://www.gnu.org/licenses/>.  *//* clone() is even more special than fork() as it mucks with stacks   and invokes a function in the right context after its all over.  */#include <asm/unistd.h>#include <sysdep.h>#define _ERRNO_H	1#include <bits/errno.h>/* Non-thread code calls __clone with the following parameters:   int clone(int (*fn)(void *arg),	     void *child_stack,	     int flags,	     void *arg)   NPTL Code will call __clone with the following parameters:   int clone(int (*fn)(void *arg),	     void *child_stack,	     int flags,	     void *arg,	     int *parent_tidptr,	     struct user_desc *newtls,	     int *child_pidptr)   The code should not mangle the extra input registers.   Syscall expects:				Input to __clone:	4(r25) - function pointer 		(r26, arg0)	0(r25) - argument			(r23, arg3)	r26 - clone flags.			(r24, arg2)	r25+64 - user stack pointer.		(r25, arg1)	r24 - parent tid pointer.		(stack - 52)	r23 - struct user_desc newtls pointer.	(stack - 56)	r22 - child tid pointer.		(stack - 60)	r20 - clone syscall number		(constant)   Return:	On success the thread ID of the child process is returend in	the callers context.	On error return -1, and set errno to the value returned by	the syscall. */        .textENTRY(__clone)	/* Prologue */	stwm	%r4, 64(%sp)	.cfi_def_cfa_offset -64	.cfi_offset 4, 0	stw	%sp, -4(%sp)#ifdef __PIC__	stw	%r19, -32(%sp)	.cfi_offset 19, 32#endif	/* Sanity check arguments.  */	comib,=,n  0, %arg0, .LerrorSanity        /* no NULL function pointers */	comib,=,n  0, %arg1, .LerrorSanity        /* no NULL stack pointers */	/* Save the function pointer, arg, and flags on the new stack.  */	stwm    %r26, 64(%r25)	stw	%r23, -60(%r25)	stw     %r24, -56(%r25)	/* Clone arguments are (int flags, void * child_stack) */	copy	%r24, %r26		/* flags are first */	/* User stack pointer is in the correct register already */	/* Load args from stack... */	ldw	-116(%sp), %r24		/* Load parent_tidptr */	ldw	-120(%sp), %r23 	/* Load newtls */	ldw	-124(%sp), %r22		/* Load child_tidptr */	/* Save the PIC register. */#ifdef __PIC__	copy	%r19, %r4		/* parent */#endif	/* Do the system call */	ble     0x100(%sr2, %r0)	ldi	__NR_clone, %r20	ldi	-4096, %r1	comclr,>>= %r1, %ret0, %r0	/* Note: unsigned compare. */	b,n	.LerrorRest	/* Restore the PIC register.  */#ifdef __PIC__	copy	%r4, %r19		/* parent */#endif	comib,=,n 0, %ret0, .LthreadStart	/* Successful return from the parent	   No need to restore the PIC register,	   since we return immediately. */	ldw	-84(%sp), %rp	bv	%r0(%rp)	ldwm	-64(%sp), %r4.LerrorRest:	/* Something bad happened -- no child created */	bl	__syscall_error, %rp	sub     %r0, %ret0, %arg0	ldw	-84(%sp), %rp	/* Return after setting errno, ret0 is set to -1 by __syscall_error. */	bv	%r0(%rp)	ldwm	-64(%sp), %r4.LerrorSanity:	/* Sanity checks failed, return -1, and set errno to EINVAL. */	bl	__syscall_error, %rp	ldi     EINVAL, %arg0	ldw	-84(%sp), %rp	bv	%r0(%rp)	ldwm	-64(%sp), %r4.LthreadStart:	/* Load up the arguments.  */	ldw	-60(%sp), %arg0	ldw     -64(%sp), %r22	/* $$dyncall fixes child's PIC register */	/* Call the user's function */#ifdef __PIC__	copy	%r19, %r4#endif	bl	$$dyncall, %r31	copy	%r31, %rp#ifdef __PIC__	copy	%r4, %r19#endif	copy	%r28, %r26	ble     0x100(%sr2, %r0)	ldi	__NR_exit, %r20	/* We should not return from exit.           We do not restore r4, or the stack state.  */	iitlbp	%r0, (%sr0, %r0)PSEUDO_END(__clone)libc_hidden_def (__clone)weak_alias (__clone, clone)
 |