Merge "Add Silvermont architecture cache sizes"
diff --git a/libc/Android.mk b/libc/Android.mk
index 3faa47f..44bf388 100644
--- a/libc/Android.mk
+++ b/libc/Android.mk
@@ -292,6 +292,7 @@
upstream-netbsd/lib/libc/stdlib/ldiv.c \
upstream-netbsd/lib/libc/stdlib/lldiv.c \
upstream-netbsd/lib/libc/stdlib/lrand48.c \
+ upstream-netbsd/lib/libc/stdlib/lsearch.c \
upstream-netbsd/lib/libc/stdlib/mrand48.c \
upstream-netbsd/lib/libc/stdlib/nrand48.c \
upstream-netbsd/lib/libc/stdlib/_rand48.c \
diff --git a/libc/arch-arm/arm.mk b/libc/arch-arm/arm.mk
index 89a1ce0..cbc5fa7 100644
--- a/libc/arch-arm/arm.mk
+++ b/libc/arch-arm/arm.mk
@@ -70,7 +70,7 @@
endif
cpu_variant_mk := $(LOCAL_PATH)/arch-arm/$(TARGET_$(my_2nd_arch_prefix)CPU_VARIANT)/$(TARGET_$(my_2nd_arch_prefix)CPU_VARIANT).mk
ifeq ($(wildcard $(cpu_variant_mk)),)
-$(error "TARGET_$(my_2nd_arch_prefix)CPU_VARIANT not set or set to an unknown value. Possible values are cortex-a7, cortex-a8, cortex-a9, cortex-a15, krait. Use generic for devices that do not have a CPU similar to any of the supported cpu variants.")
+$(error "TARGET_$(my_2nd_arch_prefix)CPU_VARIANT not set or set to an unknown value. Possible values are cortex-a7, cortex-a8, cortex-a9, cortex-a15, krait, denver. Use generic for devices that do not have a CPU similar to any of the supported cpu variants.")
endif
include $(cpu_variant_mk)
libc_common_additional_dependencies += $(cpu_variant_mk)
diff --git a/libc/arch-arm/denver/bionic/__strcat_chk.S b/libc/arch-arm/denver/bionic/__strcat_chk.S
new file mode 100644
index 0000000..36da2d9
--- /dev/null
+++ b/libc/arch-arm/denver/bionic/__strcat_chk.S
@@ -0,0 +1,221 @@
+/*
+ * 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>
+#include <private/libc_events.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}
+ .save {r0, lr}
+ .cfi_def_cfa_offset 8
+ .cfi_rel_offset r0, 0
+ .cfi_rel_offset lr, 4
+ push {r4, r5}
+ .save {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
+ bhi __strcat_chk_failed
+
+ // Set up the registers for the memcpy code.
+ mov r1, r5
+ pld [r1, #64]
+ mov r2, r4
+ add r0, r0, r3
+ pop {r4, r5}
+END(__strcat_chk)
+
+#define MEMCPY_BASE __strcat_chk_memcpy_base
+#define MEMCPY_BASE_ALIGNED __strcat_chk_memcpy_base_aligned
+
+#include "memcpy_base.S"
+
+ENTRY_PRIVATE(__strcat_chk_failed)
+ .save {r0, lr}
+ .save {r4, r5}
+
+ .cfi_def_cfa_offset 8
+ .cfi_rel_offset r0, 0
+ .cfi_rel_offset lr, 4
+ .cfi_adjust_cfa_offset 8
+ .cfi_rel_offset r4, 0
+ .cfi_rel_offset r5, 4
+
+ ldr r0, error_message
+ ldr r1, error_code
+1:
+ add r0, pc
+ bl __fortify_chk_fail
+error_code:
+ .word BIONIC_EVENT_STRCAT_BUFFER_OVERFLOW
+error_message:
+ .word error_string-(1b+4)
+END(__strcat_chk_failed)
+
+ .data
+error_string:
+ .string "strcat: prevented write past end of buffer"
diff --git a/libc/arch-arm/denver/bionic/__strcpy_chk.S b/libc/arch-arm/denver/bionic/__strcpy_chk.S
new file mode 100644
index 0000000..c3e3e14
--- /dev/null
+++ b/libc/arch-arm/denver/bionic/__strcpy_chk.S
@@ -0,0 +1,182 @@
+/*
+ * 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>
+#include <private/libc_events.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}
+ .save {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]
+ cmp r3, lr
+ bhs __strcpy_chk_failed
+
+ // Add 1 for copy length to get the string terminator.
+ add r2, r3, #1
+END(__strcpy_chk)
+
+#define MEMCPY_BASE __strcpy_chk_memcpy_base
+#define MEMCPY_BASE_ALIGNED __strcpy_chk_memcpy_base_aligned
+#include "memcpy_base.S"
+
+ENTRY_PRIVATE(__strcpy_chk_failed)
+ .save {r0, lr}
+ .cfi_def_cfa_offset 8
+ .cfi_rel_offset r0, 0
+ .cfi_rel_offset lr, 4
+
+ ldr r0, error_message
+ ldr r1, error_code
+1:
+ add r0, pc
+ bl __fortify_chk_fail
+error_code:
+ .word BIONIC_EVENT_STRCPY_BUFFER_OVERFLOW
+error_message:
+ .word error_string-(1b+4)
+END(__strcpy_chk_failed)
+
+ .data
+error_string:
+ .string "strcpy: prevented write past end of buffer"
diff --git a/libc/arch-arm/denver/bionic/memcpy.S b/libc/arch-arm/denver/bionic/memcpy.S
new file mode 100644
index 0000000..da4f3dd
--- /dev/null
+++ b/libc/arch-arm/denver/bionic/memcpy.S
@@ -0,0 +1,105 @@
+/*
+ * 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.
+ */
+
+// Prototype: void *memcpy (void *dst, const void *src, size_t count).
+
+#include <private/bionic_asm.h>
+#include <private/libc_events.h>
+
+ .text
+ .syntax unified
+ .fpu neon
+
+ENTRY(__memcpy_chk)
+ cmp r2, r3
+ bhi __memcpy_chk_fail
+
+ // Fall through to memcpy...
+END(__memcpy_chk)
+
+ENTRY(memcpy)
+ pld [r1, #64]
+ push {r0, lr}
+ .save {r0, lr}
+ .cfi_def_cfa_offset 8
+ .cfi_rel_offset r0, 0
+ .cfi_rel_offset lr, 4
+END(memcpy)
+
+#define MEMCPY_BASE __memcpy_base
+#define MEMCPY_BASE_ALIGNED __memcpy_base_aligned
+#include "memcpy_base.S"
+
+ENTRY_PRIVATE(__memcpy_chk_fail)
+ // Preserve lr for backtrace.
+ push {lr}
+ .save {lr}
+ .cfi_def_cfa_offset 4
+ .cfi_rel_offset lr, 0
+
+ ldr r0, error_message
+ ldr r1, error_code
+1:
+ add r0, pc
+ bl __fortify_chk_fail
+error_code:
+ .word BIONIC_EVENT_MEMCPY_BUFFER_OVERFLOW
+error_message:
+ .word error_string-(1b+8)
+END(__memcpy_chk_fail)
+
+ .data
+error_string:
+ .string "memcpy: prevented write past end of buffer"
diff --git a/libc/arch-arm/denver/bionic/memcpy_base.S b/libc/arch-arm/denver/bionic/memcpy_base.S
new file mode 100644
index 0000000..2abb486
--- /dev/null
+++ b/libc/arch-arm/denver/bionic/memcpy_base.S
@@ -0,0 +1,234 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ * Copyright (c) 2013-2014, NVIDIA Corporation. 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.
+ */
+
+#define CACHE_LINE_SIZE (64)
+#define PREFETCH_DISTANCE (CACHE_LINE_SIZE*6)
+
+ENTRY_PRIVATE(MEMCPY_BASE)
+ .cfi_def_cfa_offset 8
+ .cfi_rel_offset r0, 0
+ .cfi_rel_offset lr, 4
+
+ cmp r2, #0
+ beq .L_memcpy_done
+ cmp r0, r1
+ beq .L_memcpy_done
+
+ /* preload next cache line */
+ pld [r1, #CACHE_LINE_SIZE*1]
+
+ /* Deal with very small blocks (< 32bytes) asap */
+ cmp r2, #32
+ blo .L_memcpy_lt_32bytes
+ /* no need to align if len < 128 bytes */
+ cmp r2, #128
+ blo .L_memcpy_lt_128bytes
+
+ /* large copy, align dest to 64 byte boundry */
+ pld [r1, #CACHE_LINE_SIZE*2]
+ rsb r3, r0, #0
+ ands r3, r3, #0x3F
+ pld [r1, #CACHE_LINE_SIZE*3]
+ beq .L_memcpy_dispatch
+ sub r2, r2, r3
+ /* copy 1 byte */
+ movs ip, r3, lsl #31
+ itt mi
+ ldrbmi ip, [r1], #1
+ strbmi ip, [r0], #1
+ /* copy 2 bytes */
+ itt cs
+ ldrhcs ip, [r1], #2
+ strhcs ip, [r0], #2
+ /* copy 4 bytes */
+ movs ip, r3, lsl #29
+ itt mi
+ ldrmi ip, [r1], #4
+ strmi ip, [r0], #4
+ /* copy 8 bytes */
+ bcc 1f
+ vld1.8 {d0}, [r1]!
+ vst1.8 {d0}, [r0, :64]!
+1: /* copy 16 bytes */
+ movs ip, r3, lsl #27
+ bpl 1f
+ vld1.8 {q0}, [r1]!
+ vst1.8 {q0}, [r0, :128]!
+1: /* copy 32 bytes */
+ bcc .L_memcpy_dispatch
+ vld1.8 {q0, q1}, [r1]!
+ vst1.8 {q0, q1}, [r0, :256]!
+
+.L_memcpy_dispatch:
+ // pre-decrement by 128 to detect nearly-done condition easily, but
+ // also need to check if we have less than 128 bytes left at this
+ // point due to alignment code above
+ subs r2, r2, #128
+ blo .L_memcpy_lt_128presub
+
+ // Denver does better if both source and dest are aligned so
+ // we'll special-case that even though the code is virually identical
+ tst r1, #0xF
+ bne .L_memcpy_neon_unalign_src_pld
+
+ // DRAM memcpy should be throttled slightly to get full bandwidth
+ //
+ cmp r2, #32768
+ bhi .L_memcpy_neon_unalign_src_pld
+ .align 4
+1:
+ /* copy 128 bytes in each loop */
+ subs r2, r2, #128
+
+ /* preload a cache line */
+ pld [r1, #PREFETCH_DISTANCE]
+ /* copy a cache line */
+ vld1.8 {q0, q1}, [r1, :128]!
+ vst1.8 {q0, q1}, [r0, :256]!
+ vld1.8 {q0, q1}, [r1, :128]!
+ vst1.8 {q0, q1}, [r0, :256]!
+ /* preload a cache line */
+ pld [r1, #PREFETCH_DISTANCE]
+ /* copy a cache line */
+ vld1.8 {q0, q1}, [r1, :128]!
+ vst1.8 {q0, q1}, [r0, :256]!
+ vld1.8 {q0, q1}, [r1, :128]!
+ vst1.8 {q0, q1}, [r0, :256]!
+
+ bhs 1b
+ adds r2, r2, #128
+ bne .L_memcpy_lt_128bytes_align
+ pop {r0, pc}
+
+ .align 4
+.L_memcpy_neon_unalign_src_pld:
+1:
+ /* copy 128 bytes in each loop */
+ subs r2, r2, #128
+
+ /* preload a cache line */
+ pld [r1, #PREFETCH_DISTANCE]
+ /* copy a cache line */
+ vld1.8 {q0, q1}, [r1]!
+ vst1.8 {q0, q1}, [r0, :256]!
+ vld1.8 {q0, q1}, [r1]!
+ vst1.8 {q0, q1}, [r0, :256]!
+ /* preload a cache line */
+ pld [r1, #PREFETCH_DISTANCE]
+ /* copy a cache line */
+ vld1.8 {q0, q1}, [r1]!
+ vst1.8 {q0, q1}, [r0, :256]!
+ vld1.8 {q0, q1}, [r1]!
+ vst1.8 {q0, q1}, [r0, :256]!
+
+ bhs 1b
+ adds r2, r2, #128
+ bne .L_memcpy_lt_128bytes_align
+ pop {r0, pc}
+
+.L_memcpy_lt_128presub:
+ add r2, r2, #128
+.L_memcpy_lt_128bytes_align:
+ /* copy 64 bytes */
+ movs ip, r2, lsl #26
+ bcc 1f
+ vld1.8 {q0, q1}, [r1]!
+ vst1.8 {q0, q1}, [r0, :256]!
+ vld1.8 {q0, q1}, [r1]!
+ vst1.8 {q0, q1}, [r0, :256]!
+1: /* copy 32 bytes */
+ bpl 1f
+ vld1.8 {q0, q1}, [r1]!
+ vst1.8 {q0, q1}, [r0, :256]!
+1: /* copy 16 bytes */
+ movs ip, r2, lsl #28
+ bcc 1f
+ vld1.8 {q0}, [r1]!
+ vst1.8 {q0}, [r0, :128]!
+1: /* copy 8 bytes */
+ bpl 1f
+ vld1.8 {d0}, [r1]!
+ vst1.8 {d0}, [r0, :64]!
+1: /* copy 4 bytes */
+ tst r2, #4
+ itt ne
+ ldrne ip, [r1], #4
+ strne ip, [r0], #4
+ /* copy 2 bytes */
+ movs ip, r2, lsl #31
+ itt cs
+ ldrhcs ip, [r1], #2
+ strhcs ip, [r0], #2
+ /* copy 1 byte */
+ itt mi
+ ldrbmi ip, [r1]
+ strbmi ip, [r0]
+
+ pop {r0, pc}
+
+.L_memcpy_lt_128bytes:
+ /* copy 64 bytes */
+ movs ip, r2, lsl #26
+ bcc 1f
+ vld1.8 {q0, q1}, [r1]!
+ vst1.8 {q0, q1}, [r0]!
+ vld1.8 {q0, q1}, [r1]!
+ vst1.8 {q0, q1}, [r0]!
+1: /* copy 32 bytes */
+ bpl .L_memcpy_lt_32bytes
+ vld1.8 {q0, q1}, [r1]!
+ vst1.8 {q0, q1}, [r0]!
+.L_memcpy_lt_32bytes:
+ /* copy 16 bytes */
+ movs ip, r2, lsl #28
+ bcc 1f
+ vld1.8 {q0}, [r1]!
+ vst1.8 {q0}, [r0]!
+1: /* copy 8 bytes */
+ bpl 1f
+ vld1.8 {d0}, [r1]!
+ vst1.8 {d0}, [r0]!
+1: /* copy 4 bytes */
+ tst r2, #4
+ itt ne
+ ldrne ip, [r1], #4
+ strne ip, [r0], #4
+ /* copy 2 bytes */
+ movs ip, r2, lsl #31
+ itt cs
+ ldrhcs ip, [r1], #2
+ strhcs ip, [r0], #2
+ /* copy 1 byte */
+ itt mi
+ ldrbmi ip, [r1]
+ strbmi ip, [r0]
+
+.L_memcpy_done:
+ pop {r0, pc}
+END(MEMCPY_BASE)
diff --git a/libc/arch-arm/denver/bionic/memset.S b/libc/arch-arm/denver/bionic/memset.S
new file mode 100644
index 0000000..bf3d9ad
--- /dev/null
+++ b/libc/arch-arm/denver/bionic/memset.S
@@ -0,0 +1,207 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved.
+ * 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 <machine/cpu-features.h>
+#include <private/bionic_asm.h>
+#include <private/libc_events.h>
+
+ /*
+ * Optimized memset() for ARM.
+ *
+ * memset() returns its first argument.
+ */
+
+ .fpu neon
+ .syntax unified
+
+ENTRY(__memset_chk)
+ cmp r2, r3
+ bls .L_done
+
+ // Preserve lr for backtrace.
+ push {lr}
+ .cfi_def_cfa_offset 4
+ .cfi_rel_offset lr, 0
+
+
+ ldr r0, error_message
+ ldr r1, error_code
+1:
+ add r0, pc
+ bl __fortify_chk_fail
+error_code:
+ .word BIONIC_EVENT_MEMSET_BUFFER_OVERFLOW
+error_message:
+ .word error_string-(1b+8)
+END(__memset_chk)
+
+ENTRY(bzero)
+ mov r2, r1
+ mov r1, #0
+.L_done:
+ // Fall through to memset...
+END(bzero)
+
+ENTRY(memset)
+ pldw [r0]
+ mov r3, r0
+
+ // Duplicate the low byte of r1
+ mov r1, r1, lsl #24
+ orr r1, r1, r1, lsr #8
+ orr r1, r1, r1, lsr #16
+
+ cmp r2, #16
+ blo .L_less_than_16
+
+ // This section handles regions 16 bytes or larger
+ //
+ // Use aligned vst1.8 and vstm when possible. Register values will be:
+ // ip is scratch
+ // q0, q1, and r1 contain the memset value
+ // r2 is the number of bytes to set
+ // r3 is the advancing destination pointer
+ vdup.32 q0, r1
+
+ ands ip, r3, 0xF
+ beq .L_memset_aligned
+
+ // Align dest pointer to 16-byte boundary.
+ pldw [r0, #64]
+ rsb ip, ip, #16
+
+ // Pre-adjust the byte count to reflect post-aligment value. Expecting
+ // 8-byte alignment to be rather common so we special case that one.
+ sub r2, r2, ip
+
+ /* set 1 byte */
+ tst ip, #1
+ it ne
+ strbne r1, [r3], #1
+ /* set 2 bytes */
+ tst ip, #2
+ it ne
+ strhne r1, [r3], #2
+ /* set 4 bytes */
+ movs ip, ip, lsl #29
+ it mi
+ strmi r1, [r3], #4
+ /* set 8 bytes */
+ itt cs
+ strcs r1, [r3], #4
+ strcs r1, [r3], #4
+
+.L_memset_aligned:
+ // Destination is now 16-byte aligned. Determine how to handle
+ // remaining bytes.
+ vmov q1, q0
+ cmp r2, #128
+ blo .L_less_than_128
+
+ // We need to set a larger block of memory. Use four Q regs to
+ // set a full cache line in one instruction. Pre-decrement
+ // r2 to simplify end-of-loop detection
+ vmov q2, q0
+ vmov q3, q0
+ pldw [r0, #128]
+ sub r2, r2, #128
+ .align 4
+.L_memset_loop_128:
+ pldw [r3, #192]
+ vstm r3!, {q0, q1, q2, q3}
+ vstm r3!, {q0, q1, q2, q3}
+ subs r2, r2, #128
+ bhs .L_memset_loop_128
+
+ // Un-bias r2 so it contains the number of bytes left. Early
+ // exit if we are done.
+ adds r2, r2, #128
+ beq 2f
+
+ .align 4
+.L_less_than_128:
+ // set 64 bytes
+ movs ip, r2, lsl #26
+ bcc 1f
+ vst1.8 {q0, q1}, [r3, :128]!
+ vst1.8 {q0, q1}, [r3, :128]!
+ beq 2f
+1:
+ // set 32 bytes
+ bpl 1f
+ vst1.8 {q0, q1}, [r3, :128]!
+1:
+ // set 16 bytes
+ movs ip, r2, lsl #28
+ bcc 1f
+ vst1.8 {q0}, [r3, :128]!
+ beq 2f
+1:
+ // set 8 bytes
+ bpl 1f
+ vst1.8 {d0}, [r3, :64]!
+1:
+ // set 4 bytes
+ tst r2, #4
+ it ne
+ strne r1, [r3], #4
+1:
+ // set 2 bytes
+ movs ip, r2, lsl #31
+ it cs
+ strhcs r1, [r3], #2
+ // set 1 byte
+ it mi
+ strbmi r1, [r3]
+2:
+ bx lr
+
+.L_less_than_16:
+ // Store up to 15 bytes without worrying about byte alignment
+ movs ip, r2, lsl #29
+ bcc 1f
+ str r1, [r3], #4
+ str r1, [r3], #4
+ beq 2f
+1:
+ it mi
+ strmi r1, [r3], #4
+ movs ip, r2, lsl #31
+ it mi
+ strbmi r1, [r3], #1
+ itt cs
+ strbcs r1, [r3], #1
+ strbcs r1, [r3]
+2:
+ bx lr
+END(memset)
+
+ .data
+error_string:
+ .string "memset: prevented write past end of buffer"
diff --git a/libc/arch-arm/denver/denver.mk b/libc/arch-arm/denver/denver.mk
new file mode 100644
index 0000000..3fcc457
--- /dev/null
+++ b/libc/arch-arm/denver/denver.mk
@@ -0,0 +1,12 @@
+libc_bionic_src_files_arm += \
+ arch-arm/denver/bionic/memcpy.S \
+ arch-arm/denver/bionic/memset.S \
+ arch-arm/denver/bionic/__strcat_chk.S \
+ arch-arm/denver/bionic/__strcpy_chk.S
+
+# Use cortex-a15 versions of strcat/strcpy/strlen.
+libc_bionic_src_files_arm += \
+ arch-arm/cortex-a15/bionic/strcat.S \
+ arch-arm/cortex-a15/bionic/strcpy.S \
+ arch-arm/cortex-a15/bionic/strlen.S \
+ arch-arm/cortex-a15/bionic/strcmp.S
diff --git a/libc/bionic/malloc_debug_common.cpp b/libc/bionic/malloc_debug_common.cpp
index 85f7791..4fa4b6e 100644
--- a/libc/bionic/malloc_debug_common.cpp
+++ b/libc/bionic/malloc_debug_common.cpp
@@ -379,7 +379,7 @@
if (gMallocDebugBacklog == 0) {
gMallocDebugBacklog = BACKLOG_DEFAULT_LEN;
}
- so_name = "/system/lib/libc_malloc_debug_leak.so";
+ so_name = "libc_malloc_debug_leak.so";
break;
}
case 20:
@@ -395,7 +395,7 @@
__progname);
return;
}
- so_name = "/system/lib/libc_malloc_debug_qemu.so";
+ so_name = "libc_malloc_debug_qemu.so";
break;
default:
error_log("%s: Debug level %d is unknown\n", __progname, gMallocDebugLevel);
diff --git a/libc/include/search.h b/libc/include/search.h
index 1301a08..b2c0e6b 100644
--- a/libc/include/search.h
+++ b/libc/include/search.h
@@ -10,29 +10,34 @@
#define _SEARCH_H_
#include <sys/cdefs.h>
+#include <sys/types.h>
-typedef enum {
- preorder,
- postorder,
- endorder,
- leaf
+typedef enum {
+ preorder,
+ postorder,
+ endorder,
+ leaf
} VISIT;
#ifdef _SEARCH_PRIVATE
-typedef struct node {
- char *key;
- struct node *llink, *rlink;
+typedef struct node {
+ char* key;
+ struct node* llink;
+ struct node* rlink;
} node_t;
#endif
__BEGIN_DECLS
-void *tdelete(const void * __restrict, void ** __restrict,
- int (*)(const void *, const void *));
-void *tfind(const void *, void * const *,
- int (*)(const void *, const void *));
-void *tsearch(const void *, void **, int (*)(const void *, const void *));
-void twalk(const void *, void (*)(const void *, VISIT, int));
-void tdestroy(void *, void (*)(void *));
+
+void* lfind(const void*, const void*, size_t*, size_t, int (*)(const void*, const void*));
+void* lsearch(const void*, void*, size_t*, size_t, int (*)(const void*, const void*));
+
+void* tdelete(const void* __restrict, void** __restrict, int (*)(const void*, const void*));
+void tdestroy(void*, void (*)(void*));
+void* tfind(const void*, void* const*, int (*)(const void*, const void*));
+void* tsearch(const void*, void**, int (*)(const void*, const void*));
+void twalk(const void*, void (*)(const void*, VISIT, int));
+
__END_DECLS
#endif /* !_SEARCH_H_ */
diff --git a/libc/include/sys/socket.h b/libc/include/sys/socket.h
index 5001b2e..86fd3cf 100644
--- a/libc/include/sys/socket.h
+++ b/libc/include/sys/socket.h
@@ -284,6 +284,7 @@
#endif
__socketcall int accept(int, struct sockaddr*, socklen_t*);
+__socketcall int accept4(int, struct sockaddr*, socklen_t*, int);
__socketcall int bind(int, const struct sockaddr*, int);
__socketcall int connect(int, const struct sockaddr*, socklen_t);
__socketcall int getpeername(int, struct sockaddr*, socklen_t*);
@@ -298,7 +299,6 @@
__socketcall int shutdown(int, int);
__socketcall int socket(int, int, int);
__socketcall int socketpair(int, int, int, int*);
-__socketcall int accept4(int, struct sockaddr*, socklen_t*, int);
extern ssize_t send(int, const void*, size_t, int);
extern ssize_t recv(int, void*, size_t, int);
diff --git a/libc/include/sys/socketcalls.h b/libc/include/sys/socketcalls.h
index 09c079f..131e0bb 100644
--- a/libc/include/sys/socketcalls.h
+++ b/libc/include/sys/socketcalls.h
@@ -48,5 +48,7 @@
#define SYS_SENDMSG 16 /* sys_sendmsg(2) */
#define SYS_RECVMSG 17 /* sys_recvmsg(2) */
#define SYS_ACCEPT4 18 /* sys_accept4(2) */
+#define SYS_RECVMMSG 19 /* sys_recvmmsg(2) */
+#define SYS_SENDMMSG 20 /* sys_sendmmsg(2) */
#endif /* _SYS_SOCKETCALLS_H_ */
diff --git a/libc/upstream-netbsd/lib/libc/stdlib/lsearch.c b/libc/upstream-netbsd/lib/libc/stdlib/lsearch.c
new file mode 100644
index 0000000..e17130b
--- /dev/null
+++ b/libc/upstream-netbsd/lib/libc/stdlib/lsearch.c
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Roger L. Snyder.
+ *
+ * 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. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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 <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)lsearch.c 8.1 (Berkeley) 6/4/93";
+#else
+__RCSID("$NetBSD: lsearch.c,v 1.7 2012/06/25 22:32:45 abs Exp $");
+#endif
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+#include <search.h>
+
+typedef int (*cmp_fn_t)(const void *, const void *);
+static void *linear_base(const void *, void *, size_t *, size_t,
+ cmp_fn_t, int);
+
+void *
+lsearch(const void *key, void *base, size_t *nelp, size_t width,
+ cmp_fn_t compar)
+{
+
+ _DIAGASSERT(key != NULL);
+ _DIAGASSERT(base != NULL);
+ _DIAGASSERT(compar != NULL);
+
+ return(linear_base(key, base, nelp, width, compar, 1));
+}
+
+void *
+lfind(const void *key, const void *base, size_t *nelp, size_t width,
+ cmp_fn_t compar)
+{
+
+ _DIAGASSERT(key != NULL);
+ _DIAGASSERT(base != NULL);
+ _DIAGASSERT(compar != NULL);
+
+ return(linear_base(key, __UNCONST(base), nelp, width, compar, 0));
+}
+
+static void *
+linear_base(const void *key, void *base, size_t *nelp, size_t width,
+ cmp_fn_t compar, int add_flag)
+{
+ char *element, *end;
+
+ _DIAGASSERT(key != NULL);
+ _DIAGASSERT(base != NULL);
+ _DIAGASSERT(compar != NULL);
+
+ end = (char *)base + *nelp * width;
+ for (element = (char *)base; element < end; element += width)
+ if (!compar(element, key)) /* key found */
+ return element;
+
+ if (!add_flag) /* key not found */
+ return(NULL);
+
+ /*
+ * The UNIX System User's Manual, 1986 edition claims that
+ * a NULL pointer is returned by lsearch with errno set
+ * appropriately, if there is not enough room in the table
+ * to add a new item. This can't be done as none of these
+ * routines have any method of determining the size of the
+ * table. This comment isn't in the 1986-87 System V
+ * manual.
+ */
+ ++*nelp;
+ memcpy(end, key, width);
+ return end;
+}
diff --git a/linker/Android.mk b/linker/Android.mk
index c517a30..f0e6c13 100644
--- a/linker/Android.mk
+++ b/linker/Android.mk
@@ -1,6 +1,5 @@
-LOCAL_PATH:= $(call my-dir)
+LOCAL_PATH := $(call my-dir)
-LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
diff --git a/tests/Android.mk b/tests/Android.mk
index 788dbcf..7482ebc 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -82,7 +82,6 @@
system_properties_test.cpp \
time_test.cpp \
unistd_test.cpp \
- accept4_test.cpp \
libBionicStandardTests_cflags := \
$(test_cflags) \
diff --git a/tests/accept4_test.cpp b/tests/accept4_test.cpp
deleted file mode 100644
index 2e6c808..0000000
--- a/tests/accept4_test.cpp
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright (C) 2014 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.
- */
-
-/*
- * Contributed by: Intel Corporation, 2014
- */
-
-#include <gtest/gtest.h>
-
-#if defined(__BIONIC__)
- #define SOCK_CLOEXEC_SUPPORTED 1
-#elif defined(__GLIBC_PREREQ)
- #if __GLIBC_PREREQ(2, 9)
- #define SOCK_CLOEXEC_SUPPORTED 1
- #endif
-#endif
-
-#if defined(SOCK_CLOEXEC_SUPPORTED)
-
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <fcntl.h>
-
-#define SOCK_PATH "test"
-
-static void* ConnectFn(void*) {
- int fd = socket(PF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC | SOCK_NONBLOCK, 0);
- if (fd < 0) {
- GTEST_LOG_(ERROR) << "socket call failed: " << strerror(errno);
- return reinterpret_cast<void*>(-1);
- }
-
- struct sockaddr_un addr;
- memset(&addr, 0, sizeof(addr));
- addr.sun_family = AF_UNIX;
- addr.sun_path[0] = '\0';
- strcpy(addr.sun_path + 1, SOCK_PATH);
-
- if (connect(fd, reinterpret_cast<struct sockaddr*>(&addr), sizeof(addr)) < 0) {
- GTEST_LOG_(ERROR) << "connect call failed: " << strerror(errno);
- close(fd);
- return reinterpret_cast<void*>(-1);
- }
-
- close(fd);
-
- return NULL;
-}
-#endif
-
-TEST(accept4, smoke) {
-#if defined(SOCK_CLOEXEC_SUPPORTED)
- int fd = socket(PF_UNIX, SOCK_SEQPACKET, 0);
- ASSERT_NE(fd, -1) << strerror(errno);
-
- struct sockaddr_un addr;
- memset(&addr, 0, sizeof(addr));
- addr.sun_family = AF_UNIX;
- addr.sun_path[0] = '\0';
- strcpy(addr.sun_path + 1, SOCK_PATH);
-
- ASSERT_NE(-1, bind(fd, reinterpret_cast<struct sockaddr*>(&addr), sizeof(addr))) << strerror(errno);
-
- ASSERT_NE(-1, listen(fd, 1)) << strerror(errno);
-
- pthread_t thread;
- ASSERT_EQ(0, pthread_create(&thread, NULL, ConnectFn, NULL));
-
- fd_set read_set;
- FD_ZERO(&read_set);
- FD_SET(fd, &read_set);
- timeval tv;
- tv.tv_sec = 5;
- tv.tv_usec = 0;
- ASSERT_LT(0, select(fd+1, &read_set, NULL, NULL, &tv));
-
- socklen_t len = sizeof(addr);
- int fd_acc = accept4(fd, reinterpret_cast<struct sockaddr*>(&addr), &len, SOCK_CLOEXEC);
- ASSERT_NE(fd_acc, -1) << strerror(errno);
-
- // Check that the flag was set properly.
- ASSERT_EQ(FD_CLOEXEC, fcntl(fd_acc, F_GETFD) & FD_CLOEXEC);
-
- void* ret_val;
- pthread_join(thread, &ret_val);
- ASSERT_EQ(NULL, ret_val);
-
- close(fd_acc);
- close(fd);
-#else
- GTEST_LOG_(INFO) << "This test does nothing.\n";
-#endif
-}
diff --git a/tests/math_test.cpp b/tests/math_test.cpp
index 80083fa..c1a9f4f 100644
--- a/tests/math_test.cpp
+++ b/tests/math_test.cpp
@@ -1226,6 +1226,11 @@
double di;
double df = modf(123.456, &di);
ASSERT_DOUBLE_EQ(123.0, di);
+ // ASSERT_DOUBLE uses more decimals than the double precision when performing
+ // the comparison which can result in false failures. And it seems that modf
+ // results are not 100% precise as expected but within the acceptable delta.
+ // Work around this by tweaking the expected value (taken) from the result of
+ // glibc modf).
ASSERT_DOUBLE_EQ(0.45600000000000307, df);
}
@@ -1233,6 +1238,7 @@
float fi;
float ff = modff(123.456f, &fi);
ASSERT_FLOAT_EQ(123.0f, fi);
+ // See modf comment on why we don't use 0.456f as an excepted value.
ASSERT_FLOAT_EQ(0.45600128f, ff);
}
@@ -1240,7 +1246,14 @@
long double ldi;
long double ldf = modfl(123.456l, &ldi);
ASSERT_DOUBLE_EQ(123.0l, ldi);
- ASSERT_DOUBLE_EQ(0.45600000000000002l, ldf);
+ // See modf comment on why we don't use 0.456l as an excepted value when the
+ // modf == modfl. For LP64, where long double != double, modfl algorithm
+ // gives precise results and thus we don't need to tweak the expected value.
+#if defined(__LP64__) || !defined(__BIONIC__)
+ ASSERT_DOUBLE_EQ(0.456l, ldf);
+#else
+ ASSERT_DOUBLE_EQ(0.45600000000000307, ldf);
+#endif // __LP64__ || !__BIONIC__
}
TEST(math, remquo) {
diff --git a/tests/sys_socket_test.cpp b/tests/sys_socket_test.cpp
index 901ac17..018889a 100644
--- a/tests/sys_socket_test.cpp
+++ b/tests/sys_socket_test.cpp
@@ -17,18 +17,257 @@
#include <gtest/gtest.h>
#include <errno.h>
+#include <sys/types.h>
#include <sys/socket.h>
+#include <sys/un.h>
+#include <fcntl.h>
-TEST(sys_socket, recvmmsg) {
-#if !defined(__GLIBC__) // TODO: Android's prebuilt gcc is too old for recvmmsg/sendmmsg.
- ASSERT_EQ(-1, recvmmsg(-1, NULL, 0, 0, NULL));
+#if defined(__BIONIC__)
+ #define ACCEPT4_SUPPORTED 1
+ #define RECVMMSG_SUPPORTED 1
+ #define SENDMMSG_SUPPORTED 1
+#elif defined(__GLIBC_PREREQ)
+ #if __GLIBC_PREREQ(2, 9)
+ #define ACCEPT4_SUPPORTED 1
+ #endif
+ #if __GLIBC_PREREQ(2, 12)
+ #define RECVMMSG_SUPPORTED 1
+ #endif
+ #if __GLIBC_PREREQ(2, 14)
+ #define SENDMMSG_SUPPORTED 1
+ #endif
+#endif
+
+#if defined(ACCEPT4_SUPPORTED) || defined(RECVMMSG_SUPPORTED) || defined(SENDMMSG_SUPPORTED)
+
+#define SOCK_PATH "test"
+
+static void* ConnectFn(void* data) {
+ bool (*callback_fn)(int) = reinterpret_cast<bool (*)(int)>(data);
+ void* return_value = NULL;
+
+ int fd = socket(PF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC | SOCK_NONBLOCK, 0);
+ if (fd < 0) {
+ GTEST_LOG_(ERROR) << "socket call failed: " << strerror(errno);
+ return reinterpret_cast<void*>(-1);
+ }
+
+ struct sockaddr_un addr;
+ memset(&addr, 0, sizeof(addr));
+ addr.sun_family = AF_UNIX;
+ addr.sun_path[0] = '\0';
+ strcpy(addr.sun_path + 1, SOCK_PATH);
+
+ if (connect(fd, reinterpret_cast<struct sockaddr*>(&addr), sizeof(addr)) < 0) {
+ GTEST_LOG_(ERROR) << "connect call failed: " << strerror(errno);
+ return_value = reinterpret_cast<void*>(-1);
+ }
+ else if (callback_fn != NULL && !callback_fn(fd)) {
+ return_value = reinterpret_cast<void*>(-1);
+ }
+
+ close(fd);
+
+ return return_value;
+}
+
+static void RunTest(void (*test_fn)(struct sockaddr_un*, int),
+ bool (*callback_fn)(int fd)) {
+ int fd = socket(PF_UNIX, SOCK_SEQPACKET, 0);
+ ASSERT_NE(fd, -1) << strerror(errno);
+
+ struct sockaddr_un addr;
+ memset(&addr, 0, sizeof(addr));
+ addr.sun_family = AF_UNIX;
+ addr.sun_path[0] = '\0';
+ strcpy(addr.sun_path + 1, SOCK_PATH);
+
+ ASSERT_NE(-1, bind(fd, reinterpret_cast<struct sockaddr*>(&addr), sizeof(addr))) << strerror(errno);
+
+ ASSERT_NE(-1, listen(fd, 1)) << strerror(errno);
+
+ pthread_t thread;
+ ASSERT_EQ(0, pthread_create(&thread, NULL, ConnectFn, reinterpret_cast<void*>(callback_fn)));
+
+ fd_set read_set;
+ FD_ZERO(&read_set);
+ FD_SET(fd, &read_set);
+ timeval tv;
+ tv.tv_sec = 5;
+ tv.tv_usec = 0;
+ ASSERT_LT(0, select(fd+1, &read_set, NULL, NULL, &tv));
+
+ test_fn(&addr, fd);
+
+ void* ret_val;
+ ASSERT_EQ(0, pthread_join(thread, &ret_val));
+ ASSERT_EQ(NULL, ret_val);
+
+ close(fd);
+}
+#endif
+
+TEST(sys_socket, accept4_error) {
+#if defined(ACCEPT4_SUPPORTED)
+ ASSERT_EQ(-1, accept4(-1, NULL, NULL, 0));
ASSERT_EQ(EBADF, errno);
+#else
+ GTEST_LOG_(INFO) << "This test does nothing.\n";
#endif
}
-TEST(sys_socket, sendmmsg) {
-#if !defined(__GLIBC__) // TODO: Android's prebuilt gcc is too old for recvmmsg/sendmmsg.
+#if defined(ACCEPT4_SUPPORTED)
+static void TestAccept4(struct sockaddr_un* addr, int fd) {
+ socklen_t len = sizeof(*addr);
+ int fd_acc = accept4(fd, reinterpret_cast<struct sockaddr*>(addr), &len, SOCK_CLOEXEC);
+ ASSERT_NE(fd_acc, -1) << strerror(errno);
+
+ // Check that the flag was set properly.
+ ASSERT_EQ(FD_CLOEXEC, fcntl(fd_acc, F_GETFD) & FD_CLOEXEC);
+
+ close(fd_acc);
+}
+#endif
+
+TEST(sys_socket, accept4_smoke) {
+#if defined(ACCEPT4_SUPPORTED)
+ RunTest(TestAccept4, NULL);
+#else
+ GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif
+}
+
+#if defined(RECVMMSG_SUPPORTED)
+const char* g_RecvMsgs[] = {
+ "RECVMMSG_ONE",
+ "RECVMMSG_TWO",
+ "RECVMMSG_THREE",
+};
+#define NUM_RECV_MSGS (sizeof(g_RecvMsgs)/sizeof(const char*))
+
+static bool SendMultiple(int fd) {
+ for (size_t i = 0; i < NUM_RECV_MSGS; i++) {
+ if (send(fd, g_RecvMsgs[i], strlen(g_RecvMsgs[i]) + 1, 0) < 0) {
+ GTEST_LOG_(ERROR) << "send call failed: " << strerror(errno);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+static void TestRecvMMsg(struct sockaddr_un *addr, int fd) {
+ socklen_t len = sizeof(*addr);
+ int fd_acc = accept(fd, reinterpret_cast<struct sockaddr*>(addr), &len);
+ ASSERT_NE(fd_acc, -1) << strerror(errno);
+
+ struct mmsghdr msgs[NUM_RECV_MSGS];
+ memset(msgs, 0, sizeof(struct mmsghdr)*NUM_RECV_MSGS);
+
+ struct iovec io[NUM_RECV_MSGS];
+ char bufs[NUM_RECV_MSGS][100];
+ for (size_t i = 0; i < NUM_RECV_MSGS; i++) {
+ io[i].iov_base = reinterpret_cast<void*>(bufs[i]);
+ io[i].iov_len = strlen(g_RecvMsgs[i]) + 1;
+
+ msgs[i].msg_hdr.msg_iov = &io[i];
+ msgs[i].msg_hdr.msg_iovlen = 1;
+ msgs[i].msg_len = sizeof(struct msghdr);
+ }
+
+ struct timespec ts;
+ memset(&ts, 0, sizeof(ts));
+ ts.tv_sec = 5;
+ ts.tv_nsec = 0;
+ ASSERT_EQ(NUM_RECV_MSGS, recvmmsg(fd_acc, msgs, NUM_RECV_MSGS, 0, &ts)) << strerror(errno);
+ for (size_t i = 0; i < NUM_RECV_MSGS; i++) {
+ ASSERT_STREQ(g_RecvMsgs[i], bufs[i]);
+ }
+
+ close(fd_acc);
+}
+#endif
+
+TEST(sys_socket, recvmmsg_smoke) {
+#if defined(RECVMMSG_SUPPORTED)
+ RunTest(TestRecvMMsg, SendMultiple);
+#else
+ GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif
+}
+
+TEST(sys_socket, recvmmsg_error) {
+#if defined(RECVMMSG_SUPPORTED)
+ ASSERT_EQ(-1, recvmmsg(-1, NULL, 0, 0, NULL));
+ ASSERT_EQ(EBADF, errno);
+#else
+ GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif
+}
+
+#if defined(SENDMMSG_SUPPORTED)
+const char* g_SendMsgs[] = {
+ "MSG_ONE",
+ "MSG_TWO",
+ "MSG_THREE"
+};
+#define NUM_SEND_MSGS (sizeof(g_SendMsgs)/sizeof(const char*))
+
+static bool SendMMsg(int fd) {
+ struct mmsghdr msgs[NUM_SEND_MSGS];
+ memset(msgs, 0, sizeof(struct mmsghdr)*NUM_SEND_MSGS);
+ struct iovec io[NUM_SEND_MSGS];
+ for (size_t i = 0; i < NUM_SEND_MSGS; i++) {
+ io[i].iov_base = reinterpret_cast<void*>(const_cast<char*>(g_SendMsgs[i]));
+ io[i].iov_len = strlen(g_SendMsgs[i]) + 1;
+ msgs[i].msg_hdr.msg_iov = &io[i];
+ msgs[i].msg_hdr.msg_iovlen = 1;
+ msgs[i].msg_len = sizeof(struct msghdr);
+ }
+
+ if (sendmmsg(fd, msgs, NUM_SEND_MSGS, 0) < 0) {
+ GTEST_LOG_(ERROR) << "sendmmsg call failed: " << strerror(errno);
+ return false;
+ }
+ return true;
+}
+
+static void TestSendMMsg(struct sockaddr_un *addr, int fd) {
+ socklen_t len = sizeof(*addr);
+ int fd_acc = accept(fd, reinterpret_cast<struct sockaddr*>(addr), &len);
+ ASSERT_NE(fd_acc, -1) << strerror(errno);
+
+ fd_set read_set;
+ FD_ZERO(&read_set);
+ FD_SET(fd_acc, &read_set);
+
+ for (size_t i = 0; i < NUM_SEND_MSGS; i++) {
+ timeval tv;
+ tv.tv_sec = 5;
+ tv.tv_usec = 0;
+ ASSERT_LT(0, select(fd_acc+1, &read_set, NULL, NULL, &tv));
+ char buffer[100];
+ ASSERT_EQ(strlen(g_SendMsgs[i]) + 1, recv(fd_acc, buffer, sizeof(buffer), 0));
+ ASSERT_STREQ(g_SendMsgs[i], buffer);
+ }
+
+ close(fd_acc);
+}
+#endif
+
+TEST(sys_socket, sendmmsg_smoke) {
+#if defined(SENDMMSG_SUPPORTED)
+ RunTest(TestSendMMsg, SendMMsg);
+#else
+ GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif
+}
+
+TEST(sys_socket, sendmmsg_error) {
+#if defined(SENDMMSG_SUPPORTED)
ASSERT_EQ(-1, sendmmsg(-1, NULL, 0, 0));
ASSERT_EQ(EBADF, errno);
+#else
+ GTEST_LOG_(INFO) << "This test does nothing.\n";
#endif
}