#include "SYS.h"
-#if defined(__ppc__) || defined(__ppc64__)
-
-/* We use mode-independent "g" opcodes such as "srgi", and/or
- * mode-independent macros such as MI_GET_ADDRESS. These expand
- * into word operations when targeting __ppc__, and into doubleword
- * operations when targeting __ppc64__.
- */
-#include <architecture/ppc/mode_independent_asm.h>
-
-/* In vfork(), the child runs in parent's address space. */
-
-
-MI_ENTRY_POINT(___vfork)
- MI_GET_ADDRESS(r5,__current_pid) // get address of __current_pid in r5
-2:
- lwarx r6,0,r5 // don't cache pid across vfork
- cmpwi r6,0
- ble-- 3f // is another vfork in progress
- li r6,0 // if not, erase the stored pid
-3:
- addi r6,r6,-1 // count the parallel vforks in
- stwcx. r6,0,r5 // negative cached pid values
- bne-- 2b
-
- li r0,SYS_vfork
- sc
- b Lbotch // error return
-
- cmpwi r4,0
- beq Lparent // parent, since a1 == 0 in parent,
-
- li r3,0 // child
- blr
-
-Lparent: // r3 == child's pid
- lwarx r6,0,r5 // we're back, decrement vfork count
- addi r6,r6,1
- stwcx. r6,0,r5
- bne-- Lparent
- blr // return pid
-
-Lbotch:
- lwarx r6,0,r5 // never went, decrement vfork count
- addi r6,r6,1
- stwcx. r6,0,r5
- bne-- Lbotch
-
- MI_BRANCH_EXTERNAL(cerror)
-
-#elif defined(__i386__)
+#if defined(__i386__)
#if defined(__DYNAMIC__)
#define GET_CURRENT_PID PICIFY(__current_pid)
movq $ SYSCALL_CONSTRUCT_UNIX(SYS_vfork), %rax // code for vfork -> rax
UNIX_SYSCALL_TRAP // do the system call
jnb L1 // jump if CF==0
+ pushq %rdi // put return address back on stack for cerror
movq __current_pid@GOTPCREL(%rip), %rcx
lock
addq $1, (%rcx)
addq $1, (%rdx)
jmp *%rdi
-#elif defined(__arm__)
-
-#include <arm/arch.h>
-
- .globl cerror
- MI_ENTRY_POINT(_vfork)
-
- MI_GET_ADDRESS(r3, __current_pid) // get address of __current_pid
-#ifdef _ARM_ARCH_6
-L0:
- ldrex r1, [r3]
- subs r1, r1, #1 // if __current_pid <= 0, decrement it
- movpl r1, #-1 // otherwise put -1 in there
- strex r2, r1, [r3]
- cmp r2, #0
- bne L0
-#else
- mov r2, #0x80000000 // load "looking" value
-L0:
- swp r1, r2, [r3] // look at the value, lock others out
- cmp r1, r2 // anyone else trying to look?
- beq L0 // yes, so wait our turn
- subs r1, r1, #1 // if __current_pid <= 0, decrement it
- movpl r1, #-1 // otherwise put -1 in there
- str r1, [r3]
-#endif
-
- mov r1, #1 // prime results
- mov r12, #SYS_vfork
- swi #SWI_SYSCALL // make the syscall
- bcs Lbotch // error?
- cmp r1, #0 // parent (r1=0) or child(r1=1)
- beq Lparent
-
- //child here...
- mov r0, #0
- bx lr // return
-
-Lbotch:
- MI_CALL_EXTERNAL(cerror) // jump here on error
- mov r0,#-1 // set the error
- // reload values clobbered by cerror (so we can treat them as live in Lparent)
- MI_GET_ADDRESS(r3, __current_pid) // get address of __current_pid
-#ifndef _ARM_ARCH_6
- mov r2, #0x80000000 // load "looking" value
-#endif
- // fall thru
-
-Lparent:
-#ifdef _ARM_ARCH_6
- ldrex r1, [r3]
- add r1, r1, #1 // we're back, decrement vfork count
- strex r2, r1, [r3]
- cmp r2, #0
- bne Lparent
-#else
- swp r1, r2, [r3] // look at the value, lock others out
- cmp r1, r2 // anyone else trying to look?
- beq Lparent // yes, so wait our turn
- add r1, r1, #1 // we're back, decrement vfork count
- str r1, [r3]
-#endif
-
- bx lr // return
-
#else
#error Unsupported architecture
#endif