Revert "Replaces vfork() implementation with fork()"

We're getting cold feet on this one... let's put it back.

This reverts commit 210331d9762037afb9b5ed8413079c6f65872df9.

Change-Id: I6b0d3c2b1dbf7f1dc9566979a91b7504c2189269
diff --git a/libc/SYSCALLS.TXT b/libc/SYSCALLS.TXT
index 128ec6b..38ae831 100644
--- a/libc/SYSCALLS.TXT
+++ b/libc/SYSCALLS.TXT
@@ -77,6 +77,7 @@
 int     setgroups:setgroups32(int, const gid_t*)   arm,x86
 int     setgroups:setgroups(int, const gid_t*)     arm64,mips,mips64,x86_64
 int     setpgid(pid_t, pid_t)  all
+pid_t   vfork(void)  arm
 int     setregid:setregid32(gid_t, gid_t)  arm,x86
 int     setregid:setregid(gid_t, gid_t)    arm64,mips,mips64,x86_64
 int     chroot(const char*)  all
diff --git a/libc/arch-arm/syscalls/vfork.S b/libc/arch-arm/syscalls/vfork.S
new file mode 100644
index 0000000..e12fba5
--- /dev/null
+++ b/libc/arch-arm/syscalls/vfork.S
@@ -0,0 +1,14 @@
+/* Generated by gensyscalls.py. Do not edit. */
+
+#include <private/bionic_asm.h>
+
+ENTRY(vfork)
+    mov     ip, r7
+    ldr     r7, =__NR_vfork
+    swi     #0
+    mov     r7, ip
+    cmn     r0, #(MAX_ERRNO + 1)
+    bxls    lr
+    neg     r0, r0
+    b       __set_errno
+END(vfork)
diff --git a/libc/arch-arm64/arm64.mk b/libc/arch-arm64/arm64.mk
index 314358e..ed991ce 100644
--- a/libc/arch-arm64/arm64.mk
+++ b/libc/arch-arm64/arm64.mk
@@ -36,6 +36,7 @@
     arch-arm64/bionic/__set_tls.c \
     arch-arm64/bionic/sigsetjmp.S \
     arch-arm64/bionic/syscall.S \
+    arch-arm64/bionic/vfork.S \
 
 
 libc_crt_target_cflags_arm64 := \
diff --git a/libc/bionic/vfork.cpp b/libc/arch-arm64/bionic/vfork.S
similarity index 75%
rename from libc/bionic/vfork.cpp
rename to libc/arch-arm64/bionic/vfork.S
index b706a7f..c700623 100644
--- a/libc/bionic/vfork.cpp
+++ b/libc/arch-arm64/bionic/vfork.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright (C) 2013 The Android Open Source Project
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -26,10 +26,23 @@
  * SUCH DAMAGE.
  */
 
-#include <unistd.h>
+#include <private/bionic_asm.h>
+#include <asm/signal.h>
+#include <linux/sched.h>
 
-// vfork(2) was removed from POSIX 2008, but it's common enough that we can't
-// actually remove it entirely.
-extern "C" pid_t vfork(void) {
-  return fork();
-}
+ENTRY(vfork)
+    mov     x0, #(CLONE_VM | CLONE_VFORK | SIGCHLD)
+    mov     x1, xzr
+    mov     x2, xzr
+    mov     x3, xzr
+    mov     x4, xzr
+
+    mov     x8, __NR_clone
+    svc     #0
+
+    cmn     x0, #(MAX_ERRNO + 1)
+    cneg    x0, x0, hi
+    b.hi    __set_errno
+
+    ret
+END(vfork)
diff --git a/libc/bionic/vfork.cpp b/libc/arch-mips/bionic/vfork.S
similarity index 72%
copy from libc/bionic/vfork.cpp
copy to libc/arch-mips/bionic/vfork.S
index b706a7f..96de69e 100644
--- a/libc/bionic/vfork.cpp
+++ b/libc/arch-mips/bionic/vfork.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright (C) 2008 The Android Open Source Project
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -26,10 +26,33 @@
  * SUCH DAMAGE.
  */
 
-#include <unistd.h>
+#include <private/bionic_asm.h>
+#include <linux/sched.h>
 
-// vfork(2) was removed from POSIX 2008, but it's common enough that we can't
-// actually remove it entirely.
-extern "C" pid_t vfork(void) {
-  return fork();
-}
+// TODO: mips' uapi signal.h is missing #ifndef __ASSEMBLY__.
+// #include <asm/signal.h>
+#define SIGCHLD 18
+
+ENTRY(vfork)
+	.set	noreorder
+	.cpload	t9
+
+	li	a0, (CLONE_VM | CLONE_VFORK | SIGCHLD)
+	li	a1, 0
+	li	a2, 0
+	li	a3, 0
+	subu	sp, 8
+	sw	$0, 16(sp)
+	li	v0, __NR_clone
+	syscall
+	addu	sp, 8
+	bnez	a3, 1f
+	 move	a0, v0
+
+	j	ra
+	 nop
+1:
+	la	t9, __set_errno
+	j	t9
+	 nop
+END(vfork)
diff --git a/libc/arch-mips/mips.mk b/libc/arch-mips/mips.mk
index bf3b8ae..8e415f9 100644
--- a/libc/arch-mips/mips.mk
+++ b/libc/arch-mips/mips.mk
@@ -59,6 +59,7 @@
     arch-mips/bionic/setjmp.S \
     arch-mips/bionic/sigsetjmp.S \
     arch-mips/bionic/syscall.S \
+    arch-mips/bionic/vfork.S \
 
 ifndef ARCH_MIPS_REV6
 libc_bionic_src_files_mips += \
diff --git a/libc/bionic/vfork.cpp b/libc/arch-mips64/bionic/vfork.S
similarity index 62%
copy from libc/bionic/vfork.cpp
copy to libc/arch-mips64/bionic/vfork.S
index b706a7f..911a264 100644
--- a/libc/bionic/vfork.cpp
+++ b/libc/arch-mips64/bionic/vfork.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright (C) 2008 The Android Open Source Project
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -26,10 +26,46 @@
  * SUCH DAMAGE.
  */
 
-#include <unistd.h>
+#include <private/bionic_asm.h>
+#include <linux/sched.h>
 
-// vfork(2) was removed from POSIX 2008, but it's common enough that we can't
-// actually remove it entirely.
-extern "C" pid_t vfork(void) {
-  return fork();
-}
+// TODO: mips' uapi signal.h is missing #ifndef __ASSEMBLY__.
+// #include <asm/signal.h>
+#define SIGCHLD 18
+
+	.text
+
+#if (_MIPS_SIM == _ABIO32) || (_MIPS_SIM == _ABI32)
+FRAMESZ		=	MKFSIZ(5,0)
+#else
+FRAMESZ		=	MKFSIZ(0,0)
+#endif
+
+LEAF(vfork,FRAMESZ)
+#if FRAMESZ!=0
+	PTR_SUBU sp, FRAMESZ
+#endif
+	SETUP_GP64(a5, vfork)
+	LI	a0, (CLONE_VM | CLONE_VFORK | SIGCHLD)
+	move	a1, $0
+	move	a2, $0
+	move	a3, $0
+#if (_MIPS_SIM == _ABIO32) || (_MIPS_SIM == _ABI32)
+	REG_S	$0, 4*REGSZ(sp)
+#else
+	move	a4, $0
+#endif
+	LI	v0, __NR_clone
+	syscall
+#if FRAMESZ!=0
+	PTR_ADDU sp,FRAMESZ
+#endif
+	move	a0, v0
+	bnez	a3, 1f
+	RESTORE_GP64
+	j	ra
+1:
+	LA	t9,__set_errno
+	RESTORE_GP64
+	j	t9
+	END(vfork)
diff --git a/libc/arch-mips64/mips64.mk b/libc/arch-mips64/mips64.mk
index 6f7a928..230cb26 100644
--- a/libc/arch-mips64/mips64.mk
+++ b/libc/arch-mips64/mips64.mk
@@ -46,6 +46,7 @@
     arch-mips64/bionic/setjmp.S \
     arch-mips64/bionic/sigsetjmp.S \
     arch-mips64/bionic/syscall.S \
+    arch-mips64/bionic/vfork.S \
 
 # FIXME TODO
 ## libc_bionic_src_files_mips64 += arch-mips64/string/memcpy.S
diff --git a/libc/bionic/vfork.cpp b/libc/arch-x86/bionic/vfork.S
similarity index 75%
copy from libc/bionic/vfork.cpp
copy to libc/arch-x86/bionic/vfork.S
index b706a7f..ffa6b16 100644
--- a/libc/bionic/vfork.cpp
+++ b/libc/arch-x86/bionic/vfork.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright (C) 2008 The Android Open Source Project
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -26,10 +26,19 @@
  * SUCH DAMAGE.
  */
 
-#include <unistd.h>
+#include <private/bionic_asm.h>
 
-// vfork(2) was removed from POSIX 2008, but it's common enough that we can't
-// actually remove it entirely.
-extern "C" pid_t vfork(void) {
-  return fork();
-}
+// This custom code preserves the return address across the system call.
+
+ENTRY(vfork)
+  popl    %ecx  // Grab the return address.
+  movl    $__NR_vfork, %eax
+  int     $0x80
+  cmpl    $-MAX_ERRNO, %eax
+  jb      1f
+  negl    %eax
+  pushl   %eax
+  call    __set_errno
+1:
+  jmp     *%ecx  // Jump to the stored return address.
+END(vfork)
diff --git a/libc/arch-x86/x86.mk b/libc/arch-x86/x86.mk
index 8aa2645..019dc8e 100644
--- a/libc/arch-x86/x86.mk
+++ b/libc/arch-x86/x86.mk
@@ -31,6 +31,7 @@
     arch-x86/bionic/__set_tls.c \
     arch-x86/bionic/sigsetjmp.S \
     arch-x86/bionic/syscall.S \
+    arch-x86/bionic/vfork.S \
 
 ## ARCH variant specific source files
 arch_variant_mk := $(LOCAL_PATH)/arch-x86/$(TARGET_ARCH_VARIANT)/$(TARGET_ARCH_VARIANT).mk
diff --git a/libc/bionic/vfork.cpp b/libc/arch-x86_64/bionic/vfork.S
similarity index 75%
copy from libc/bionic/vfork.cpp
copy to libc/arch-x86_64/bionic/vfork.S
index b706a7f..7c14cc0 100644
--- a/libc/bionic/vfork.cpp
+++ b/libc/arch-x86_64/bionic/vfork.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright (C) 2013 The Android Open Source Project
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -26,10 +26,20 @@
  * SUCH DAMAGE.
  */
 
-#include <unistd.h>
+#include <private/bionic_asm.h>
 
-// vfork(2) was removed from POSIX 2008, but it's common enough that we can't
-// actually remove it entirely.
-extern "C" pid_t vfork(void) {
-  return fork();
-}
+// This custom code preserves the return address across the system call.
+
+ENTRY(vfork)
+  popq    %rdi  // Grab the return address.
+  movl    $__NR_vfork, %eax
+  syscall
+  pushq   %rdi  // Restore the return address.
+  cmpq    $-MAX_ERRNO, %rax
+  jb      1f
+  negl    %eax
+  movl    %eax, %edi
+  call    __set_errno
+1:
+  ret
+END(vfork)
diff --git a/libc/arch-x86_64/x86_64.mk b/libc/arch-x86_64/x86_64.mk
index 234cf67..7887c51 100644
--- a/libc/arch-x86_64/x86_64.mk
+++ b/libc/arch-x86_64/x86_64.mk
@@ -37,6 +37,7 @@
     arch-x86_64/bionic/__set_tls.c \
     arch-x86_64/bionic/sigsetjmp.S \
     arch-x86_64/bionic/syscall.S \
+    arch-x86_64/bionic/vfork.S \
 
 libc_bionic_src_files_x86_64 += \
     arch-x86_64/string/sse2-memcpy-slm.S \