Track whether a thread is currently vforked.

Our various fd debugging facilities get extremely confused by a vforked
process closing file descriptors in preparation to exec: fdsan can
abort, and fdtrack will delete backtraces for any file descriptors that
get closed. Keep track of whether we're in a vforked child in order to
be able to detect this.

Bug: http://b/153926671
Test: 32/64-bit bionic-unit-tests on blueline, x86_64 emulator
Change-Id: I8a082fd06bfdfef0e2a88dbce350b6f667f7df9f
diff --git a/libc/arch-arm/bionic/vfork.S b/libc/arch-arm/bionic/vfork.S
index 6855db7..a964be5 100644
--- a/libc/arch-arm/bionic/vfork.S
+++ b/libc/arch-arm/bionic/vfork.S
@@ -31,17 +31,27 @@
 
 ENTRY(vfork)
 __BIONIC_WEAK_ASM_FOR_NATIVE_BRIDGE(vfork)
-    // __get_tls()[TLS_SLOT_THREAD_ID]->cached_pid_ = 0
+    // r3 = &__get_tls()[TLS_SLOT_THREAD_ID]
     mrc     p15, 0, r3, c13, c0, 3
     ldr     r3, [r3, #(TLS_SLOT_THREAD_ID * 4)]
-    mov     r0, #0
+
+    // Set cached_pid_ to 0, vforked_ to 1, and stash the previous value.
+    mov     r0, #0x80000000
+    ldr     r1, [r3, #12]
     str     r0, [r3, #12]
 
     mov     ip, r7
     ldr     r7, =__NR_vfork
     swi     #0
     mov     r7, ip
+
+    teq     r0, #0
+    bxeq    lr
+
+    // rc != 0: reset cached_pid_ and vforked_.
+    str     r1, [r3, #12]
     cmn     r0, #(MAX_ERRNO + 1)
+
     bxls    lr
     neg     r0, r0
     b       __set_errno_internal