summaryrefslogtreecommitdiff
path: root/libc/sysdeps/linux/nds32/vfork.S
diff options
context:
space:
mode:
Diffstat (limited to 'libc/sysdeps/linux/nds32/vfork.S')
-rw-r--r--libc/sysdeps/linux/nds32/vfork.S114
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)