diff options
Diffstat (limited to 'sysdeps/unix/sysv/linux/powerpc/powerpc32')
-rw-r--r-- | sysdeps/unix/sysv/linux/powerpc/powerpc32/vfork.S | 31 |
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) |