Blame sysdeps/unix/sysv/linux/riscv/clone.S

Packit Service 82fcde
/* Wrapper around clone system call.  RISC-V version.
Packit Service 82fcde
   Copyright (C) 1996-2018 Free Software Foundation, Inc.
Packit Service 82fcde
   This file is part of the GNU C Library.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is free software; you can redistribute it and/or
Packit Service 82fcde
   modify it under the terms of the GNU Lesser General Public
Packit Service 82fcde
   License as published by the Free Software Foundation; either
Packit Service 82fcde
   version 2.1 of the License, or (at your option) any later version.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is distributed in the hope that it will be useful,
Packit Service 82fcde
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 82fcde
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 82fcde
   Lesser General Public License for more details.
Packit Service 82fcde
Packit Service 82fcde
   You should have received a copy of the GNU Lesser General Public
Packit Service 82fcde
   License along with the GNU C Library.  If not, see
Packit Service 82fcde
   <http://www.gnu.org/licenses/>.  */
Packit Service 82fcde
Packit Service 82fcde
/* clone() is even more special than fork() as it mucks with stacks
Packit Service 82fcde
   and invokes a function in the right context after its all over.  */
Packit Service 82fcde
Packit Service 82fcde
#include <sys/asm.h>
Packit Service 82fcde
#include <sysdep.h>
Packit Service 82fcde
#define _ERRNO_H	1
Packit Service 82fcde
#include <bits/errno.h>
Packit Service 82fcde
#include <tls.h>
Packit Service 82fcde
#include "tcb-offsets.h"
Packit Service 82fcde
Packit Service 82fcde
/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg,
Packit Service 82fcde
	     void *parent_tidptr, void *tls, void *child_tidptr) */
Packit Service 82fcde
Packit Service 82fcde
	.text
Packit Service 82fcde
LEAF (__clone)
Packit Service 82fcde
Packit Service 82fcde
	/* Sanity check arguments.  */
Packit Service 82fcde
	beqz		a0,L (invalid)	/* No NULL function pointers.  */
Packit Service 82fcde
	beqz		a1,L (invalid)	/* No NULL stack pointers.  */
Packit Service 82fcde
Packit Service 82fcde
	addi		a1,a1,-16	/* Reserve argument save space.  */
Packit Service 82fcde
	REG_S		a0,0(a1)	/* Save function pointer.  */
Packit Service 82fcde
	REG_S		a3,SZREG(a1)	/* Save argument pointer.  */
Packit Service 82fcde
Packit Service 82fcde
	/* The syscall expects the args to be in different slots.  */
Packit Service 82fcde
	mv		a0,a2
Packit Service 82fcde
	mv		a2,a4
Packit Service 82fcde
	mv		a3,a5
Packit Service 82fcde
	mv		a4,a6
Packit Service 82fcde
Packit Service 82fcde
	/* Do the system call.  */
Packit Service 82fcde
	li		a7,__NR_clone
Packit Service 82fcde
	scall
Packit Service 82fcde
Packit Service 82fcde
	bltz		a0,L (error)
Packit Service 82fcde
	beqz		a0,L (thread_start)
Packit Service 82fcde
Packit Service 82fcde
	/* Successful return from the parent.  */
Packit Service 82fcde
	ret
Packit Service 82fcde
Packit Service 82fcde
L (invalid):
Packit Service 82fcde
	li		a0, -EINVAL
Packit Service 82fcde
	/* Something bad happened -- no child created.  */
Packit Service 82fcde
L (error):
Packit Service 82fcde
	j		__syscall_error
Packit Service 82fcde
	END (__clone)
Packit Service 82fcde
Packit Service 82fcde
/* Load up the arguments to the function.  Put this block of code in
Packit Service 82fcde
   its own function so that we can terminate the stack trace with our
Packit Service 82fcde
   debug info.  */
Packit Service 82fcde
Packit Service 82fcde
ENTRY (__thread_start)
Packit Service 82fcde
L (thread_start):
Packit Service 82fcde
	/* Restore the arg for user's function.  */
Packit Service 82fcde
	REG_L		a1,0(sp)	/* Function pointer.  */
Packit Service 82fcde
	REG_L		a0,SZREG(sp)	/* Argument pointer.  */
Packit Service 82fcde
Packit Service 82fcde
	/* Call the user's function.  */
Packit Service 82fcde
	jalr		a1
Packit Service 82fcde
Packit Service 82fcde
	/* Call exit with the function's return value.  */
Packit Service 82fcde
	li		a7, __NR_exit
Packit Service 82fcde
	scall
Packit Service 82fcde
Packit Service 82fcde
	END (__thread_start)
Packit Service 82fcde
Packit Service 82fcde
libc_hidden_def (__clone)
Packit Service 82fcde
weak_alias (__clone, clone)