diff options
Diffstat (limited to 'libc/sysdeps/linux/mips/vfork.S')
-rw-r--r-- | libc/sysdeps/linux/mips/vfork.S | 39 |
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 |