| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586 | /* Wrapper around clone system call.  RISC-V version.   Copyright (C) 1996-2018 Free Software Foundation, Inc.   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 <sys/asm.h>#include <sysdep.h>#define _ERRNO_H	1#include <bits/errno.h>/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg,	     void *parent_tidptr, void *tls, void *child_tidptr) */	.textLEAF (clone)	/* Align stack to a 128-bit boundary as per RISC-V ABI.  */	andi            a1,a1,ALMASK	/* Sanity check arguments.  */	beqz		a0,L (invalid)	/* No NULL function pointers.  */	beqz		a1,L (invalid)	/* No NULL stack pointers.  */	addi		a1,a1,-16	/* Reserve argument save space.  */	REG_S		a0,0(a1)	/* Save function pointer.  */	REG_S		a3,SZREG(a1)	/* Save argument pointer.  */	/* The syscall expects the args to be in different slots.  */	mv		a0,a2	mv		a2,a4	mv		a3,a5	mv		a4,a6	/* Do the system call.  */	li		a7,__NR_clone	scall	bltz		a0,L (error)	beqz		a0,L (thread_start)	/* Successful return from the parent.  */	retL (invalid):	li		a0, -EINVAL	/* Something bad happened -- no child created.  */L (error):	tail		__syscall_error	END (clone)/* Load up the arguments to the function.  Put this block of code in   its own function so that we can terminate the stack trace with our   debug info.  */ENTRY (__thread_start)L (thread_start):	.cfi_label .Ldummy	cfi_undefined (ra)	/* Restore the arg for user's function.  */	REG_L		a1,0(sp)	/* Function pointer.  */	REG_L		a0,SZREG(sp)	/* Argument pointer.  */	/* Call the user's function.  */	jalr		a1	/* Call exit with the function's return value.  */	li		a7, __NR_exit	scall	END (__thread_start)
 |