summaryrefslogtreecommitdiff
path: root/sysdeps/unix/sysv/linux/powerpc/powerpc32/vfork.S
diff options
context:
space:
mode:
authorAdhemerval Zanella <azanella@linux.vnet.ibm.com>2014-05-26 11:41:28 -0500
committerAdhemerval Zanella <azanella@linux.vnet.ibm.com>2014-05-26 11:41:28 -0500
commit3d1024e8d159ec5f0f3899c02af5473f5b0ec49c (patch)
tree5d25753af4e67b172b26c741eda7881e839c3774 /sysdeps/unix/sysv/linux/powerpc/powerpc32/vfork.S
parentfdfd175d46ac6a810ebdeb2a2936e6d7d13995ab (diff)
PowerPC: Consolidate NPTL/non versions of vfork
Diffstat (limited to 'sysdeps/unix/sysv/linux/powerpc/powerpc32/vfork.S')
-rw-r--r--sysdeps/unix/sysv/linux/powerpc/powerpc32/vfork.S31
1 files changed, 31 insertions, 0 deletions
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/vfork.S b/sysdeps/unix/sysv/linux/powerpc/powerpc32/vfork.S
index 7a1e8422ad..8a8433617f 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/vfork.S
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/vfork.S
@@ -19,6 +19,7 @@
#define _ERRNO_H 1
#include <bits/errno.h>
#include <kernel-features.h>
+#include <tcb-offsets.h>
/* Clone the calling process, but without copying the whole address space.
The calling process is suspended until the new process exits or is
@@ -26,9 +27,39 @@
and the process ID of the new process to the old process. */
ENTRY (__vfork)
+
+ /* Load the TCB-cached PID value and negates it. If It it is zero
+ sets it to 0x800000. And then sets its value again on TCB field.
+ See raise.c for the logic that relies on this value. */
+
+ lwz r0,PID(r2)
+ cmpwi cr0,r0,0
+ neg r0,r0
+ bne- cr0,1f
+ lis r0,0x8000
+1: stw r0,PID(r2)
+
DO_CALL (SYS_ify (vfork))
+
+ cmpwi cr1,r3,0
+ beqlr- 1
+
+ /* Restore the original value of the TCB cache of the PID, if we're
+ the parent. But in the child (syscall return value equals zero),
+ leave things as they are. */
+ lwz r0,PID(r2)
+ /* Cannot use clrlwi. here, because cr0 needs to be preserved
+ until PSEUDO_RET. */
+ clrlwi r4,r0,1
+ cmpwi cr1,r4,0
+ beq- cr1,1f
+ neg r4,r0
+1: stw r4,PID(r2)
+
PSEUDO_RET
+
PSEUDO_END (__vfork)
libc_hidden_def (__vfork)
weak_alias (__vfork, vfork)
+strong_alias (__vfork, __libc_vfork)