Merge "Fix format macros for fast16 and fast32 int types."
diff --git a/libc/arch-arm/bionic/__bionic_clone.S b/libc/arch-arm/bionic/__bionic_clone.S
index 8836748..6669b93 100644
--- a/libc/arch-arm/bionic/__bionic_clone.S
+++ b/libc/arch-arm/bionic/__bionic_clone.S
@@ -29,7 +29,7 @@
 #include <private/bionic_asm.h>
 
 // pid_t __bionic_clone(int flags, void* child_stack, pid_t* parent_tid, void* tls, pid_t* child_tid, int (*fn)(void*), void* arg);
-ENTRY(__bionic_clone)
+ENTRY_PRIVATE(__bionic_clone)
     mov     ip, sp
     # save registers to parent stack
     stmfd   sp!, {r4, r5, r6, r7}
@@ -67,4 +67,3 @@
     pop    {r0, r1}
     b      __start_thread
 END(__bionic_clone)
-.hidden __bionic_clone
diff --git a/libc/arch-arm/cortex-a15/bionic/__strcat_chk.S b/libc/arch-arm/cortex-a15/bionic/__strcat_chk.S
index 3692f04..da40f6c 100644
--- a/libc/arch-arm/cortex-a15/bionic/__strcat_chk.S
+++ b/libc/arch-arm/cortex-a15/bionic/__strcat_chk.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2015 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,7 +26,174 @@
  * SUCH DAMAGE.
  */
 
-// Indicate which memcpy base file to include.
-#define MEMCPY_BASE "memcpy_base.S"
+#include <private/bionic_asm.h>
 
-#include "__strcat_chk_common.S"
+    .syntax unified
+
+    .thumb
+    .thumb_func
+
+// Get the length of src string, then get the source of the dst string.
+// Check that the two lengths together don't exceed the threshold, then
+// do a memcpy of the data.
+ENTRY(__strcat_chk)
+    pld     [r0, #0]
+    push    {r0, lr}
+    .cfi_def_cfa_offset 8
+    .cfi_rel_offset r0, 0
+    .cfi_rel_offset lr, 4
+    push    {r4, r5}
+    .cfi_adjust_cfa_offset 8
+    .cfi_rel_offset r4, 0
+    .cfi_rel_offset r5, 4
+
+    mov     lr, r2
+
+    // Save the dst register to r5
+    mov     r5, r0
+
+    // Zero out r4
+    eor     r4, r4, r4
+
+    // r1 contains the address of the string to count.
+.L_strlen_start:
+    mov     r0, r1
+    ands    r3, r1, #7
+    beq     .L_mainloop
+
+    // Align to a double word (64 bits).
+    rsb     r3, r3, #8
+    lsls    ip, r3, #31
+    beq     .L_align_to_32
+
+    ldrb    r2, [r1], #1
+    cbz     r2, .L_update_count_and_finish
+
+.L_align_to_32:
+    bcc     .L_align_to_64
+    ands    ip, r3, #2
+    beq     .L_align_to_64
+
+    ldrb    r2, [r1], #1
+    cbz     r2, .L_update_count_and_finish
+    ldrb    r2, [r1], #1
+    cbz     r2, .L_update_count_and_finish
+
+.L_align_to_64:
+    tst     r3, #4
+    beq     .L_mainloop
+    ldr     r3, [r1], #4
+
+    sub     ip, r3, #0x01010101
+    bic     ip, ip, r3
+    ands    ip, ip, #0x80808080
+    bne     .L_zero_in_second_register
+
+    .p2align 2
+.L_mainloop:
+    ldrd    r2, r3, [r1], #8
+
+    pld     [r1, #64]
+
+    sub     ip, r2, #0x01010101
+    bic     ip, ip, r2
+    ands    ip, ip, #0x80808080
+    bne     .L_zero_in_first_register
+
+    sub     ip, r3, #0x01010101
+    bic     ip, ip, r3
+    ands    ip, ip, #0x80808080
+    bne     .L_zero_in_second_register
+    b       .L_mainloop
+
+.L_update_count_and_finish:
+    sub     r3, r1, r0
+    sub     r3, r3, #1
+    b       .L_finish
+
+.L_zero_in_first_register:
+    sub     r3, r1, r0
+    lsls    r2, ip, #17
+    bne     .L_sub8_and_finish
+    bcs     .L_sub7_and_finish
+    lsls    ip, ip, #1
+    bne     .L_sub6_and_finish
+
+    sub     r3, r3, #5
+    b       .L_finish
+
+.L_sub8_and_finish:
+    sub     r3, r3, #8
+    b       .L_finish
+
+.L_sub7_and_finish:
+    sub     r3, r3, #7
+    b       .L_finish
+
+.L_sub6_and_finish:
+    sub     r3, r3, #6
+    b       .L_finish
+
+.L_zero_in_second_register:
+    sub     r3, r1, r0
+    lsls    r2, ip, #17
+    bne     .L_sub4_and_finish
+    bcs     .L_sub3_and_finish
+    lsls    ip, ip, #1
+    bne     .L_sub2_and_finish
+
+    sub     r3, r3, #1
+    b       .L_finish
+
+.L_sub4_and_finish:
+    sub     r3, r3, #4
+    b       .L_finish
+
+.L_sub3_and_finish:
+    sub     r3, r3, #3
+    b       .L_finish
+
+.L_sub2_and_finish:
+    sub     r3, r3, #2
+
+.L_finish:
+    cmp     r4, #0
+    bne     .L_strlen_done
+
+    // Time to get the dst string length.
+    mov     r1, r5
+
+    // Save the original source address to r5.
+    mov     r5, r0
+
+    // Save the current length (adding 1 for the terminator).
+    add     r4, r3, #1
+    b       .L_strlen_start
+
+    // r0 holds the pointer to the dst string.
+    // r3 holds the dst string length.
+    // r4 holds the src string length + 1.
+.L_strlen_done:
+    add     r2, r3, r4
+    cmp     r2, lr
+    itt     hi
+    movhi   r0, lr
+    bhi     __strcat_chk_fail
+
+    // Set up the registers for the memcpy code.
+    mov     r1, r5
+    pld     [r1, #64]
+    mov     r2, r4
+    add     r0, r0, r3
+    pop     {r4, r5}
+    .cfi_adjust_cfa_offset -8
+    .cfi_restore r4
+    .cfi_restore r5
+
+#include "memcpy_base.S"
+
+    // Undo the above cfi directives
+    .cfi_adjust_cfa_offset 8
+    .cfi_rel_offset r4, 0
+    .cfi_rel_offset r5, 4
+END(__strcat_chk)
diff --git a/libc/arch-arm/cortex-a15/bionic/__strcat_chk_common.S b/libc/arch-arm/cortex-a15/bionic/__strcat_chk_common.S
deleted file mode 100644
index a610dd5..0000000
--- a/libc/arch-arm/cortex-a15/bionic/__strcat_chk_common.S
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <private/bionic_asm.h>
-
-    .syntax unified
-
-    .thumb
-    .thumb_func
-
-// Get the length of src string, then get the source of the dst string.
-// Check that the two lengths together don't exceed the threshold, then
-// do a memcpy of the data.
-ENTRY(__strcat_chk)
-    pld     [r0, #0]
-    push    {r0, lr}
-    .cfi_def_cfa_offset 8
-    .cfi_rel_offset r0, 0
-    .cfi_rel_offset lr, 4
-    push    {r4, r5}
-    .cfi_adjust_cfa_offset 8
-    .cfi_rel_offset r4, 0
-    .cfi_rel_offset r5, 4
-
-    mov     lr, r2
-
-    // Save the dst register to r5
-    mov     r5, r0
-
-    // Zero out r4
-    eor     r4, r4, r4
-
-    // r1 contains the address of the string to count.
-.L_strlen_start:
-    mov     r0, r1
-    ands    r3, r1, #7
-    beq     .L_mainloop
-
-    // Align to a double word (64 bits).
-    rsb     r3, r3, #8
-    lsls    ip, r3, #31
-    beq     .L_align_to_32
-
-    ldrb    r2, [r1], #1
-    cbz     r2, .L_update_count_and_finish
-
-.L_align_to_32:
-    bcc     .L_align_to_64
-    ands    ip, r3, #2
-    beq     .L_align_to_64
-
-    ldrb    r2, [r1], #1
-    cbz     r2, .L_update_count_and_finish
-    ldrb    r2, [r1], #1
-    cbz     r2, .L_update_count_and_finish
-
-.L_align_to_64:
-    tst     r3, #4
-    beq     .L_mainloop
-    ldr     r3, [r1], #4
-
-    sub     ip, r3, #0x01010101
-    bic     ip, ip, r3
-    ands    ip, ip, #0x80808080
-    bne     .L_zero_in_second_register
-
-    .p2align 2
-.L_mainloop:
-    ldrd    r2, r3, [r1], #8
-
-    pld     [r1, #64]
-
-    sub     ip, r2, #0x01010101
-    bic     ip, ip, r2
-    ands    ip, ip, #0x80808080
-    bne     .L_zero_in_first_register
-
-    sub     ip, r3, #0x01010101
-    bic     ip, ip, r3
-    ands    ip, ip, #0x80808080
-    bne     .L_zero_in_second_register
-    b       .L_mainloop
-
-.L_update_count_and_finish:
-    sub     r3, r1, r0
-    sub     r3, r3, #1
-    b       .L_finish
-
-.L_zero_in_first_register:
-    sub     r3, r1, r0
-    lsls    r2, ip, #17
-    bne     .L_sub8_and_finish
-    bcs     .L_sub7_and_finish
-    lsls    ip, ip, #1
-    bne     .L_sub6_and_finish
-
-    sub     r3, r3, #5
-    b       .L_finish
-
-.L_sub8_and_finish:
-    sub     r3, r3, #8
-    b       .L_finish
-
-.L_sub7_and_finish:
-    sub     r3, r3, #7
-    b       .L_finish
-
-.L_sub6_and_finish:
-    sub     r3, r3, #6
-    b       .L_finish
-
-.L_zero_in_second_register:
-    sub     r3, r1, r0
-    lsls    r2, ip, #17
-    bne     .L_sub4_and_finish
-    bcs     .L_sub3_and_finish
-    lsls    ip, ip, #1
-    bne     .L_sub2_and_finish
-
-    sub     r3, r3, #1
-    b       .L_finish
-
-.L_sub4_and_finish:
-    sub     r3, r3, #4
-    b       .L_finish
-
-.L_sub3_and_finish:
-    sub     r3, r3, #3
-    b       .L_finish
-
-.L_sub2_and_finish:
-    sub     r3, r3, #2
-
-.L_finish:
-    cmp     r4, #0
-    bne     .L_strlen_done
-
-    // Time to get the dst string length.
-    mov     r1, r5
-
-    // Save the original source address to r5.
-    mov     r5, r0
-
-    // Save the current length (adding 1 for the terminator).
-    add     r4, r3, #1
-    b       .L_strlen_start
-
-    // r0 holds the pointer to the dst string.
-    // r3 holds the dst string length.
-    // r4 holds the src string length + 1.
-.L_strlen_done:
-    add     r2, r3, r4
-    cmp     r2, lr
-    itt     hi
-    movhi   r0, lr
-    bhi     __strcat_chk_fail
-
-    // Set up the registers for the memcpy code.
-    mov     r1, r5
-    pld     [r1, #64]
-    mov     r2, r4
-    add     r0, r0, r3
-    pop     {r4, r5}
-    .cfi_adjust_cfa_offset -8
-    .cfi_restore r4
-    .cfi_restore r5
-
-#include MEMCPY_BASE
-
-    // Undo the above cfi directives
-    .cfi_adjust_cfa_offset 8
-    .cfi_rel_offset r4, 0
-    .cfi_rel_offset r5, 4
-END(__strcat_chk)
diff --git a/libc/arch-arm/cortex-a15/bionic/__strcpy_chk.S b/libc/arch-arm/cortex-a15/bionic/__strcpy_chk.S
index d8cb3d9..026adcc 100644
--- a/libc/arch-arm/cortex-a15/bionic/__strcpy_chk.S
+++ b/libc/arch-arm/cortex-a15/bionic/__strcpy_chk.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2015 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,7 +26,136 @@
  * SUCH DAMAGE.
  */
 
-// Indicate which memcpy base file to include.
-#define MEMCPY_BASE "memcpy_base.S"
+#include <private/bionic_asm.h>
 
-#include "__strcpy_chk_common.S"
+    .syntax unified
+
+    .thumb
+    .thumb_func
+
+// Get the length of the source string first, then do a memcpy of the data
+// instead of a strcpy.
+ENTRY(__strcpy_chk)
+    pld     [r0, #0]
+    push    {r0, lr}
+    .cfi_def_cfa_offset 8
+    .cfi_rel_offset r0, 0
+    .cfi_rel_offset lr, 4
+
+    mov     lr, r2
+    mov     r0, r1
+
+    ands    r3, r1, #7
+    beq     .L_mainloop
+
+    // Align to a double word (64 bits).
+    rsb     r3, r3, #8
+    lsls    ip, r3, #31
+    beq     .L_align_to_32
+
+    ldrb    r2, [r0], #1
+    cbz     r2, .L_update_count_and_finish
+
+.L_align_to_32:
+    bcc     .L_align_to_64
+    ands    ip, r3, #2
+    beq     .L_align_to_64
+
+    ldrb    r2, [r0], #1
+    cbz     r2, .L_update_count_and_finish
+    ldrb    r2, [r0], #1
+    cbz     r2, .L_update_count_and_finish
+
+.L_align_to_64:
+    tst     r3, #4
+    beq     .L_mainloop
+    ldr     r3, [r0], #4
+
+    sub     ip, r3, #0x01010101
+    bic     ip, ip, r3
+    ands    ip, ip, #0x80808080
+    bne     .L_zero_in_second_register
+
+    .p2align 2
+.L_mainloop:
+    ldrd    r2, r3, [r0], #8
+
+    pld     [r0, #64]
+
+    sub     ip, r2, #0x01010101
+    bic     ip, ip, r2
+    ands    ip, ip, #0x80808080
+    bne     .L_zero_in_first_register
+
+    sub     ip, r3, #0x01010101
+    bic     ip, ip, r3
+    ands    ip, ip, #0x80808080
+    bne     .L_zero_in_second_register
+    b       .L_mainloop
+
+.L_update_count_and_finish:
+    sub     r3, r0, r1
+    sub     r3, r3, #1
+    b       .L_check_size
+
+.L_zero_in_first_register:
+    sub     r3, r0, r1
+    lsls    r2, ip, #17
+    bne     .L_sub8_and_finish
+    bcs     .L_sub7_and_finish
+    lsls    ip, ip, #1
+    bne     .L_sub6_and_finish
+
+    sub     r3, r3, #5
+    b       .L_check_size
+
+.L_sub8_and_finish:
+    sub     r3, r3, #8
+    b       .L_check_size
+
+.L_sub7_and_finish:
+    sub     r3, r3, #7
+    b       .L_check_size
+
+.L_sub6_and_finish:
+    sub     r3, r3, #6
+    b       .L_check_size
+
+.L_zero_in_second_register:
+    sub     r3, r0, r1
+    lsls    r2, ip, #17
+    bne     .L_sub4_and_finish
+    bcs     .L_sub3_and_finish
+    lsls    ip, ip, #1
+    bne     .L_sub2_and_finish
+
+    sub     r3, r3, #1
+    b       .L_check_size
+
+.L_sub4_and_finish:
+    sub     r3, r3, #4
+    b       .L_check_size
+
+.L_sub3_and_finish:
+    sub     r3, r3, #3
+    b       .L_check_size
+
+.L_sub2_and_finish:
+    sub     r3, r3, #2
+
+.L_check_size:
+    pld     [r1, #0]
+    pld     [r1, #64]
+    ldr     r0, [sp]
+
+    // Add 1 for copy length to get the string terminator.
+    add     r2, r3, #1
+
+    cmp     r2, lr
+    itt     hi
+    movhi   r0, r2
+    bhi     __strcpy_chk_fail
+
+#include "memcpy_base.S"
+
+END(__strcpy_chk)
diff --git a/libc/arch-arm/cortex-a15/bionic/__strcpy_chk_common.S b/libc/arch-arm/cortex-a15/bionic/__strcpy_chk_common.S
deleted file mode 100644
index 377e720..0000000
--- a/libc/arch-arm/cortex-a15/bionic/__strcpy_chk_common.S
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <private/bionic_asm.h>
-
-    .syntax unified
-
-    .thumb
-    .thumb_func
-
-// Get the length of the source string first, then do a memcpy of the data
-// instead of a strcpy.
-ENTRY(__strcpy_chk)
-    pld     [r0, #0]
-    push    {r0, lr}
-    .cfi_def_cfa_offset 8
-    .cfi_rel_offset r0, 0
-    .cfi_rel_offset lr, 4
-
-    mov     lr, r2
-    mov     r0, r1
-
-    ands    r3, r1, #7
-    beq     .L_mainloop
-
-    // Align to a double word (64 bits).
-    rsb     r3, r3, #8
-    lsls    ip, r3, #31
-    beq     .L_align_to_32
-
-    ldrb    r2, [r0], #1
-    cbz     r2, .L_update_count_and_finish
-
-.L_align_to_32:
-    bcc     .L_align_to_64
-    ands    ip, r3, #2
-    beq     .L_align_to_64
-
-    ldrb    r2, [r0], #1
-    cbz     r2, .L_update_count_and_finish
-    ldrb    r2, [r0], #1
-    cbz     r2, .L_update_count_and_finish
-
-.L_align_to_64:
-    tst     r3, #4
-    beq     .L_mainloop
-    ldr     r3, [r0], #4
-
-    sub     ip, r3, #0x01010101
-    bic     ip, ip, r3
-    ands    ip, ip, #0x80808080
-    bne     .L_zero_in_second_register
-
-    .p2align 2
-.L_mainloop:
-    ldrd    r2, r3, [r0], #8
-
-    pld     [r0, #64]
-
-    sub     ip, r2, #0x01010101
-    bic     ip, ip, r2
-    ands    ip, ip, #0x80808080
-    bne     .L_zero_in_first_register
-
-    sub     ip, r3, #0x01010101
-    bic     ip, ip, r3
-    ands    ip, ip, #0x80808080
-    bne     .L_zero_in_second_register
-    b       .L_mainloop
-
-.L_update_count_and_finish:
-    sub     r3, r0, r1
-    sub     r3, r3, #1
-    b       .L_check_size
-
-.L_zero_in_first_register:
-    sub     r3, r0, r1
-    lsls    r2, ip, #17
-    bne     .L_sub8_and_finish
-    bcs     .L_sub7_and_finish
-    lsls    ip, ip, #1
-    bne     .L_sub6_and_finish
-
-    sub     r3, r3, #5
-    b       .L_check_size
-
-.L_sub8_and_finish:
-    sub     r3, r3, #8
-    b       .L_check_size
-
-.L_sub7_and_finish:
-    sub     r3, r3, #7
-    b       .L_check_size
-
-.L_sub6_and_finish:
-    sub     r3, r3, #6
-    b       .L_check_size
-
-.L_zero_in_second_register:
-    sub     r3, r0, r1
-    lsls    r2, ip, #17
-    bne     .L_sub4_and_finish
-    bcs     .L_sub3_and_finish
-    lsls    ip, ip, #1
-    bne     .L_sub2_and_finish
-
-    sub     r3, r3, #1
-    b       .L_check_size
-
-.L_sub4_and_finish:
-    sub     r3, r3, #4
-    b       .L_check_size
-
-.L_sub3_and_finish:
-    sub     r3, r3, #3
-    b       .L_check_size
-
-.L_sub2_and_finish:
-    sub     r3, r3, #2
-
-.L_check_size:
-    pld     [r1, #0]
-    pld     [r1, #64]
-    ldr     r0, [sp]
-
-    // Add 1 for copy length to get the string terminator.
-    add     r2, r3, #1
-
-    cmp     r2, lr
-    itt     hi
-    movhi   r0, r2
-    bhi     __strcpy_chk_fail
-
-#include MEMCPY_BASE
-
-END(__strcpy_chk)
diff --git a/libc/arch-arm/cortex-a15/bionic/memcpy.S b/libc/arch-arm/cortex-a15/bionic/memcpy.S
index 537f3de..9407a08 100644
--- a/libc/arch-arm/cortex-a15/bionic/memcpy.S
+++ b/libc/arch-arm/cortex-a15/bionic/memcpy.S
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2015 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
@@ -25,8 +25,58 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
+/*
+ * Copyright (c) 2013 ARM Ltd
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the company may not be used to endorse or promote
+ *    products derived from this software without specific prior written
+ *    permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ARM LTD ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL ARM LTD BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
 
-// Indicate which memcpy base file to include.
-#define MEMCPY_BASE "memcpy_base.S"
+#include <private/bionic_asm.h>
 
-#include "memcpy_common.S"
+        .text
+        .syntax unified
+        .fpu    neon
+
+ENTRY(__memcpy_chk)
+        cmp r2, r3
+        bls memcpy
+
+        // Preserve lr for backtrace.
+        push        {lr}
+        .cfi_def_cfa_offset 4
+        .cfi_rel_offset lr, 0
+        bl          __memcpy_chk_fail
+END(__memcpy_chk)
+
+// Prototype: void *memcpy (void *dst, const void *src, size_t count).
+ENTRY(memcpy)
+        pld     [r1, #64]
+        push    {r0, lr}
+        .cfi_def_cfa_offset 8
+        .cfi_rel_offset r0, 0
+        .cfi_rel_offset lr, 4
+
+#include "memcpy_base.S"
+END(memcpy)
diff --git a/libc/arch-arm/cortex-a15/bionic/memcpy_base.S b/libc/arch-arm/cortex-a15/bionic/memcpy_base.S
index aac737d..1d152bb 100644
--- a/libc/arch-arm/cortex-a15/bionic/memcpy_base.S
+++ b/libc/arch-arm/cortex-a15/bionic/memcpy_base.S
@@ -68,11 +68,6 @@
         cmp     r2, #16
         blo     .L_copy_less_than_16_unknown_align
 
-        // TODO: The aligned copy code is extremely slow copying some large
-        //       buffers so always go through the unaligned path for now.
-        //cmp     r2, #832
-        //bge     .L_check_alignment
-
 .L_copy_unknown_alignment:
         // Unknown alignment of src and dst.
         // Assumes that the first few bytes have already been prefetched.
@@ -157,178 +152,3 @@
         strbcs      lr, [r0]
 
         pop         {r0, pc}
-
-.L_check_alignment:
-        // If src and dst cannot both be aligned to a word boundary,
-        // use the unaligned copy version.
-        eor     r3, r0, r1
-        ands    r3, r3, #0x3
-        bne     .L_copy_unknown_alignment
-
-        // To try and improve performance, stack layout changed,
-        // i.e., not keeping the stack looking like users expect
-        // (highest numbered register at highest address).
-        strd    r4, r5, [sp, #-8]!
-        .cfi_adjust_cfa_offset 8
-        .cfi_rel_offset r4, 0
-        .cfi_rel_offset r5, 4
-        strd    r6, r7, [sp, #-8]!
-        .cfi_adjust_cfa_offset 8
-        .cfi_rel_offset r6, 0
-        .cfi_rel_offset r7, 4
-        strd    r8, r9, [sp, #-8]!
-        .cfi_adjust_cfa_offset 8
-        .cfi_rel_offset r8, 0
-        .cfi_rel_offset r9, 4
-
-        // Optimized for already aligned dst code.
-        ands    ip, r0, #3
-        bne     .L_dst_not_word_aligned
-
-.L_word_aligned:
-        // Align the destination buffer to 8 bytes, to make sure double
-        // loads and stores don't cross a cache line boundary,
-        // as they are then more expensive even if the data is in the cache
-        // (require two load/store issue cycles instead of one).
-        // If only one of the buffers is not 8 bytes aligned,
-        // then it's more important to align dst than src,
-        // because there is more penalty for stores
-        // than loads that cross a cacheline boundary.
-        // This check and realignment are only done if there is >= 832
-        // bytes to copy.
-
-        // Dst is word aligned, but check if it is already double word aligned.
-        ands    r3, r0, #4
-        beq     1f
-        ldr     r3, [r1], #4
-        str     r3, [r0], #4
-        sub     r2, #4
-
-1:      // Can only get here if > 64 bytes to copy, so don't do check r2.
-        sub     r2, #64
-
-2:      // Every loop iteration copies 64 bytes.
-        .irp    offset, #0, #8, #16, #24, #32
-        ldrd    r4, r5, [r1, \offset]
-        strd    r4, r5, [r0, \offset]
-        .endr
-
-        ldrd    r4, r5, [r1, #40]
-        ldrd    r6, r7, [r1, #48]
-        ldrd    r8, r9, [r1, #56]
-
-        // Keep the pld as far from the next load as possible.
-        // The amount to prefetch was determined experimentally using
-        // large sizes, and verifying the prefetch size does not affect
-        // the smaller copies too much.
-        // WARNING: If the ldrd and strd instructions get too far away
-        //          from each other, performance suffers. Three loads
-        //          in a row is the best tradeoff.
-        pld     [r1, #(64*16)]
-        strd    r4, r5, [r0, #40]
-        strd    r6, r7, [r0, #48]
-        strd    r8, r9, [r0, #56]
-
-        add     r0, r0, #64
-        add     r1, r1, #64
-        subs    r2, r2, #64
-        bge     2b
-
-        // Fix-up the remaining count and make sure we have >= 32 bytes left.
-        adds    r2, r2, #32
-        blo     4f
-
-        // Copy 32 bytes. These cache lines were already preloaded.
-        .irp    offset, #0, #8, #16, #24
-        ldrd    r4, r5, [r1, \offset]
-        strd    r4, r5, [r0, \offset]
-        .endr
-        add     r1, r1, #32
-        add     r0, r0, #32
-        sub     r2, r2, #32
-4:      // Less than 32 left.
-        add     r2, r2, #32
-        tst     r2, #0x10
-        beq     5f
-        // Copy 16 bytes.
-        .irp    offset, #0, #8
-        ldrd    r4, r5, [r1, \offset]
-        strd    r4, r5, [r0, \offset]
-        .endr
-        add     r1, r1, #16
-        add     r0, r0, #16
-
-5:      // Copy up to 15 bytes (count in r2).
-        movs    ip, r2, lsl #29
-        bcc     1f
-        // Copy 8 bytes.
-        ldrd    r4, r5, [r1], #8
-        strd    r4, r5, [r0], #8
-1:      bge         2f
-        // Copy 4 bytes.
-        ldr     r4, [r1], #4
-        str     r4, [r0], #4
-2:      // Copy 0 to 4 bytes.
-        lsls    r2, r2, #31
-        itt     ne
-        ldrbne  lr, [r1], #1
-        strbne  lr, [r0], #1
-        itttt   cs
-        ldrbcs  ip, [r1], #1
-        ldrbcs  lr, [r1]
-        strbcs  ip, [r0], #1
-        strbcs  lr, [r0]
-
-        // Restore registers: optimized pop {r0, pc}
-        ldrd    r8, r9, [sp], #8
-        .cfi_adjust_cfa_offset -8
-        .cfi_restore r8
-        .cfi_restore r9
-        ldrd    r6, r7, [sp], #8
-        .cfi_adjust_cfa_offset -8
-        .cfi_restore r6
-        .cfi_restore r7
-        ldrd    r4, r5, [sp], #8
-        .cfi_adjust_cfa_offset -8
-        .cfi_restore r4
-        .cfi_restore r5
-        pop     {r0, pc}
-
-        // Put the cfi directives back for the below instructions.
-        .cfi_adjust_cfa_offset 24
-        .cfi_rel_offset r4, 0
-        .cfi_rel_offset r5, 4
-        .cfi_rel_offset r6, 8
-        .cfi_rel_offset r7, 12
-        .cfi_rel_offset r8, 16
-        .cfi_rel_offset r9, 20
-
-.L_dst_not_word_aligned:
-        // Align dst to word.
-        rsb     ip, ip, #4
-        cmp     ip, #2
-
-        itt     gt
-        ldrbgt  lr, [r1], #1
-        strbgt  lr, [r0], #1
-
-        itt     ge
-        ldrbge  lr, [r1], #1
-        strbge  lr, [r0], #1
-
-        ldrb    lr, [r1], #1
-        strb    lr, [r0], #1
-
-        sub     r2, r2, ip
-
-        // Src is guaranteed to be at least word aligned by this point.
-        b       .L_word_aligned
-
-        // Undo any cfi directives from above.
-        .cfi_adjust_cfa_offset -24
-        .cfi_restore r4
-        .cfi_restore r5
-        .cfi_restore r6
-        .cfi_restore r7
-        .cfi_restore r8
-        .cfi_restore r9
diff --git a/libc/arch-arm/cortex-a15/bionic/memcpy_common.S b/libc/arch-arm/cortex-a15/bionic/memcpy_common.S
deleted file mode 100644
index 4d1167f..0000000
--- a/libc/arch-arm/cortex-a15/bionic/memcpy_common.S
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-/*
- * Copyright (c) 2013 ARM Ltd
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. The name of the company may not be used to endorse or promote
- *    products derived from this software without specific prior written
- *    permission.
- *
- * THIS SOFTWARE IS PROVIDED BY ARM LTD ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL ARM LTD BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
- * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <private/bionic_asm.h>
-
-        .text
-        .syntax unified
-        .fpu    neon
-
-ENTRY(__memcpy_chk)
-        cmp r2, r3
-        bls memcpy
-
-        // Preserve lr for backtrace.
-        push        {lr}
-        .cfi_def_cfa_offset 4
-        .cfi_rel_offset lr, 0
-        bl          __memcpy_chk_fail
-END(__memcpy_chk)
-
-// Prototype: void *memcpy (void *dst, const void *src, size_t count).
-ENTRY(memcpy)
-        pld     [r1, #64]
-        push    {r0, lr}
-        .cfi_def_cfa_offset 8
-        .cfi_rel_offset r0, 0
-        .cfi_rel_offset lr, 4
-
-#include MEMCPY_BASE
-END(memcpy)
diff --git a/libc/arch-arm64/bionic/__bionic_clone.S b/libc/arch-arm64/bionic/__bionic_clone.S
index 27e44e7..c3ff0e5 100644
--- a/libc/arch-arm64/bionic/__bionic_clone.S
+++ b/libc/arch-arm64/bionic/__bionic_clone.S
@@ -30,7 +30,7 @@
 
 // pid_t __bionic_clone(int flags, void* child_stack, pid_t* parent_tid, void* tls, pid_t* child_tid, int (*fn)(void*), void* arg);
 
-ENTRY(__bionic_clone)
+ENTRY_PRIVATE(__bionic_clone)
     # Push 'fn' and 'arg' onto the child stack.
     stp     x5, x6, [x1, #-16]!
 
@@ -57,4 +57,3 @@
     ldp     x0, x1, [sp], #16
     b       __start_thread
 END(__bionic_clone)
-.hidden __bionic_clone
diff --git a/libc/arch-mips/bionic/__bionic_clone.S b/libc/arch-mips/bionic/__bionic_clone.S
index b216efe..a3cacd1 100644
--- a/libc/arch-mips/bionic/__bionic_clone.S
+++ b/libc/arch-mips/bionic/__bionic_clone.S
@@ -31,7 +31,7 @@
 #include <linux/sched.h>
 
 // pid_t __bionic_clone(int flags, void* child_stack, pid_t* parent_tid, void* tls, pid_t* child_tid, int (*fn)(void*), void* arg);
-ENTRY(__bionic_clone)
+ENTRY_PRIVATE(__bionic_clone)
         .set	noreorder
         .cpload t9
         .set	reorder
@@ -69,4 +69,3 @@
 	la	t9,__set_errno_internal
 	j	t9
 END(__bionic_clone)
-.hidden __bionic_clone
diff --git a/libc/arch-mips/include/machine/asm.h b/libc/arch-mips/include/machine/asm.h
index 74412c1..dc83088 100644
--- a/libc/arch-mips/include/machine/asm.h
+++ b/libc/arch-mips/include/machine/asm.h
@@ -28,7 +28,7 @@
 #ifndef _MIPS64_ASM_H
 #define _MIPS64_ASM_H
 
-#define __bionic_asm_align 4
+#define __bionic_asm_align 16
 
 #undef __bionic_asm_custom_entry
 #undef __bionic_asm_custom_end
diff --git a/libc/arch-x86/bionic/__bionic_clone.S b/libc/arch-x86/bionic/__bionic_clone.S
index 1a6f642..b682b48 100644
--- a/libc/arch-x86/bionic/__bionic_clone.S
+++ b/libc/arch-x86/bionic/__bionic_clone.S
@@ -1,7 +1,7 @@
 #include <private/bionic_asm.h>
 
 // pid_t __bionic_clone(int flags, void* child_stack, pid_t* parent_tid, void* tls, pid_t* child_tid, int (*fn)(void*), void* arg);
-ENTRY(__bionic_clone)
+ENTRY_PRIVATE(__bionic_clone)
         pushl   %ebx
         .cfi_adjust_cfa_offset 4
         .cfi_rel_offset ebx, 0
@@ -62,4 +62,3 @@
         .cfi_restore ebx
         ret
 END(__bionic_clone)
-.hidden __bionic_clone
diff --git a/libc/arch-x86_64/bionic/__bionic_clone.S b/libc/arch-x86_64/bionic/__bionic_clone.S
index 0c73e5f..a4245b8 100644
--- a/libc/arch-x86_64/bionic/__bionic_clone.S
+++ b/libc/arch-x86_64/bionic/__bionic_clone.S
@@ -29,7 +29,7 @@
 #include <private/bionic_asm.h>
 
 // pid_t __bionic_clone(int flags, void* child_stack, pid_t* parent_tid, void* tls, pid_t* child_tid, int (*fn)(void*), void* arg);
-ENTRY(__bionic_clone)
+ENTRY_PRIVATE(__bionic_clone)
         # Copy 'fn' and 'arg' onto the child stack.
         movq    %r9, -16(%rsi)  # fn
         movq    8(%rsp), %rax   # Read 'arg'.
@@ -74,4 +74,3 @@
         # We're the parent; nothing to do.
         ret
 END(__bionic_clone)
-.hidden __bionic_clone
diff --git a/libc/bionic/clone.cpp b/libc/bionic/clone.cpp
index 8281ac8..3a20aa9 100644
--- a/libc/bionic/clone.cpp
+++ b/libc/bionic/clone.cpp
@@ -38,6 +38,11 @@
 
 // Called from the __bionic_clone assembler to call the thread function then exit.
 extern "C" __LIBC_HIDDEN__ void __start_thread(int (*fn)(void*), void* arg) {
+  pthread_internal_t* self = __get_thread();
+  if (self && self->tid == -1) {
+    self->tid = syscall(__NR_gettid);
+  }
+
   int status = (*fn)(arg);
   __exit(status);
 }
@@ -75,6 +80,15 @@
   pthread_internal_t* self = __get_thread();
   pid_t parent_pid = self->invalidate_cached_pid();
 
+  // Remmber the caller's tid so that it can be restored in the parent after clone.
+  pid_t caller_tid = self->tid;
+  // Invalidate the tid before the syscall. The value is lazily cached in gettid(),
+  // and it will be updated by fork() and pthread_create(). We don't do this if
+  // we are sharing address space with the child.
+  if (!(flags & (CLONE_VM|CLONE_VFORK))) {
+    self->tid = -1;
+  }
+
   // Actually do the clone.
   int clone_result;
   if (fn != nullptr) {
@@ -87,11 +101,19 @@
 #endif
   }
 
-  // We're the parent, so put our known pid back in place.
-  // We leave the child without a cached pid, but:
-  // 1. pthread_create gives its children their own pthread_internal_t with the correct pid.
-  // 2. fork makes a clone system call directly.
-  // If any other cases become important, we could use a double trampoline like __pthread_start.
-  self->set_cached_pid(parent_pid);
+  if (clone_result != 0) {
+    // We're the parent, so put our known pid and tid back in place.
+    // We leave the child without a cached pid and tid, but:
+    // 1. pthread_create gives its children their own pthread_internal_t with the correct pid and tid.
+    // 2. fork uses CLONE_CHILD_SETTID to get the new pid/tid.
+    // 3. The tid is lazily fetched in gettid().
+    // If any other cases become important, we could use a double trampoline like __pthread_start.
+    self->set_cached_pid(parent_pid);
+    self->tid = caller_tid;
+  } else if (self->tid == -1) {
+    self->tid = syscall(__NR_gettid);
+    self->set_cached_pid(self->tid);
+  }
+
   return clone_result;
 }
diff --git a/libc/bionic/fork.cpp b/libc/bionic/fork.cpp
index ffe94f4..32ea255 100644
--- a/libc/bionic/fork.cpp
+++ b/libc/bionic/fork.cpp
@@ -36,9 +36,6 @@
 
   pthread_internal_t* self = __get_thread();
 
-  // Remember the parent pid and invalidate the cached value while we fork.
-  pid_t parent_pid = self->invalidate_cached_pid();
-
   int result = clone(nullptr,
                      nullptr,
                      (CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD),
@@ -47,10 +44,11 @@
                      nullptr,
                      &(self->tid));
   if (result == 0) {
+    // Update the cached pid, since clone() will not set it directly (as
+    // self->tid is updated by the kernel).
     self->set_cached_pid(gettid());
     __bionic_atfork_run_child();
   } else {
-    self->set_cached_pid(parent_pid);
     __bionic_atfork_run_parent();
   }
   return result;
diff --git a/libc/bionic/gettid.cpp b/libc/bionic/gettid.cpp
index f42e36a..fe25a4d 100644
--- a/libc/bionic/gettid.cpp
+++ b/libc/bionic/gettid.cpp
@@ -31,5 +31,14 @@
 #include "pthread_internal.h"
 
 pid_t gettid() {
-  return __get_thread()->tid;
+  pthread_internal_t* self = __get_thread();
+  if (__predict_true(self)) {
+    pid_t tid = self->tid;
+    if (__predict_true(tid != -1)) {
+      return tid;
+    }
+    self->tid = syscall(__NR_gettid);
+    return self->tid;
+  }
+  return syscall(__NR_gettid);
 }
diff --git a/libc/include/android/legacy_ctype_inlines.h b/libc/include/android/legacy_ctype_inlines.h
deleted file mode 100644
index ca01e3f..0000000
--- a/libc/include/android/legacy_ctype_inlines.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_LEGACY_CTYPE_INLINES_H
-#define ANDROID_LEGACY_CTYPE_INLINES_H
-
-#include <ctype.h>
-#include <sys/cdefs.h>
-
-__BEGIN_DECLS
-
-#if __ANDROID_API__ < 21
-
-static __inline int isalnum_l(int c, locale_t l __unused) {
-  return isalnum(c);
-}
-
-static __inline int isalpha_l(int c, locale_t l __unused) {
-  return isalpha(c);
-}
-
-static __inline int isblank_l(int c, locale_t l __unused) {
-  return isblank(c);
-}
-
-static __inline int iscntrl_l(int c, locale_t l __unused) {
-  return iscntrl(c);
-}
-
-static __inline int isdigit_l(int c, locale_t l __unused) {
-  return isdigit(c);
-}
-
-static __inline int isgraph_l(int c, locale_t l __unused) {
-  return isgraph(c);
-}
-
-static __inline int islower_l(int c, locale_t l __unused) {
-  return islower(c);
-}
-
-static __inline int isprint_l(int c, locale_t l __unused) {
-  return isprint(c);
-}
-
-static __inline int ispunct_l(int c, locale_t l __unused) {
-  return ispunct(c);
-}
-
-static __inline int isspace_l(int c, locale_t l __unused) {
-  return isspace(c);
-}
-
-static __inline int isupper_l(int c, locale_t l __unused) {
-  return isupper(c);
-}
-
-static __inline int isxdigit_l(int c, locale_t l __unused) {
-  return isxdigit(c);
-}
-
-static __inline int tolower_l(int c, locale_t l __unused) {
-  return tolower(c);
-}
-
-static __inline int toupper_l(int c, locale_t l __unused) {
-  return toupper(c);
-}
-
-#endif /* __ANDROID_API__ < 21 */
-
-__END_DECLS
-
-#endif /* ANDROID_LEGACY_CTYPE_INLINES_H */
diff --git a/libc/include/android/legacy_stdlib_inlines.h b/libc/include/android/legacy_stdlib_inlines.h
index 77fdd5d..93554e5 100644
--- a/libc/include/android/legacy_stdlib_inlines.h
+++ b/libc/include/android/legacy_stdlib_inlines.h
@@ -32,10 +32,10 @@
 #include <stdlib.h>
 #include <sys/cdefs.h>
 
-__BEGIN_DECLS
-
 #if __ANDROID_API__ < 21
 
+__BEGIN_DECLS
+
 static __inline float strtof(const char *nptr, char **endptr) {
   return (float)strtod(nptr, endptr);
 }
@@ -62,32 +62,7 @@
   return 0; /* devpts does this all for us! */
 }
 
-static __inline long double strtold_l(const char* nptr, char** endptr, locale_t l __unused) {
-  return strtold(nptr, endptr);
-}
-
-static __inline long long strtoll_l(const char* nptr, char** endptr, int base, locale_t l __unused) {
-  return strtoll(nptr, endptr, base);
-}
-
-static __inline unsigned long long strtoull_l(const char* nptr, char** endptr, int base,
-                                              locale_t l __unused) {
-  return strtoull(nptr, endptr, base);
-}
-
-#endif /* __ANDROID_API__ < 21 */
-
-#if __ANDROID_API__ < __ANDROID_API_FUTURE__
-
-static __inline float strtof_l(const char* nptr, char** endptr, locale_t l __unused) {
-  return strtof(nptr, endptr);
-}
-
-static __inline double strtod_l(const char* nptr, char** endptr, locale_t l __unused) {
-  return strtod(nptr, endptr);
-}
-
-#endif /* __ANDROID_API__ < __ANDROID_API_FUTURE__ */
-
 __END_DECLS
+
+#endif
 #endif /* _ANDROID_LEGACY_STDLIB_INLINES_H_ */
diff --git a/libc/include/android/legacy_string_inlines.h b/libc/include/android/legacy_string_inlines.h
deleted file mode 100644
index ceab909..0000000
--- a/libc/include/android/legacy_string_inlines.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_LEGACY_STRING_INLINES_H
-#define ANDROID_LEGACY_STRING_INLINES_H
-
-#include <string.h>
-#include <sys/cdefs.h>
-
-__BEGIN_DECLS
-
-#if __ANDROID_API__ < 21
-
-static __inline __attribute_pure__ int strcoll_l(const char* _Nonnull s1, const char* _Nonnull s2,
-                                                 locale_t l __unused)  {
-  return strcoll(s1, s2);
-}
-
-size_t strxfrm_l(char* __restrict dest, const char* _Nonnull __restrict src, size_t n,
-                 locale_t l __unused) {
-  return strxfrm(dest, src, n);
-}
-
-#endif /* __ANDROID_API__ < 21 */
-
-__END_DECLS
-
-#endif /* ANDROID_LEGACY_STRING_INLINES_H */
diff --git a/libc/include/android/legacy_sys_wait_inlines.h b/libc/include/android/legacy_sys_wait_inlines.h
new file mode 100644
index 0000000..63343eb
--- /dev/null
+++ b/libc/include/android/legacy_sys_wait_inlines.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _ANDROID_LEGACY_SYS_WAIT_INLINES_H_
+#define _ANDROID_LEGACY_SYS_WAIT_INLINES_H_
+
+#include <sys/cdefs.h>
+#include <sys/syscall.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#if __ANDROID_API__ < 18
+
+__BEGIN_DECLS
+
+static __inline pid_t wait4(pid_t pid, int* status, int options, struct rusage* rusage) {
+  return __BIONIC_CAST(static_cast, pid_t, syscall(__NR_wait4, pid, status, options, rusage));
+}
+
+__END_DECLS
+
+#endif /* __ANDROID_API__ < 18 */
+
+#endif /* _ANDROID_LEGACY_SYS_WAIT_INLINES_H_ */
diff --git a/libc/include/android/legacy_time_inlines.h b/libc/include/android/legacy_time_inlines.h
deleted file mode 100644
index 319cc7c..0000000
--- a/libc/include/android/legacy_time_inlines.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_LEGACY_TIME_INLINES_H
-#define ANDROID_LEGACY_TIME_INLINES_H
-
-#include <sys/cdefs.h>
-#include <time.h>
-
-__BEGIN_DECLS
-
-#if __ANDROID_API__ < 21
-
-static __inline int strftime_l(char* s, size_t max, const char* format, const struct tm* tm,
-                               locale_t l __unused) {
-  return strftime(s, max, format, tm);
-}
-
-#endif /* __ANDROID_API__ < 21 */
-
-__END_DECLS
-
-#endif /* ANDROID_LEGACY_TIME_INLINES_H */
diff --git a/libc/include/android/legacy_wchar_inlines.h b/libc/include/android/legacy_wchar_inlines.h
deleted file mode 100644
index 6c0d29e..0000000
--- a/libc/include/android/legacy_wchar_inlines.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_LEGACY_WCHAR_INLINES_H
-#define ANDROID_LEGACY_WCHAR_INLINES_H
-
-#include <sys/cdefs.h>
-#include <wchar.h>
-
-__BEGIN_DECLS
-
-#if __ANDROID_API__ < 21
-
-static __inline int wcscoll_l(const wchar_t* _Nonnull ws1, const wchar_t* _Nonnull ws2,
-                              locale_t l __unused) {
-  return wcscoll(ws1, ws2);
-}
-
-size_t wcsxfrm_l(wchar_t* dest, const wchar_t* _Nonnull src, size_t n, locale_t l __unused) {
-  return wcsxfrm(dest, src, n);
-}
-
-static inline long double wcstold_l(const wchar_t* nptr, wchar_t** endptr, locale_t l __unused) {
-  return wcstold(nptr, endptr);
-}
-
-static inline long long wcstoll_l(const wchar_t* nptr, wchar_t** endptr, int base,
-                                  locale_t l __unused) {
-  return wcstoll(nptr, endptr, base);
-}
-
-static inline unsigned long long wcstoull_l(const wchar_t* nptr, wchar_t** endptr, int base,
-                                            locale_t l __unused) {
-  return wcstoull(nptr, endptr, base);
-}
-
-#endif /* __ANDROID_API__ < 21 */
-
-__END_DECLS
-
-#endif /* ANDROID_LEGACY_WCHAR_INLINES_H */
diff --git a/libc/include/android/legacy_wctype_inlines.h b/libc/include/android/legacy_wctype_inlines.h
deleted file mode 100644
index c490944..0000000
--- a/libc/include/android/legacy_wctype_inlines.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_LEGACY_WCTYPE_INLINES_H
-#define ANDROID_LEGACY_WCTYPE_INLINES_H
-
-#include <sys/cdefs.h>
-#include <wctype.h>
-
-__BEGIN_DECLS
-
-#if __ANDROID_API__ < 21
-
-static __inline int iswalnum_l(wint_t wc, locale_t l __unused) {
-  return iswalnum(wc);
-}
-
-static __inline int iswalpha_l(wint_t wc, locale_t l __unused) {
-  return iswalpha(wc);
-}
-
-static __inline int iswblank_l(wint_t wc, locale_t l __unused) {
-  return iswblank(wc);
-}
-
-static __inline int iswcntrl_l(wint_t wc, locale_t l __unused) {
-  return iswcntrl(wc);
-}
-
-static __inline int iswdigit_l(wint_t wc, locale_t l __unused) {
-  return iswdigit(wc);
-}
-
-static __inline int iswgraph_l(wint_t wc, locale_t l __unused) {
-  return iswgraph(wc);
-}
-
-static __inline int iswlower_l(wint_t wc, locale_t l __unused) {
-  return iswlower(wc);
-}
-
-static __inline int iswprint_l(wint_t wc, locale_t l __unused) {
-  return iswprint(wc);
-}
-
-static __inline int iswpunct_l(wint_t wc, locale_t l __unused) {
-  return iswpunct(wc);
-}
-
-static __inline int iswspace_l(wint_t wc, locale_t l __unused) {
-  return iswspace(wc);
-}
-
-static __inline int iswupper_l(wint_t wc, locale_t l __unused) {
-  return iswupper(wc);
-}
-
-static __inline int iswxdigit_l(wint_t wc, locale_t l __unused) {
-  return iswxdigit(wc);
-}
-
-static __inline wint_t towlower_l(wint_t wc, locale_t l __unused) {
-  return towlower(wc);
-}
-
-static __inline wint_t towupper_l(wint_t wc, locale_t l __unused) {
-  return towupper(wc);
-}
-
-#endif /* __ANDROID_API__ < 21 */
-
-__END_DECLS
-
-#endif /* ANDROID_LEGACY_WCTYPE_INLINES_H */
diff --git a/libc/include/ctype.h b/libc/include/ctype.h
index e1b237a..f59b399 100644
--- a/libc/include/ctype.h
+++ b/libc/include/ctype.h
@@ -102,6 +102,4 @@
 
 __END_DECLS
 
-#include <android/legacy_ctype_inlines.h>
-
 #endif /* !_CTYPE_H_ */
diff --git a/libc/include/string.h b/libc/include/string.h
index 0114e6a..b3b3ed0 100644
--- a/libc/include/string.h
+++ b/libc/include/string.h
@@ -391,6 +391,4 @@
 
 __END_DECLS
 
-#include <android/legacy_string_inlines.h>
-
 #endif /* _STRING_H */
diff --git a/libc/include/sys/wait.h b/libc/include/sys/wait.h
index 90eb35b..f3972fc 100644
--- a/libc/include/sys/wait.h
+++ b/libc/include/sys/wait.h
@@ -51,7 +51,11 @@
 
 pid_t wait(int*);
 pid_t waitpid(pid_t, int*, int);
+#if __ANDROID_API__ >= 18
 pid_t wait4(pid_t, int*, int, struct rusage*) __INTRODUCED_IN(18);
+#else
+// Implemented as a static inline before 18.
+#endif
 
 /* Posix states that idtype_t should be an enumeration type, but
  * the kernel headers define P_ALL, P_PID and P_PGID as constant macros
@@ -63,4 +67,6 @@
 
 __END_DECLS
 
+#include <android/legacy_sys_wait_inlines.h>
+
 #endif /* _SYS_WAIT_H_ */
diff --git a/libc/include/time.h b/libc/include/time.h
index 898b816..37246b4 100644
--- a/libc/include/time.h
+++ b/libc/include/time.h
@@ -109,6 +109,4 @@
 
 __END_DECLS
 
-#include <android/legacy_time_inlines.h>
-
 #endif /* _TIME_H_ */
diff --git a/libc/include/wchar.h b/libc/include/wchar.h
index c3ad91c..2ee6c69 100644
--- a/libc/include/wchar.h
+++ b/libc/include/wchar.h
@@ -153,6 +153,4 @@
 
 __END_DECLS
 
-#include <android/legacy_wchar_inlines.h>
-
 #endif /* _WCHAR_H_ */
diff --git a/libc/include/wctype.h b/libc/include/wctype.h
index a77b212..0613e7e 100644
--- a/libc/include/wctype.h
+++ b/libc/include/wctype.h
@@ -63,6 +63,4 @@
 
 __END_DECLS
 
-#include <android/legacy_wctype_inlines.h>
-
 #endif /* _WCTYPE_H_ */
diff --git a/libc/private/bionic_asm.h b/libc/private/bionic_asm.h
index e2084d4..c1fab1f 100644
--- a/libc/private/bionic_asm.h
+++ b/libc/private/bionic_asm.h
@@ -41,7 +41,7 @@
 #define ENTRY_NO_DWARF(f) \
     .text; \
     .globl f; \
-    .align __bionic_asm_align; \
+    .balign __bionic_asm_align; \
     .type f, __bionic_asm_function_type; \
     f: \
     __bionic_asm_custom_entry(f); \
diff --git a/libc/zoneinfo/tzdata b/libc/zoneinfo/tzdata
index abfe234..ce00600 100644
--- a/libc/zoneinfo/tzdata
+++ b/libc/zoneinfo/tzdata
Binary files differ
diff --git a/linker/arch/mips/begin.S b/linker/arch/mips/begin.S
index cbe1e37..1bdd358 100644
--- a/linker/arch/mips/begin.S
+++ b/linker/arch/mips/begin.S
@@ -27,7 +27,7 @@
  */
 
     .text
-    .align    4
+    .balign   16
     .type    __start,@function
 
     .ent    __start
diff --git a/linker/arch/mips64/begin.S b/linker/arch/mips64/begin.S
index 8f6b94a..b9637e7 100644
--- a/linker/arch/mips64/begin.S
+++ b/linker/arch/mips64/begin.S
@@ -41,7 +41,7 @@
 #endif
 
     .text
-    .align	4
+    .balign	16
     .type	__start,@function
 
     .ent	__start
diff --git a/tests/sys_prctl_test.cpp b/tests/sys_prctl_test.cpp
index f1b08c1..8fdd28f 100644
--- a/tests/sys_prctl_test.cpp
+++ b/tests/sys_prctl_test.cpp
@@ -14,11 +14,19 @@
  * limitations under the License.
  */
 
-#include <gtest/gtest.h>
-
+#include <inttypes.h>
+#include <stdio.h>
 #include <sys/mman.h>
 #include <sys/prctl.h>
 #include <unistd.h>
+
+#include <string>
+#include <vector>
+
+#include <gtest/gtest.h>
+
+#include "android-base/file.h"
+#include "android-base/strings.h"
 #include "private/bionic_prctl.h"
 
 // http://b/20017123.
@@ -29,9 +37,27 @@
   ASSERT_NE(MAP_FAILED, p);
   ASSERT_EQ(0, mprotect(p, page_size, PROT_NONE));
   ASSERT_NE(-1, prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, p, page_size * 3, "anonymous map space"));
-  volatile char* vp = reinterpret_cast<volatile char*>(p);
-  // Below memory access causes SEGV if the memory map is screwed up.
-  *(vp + page_size) = 0;
+  // Now read the maps and verify that there are no overlapped maps.
+  std::string file_data;
+  ASSERT_TRUE(android::base::ReadFileToString("/proc/self/maps", &file_data));
+
+  uintptr_t last_start = 0;
+  uintptr_t last_end = 0;
+  std::vector<std::string> lines = android::base::Split(file_data, "\n");
+  for (size_t i = 0; i < lines.size(); i++) {
+    if (lines[i].empty()) {
+      continue;
+    }
+    uintptr_t start;
+    uintptr_t end;
+    ASSERT_EQ(2, sscanf(lines[i].c_str(), "%" SCNxPTR "-%" SCNxPTR " ", &start, &end))
+        << "Failed to parse line: " << lines[i];
+    // This will never fail on the first line, so no need to do any special checking.
+    ASSERT_GE(start, last_end) << "Overlapping map detected:\n" << lines[i -1] << lines[i];
+    last_start = start;
+    last_end = end;
+  }
+
   ASSERT_EQ(0, munmap(p, page_size * 3));
 #else
   GTEST_LOG_(INFO) << "This test does nothing as it tests an Android specific kernel feature.";
diff --git a/tests/unistd_test.cpp b/tests/unistd_test.cpp
index 80ebf6b..b488e82 100644
--- a/tests/unistd_test.cpp
+++ b/tests/unistd_test.cpp
@@ -426,7 +426,7 @@
   }
 }
 
-static void TestGetPidCachingWithFork(int (*fork_fn)()) {
+static void TestGetPidCachingWithFork(int (*fork_fn)(), void (*exit_fn)(int)) {
   pid_t parent_pid = getpid();
   ASSERT_EQ(syscall(__NR_getpid), parent_pid);
 
@@ -434,9 +434,9 @@
   ASSERT_NE(fork_result, -1);
   if (fork_result == 0) {
     // We're the child.
-    AssertGetPidCorrect();
+    ASSERT_NO_FATAL_FAILURE(AssertGetPidCorrect());
     ASSERT_EQ(parent_pid, getppid());
-    _exit(123);
+    exit_fn(123);
   } else {
     // We're the parent.
     ASSERT_EQ(parent_pid, getpid());
@@ -444,12 +444,98 @@
   }
 }
 
+// gettid() is marked as __attribute_const__, which will have the compiler
+// optimize out multiple calls to gettid in the same function. This wrapper
+// defeats that optimization.
+static __attribute__((__noinline__)) pid_t GetTidForTest() {
+  __asm__("");
+  return gettid();
+}
+
+static void AssertGetTidCorrect() {
+  // The loop is just to make manual testing/debugging with strace easier.
+  pid_t gettid_syscall_result = syscall(__NR_gettid);
+  for (size_t i = 0; i < 128; ++i) {
+    ASSERT_EQ(gettid_syscall_result, GetTidForTest());
+  }
+}
+
+static void TestGetTidCachingWithFork(int (*fork_fn)(), void (*exit_fn)(int)) {
+  pid_t parent_tid = GetTidForTest();
+  ASSERT_EQ(syscall(__NR_gettid), parent_tid);
+
+  pid_t fork_result = fork_fn();
+  ASSERT_NE(fork_result, -1);
+  if (fork_result == 0) {
+    // We're the child.
+    EXPECT_EQ(syscall(__NR_getpid), syscall(__NR_gettid));
+    EXPECT_EQ(getpid(), GetTidForTest()) << "real tid is " << syscall(__NR_gettid)
+                                         << ", pid is " << syscall(__NR_getpid);
+    ASSERT_NO_FATAL_FAILURE(AssertGetTidCorrect());
+    exit_fn(123);
+  } else {
+    // We're the parent.
+    ASSERT_EQ(parent_tid, GetTidForTest());
+    AssertChildExited(fork_result, 123);
+  }
+}
+
 TEST(UNISTD_TEST, getpid_caching_and_fork) {
-  TestGetPidCachingWithFork(fork);
+  TestGetPidCachingWithFork(fork, exit);
+}
+
+TEST(UNISTD_TEST, gettid_caching_and_fork) {
+  TestGetTidCachingWithFork(fork, exit);
 }
 
 TEST(UNISTD_TEST, getpid_caching_and_vfork) {
-  TestGetPidCachingWithFork(vfork);
+  TestGetPidCachingWithFork(vfork, _exit);
+}
+
+static int CloneLikeFork() {
+  return clone(nullptr, nullptr, SIGCHLD, nullptr);
+}
+
+TEST(UNISTD_TEST, getpid_caching_and_clone_process) {
+  TestGetPidCachingWithFork(CloneLikeFork, exit);
+}
+
+TEST(UNISTD_TEST, gettid_caching_and_clone_process) {
+  TestGetTidCachingWithFork(CloneLikeFork, exit);
+}
+
+static int CloneAndSetTid() {
+  pid_t child_tid = 0;
+  pid_t parent_tid = GetTidForTest();
+
+  int rv = clone(nullptr, nullptr, CLONE_CHILD_SETTID | SIGCHLD, nullptr, nullptr, nullptr, &child_tid);
+  EXPECT_NE(-1, rv);
+
+  if (rv == 0) {
+    // Child.
+    EXPECT_EQ(child_tid, GetTidForTest());
+    EXPECT_NE(child_tid, parent_tid);
+  } else {
+    EXPECT_NE(child_tid, GetTidForTest());
+    EXPECT_NE(child_tid, parent_tid);
+    EXPECT_EQ(GetTidForTest(), parent_tid);
+  }
+
+  return rv;
+}
+
+TEST(UNISTD_TEST, gettid_caching_and_clone_process_settid) {
+  TestGetTidCachingWithFork(CloneAndSetTid, exit);
+}
+
+static int CloneStartRoutine(int (*start_routine)(void*)) {
+  void* child_stack[1024];
+  int clone_result = clone(start_routine, &child_stack[1024], CLONE_NEWNS | SIGCHLD, NULL);
+  if (clone_result == -1 && errno == EPERM && getuid() != 0) {
+    GTEST_LOG_(INFO) << "This test only works if you have permission to CLONE_NEWNS; try running as root.\n";
+    return clone_result;
+  }
+  return clone_result;
 }
 
 static int GetPidCachingCloneStartRoutine(void*) {
@@ -461,12 +547,7 @@
   pid_t parent_pid = getpid();
   ASSERT_EQ(syscall(__NR_getpid), parent_pid);
 
-  void* child_stack[1024];
-  int clone_result = clone(GetPidCachingCloneStartRoutine, &child_stack[1024], CLONE_NEWNS | SIGCHLD, NULL);
-  if (clone_result == -1 && errno == EPERM && getuid() != 0) {
-    GTEST_LOG_(INFO) << "This test only works if you have permission to CLONE_NEWNS; try running as root.\n";
-    return;
-  }
+  int clone_result = CloneStartRoutine(GetPidCachingCloneStartRoutine);
   ASSERT_NE(clone_result, -1);
 
   ASSERT_EQ(parent_pid, getpid());
@@ -474,6 +555,39 @@
   AssertChildExited(clone_result, 123);
 }
 
+static int GetTidCachingCloneStartRoutine(void*) {
+  AssertGetTidCorrect();
+  return 123;
+}
+
+TEST(UNISTD_TEST, gettid_caching_and_clone) {
+  pid_t parent_tid = GetTidForTest();
+  ASSERT_EQ(syscall(__NR_gettid), parent_tid);
+
+  int clone_result = CloneStartRoutine(GetTidCachingCloneStartRoutine);
+  ASSERT_NE(clone_result, -1);
+
+  ASSERT_EQ(parent_tid, GetTidForTest());
+
+  AssertChildExited(clone_result, 123);
+}
+
+static int CloneChildExit(void*) {
+  AssertGetPidCorrect();
+  AssertGetTidCorrect();
+  exit(33);
+}
+
+TEST(UNISTD_TEST, clone_fn_and_exit) {
+  int clone_result = CloneStartRoutine(CloneChildExit);
+  ASSERT_NE(-1, clone_result);
+
+  AssertGetPidCorrect();
+  AssertGetTidCorrect();
+
+  AssertChildExited(clone_result, 33);
+}
+
 static void* GetPidCachingPthreadStartRoutine(void*) {
   AssertGetPidCorrect();
   return NULL;
@@ -492,6 +606,25 @@
   ASSERT_EQ(NULL, result);
 }
 
+static void* GetTidCachingPthreadStartRoutine(void*) {
+  AssertGetTidCorrect();
+  uint64_t tid = GetTidForTest();
+  return reinterpret_cast<void*>(tid);
+}
+
+TEST(UNISTD_TEST, gettid_caching_and_pthread_create) {
+  pid_t parent_tid = GetTidForTest();
+
+  pthread_t t;
+  ASSERT_EQ(0, pthread_create(&t, NULL, GetTidCachingPthreadStartRoutine, &parent_tid));
+
+  ASSERT_EQ(parent_tid, GetTidForTest());
+
+  void* result;
+  ASSERT_EQ(0, pthread_join(t, &result));
+  ASSERT_NE(static_cast<uint64_t>(parent_tid), reinterpret_cast<uint64_t>(result));
+}
+
 class UNISTD_DEATHTEST : public BionicDeathTest {};
 
 TEST_F(UNISTD_DEATHTEST, abort) {
diff --git a/tools/update_headers.sh b/tools/update_headers.sh
index 345b657..0095d50 100755
--- a/tools/update_headers.sh
+++ b/tools/update_headers.sh
@@ -35,11 +35,19 @@
 HEADERS_INSTALL=$PREBUILTS_DIR/headers
 if [ -d "$HEADERS_INSTALL" ]; then
   git -C $PREBUILTS_DIR rm -r --ignore-unmatch $HEADERS_INSTALL
-  rm -r $HEADERS_INSTALL
+  if [ -d $HEADERS_INSTALL ]; then
+    rm -r $HEADERS_INSTALL
+  fi
 fi
 
 versioner -p versioner/platforms versioner/current versioner/dependencies \
   -o $HEADERS_INSTALL
+if [ $? -ne 0 ]; then
+  >&2 echo "Header preprocessing failed"
+  exit 1
+fi
 
-git -C $PREBUILTS_DIR add $HEADERS_INSTALL
+cp ../libc/NOTICE $PREBUILTS_DIR
+
+git -C $PREBUILTS_DIR add $HEADERS_INSTALL $PREBUILTS_DIR/NOTICE
 git -C $PREBUILTS_DIR commit -m "Update bionic headers to $VERSION."
diff --git a/tools/versioner/src/DeclarationDatabase.h b/tools/versioner/src/DeclarationDatabase.h
index e957019..cf3589b 100644
--- a/tools/versioner/src/DeclarationDatabase.h
+++ b/tools/versioner/src/DeclarationDatabase.h
@@ -173,9 +173,9 @@
 
       fprintf(out, "\n%s  ", indent_str.c_str());
       if (!calculateAvailability(&avail)) {
-        fprintf(out, "invalid availability");
+        fprintf(out, "invalid availability\n");
       } else {
-        fprintf(out, "%s", to_string(avail).c_str());
+        fprintf(out, "%s\n", to_string(avail).c_str());
       }
     }
   }
@@ -209,7 +209,6 @@
 
     for (auto& it : declarations) {
       it.second.dump(base_path, out, 4);
-      fprintf(out, "\n");
     }
   }
 };
diff --git a/tools/versioner/src/versioner.cpp b/tools/versioner/src/versioner.cpp
index 74650d5..2f0656c 100644
--- a/tools/versioner/src/versioner.cpp
+++ b/tools/versioner/src/versioner.cpp
@@ -276,6 +276,21 @@
   return result;
 }
 
+static std::set<CompilationType> getCompilationTypes(const Declaration* decl) {
+  std::set<CompilationType> result;
+  for (const auto& it : decl->availability) {
+    result.insert(it.first);
+  }
+  return result;
+}
+
+template<typename T>
+static std::vector<T> Intersection(const std::set<T>& a, const std::set<T>& b) {
+  std::vector<T> intersection;
+  std::set_intersection(a.begin(), a.end(), b.begin(), b.end(), std::back_inserter(intersection));
+  return intersection;
+}
+
 // Perform a sanity check on a symbol's declarations, enforcing the following invariants:
 //   1. At most one inline definition of the function exists.
 //   2. All of the availability declarations for a symbol are compatible.
@@ -287,18 +302,23 @@
 static bool checkSymbol(const Symbol& symbol) {
   std::string cwd = getWorkingDir() + "/";
 
-  const Declaration* inline_definition = nullptr;
+  std::unordered_map<const Declaration*, std::set<CompilationType>> inline_definitions;
   for (const auto& decl_it : symbol.declarations) {
     const Declaration* decl = &decl_it.second;
     if (decl->is_definition) {
-      if (inline_definition) {
-        fprintf(stderr, "versioner: multiple definitions of symbol %s\n", symbol.name.c_str());
-        symbol.dump(cwd);
-        inline_definition->dump(cwd);
-        return false;
+      std::set<CompilationType> compilation_types = getCompilationTypes(decl);
+      for (const auto& inline_def_it : inline_definitions) {
+        auto intersection = Intersection(compilation_types, inline_def_it.second);
+        if (!intersection.empty()) {
+          fprintf(stderr, "versioner: conflicting inline definitions:\n");
+          fprintf(stderr, "  declarations visible in: %s\n", Join(intersection, ", ").c_str());
+          decl->dump(cwd, stderr, 4);
+          inline_def_it.first->dump(cwd, stderr, 4);
+          return false;
+        }
       }
 
-      inline_definition = decl;
+      inline_definitions[decl] = std::move(compilation_types);
     }
 
     DeclarationAvailability availability;
diff --git a/tools/versioner/tests/multiple_definition/expected_fail b/tools/versioner/tests/multiple_definition/expected_fail
new file mode 100644
index 0000000..6c531bd
--- /dev/null
+++ b/tools/versioner/tests/multiple_definition/expected_fail
@@ -0,0 +1,7 @@
+versioner: conflicting inline definitions:
+  declarations visible in: arm-9 [fob = 32], arm-9 [fob = 64], arm-12 [fob = 32], arm-12 [fob = 64]
+    static definition @ headers/foo.h:1:1
+      no availability
+    static definition @ headers/bar.h:1:1
+      no availability
+versioner: sanity check failed
diff --git a/tools/versioner/tests/multiple_definition/headers/bar.h b/tools/versioner/tests/multiple_definition/headers/bar.h
new file mode 100644
index 0000000..a9d0197
--- /dev/null
+++ b/tools/versioner/tests/multiple_definition/headers/bar.h
@@ -0,0 +1,3 @@
+static int foo() {
+  return 0;
+}
diff --git a/tools/versioner/tests/multiple_definition/headers/foo.h b/tools/versioner/tests/multiple_definition/headers/foo.h
new file mode 100644
index 0000000..a9d0197
--- /dev/null
+++ b/tools/versioner/tests/multiple_definition/headers/foo.h
@@ -0,0 +1,3 @@
+static int foo() {
+  return 0;
+}
diff --git a/tools/versioner/tests/multiple_definition/platforms/android-9/arch-arm/symbols/libc.so.functions.txt b/tools/versioner/tests/multiple_definition/platforms/android-9/arch-arm/symbols/libc.so.functions.txt
new file mode 100644
index 0000000..257cc56
--- /dev/null
+++ b/tools/versioner/tests/multiple_definition/platforms/android-9/arch-arm/symbols/libc.so.functions.txt
@@ -0,0 +1 @@
+foo
diff --git a/tools/versioner/tests/multiple_definition/run.sh b/tools/versioner/tests/multiple_definition/run.sh
new file mode 100644
index 0000000..e4abbe7
--- /dev/null
+++ b/tools/versioner/tests/multiple_definition/run.sh
@@ -0,0 +1 @@
+versioner headers -p platforms -r arm -a 9 -a 12 -i
diff --git a/tools/versioner/tests/multiple_definition_ok/headers/bar.h b/tools/versioner/tests/multiple_definition_ok/headers/bar.h
new file mode 100644
index 0000000..c3c87bb
--- /dev/null
+++ b/tools/versioner/tests/multiple_definition_ok/headers/bar.h
@@ -0,0 +1,5 @@
+#if __ANDROID_API__ == 12
+static int foo() {
+  return 0;
+}
+#endif
diff --git a/tools/versioner/tests/multiple_definition_ok/headers/foo.h b/tools/versioner/tests/multiple_definition_ok/headers/foo.h
new file mode 100644
index 0000000..9da9b2a
--- /dev/null
+++ b/tools/versioner/tests/multiple_definition_ok/headers/foo.h
@@ -0,0 +1,5 @@
+#if __ANDROID_API__ == 9
+static int foo() {
+  return 0;
+}
+#endif
diff --git a/tools/versioner/tests/multiple_definition_ok/platforms/android-9/arch-arm/symbols/libc.so.functions.txt b/tools/versioner/tests/multiple_definition_ok/platforms/android-9/arch-arm/symbols/libc.so.functions.txt
new file mode 100644
index 0000000..257cc56
--- /dev/null
+++ b/tools/versioner/tests/multiple_definition_ok/platforms/android-9/arch-arm/symbols/libc.so.functions.txt
@@ -0,0 +1 @@
+foo
diff --git a/tools/versioner/tests/multiple_definition_ok/run.sh b/tools/versioner/tests/multiple_definition_ok/run.sh
new file mode 100644
index 0000000..e4abbe7
--- /dev/null
+++ b/tools/versioner/tests/multiple_definition_ok/run.sh
@@ -0,0 +1 @@
+versioner headers -p platforms -r arm -a 9 -a 12 -i