diff options
Diffstat (limited to 'libc/sysdeps/linux/nds32/vfork.S')
-rw-r--r-- | libc/sysdeps/linux/nds32/vfork.S | 114 |
1 files changed, 85 insertions, 29 deletions
diff --git a/libc/sysdeps/linux/nds32/vfork.S b/libc/sysdeps/linux/nds32/vfork.S index c955359fb..ac3fa30fd 100644 --- a/libc/sysdeps/linux/nds32/vfork.S +++ b/libc/sysdeps/linux/nds32/vfork.S @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016 Andes Technology, Inc. + * Copyright (C) 2016-2017 Andes Technology, Inc. * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. */ @@ -21,24 +21,36 @@ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#include <sys/syscall.h> #include <sysdep.h> - #define _ERRNO_H 1 +#include <bits/errno.h> + +#ifndef SAVE_PID +#define SAVE_PID +#endif +#ifndef RESTORE_PID +#define RESTORE_PID +#endif /* Clone the calling process, but without copying the whole address space. The calling process is suspended until the new process exits or is replaced by a call to `execve'. Return -1 for errors, 0 to the new process, and the process ID of the new process to the old process. */ + ENTRY (__vfork) #ifdef PIC .pic #endif #ifdef __NR_vfork - +# ifdef SAVE_PID + SAVE_PID +# endif syscall __NR_vfork +# ifdef RESTORE_PID + RESTORE_PID +# endif bltz $r0, 2f 1: ret @@ -46,42 +58,86 @@ ENTRY (__vfork) sltsi $r1, $r0, -4096 bnez $r1, 1b; +# ifdef __ASSUME_VFORK_SYSCALL # ifdef PIC - #ifdef __NDS32_N1213_43U1H__ - ! save lp - addi $r2, $lp, 0 - - ! set r1 as gp - jal 1b - sethi $r1, hi20(_GLOBAL_OFFSET_TABLE_) - ori $r1, $r1, lo12(_GLOBAL_OFFSET_TABLE_+4) - add $r1, $lp, $r1 - - ! restore lp - addi $lp, $r2, 0 - #else - ! set r1 as gp - mfusr $r15, $PC - sethi $r1, hi20(_GLOBAL_OFFSET_TABLE_+4) - ori $r1, $r1, lo12(_GLOBAL_OFFSET_TABLE_+8) - add $r1, $r1, $r15 - #endif + pushm $gp, $lp + cfi_adjust_cfa_offset(8) + cfi_rel_offset(gp, 0) + cfi_rel_offset(lp, 4) + mfusr $r15, $PC + sethi $gp, hi20(_GLOBAL_OFFSET_TABLE_+4) + ori $gp, $gp, lo12(_GLOBAL_OFFSET_TABLE_+8) + add $gp, $gp, $r15 ! r15=C_SYMBOL_NAME(__syscall_error)@PLT - sethi $r15, hi20(C_SYMBOL_NAME(__syscall_error)@PLT) + sethi $r15, hi20(C_SYMBOL_NAME(__syscall_error)@PLT) ori $r15, $r15, lo12(C_SYMBOL_NAME(__syscall_error)@PLT) - add $r15, $r15, $r1 + add $r15, $r15, $gp ! jump to SYSCALL_ERROR - jr $r15 + jral $r15 + popm $gp, $lp + cfi_adjust_cfa_offset(-8) + cfi_restore(lp) + cfi_restore(gp) + ret # else j C_SYMBOL_NAME(__syscall_error) # endif +# else + /* Check if vfork syscall is known at all. */ + li $r1, -ENOSYS + beq $r0, $r1, 1f + +# ifdef PIC +3: + pushm $gp, $lp + cfi_adjust_cfa_offset(8) + cfi_rel_offset(gp, 0) + cfi_rel_offset(lp, 4) + mfusr $r15, $PC + sethi $gp, hi20(_GLOBAL_OFFSET_TABLE_+4) + ori $gp, $gp, lo12(_GLOBAL_OFFSET_TABLE_+8) + add $gp, $gp, $r15 + + ! r15=C_SYMBOL_NAME(__syscall_error)@PLT + sethi $r15, hi20(C_SYMBOL_NAME(__syscall_error)@PLT) + ori $r15, $r15, lo12(C_SYMBOL_NAME(__syscall_error)@PLT) + add $r15, $r15, $gp + + ! jump to SYSCALL_ERROR + jral $r15 + popm $gp, $lp + cfi_adjust_cfa_offset(-8) + cfi_restore(lp) + cfi_restore(gp) + ret +# else + j C_SYMBOL_NAME(__syscall_error) +# endif +1: +# endif +#endif + +#ifndef __ASSUME_VFORK_SYSCALL + /* If we don't have vfork, fork is close enough. */ + syscall __NR_fork + bgez $r0, 1f + sltsi $r1, $r0, -4096 + bnez $r1, 1f + +# ifdef PIC + b 3b +# else + j C_SYMBOL_NAME(__syscall_error) +# endif +1: + ret -#else -# error "__NR_vfork not available" +#elif !defined __NR_vfork +# error "__NR_vfork not available and __ASSUME_VFORK_SYSCALL defined" #endif PSEUDO_END (__vfork) weak_alias (__vfork, vfork) -libc_hidden_def(vfork) +libc_hidden_def (vfork) |