summaryrefslogtreecommitdiffstats
path: root/libc/sysdeps/linux/mips/vfork.S
diff options
context:
space:
mode:
Diffstat (limited to 'libc/sysdeps/linux/mips/vfork.S')
-rw-r--r--libc/sysdeps/linux/mips/vfork.S39
1 files changed, 33 insertions, 6 deletions
diff --git a/libc/sysdeps/linux/mips/vfork.S b/libc/sysdeps/linux/mips/vfork.S
index bdac50b02..0dbf62e31 100644
--- a/libc/sysdeps/linux/mips/vfork.S
+++ b/libc/sysdeps/linux/mips/vfork.S
@@ -20,11 +20,37 @@
#include <sys/asm.h>
#include <sysdep.h>
-#ifndef __UCLIBC__
-#include <asm/unistd.h>
-#endif
#include <sgidefs.h>
+#ifdef __PTHREADS_NATIVE__
+#include <tls.h>
+
+/* Save the PID value. */
+#ifndef SAVE_PID
+#define SAVE_PID \
+ READ_THREAD_POINTER(v1); /* Get the thread pointer. */ \
+ lw a2, PID_OFFSET(v1); /* Load the saved PID. */ \
+ subu a2, $0, a2; /* Negate it. */ \
+ bnez a2, 1f; /* If it was zero... */ \
+ lui a2, 0x8000; /* use 0x80000000 instead. */ \
+1: sw a2, PID_OFFSET(v1); /* Store the temporary PID. */
+#endif
+
+/* Restore the old PID value in the parent. */
+#ifndef RESTORE_PID
+#define RESTORE_PID \
+ beqz v0, 1f; /* If we are the parent... */ \
+ READ_THREAD_POINTER(v1); /* Get the thread pointer. */ \
+ lw a2, PID_OFFSET(v1); /* Load the saved PID. */ \
+ subu a2, $0, a2; /* Re-negate it. */ \
+ lui a0, 0x8000; /* Load 0x80000000... */ \
+ bne a2, a0, 2f; /* ... compare against it... */ \
+ li a2, 0; /* ... use 0 instead. */ \
+2: sw a2, PID_OFFSET(v1); /* Restore the PID. */ \
+1:
+#endif
+#endif
+
#ifndef SAVE_PID
#define SAVE_PID
#endif
@@ -82,7 +108,8 @@ NESTED(__vfork,FRAMESZ,sp)
/* Successful return from the parent or child. */
RESTORE_GP64
- ret
+ j ra
+ nop
/* Something bad happened -- no child created. */
L(error):
@@ -96,5 +123,5 @@ L(error):
#endif
END(__vfork)
-libc_hidden_def(__vfork)
-weak_alias (__vfork, vfork)
+.weak vfork;
+ vfork = __vfork