Merge "Load /etc/{passwd,group} from all partitions"
diff --git a/libc/Android.bp b/libc/Android.bp
index 7b817c6..52a7aca 100644
--- a/libc/Android.bp
+++ b/libc/Android.bp
@@ -273,6 +273,7 @@
"upstream-freebsd/lib/libc/string/wcscat.c",
"upstream-freebsd/lib/libc/string/wcscpy.c",
"upstream-freebsd/lib/libc/string/wmemcmp.c",
+ "upstream-freebsd/lib/libc/string/wmemset.c",
],
},
},
@@ -902,6 +903,7 @@
"arch-x86/generic/string/wcscat.c",
"arch-x86/generic/string/wcscpy.c",
"arch-x86/generic/string/wmemcmp.c",
+ "arch-x86/generic/string/wmemset.c",
"arch-x86/atom/string/sse2-memchr-atom.S",
"arch-x86/atom/string/sse2-memrchr-atom.S",
@@ -950,6 +952,9 @@
"arch-x86/atom/string/ssse3-strcpy-atom.S",
"arch-x86/atom/string/ssse3-strncpy-atom.S",
"arch-x86/atom/string/ssse3-wmemcmp-atom.S",
+
+ // avx2 functions
+ "arch-x86/kabylake/string/avx2-wmemset-kbl.S",
],
exclude_srcs: [
@@ -972,6 +977,7 @@
"arch-x86_64/string/sse4-memcmp-slm.S",
"arch-x86_64/string/ssse3-strcmp-slm.S",
"arch-x86_64/string/ssse3-strncmp-slm.S",
+ "arch-x86_64/string/avx2-wmemset-kbl.S",
"arch-x86_64/bionic/__bionic_clone.S",
"arch-x86_64/bionic/_exit_with_stack_teardown.S",
@@ -1704,6 +1710,19 @@
cmd: "$(location :bionic-generate-version-script) x86_64 $(in) $(out)",
}
+// Makes bionic_tls.h available for art to use in its implementation of Thread::Current().
+cc_library_headers {
+ name: "bionic_libc_private_headers",
+ visibility: [
+ "//art:__subpackages__",
+ ],
+ host_supported: true,
+ export_include_dirs: [
+ "private",
+ ],
+ sdk_version: "current",
+}
+
// libc_headers for libasync_safe and libpropertyinfoparser
cc_library_headers {
name: "libc_headers",
diff --git a/libc/NOTICE b/libc/NOTICE
index ef31733..d9ac638 100644
--- a/libc/NOTICE
+++ b/libc/NOTICE
@@ -1025,6 +1025,22 @@
-------------------------------------------------------------------
Copyright (C) 2019 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.
+
+-------------------------------------------------------------------
+
+Copyright (C) 2019 The Android Open Source Project
All rights reserved.
Redistribution and use in source and binary forms, with or without
@@ -1052,6 +1068,34 @@
-------------------------------------------------------------------
+Copyright (C) 2019 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) 1980, 1983, 1988, 1993
The Regents of the University of California. All rights reserved.
diff --git a/libc/SECCOMP_WHITELIST_COMMON.TXT b/libc/SECCOMP_WHITELIST_COMMON.TXT
index 2faa559..43e7d1c 100644
--- a/libc/SECCOMP_WHITELIST_COMMON.TXT
+++ b/libc/SECCOMP_WHITELIST_COMMON.TXT
@@ -32,6 +32,7 @@
pid_t gettid:gettid() all
int futex:futex(int *uaddr, int futex_op, int val, const struct timespec *timeout, int *uaddr2, int val3) all
int clone:clone(int (*fn)(void *), void *child_stack, int flags, void *arg, ..) all
+int sigreturn:sigreturn(unsigned long __unused) arm,x86,mips
int rt_sigreturn:rt_sigreturn(unsigned long __unused) all
int rt_tgsigqueueinfo:int rt_tgsigqueueinfo(pid_t tgid, pid_t tid, int sig, siginfo_t *uinfo) all
int restart_syscall:int restart_syscall() all
@@ -54,17 +55,14 @@
# Needed for debugging 32-bit Chrome
int pipe:pipe(int pipefd[2]) arm,x86,mips
-# b/34813887
+# Needed by breakpad (b/34813887).
int open:open(const char *path, int oflag, ... ) arm,x86,x86_64,mips
int getdents:getdents(unsigned int fd, struct linux_dirent *dirp, unsigned int count) arm,x86,x86_64,mips
-# syscalls needed to boot android
-int sigreturn:sigreturn(unsigned long __unused) arm,x86,mips
-
-# Needed by sanitizers (b/34606909)
-# 5 (__NR_open) and 195 (__NR_stat64) are also required, but they are
-# already allowed.
-ssize_t readlink:readlink(const char *path, char *buf, size_t bufsiz) arm,x86,x86_64,mips
+# Needed by sanitizers (b/34606909, b/136777266).
+int open:open(const char*, int, ...) arm,x86,x86_64
+int stat64:stat64(const char*, struct stat64*) arm,x86
+ssize_t readlink:readlink(const char*, char*, size_t) arm,x86,x86_64
# Probed for and conditionally used by ART.
int membarrier(int cmd, int flags) all
diff --git a/libc/arch-x86/dynamic_function_dispatch.cpp b/libc/arch-x86/dynamic_function_dispatch.cpp
index 70f4b3e..370b372 100644
--- a/libc/arch-x86/dynamic_function_dispatch.cpp
+++ b/libc/arch-x86/dynamic_function_dispatch.cpp
@@ -107,6 +107,13 @@
RETURN_FUNC(wmemcmp_func, wmemcmp_freebsd);
}
+typedef int wmemset_func(const wchar_t* __lhs, const wchar_t* __rhs, size_t __n);
+DEFINE_IFUNC_FOR(wmemset) {
+ __builtin_cpu_init();
+ if (__builtin_cpu_supports("avx2")) RETURN_FUNC(wmemset_func, wmemset_avx2);
+ RETURN_FUNC(wmemset_func, wmemset_freebsd);
+}
+
typedef int strcmp_func(const char* __lhs, const char* __rhs);
DEFINE_IFUNC_FOR(strcmp) {
__builtin_cpu_init();
diff --git a/libc/arch-x86/generic/string/wmemset.c b/libc/arch-x86/generic/string/wmemset.c
new file mode 100644
index 0000000..eff533c
--- /dev/null
+++ b/libc/arch-x86/generic/string/wmemset.c
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2019 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.
+*/
+
+#define wmemset wmemset_freebsd
+
+#include <upstream-freebsd/lib/libc/string/wmemset.c>
diff --git a/libc/arch-x86/kabylake/string/avx2-wmemset-kbl.S b/libc/arch-x86/kabylake/string/avx2-wmemset-kbl.S
new file mode 100644
index 0000000..69b66c7
--- /dev/null
+++ b/libc/arch-x86/kabylake/string/avx2-wmemset-kbl.S
@@ -0,0 +1,148 @@
+/*
+Copyright (C) 2019 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>
+
+#ifndef WMEMSET
+ #define WMEMSET wmemset_avx2
+#endif
+
+ENTRY(WMEMSET)
+# BB#0:
+ pushl %ebp
+ pushl %ebx
+ pushl %edi
+ pushl %esi
+ pushl %eax
+ movl 32(%esp), %ecx
+ movl 24(%esp), %eax
+ testl %ecx, %ecx
+ je .LBB0_12
+# BB#1:
+ movl 28(%esp), %edx
+ xorl %edi, %edi
+ movl %eax, %esi
+ cmpl $32, %ecx
+ jb .LBB0_10
+# BB#2:
+ movl %ecx, %eax
+ andl $-32, %eax
+ vmovd %edx, %xmm0
+ vpbroadcastd %xmm0, %ymm0
+ movl %eax, (%esp) # 4-byte Spill
+ leal -32(%eax), %esi
+ movl %esi, %eax
+ shrl $5, %eax
+ leal 1(%eax), %edi
+ andl $7, %edi
+ xorl %ebx, %ebx
+ cmpl $224, %esi
+ jb .LBB0_5
+# BB#3:
+ movl 24(%esp), %esi
+ leal 992(%esi), %ebp
+ leal -1(%edi), %esi
+ subl %eax, %esi
+ xorl %ebx, %ebx
+ .p2align 4, 0x90
+.LBB0_4: # =>This Inner Loop Header: Depth=1
+ vmovdqu %ymm0, -992(%ebp,%ebx,4)
+ vmovdqu %ymm0, -960(%ebp,%ebx,4)
+ vmovdqu %ymm0, -928(%ebp,%ebx,4)
+ vmovdqu %ymm0, -896(%ebp,%ebx,4)
+ vmovdqu %ymm0, -864(%ebp,%ebx,4)
+ vmovdqu %ymm0, -832(%ebp,%ebx,4)
+ vmovdqu %ymm0, -800(%ebp,%ebx,4)
+ vmovdqu %ymm0, -768(%ebp,%ebx,4)
+ vmovdqu %ymm0, -736(%ebp,%ebx,4)
+ vmovdqu %ymm0, -704(%ebp,%ebx,4)
+ vmovdqu %ymm0, -672(%ebp,%ebx,4)
+ vmovdqu %ymm0, -640(%ebp,%ebx,4)
+ vmovdqu %ymm0, -608(%ebp,%ebx,4)
+ vmovdqu %ymm0, -576(%ebp,%ebx,4)
+ vmovdqu %ymm0, -544(%ebp,%ebx,4)
+ vmovdqu %ymm0, -512(%ebp,%ebx,4)
+ vmovdqu %ymm0, -480(%ebp,%ebx,4)
+ vmovdqu %ymm0, -448(%ebp,%ebx,4)
+ vmovdqu %ymm0, -416(%ebp,%ebx,4)
+ vmovdqu %ymm0, -384(%ebp,%ebx,4)
+ vmovdqu %ymm0, -352(%ebp,%ebx,4)
+ vmovdqu %ymm0, -320(%ebp,%ebx,4)
+ vmovdqu %ymm0, -288(%ebp,%ebx,4)
+ vmovdqu %ymm0, -256(%ebp,%ebx,4)
+ vmovdqu %ymm0, -224(%ebp,%ebx,4)
+ vmovdqu %ymm0, -192(%ebp,%ebx,4)
+ vmovdqu %ymm0, -160(%ebp,%ebx,4)
+ vmovdqu %ymm0, -128(%ebp,%ebx,4)
+ vmovdqu %ymm0, -96(%ebp,%ebx,4)
+ vmovdqu %ymm0, -64(%ebp,%ebx,4)
+ vmovdqu %ymm0, -32(%ebp,%ebx,4)
+ vmovdqu %ymm0, (%ebp,%ebx,4)
+ addl $256, %ebx # imm = 0x100
+ addl $8, %esi
+ jne .LBB0_4
+.LBB0_5:
+ testl %edi, %edi
+ movl 24(%esp), %eax
+ je .LBB0_8
+# BB#6:
+ leal (%eax,%ebx,4), %esi
+ addl $96, %esi
+ negl %edi
+ .p2align 4, 0x90
+.LBB0_7: # =>This Inner Loop Header: Depth=1
+ vmovdqu %ymm0, -96(%esi)
+ vmovdqu %ymm0, -64(%esi)
+ vmovdqu %ymm0, -32(%esi)
+ vmovdqu %ymm0, (%esi)
+ subl $-128, %esi
+ addl $1, %edi
+ jne .LBB0_7
+.LBB0_8:
+ movl (%esp), %edi # 4-byte Reload
+ cmpl %ecx, %edi
+ je .LBB0_12
+# BB#9:
+ leal (%eax,%edi,4), %esi
+.LBB0_10:
+ subl %edi, %ecx
+ .p2align 4, 0x90
+.LBB0_11: # =>This Inner Loop Header: Depth=1
+ movl %edx, (%esi)
+ addl $4, %esi
+ addl $-1, %ecx
+ jne .LBB0_11
+.LBB0_12:
+ addl $4, %esp
+ popl %esi
+ popl %edi
+ popl %ebx
+ popl %ebp
+ vzeroupper
+ retl
+END(WMEMSET)
diff --git a/libc/arch-x86/static_function_dispatch.S b/libc/arch-x86/static_function_dispatch.S
index 7e8e63d..1560c04 100644
--- a/libc/arch-x86/static_function_dispatch.S
+++ b/libc/arch-x86/static_function_dispatch.S
@@ -45,6 +45,7 @@
FUNCTION_DELEGATE(strncmp, strncmp_generic)
FUNCTION_DELEGATE(strcat, strcat_generic)
FUNCTION_DELEGATE(wmemcmp, wmemcmp_freebsd)
+FUNCTION_DELEGATE(wmemset, wmemset_freebsd)
FUNCTION_DELEGATE(wcscat, wcscat_freebsd)
FUNCTION_DELEGATE(strncat, strncat_openbsd)
FUNCTION_DELEGATE(strlcat, strlcat_openbsd)
diff --git a/libc/arch-x86_64/string/avx2-wmemset-kbl.S b/libc/arch-x86_64/string/avx2-wmemset-kbl.S
new file mode 100644
index 0000000..7c485cf
--- /dev/null
+++ b/libc/arch-x86_64/string/avx2-wmemset-kbl.S
@@ -0,0 +1,140 @@
+/*
+Copyright (C) 2019 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>
+
+#ifndef WMEMSET
+ #define WMEMSET wmemset_avx2
+#endif
+
+ .section .text.avx2,"ax",@progbits
+
+ENTRY (WMEMSET)
+# BB#0:
+ testq %rdx, %rdx
+ je .LBB0_14
+# BB#1:
+ cmpq $32, %rdx
+ jae .LBB0_3
+# BB#2:
+ xorl %r8d, %r8d
+ movq %rdi, %rax
+ jmp .LBB0_12
+.LBB0_3:
+ movq %rdx, %r8
+ andq $-32, %r8
+ vmovd %esi, %xmm0
+ vpbroadcastd %xmm0, %ymm0
+ leaq -32(%r8), %rcx
+ movq %rcx, %rax
+ shrq $5, %rax
+ leal 1(%rax), %r9d
+ andl $7, %r9d
+ cmpq $224, %rcx
+ jae .LBB0_5
+# BB#4:
+ xorl %eax, %eax
+ testq %r9, %r9
+ jne .LBB0_8
+ jmp .LBB0_10
+.LBB0_5:
+ leaq 992(%rdi), %rcx
+ leaq -1(%r9), %r10
+ subq %rax, %r10
+ xorl %eax, %eax
+ .p2align 4, 0x90
+.LBB0_6: # =>This Inner Loop Header: Depth=1
+ vmovdqu %ymm0, -992(%rcx,%rax,4)
+ vmovdqu %ymm0, -960(%rcx,%rax,4)
+ vmovdqu %ymm0, -928(%rcx,%rax,4)
+ vmovdqu %ymm0, -896(%rcx,%rax,4)
+ vmovdqu %ymm0, -864(%rcx,%rax,4)
+ vmovdqu %ymm0, -832(%rcx,%rax,4)
+ vmovdqu %ymm0, -800(%rcx,%rax,4)
+ vmovdqu %ymm0, -768(%rcx,%rax,4)
+ vmovdqu %ymm0, -736(%rcx,%rax,4)
+ vmovdqu %ymm0, -704(%rcx,%rax,4)
+ vmovdqu %ymm0, -672(%rcx,%rax,4)
+ vmovdqu %ymm0, -640(%rcx,%rax,4)
+ vmovdqu %ymm0, -608(%rcx,%rax,4)
+ vmovdqu %ymm0, -576(%rcx,%rax,4)
+ vmovdqu %ymm0, -544(%rcx,%rax,4)
+ vmovdqu %ymm0, -512(%rcx,%rax,4)
+ vmovdqu %ymm0, -480(%rcx,%rax,4)
+ vmovdqu %ymm0, -448(%rcx,%rax,4)
+ vmovdqu %ymm0, -416(%rcx,%rax,4)
+ vmovdqu %ymm0, -384(%rcx,%rax,4)
+ vmovdqu %ymm0, -352(%rcx,%rax,4)
+ vmovdqu %ymm0, -320(%rcx,%rax,4)
+ vmovdqu %ymm0, -288(%rcx,%rax,4)
+ vmovdqu %ymm0, -256(%rcx,%rax,4)
+ vmovdqu %ymm0, -224(%rcx,%rax,4)
+ vmovdqu %ymm0, -192(%rcx,%rax,4)
+ vmovdqu %ymm0, -160(%rcx,%rax,4)
+ vmovdqu %ymm0, -128(%rcx,%rax,4)
+ vmovdqu %ymm0, -96(%rcx,%rax,4)
+ vmovdqu %ymm0, -64(%rcx,%rax,4)
+ vmovdqu %ymm0, -32(%rcx,%rax,4)
+ vmovdqu %ymm0, (%rcx,%rax,4)
+ addq $256, %rax # imm = 0x100
+ addq $8, %r10
+ jne .LBB0_6
+# BB#7:
+ testq %r9, %r9
+ je .LBB0_10
+.LBB0_8:
+ leaq (%rdi,%rax,4), %rax
+ addq $96, %rax
+ negq %r9
+ .p2align 4, 0x90
+.LBB0_9: # =>This Inner Loop Header: Depth=1
+ vmovdqu %ymm0, -96(%rax)
+ vmovdqu %ymm0, -64(%rax)
+ vmovdqu %ymm0, -32(%rax)
+ vmovdqu %ymm0, (%rax)
+ subq $-128, %rax
+ addq $1, %r9
+ jne .LBB0_9
+.LBB0_10:
+ cmpq %rdx, %r8
+ je .LBB0_14
+# BB#11:
+ leaq (%rdi,%r8,4), %rax
+.LBB0_12:
+ subq %r8, %rdx
+ .p2align 4, 0x90
+.LBB0_13: # =>This Inner Loop Header: Depth=1
+ movl %esi, (%rax)
+ addq $4, %rax
+ addq $-1, %rdx
+ jne .LBB0_13
+.LBB0_14:
+ movq %rdi, %rax
+ vzeroupper
+ retq
+END(WMEMSET)
diff --git a/libc/bionic/bionic_systrace.cpp b/libc/bionic/bionic_systrace.cpp
index 6182ed8..1140d2d 100644
--- a/libc/bionic/bionic_systrace.cpp
+++ b/libc/bionic/bionic_systrace.cpp
@@ -24,6 +24,7 @@
#include "private/bionic_systrace.h"
#include "private/CachedProperty.h"
+#include <async_safe/log.h>
#include <cutils/trace.h> // For ATRACE_TAG_BIONIC.
#define WRITE_OFFSET 32
@@ -65,7 +66,7 @@
// kernel trace_marker.
int length = strlen(message);
char buf[length + WRITE_OFFSET];
- size_t len = snprintf(buf, length + WRITE_OFFSET, "B|%d|%s", getpid(), message);
+ size_t len = async_safe_format_buffer(buf, length + WRITE_OFFSET, "B|%d|%s", getpid(), message);
// Tracing may stop just after checking property and before writing the message.
// So the write is acceptable to fail. See b/20666100.
diff --git a/libc/bionic/pthread_cond.cpp b/libc/bionic/pthread_cond.cpp
index 9f0f8fa..e857069 100644
--- a/libc/bionic/pthread_cond.cpp
+++ b/libc/bionic/pthread_cond.cpp
@@ -215,6 +215,18 @@
return __pthread_cond_timedwait(__get_internal_cond(cond_interface), mutex, false, abs_timeout);
}
+int pthread_cond_clockwait(pthread_cond_t* cond_interface, pthread_mutex_t* mutex, clockid_t clock,
+ const struct timespec* abs_timeout) {
+ switch (clock) {
+ case CLOCK_MONOTONIC:
+ return pthread_cond_timedwait_monotonic_np(cond_interface, mutex, abs_timeout);
+ case CLOCK_REALTIME:
+ return __pthread_cond_timedwait(__get_internal_cond(cond_interface), mutex, true, abs_timeout);
+ default:
+ return EINVAL;
+ }
+}
+
#if !defined(__LP64__)
// TODO: this exists only for backward binary compatibility on 32 bit platforms.
extern "C" int pthread_cond_timedwait_monotonic(pthread_cond_t* cond_interface,
diff --git a/libc/bionic/pthread_mutex.cpp b/libc/bionic/pthread_mutex.cpp
index 37031ad..de62a5c 100644
--- a/libc/bionic/pthread_mutex.cpp
+++ b/libc/bionic/pthread_mutex.cpp
@@ -989,6 +989,24 @@
return __pthread_mutex_timedlock(mutex_interface, false, abs_timeout, __FUNCTION__);
}
+int pthread_mutex_clocklock(pthread_mutex_t* mutex_interface, clockid_t clock,
+ const struct timespec* abs_timeout) {
+ switch (clock) {
+ case CLOCK_MONOTONIC:
+ return __pthread_mutex_timedlock(mutex_interface, false, abs_timeout, __FUNCTION__);
+ case CLOCK_REALTIME:
+ return __pthread_mutex_timedlock(mutex_interface, true, abs_timeout, __FUNCTION__);
+ default: {
+ pthread_mutex_internal_t* mutex = __get_internal_mutex(mutex_interface);
+ uint16_t old_state = atomic_load_explicit(&mutex->state, memory_order_relaxed);
+ if (IsMutexDestroyed(old_state)) {
+ return HandleUsingDestroyedMutex(mutex_interface, __FUNCTION__);
+ }
+ return EINVAL;
+ }
+ }
+}
+
int pthread_mutex_destroy(pthread_mutex_t* mutex_interface) {
pthread_mutex_internal_t* mutex = __get_internal_mutex(mutex_interface);
uint16_t old_state = atomic_load_explicit(&mutex->state, memory_order_relaxed);
diff --git a/libc/bionic/pthread_rwlock.cpp b/libc/bionic/pthread_rwlock.cpp
index 2b9be98..ebf6697 100644
--- a/libc/bionic/pthread_rwlock.cpp
+++ b/libc/bionic/pthread_rwlock.cpp
@@ -429,6 +429,18 @@
return __pthread_rwlock_timedrdlock(rwlock, false, abs_timeout);
}
+int pthread_rwlock_clockrdlock(pthread_rwlock_t* rwlock_interface, clockid_t clock,
+ const struct timespec* abs_timeout) {
+ switch (clock) {
+ case CLOCK_MONOTONIC:
+ return pthread_rwlock_timedrdlock_monotonic_np(rwlock_interface, abs_timeout);
+ case CLOCK_REALTIME:
+ return pthread_rwlock_timedrdlock(rwlock_interface, abs_timeout);
+ default:
+ return EINVAL;
+ }
+}
+
int pthread_rwlock_tryrdlock(pthread_rwlock_t* rwlock_interface) {
return __pthread_rwlock_tryrdlock(__get_internal_rwlock(rwlock_interface));
}
@@ -455,6 +467,18 @@
return __pthread_rwlock_timedwrlock(rwlock, false, abs_timeout);
}
+int pthread_rwlock_clockwrlock(pthread_rwlock_t* rwlock_interface, clockid_t clock,
+ const struct timespec* abs_timeout) {
+ switch (clock) {
+ case CLOCK_MONOTONIC:
+ return pthread_rwlock_timedwrlock_monotonic_np(rwlock_interface, abs_timeout);
+ case CLOCK_REALTIME:
+ return pthread_rwlock_timedwrlock(rwlock_interface, abs_timeout);
+ default:
+ return EINVAL;
+ }
+}
+
int pthread_rwlock_trywrlock(pthread_rwlock_t* rwlock_interface) {
return __pthread_rwlock_trywrlock(__get_internal_rwlock(rwlock_interface));
}
diff --git a/libc/bionic/semaphore.cpp b/libc/bionic/semaphore.cpp
index e0486b4..455e36b 100644
--- a/libc/bionic/semaphore.cpp
+++ b/libc/bionic/semaphore.cpp
@@ -275,6 +275,17 @@
return __sem_timedwait(sem, abs_timeout, false);
}
+int sem_clockwait(sem_t* sem, clockid_t clock, const timespec* abs_timeout) {
+ switch (clock) {
+ case CLOCK_MONOTONIC:
+ return sem_timedwait_monotonic_np(sem, abs_timeout);
+ case CLOCK_REALTIME:
+ return sem_timedwait(sem, abs_timeout);
+ default:
+ return EINVAL;
+ }
+}
+
int sem_post(sem_t* sem) {
atomic_uint* sem_count_ptr = SEM_TO_ATOMIC_POINTER(sem);
unsigned int shared = SEM_GET_SHARED(sem_count_ptr);
diff --git a/libc/include/pthread.h b/libc/include/pthread.h
index 724e5b7..31509b4 100644
--- a/libc/include/pthread.h
+++ b/libc/include/pthread.h
@@ -121,6 +121,8 @@
int pthread_condattr_setpshared(pthread_condattr_t* __attr, int __shared);
int pthread_cond_broadcast(pthread_cond_t* __cond);
+int pthread_cond_clockwait(pthread_cond_t* __cond, pthread_mutex_t* __mutex, clockid_t __clock,
+ const struct timespec* __timeout) __INTRODUCED_IN(30);
int pthread_cond_destroy(pthread_cond_t* __cond);
int pthread_cond_init(pthread_cond_t* __cond, const pthread_condattr_t* __attr);
int pthread_cond_signal(pthread_cond_t* __cond);
@@ -130,8 +132,10 @@
* typically inappropriate, since that clock can change dramatically, causing the timeout to
* either expire earlier or much later than intended.
* Condition variables have an initialization option to use CLOCK_MONOTONIC, and in addition,
- * Android provides this API to use CLOCK_MONOTONIC on a condition variable for this single wait
- * no matter how it was initialized.
+ * Android provides pthread_cond_timedwait_monotonic_np to use CLOCK_MONOTONIC on a condition
+ * variable for this single wait no matter how it was initialized.
+ * Note that pthread_cond_clockwait() allows specifying an arbitrary clock and has superseded this
+ * function.
*/
int pthread_cond_timedwait_monotonic_np(pthread_cond_t* __cond, pthread_mutex_t* __mutex,
const struct timespec* __timeout) __INTRODUCED_IN_64(28);
@@ -181,6 +185,8 @@
int pthread_mutexattr_settype(pthread_mutexattr_t* __attr, int __type);
int pthread_mutexattr_setprotocol(pthread_mutexattr_t* __attr, int __protocol) __INTRODUCED_IN(28);
+int pthread_mutex_clocklock(pthread_mutex_t* __mutex, clockid_t __clock,
+ const struct timespec* __abstime) __INTRODUCED_IN(30);
int pthread_mutex_destroy(pthread_mutex_t* __mutex);
int pthread_mutex_init(pthread_mutex_t* __mutex, const pthread_mutexattr_t* __attr);
int pthread_mutex_lock(pthread_mutex_t* __mutex);
@@ -188,11 +194,13 @@
__INTRODUCED_IN(21);
/*
- * POSIX only supports using pthread_mutex_timedlock() with CLOCK_REALTIME, however that is
- * typically inappropriate, since that clock can change dramatically, causing the timeout to
+ * POSIX historically only supported using pthread_mutex_timedlock() with CLOCK_REALTIME, however
+ * that is typically inappropriate, since that clock can change dramatically, causing the timeout to
* either expire earlier or much later than intended.
* This function is added to use a timespec based on CLOCK_MONOTONIC that does not suffer
* from this issue.
+ * Note that pthread_mutex_clocklock() allows specifying an arbitrary clock and has superseded this
+ * function.
*/
int pthread_mutex_timedlock_monotonic_np(pthread_mutex_t* __mutex, const struct timespec* __timeout)
__INTRODUCED_IN(28);
@@ -226,6 +234,10 @@
__INTRODUCED_IN(23);
int pthread_rwlockattr_setkind_np(pthread_rwlockattr_t* __attr, int __kind) __INTRODUCED_IN(23);
+int pthread_rwlock_clockrdlock(pthread_rwlock_t* __rwlock, clockid_t __clock,
+ const struct timespec* __timeout) __INTRODUCED_IN(30);
+int pthread_rwlock_clockwrlock(pthread_rwlock_t* __rwlock, clockid_t __clock,
+ const struct timespec* __timeout) __INTRODUCED_IN(30);
int pthread_rwlock_destroy(pthread_rwlock_t* __rwlock);
int pthread_rwlock_init(pthread_rwlock_t* __rwlock, const pthread_rwlockattr_t* __attr);
int pthread_rwlock_rdlock(pthread_rwlock_t* __rwlock);
diff --git a/libc/include/semaphore.h b/libc/include/semaphore.h
index 01d685b..5d66f7e 100644
--- a/libc/include/semaphore.h
+++ b/libc/include/semaphore.h
@@ -30,6 +30,7 @@
#define _SEMAPHORE_H
#include <sys/cdefs.h>
+#include <sys/types.h>
__BEGIN_DECLS
@@ -44,16 +45,19 @@
#define SEM_FAILED __BIONIC_CAST(reinterpret_cast, sem_t*, 0)
+int sem_clockwait(sem_t* __sem, clockid_t __clock, const struct timespec* __ts) __INTRODUCED_IN(30);
int sem_destroy(sem_t* __sem);
int sem_getvalue(sem_t* __sem, int* __value);
int sem_init(sem_t* __sem, int __shared, unsigned int __value);
int sem_post(sem_t* __sem);
int sem_timedwait(sem_t* __sem, const struct timespec* __ts);
/*
- * POSIX only supports using sem_timedwait() with CLOCK_REALTIME, however that is typically
- * inappropriate, since that clock can change dramatically, causing the timeout to either
+ * POSIX historically only supported using sem_timedwait() with CLOCK_REALTIME, however that is
+ * typically inappropriate, since that clock can change dramatically, causing the timeout to either
* expire earlier or much later than intended. This function is added to use a timespec based
* on CLOCK_MONOTONIC that does not suffer from this issue.
+ * Note that sem_clockwait() allows specifying an arbitrary clock and has superseded this
+ * function.
*/
int sem_timedwait_monotonic_np(sem_t* __sem, const struct timespec* __ts) __INTRODUCED_IN(28);
int sem_trywait(sem_t* __sem);
diff --git a/libc/libc.map.txt b/libc/libc.map.txt
index 3c23da2..0bcf761 100644
--- a/libc/libc.map.txt
+++ b/libc/libc.map.txt
@@ -1498,6 +1498,11 @@
mtx_timedlock;
mtx_trylock;
mtx_unlock;
+ pthread_cond_clockwait;
+ pthread_mutex_clocklock;
+ pthread_rwlock_clockrdlock;
+ pthread_rwlock_clockwrlock;
+ sem_clockwait;
thrd_create;
thrd_current;
thrd_detach;
diff --git a/libc/malloc_debug/Android.bp b/libc/malloc_debug/Android.bp
index aae16f1..d6b8531 100644
--- a/libc/malloc_debug/Android.bp
+++ b/libc/malloc_debug/Android.bp
@@ -16,7 +16,6 @@
whole_static_libs: [
"libbase",
"libasync_safe",
- "libdemangle",
],
include_dirs: ["bionic/libc"],
@@ -66,7 +65,6 @@
static_libs: [
"libasync_safe",
"libbase",
- "libdemangle",
"libc_malloc_debug_backtrace",
],
@@ -122,7 +120,6 @@
static_libs: [
"libc_malloc_debug",
- "libdemangle",
"libtinyxml2",
],
diff --git a/libc/malloc_debug/PointerData.cpp b/libc/malloc_debug/PointerData.cpp
index 617d128..ec7e42d 100644
--- a/libc/malloc_debug/PointerData.cpp
+++ b/libc/malloc_debug/PointerData.cpp
@@ -43,7 +43,6 @@
#include <android-base/stringprintf.h>
#include <android-base/thread_annotations.h>
-#include <demangle.h>
#include <private/bionic_macros.h>
#include "Config.h"
@@ -54,6 +53,8 @@
#include "malloc_debug.h"
#include "UnwindBacktrace.h"
+extern "C" char* __cxa_demangle(const char*, char*, size_t*, int*);
+
std::atomic_uint8_t PointerData::backtrace_enabled_;
std::atomic_bool PointerData::backtrace_dump_;
@@ -596,7 +597,16 @@
if (frame.function_name.empty()) {
fprintf(fp, " \"\" 0}");
} else {
- fprintf(fp, " \"%s\" %" PRIx64 "}", demangle(frame.function_name.c_str()).c_str(), frame.function_offset);
+ char* demangled_name = __cxa_demangle(frame.function_name.c_str(), nullptr, nullptr,
+ nullptr);
+ const char* name;
+ if (demangled_name != nullptr) {
+ name = demangled_name;
+ } else {
+ name = frame.function_name.c_str();
+ }
+ fprintf(fp, " \"%s\" %" PRIx64 "}", name, frame.function_offset);
+ free(demangled_name);
}
}
fprintf(fp, "\n");
diff --git a/libc/malloc_debug/UnwindBacktrace.cpp b/libc/malloc_debug/UnwindBacktrace.cpp
index ddafc73..92fb3fa 100644
--- a/libc/malloc_debug/UnwindBacktrace.cpp
+++ b/libc/malloc_debug/UnwindBacktrace.cpp
@@ -36,7 +36,6 @@
#include <vector>
#include <android-base/stringprintf.h>
-#include <demangle.h>
#include <unwindstack/LocalUnwinder.h>
#include <unwindstack/MapInfo.h>
@@ -49,6 +48,8 @@
#define PAD_PTR "08" PRIx64
#endif
+extern "C" char* __cxa_demangle(const char*, char*, size_t*, int*);
+
static pthread_once_t g_setup_once = PTHREAD_ONCE_INIT;
static unwindstack::LocalUnwinder* g_unwinder;
@@ -100,7 +101,14 @@
}
if (!info->function_name.empty()) {
- line += " (" + demangle(info->function_name.c_str());
+ line += " (";
+ char* demangled_name = __cxa_demangle(info->function_name.c_str(), nullptr, nullptr, nullptr);
+ if (demangled_name != nullptr) {
+ line += demangled_name;
+ free(demangled_name);
+ } else {
+ line += info->function_name;
+ }
if (info->function_offset != 0) {
line += "+" + std::to_string(info->function_offset);
}
diff --git a/libc/malloc_debug/backtrace.cpp b/libc/malloc_debug/backtrace.cpp
index 0e3a53f..ab5c505 100644
--- a/libc/malloc_debug/backtrace.cpp
+++ b/libc/malloc_debug/backtrace.cpp
@@ -36,8 +36,6 @@
#include <unistd.h>
#include <unwind.h>
-#include <demangle.h>
-
#include "MapData.h"
#include "backtrace.h"
#include "debug_log.h"
@@ -164,10 +162,18 @@
char buf[1024];
if (symbol != nullptr) {
+ char* demangled_name = __cxa_demangle(symbol, nullptr, nullptr, nullptr);
+ const char* name;
+ if (demangled_name != nullptr) {
+ name = demangled_name;
+ } else {
+ name = symbol;
+ }
async_safe_format_buffer(buf, sizeof(buf),
" #%02zd pc %" PAD_PTR " %s%s (%s+%" PRIuPTR ")\n",
- frame_num, rel_pc, soname, offset_buf, demangle(symbol).c_str(),
+ frame_num, rel_pc, soname, offset_buf, name,
frames[frame_num] - offset);
+ free(demangled_name);
} else {
async_safe_format_buffer(buf, sizeof(buf), " #%02zd pc %" PAD_PTR " %s%s\n",
frame_num, rel_pc, soname, offset_buf);
diff --git a/libc/private/WriteProtected.h b/libc/private/WriteProtected.h
index 69a6822..d240e14 100644
--- a/libc/private/WriteProtected.h
+++ b/libc/private/WriteProtected.h
@@ -46,6 +46,16 @@
WriteProtectedContents<T> contents;
+ int set_protection(int prot) {
+ auto addr = reinterpret_cast<uintptr_t>(&contents);
+#if __has_feature(hwaddress_sanitizer)
+ // The mprotect system call does not currently untag pointers, so do it
+ // ourselves.
+ addr &= (1ULL << 56) - 1;
+#endif
+ return mprotect(reinterpret_cast<void*>(addr), PAGE_SIZE, prot);
+ }
+
public:
WriteProtected() = default;
BIONIC_DISALLOW_COPY_AND_ASSIGN(WriteProtected);
@@ -55,7 +65,7 @@
// multiple times by accident.
memset(&contents, 0, sizeof(contents));
- if (mprotect(&contents, PAGE_SIZE, PROT_READ)) {
+ if (set_protection(PROT_READ)) {
async_safe_fatal("failed to make WriteProtected nonwritable in initialize");
}
}
@@ -70,12 +80,12 @@
template <typename Mutator>
void mutate(Mutator mutator) {
- if (mprotect(&contents, PAGE_SIZE, PROT_READ | PROT_WRITE) != 0) {
+ if (set_protection(PROT_READ | PROT_WRITE) != 0) {
async_safe_fatal("failed to make WriteProtected writable in mutate: %s",
strerror(errno));
}
mutator(&contents.value);
- if (mprotect(&contents, PAGE_SIZE, PROT_READ) != 0) {
+ if (set_protection(PROT_READ) != 0) {
async_safe_fatal("failed to make WriteProtected nonwritable in mutate: %s",
strerror(errno));
}
diff --git a/libdl/libdl_cfi.cpp b/libdl/libdl_cfi.cpp
index 1dd5b21..1446143 100644
--- a/libdl/libdl_cfi.cpp
+++ b/libdl/libdl_cfi.cpp
@@ -45,6 +45,10 @@
static uint16_t shadow_load(void* p) {
uintptr_t addr = reinterpret_cast<uintptr_t>(p);
+#ifdef __aarch64__
+ // Untag the pointer to move it into the address space covered by the shadow.
+ addr &= (1ULL << 56) - 1;
+#endif
uintptr_t ofs = CFIShadow::MemToShadowOffset(addr);
if (ofs > CFIShadow::kShadowSize) return CFIShadow::kInvalidShadow;
return *reinterpret_cast<uint16_t*>(shadow_base_storage.v + ofs);
diff --git a/libm/Android.bp b/libm/Android.bp
index 6d17e86..59466e4 100644
--- a/libm/Android.bp
+++ b/libm/Android.bp
@@ -324,8 +324,16 @@
x86: {
srcs: [
"i387/fenv.c",
+ "x86/ceil.S",
+ "x86/ceilf.S",
+ "x86/floor.S",
+ "x86/floorf.S",
+ "x86/rint.S",
+ "x86/rintf.S",
"x86/sqrt.S",
"x86/sqrtf.S",
+ "x86/trunc.S",
+ "x86/truncf.S",
"x86/e_acos.S",
"x86/e_asin.S",
"x86/e_atan2.S",
@@ -359,37 +367,23 @@
"upstream-freebsd/lib/msun/src/e_sqrtf.c",
"upstream-freebsd/lib/msun/src/s_atan.c",
"upstream-freebsd/lib/msun/src/s_cbrt.c",
+ "upstream-freebsd/lib/msun/src/s_ceil.c",
+ "upstream-freebsd/lib/msun/src/s_ceilf.c",
"upstream-freebsd/lib/msun/src/s_cos.c",
"upstream-freebsd/lib/msun/src/s_expm1.c",
+ "upstream-freebsd/lib/msun/src/s_floor.c",
+ "upstream-freebsd/lib/msun/src/s_floorf.c",
"upstream-freebsd/lib/msun/src/s_log1p.c",
"upstream-freebsd/lib/msun/src/s_lrint.c",
"upstream-freebsd/lib/msun/src/s_lrintf.c",
+ "upstream-freebsd/lib/msun/src/s_rint.c",
+ "upstream-freebsd/lib/msun/src/s_rintf.c",
"upstream-freebsd/lib/msun/src/s_sin.c",
"upstream-freebsd/lib/msun/src/s_tan.c",
"upstream-freebsd/lib/msun/src/s_tanh.c",
+ "upstream-freebsd/lib/msun/src/s_trunc.c",
+ "upstream-freebsd/lib/msun/src/s_truncf.c",
],
- sse4_1: {
- srcs: [
- "x86/ceil.S",
- "x86/ceilf.S",
- "x86/floor.S",
- "x86/floorf.S",
- "x86/rint.S",
- "x86/rintf.S",
- "x86/trunc.S",
- "x86/truncf.S",
- ],
- exclude_srcs: [
- "upstream-freebsd/lib/msun/src/s_ceil.c",
- "upstream-freebsd/lib/msun/src/s_ceilf.c",
- "upstream-freebsd/lib/msun/src/s_floor.c",
- "upstream-freebsd/lib/msun/src/s_floorf.c",
- "upstream-freebsd/lib/msun/src/s_rint.c",
- "upstream-freebsd/lib/msun/src/s_rintf.c",
- "upstream-freebsd/lib/msun/src/s_trunc.c",
- "upstream-freebsd/lib/msun/src/s_truncf.c",
- ],
- },
local_include_dirs: ["i387"],
pack_relocations: false,
ldflags: ["-Wl,--hash-style=both"],
@@ -399,8 +393,16 @@
x86_64: {
srcs: [
"amd64/fenv.c",
+ "x86_64/ceil.S",
+ "x86_64/ceilf.S",
+ "x86_64/floor.S",
+ "x86_64/floorf.S",
+ "x86_64/rint.S",
+ "x86_64/rintf.S",
"x86_64/sqrt.S",
"x86_64/sqrtf.S",
+ "x86_64/trunc.S",
+ "x86_64/truncf.S",
"x86_64/e_acos.S",
"x86_64/e_asin.S",
"x86_64/e_atan2.S",
@@ -431,39 +433,25 @@
"upstream-freebsd/lib/msun/src/e_sqrtf.c",
"upstream-freebsd/lib/msun/src/s_atan.c",
"upstream-freebsd/lib/msun/src/s_cbrt.c",
+ "upstream-freebsd/lib/msun/src/s_ceil.c",
+ "upstream-freebsd/lib/msun/src/s_ceilf.c",
"upstream-freebsd/lib/msun/src/s_cos.c",
"upstream-freebsd/lib/msun/src/s_expm1.c",
+ "upstream-freebsd/lib/msun/src/s_floor.c",
+ "upstream-freebsd/lib/msun/src/s_floorf.c",
"upstream-freebsd/lib/msun/src/s_log1p.c",
"upstream-freebsd/lib/msun/src/s_llrint.c",
"upstream-freebsd/lib/msun/src/s_llrintf.c",
"upstream-freebsd/lib/msun/src/s_lrint.c",
"upstream-freebsd/lib/msun/src/s_lrintf.c",
+ "upstream-freebsd/lib/msun/src/s_rint.c",
+ "upstream-freebsd/lib/msun/src/s_rintf.c",
"upstream-freebsd/lib/msun/src/s_sin.c",
"upstream-freebsd/lib/msun/src/s_tan.c",
"upstream-freebsd/lib/msun/src/s_tanh.c",
+ "upstream-freebsd/lib/msun/src/s_trunc.c",
+ "upstream-freebsd/lib/msun/src/s_truncf.c",
],
- sse4_1: {
- srcs: [
- "x86_64/ceil.S",
- "x86_64/ceilf.S",
- "x86_64/floor.S",
- "x86_64/floorf.S",
- "x86_64/rint.S",
- "x86_64/rintf.S",
- "x86_64/trunc.S",
- "x86_64/truncf.S",
- ],
- exclude_srcs: [
- "upstream-freebsd/lib/msun/src/s_ceil.c",
- "upstream-freebsd/lib/msun/src/s_ceilf.c",
- "upstream-freebsd/lib/msun/src/s_floor.c",
- "upstream-freebsd/lib/msun/src/s_floorf.c",
- "upstream-freebsd/lib/msun/src/s_rint.c",
- "upstream-freebsd/lib/msun/src/s_rintf.c",
- "upstream-freebsd/lib/msun/src/s_trunc.c",
- "upstream-freebsd/lib/msun/src/s_truncf.c",
- ],
- },
version_script: ":libm.x86_64.map",
},
},
diff --git a/tests/Android.bp b/tests/Android.bp
index 65c6035..42d280b 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -554,7 +554,6 @@
android: {
shared_libs: [
"ld-android",
- "libandroidicu",
"libdl",
"libdl_android",
"libdl_preempt_test_1",
diff --git a/tests/pthread_test.cpp b/tests/pthread_test.cpp
index 0bf8e29..d825738 100644
--- a/tests/pthread_test.cpp
+++ b/tests/pthread_test.cpp
@@ -990,6 +990,25 @@
#endif // __BIONIC__
}
+TEST(pthread, pthread_rwlock_reader_wakeup_writer_clockwait) {
+#if defined(__BIONIC__)
+ timespec ts;
+ ASSERT_EQ(0, clock_gettime(CLOCK_MONOTONIC, &ts));
+ ts.tv_sec += 1;
+ test_pthread_rwlock_reader_wakeup_writer([&](pthread_rwlock_t* lock) {
+ return pthread_rwlock_clockwrlock(lock, CLOCK_MONOTONIC, &ts);
+ });
+
+ ASSERT_EQ(0, clock_gettime(CLOCK_REALTIME, &ts));
+ ts.tv_sec += 1;
+ test_pthread_rwlock_reader_wakeup_writer([&](pthread_rwlock_t* lock) {
+ return pthread_rwlock_clockwrlock(lock, CLOCK_REALTIME, &ts);
+ });
+#else // __BIONIC__
+ GTEST_SKIP() << "pthread_rwlock_clockwrlock not available";
+#endif // __BIONIC__
+}
+
static void test_pthread_rwlock_writer_wakeup_reader(std::function<int (pthread_rwlock_t*)> lock_function) {
RwlockWakeupHelperArg wakeup_arg;
ASSERT_EQ(0, pthread_rwlock_init(&wakeup_arg.lock, nullptr));
@@ -1038,6 +1057,25 @@
#endif // __BIONIC__
}
+TEST(pthread, pthread_rwlock_writer_wakeup_reader_clockwait) {
+#if defined(__BIONIC__)
+ timespec ts;
+ ASSERT_EQ(0, clock_gettime(CLOCK_MONOTONIC, &ts));
+ ts.tv_sec += 1;
+ test_pthread_rwlock_writer_wakeup_reader([&](pthread_rwlock_t* lock) {
+ return pthread_rwlock_clockrdlock(lock, CLOCK_MONOTONIC, &ts);
+ });
+
+ ASSERT_EQ(0, clock_gettime(CLOCK_REALTIME, &ts));
+ ts.tv_sec += 1;
+ test_pthread_rwlock_writer_wakeup_reader([&](pthread_rwlock_t* lock) {
+ return pthread_rwlock_clockrdlock(lock, CLOCK_REALTIME, &ts);
+ });
+#else // __BIONIC__
+ GTEST_SKIP() << "pthread_rwlock_clockrdlock not available";
+#endif // __BIONIC__
+}
+
static void pthread_rwlock_wakeup_timeout_helper(RwlockWakeupHelperArg* arg) {
arg->tid = gettid();
ASSERT_EQ(RwlockWakeupHelperArg::LOCK_INITIALIZED, arg->progress);
@@ -1098,6 +1136,38 @@
#endif // __BIONIC__
}
+TEST(pthread, pthread_rwlock_clockrdlock_monotonic_timeout) {
+#if defined(__BIONIC__)
+ pthread_rwlock_timedrdlock_timeout_helper(
+ CLOCK_MONOTONIC, [](pthread_rwlock_t* __rwlock, const timespec* __timeout) {
+ return pthread_rwlock_clockrdlock(__rwlock, CLOCK_MONOTONIC, __timeout);
+ });
+#else // __BIONIC__
+ GTEST_SKIP() << "pthread_rwlock_clockrdlock not available";
+#endif // __BIONIC__
+}
+
+TEST(pthread, pthread_rwlock_clockrdlock_realtime_timeout) {
+#if defined(__BIONIC__)
+ pthread_rwlock_timedrdlock_timeout_helper(
+ CLOCK_REALTIME, [](pthread_rwlock_t* __rwlock, const timespec* __timeout) {
+ return pthread_rwlock_clockrdlock(__rwlock, CLOCK_REALTIME, __timeout);
+ });
+#else // __BIONIC__
+ GTEST_SKIP() << "pthread_rwlock_clockrdlock not available";
+#endif // __BIONIC__
+}
+
+TEST(pthread, pthread_rwlock_clockrdlock_invalid) {
+#if defined(__BIONIC__)
+ pthread_rwlock_t lock = PTHREAD_RWLOCK_INITIALIZER;
+ timespec ts;
+ EXPECT_EQ(EINVAL, pthread_rwlock_clockrdlock(&lock, CLOCK_PROCESS_CPUTIME_ID, &ts));
+#else // __BIONIC__
+ GTEST_SKIP() << "pthread_rwlock_clockrdlock not available";
+#endif // __BIONIC__
+}
+
static void pthread_rwlock_timedwrlock_timeout_helper(
clockid_t clock, int (*lock_function)(pthread_rwlock_t* __rwlock, const timespec* __timeout)) {
RwlockWakeupHelperArg wakeup_arg;
@@ -1134,6 +1204,38 @@
#endif // __BIONIC__
}
+TEST(pthread, pthread_rwlock_clockwrlock_monotonic_timeout) {
+#if defined(__BIONIC__)
+ pthread_rwlock_timedwrlock_timeout_helper(
+ CLOCK_MONOTONIC, [](pthread_rwlock_t* __rwlock, const timespec* __timeout) {
+ return pthread_rwlock_clockwrlock(__rwlock, CLOCK_MONOTONIC, __timeout);
+ });
+#else // __BIONIC__
+ GTEST_SKIP() << "pthread_rwlock_clockwrlock not available";
+#endif // __BIONIC__
+}
+
+TEST(pthread, pthread_rwlock_clockwrlock_realtime_timeout) {
+#if defined(__BIONIC__)
+ pthread_rwlock_timedwrlock_timeout_helper(
+ CLOCK_REALTIME, [](pthread_rwlock_t* __rwlock, const timespec* __timeout) {
+ return pthread_rwlock_clockwrlock(__rwlock, CLOCK_REALTIME, __timeout);
+ });
+#else // __BIONIC__
+ GTEST_SKIP() << "pthread_rwlock_clockwrlock not available";
+#endif // __BIONIC__
+}
+
+TEST(pthread, pthread_rwlock_clockwrlock_invalid) {
+#if defined(__BIONIC__)
+ pthread_rwlock_t lock = PTHREAD_RWLOCK_INITIALIZER;
+ timespec ts;
+ EXPECT_EQ(EINVAL, pthread_rwlock_clockwrlock(&lock, CLOCK_PROCESS_CPUTIME_ID, &ts));
+#else // __BIONIC__
+ GTEST_SKIP() << "pthread_rwlock_clockrwlock not available";
+#endif // __BIONIC__
+}
+
class RwlockKindTestHelper {
private:
struct ThreadArg {
@@ -1392,16 +1494,43 @@
ASSERT_EQ(0, pthread_condattr_destroy(&attr));
}
- void StartWaitingThread(std::function<int (pthread_cond_t* cond, pthread_mutex_t* mutex)> wait_function) {
+ void StartWaitingThread(
+ std::function<int(pthread_cond_t* cond, pthread_mutex_t* mutex)> wait_function) {
progress = INITIALIZED;
this->wait_function = wait_function;
- ASSERT_EQ(0, pthread_create(&thread, nullptr, reinterpret_cast<void* (*)(void*)>(WaitThreadFn), this));
+ ASSERT_EQ(0, pthread_create(&thread, nullptr, reinterpret_cast<void* (*)(void*)>(WaitThreadFn),
+ this));
while (progress != WAITING) {
usleep(5000);
}
usleep(5000);
}
+ void RunTimedTest(
+ clockid_t clock,
+ std::function<int(pthread_cond_t* cond, pthread_mutex_t* mutex, const timespec* timeout)>
+ wait_function) {
+ timespec ts;
+ ASSERT_EQ(0, clock_gettime(clock, &ts));
+ ts.tv_sec += 1;
+
+ StartWaitingThread([&wait_function, &ts](pthread_cond_t* cond, pthread_mutex_t* mutex) {
+ return wait_function(cond, mutex, &ts);
+ });
+
+ progress = SIGNALED;
+ ASSERT_EQ(0, pthread_cond_signal(&cond));
+ }
+
+ void RunTimedTest(clockid_t clock, std::function<int(pthread_cond_t* cond, pthread_mutex_t* mutex,
+ clockid_t clock, const timespec* timeout)>
+ wait_function) {
+ RunTimedTest(clock, [clock, &wait_function](pthread_cond_t* cond, pthread_mutex_t* mutex,
+ const timespec* timeout) {
+ return wait_function(cond, mutex, clock, timeout);
+ });
+ }
+
void TearDown() override {
ASSERT_EQ(0, pthread_join(thread, nullptr));
ASSERT_EQ(FINISHED, progress);
@@ -1442,52 +1571,80 @@
TEST_F(pthread_CondWakeupTest, signal_timedwait_CLOCK_REALTIME) {
InitCond(CLOCK_REALTIME);
- timespec ts;
- ASSERT_EQ(0, clock_gettime(CLOCK_REALTIME, &ts));
- ts.tv_sec += 1;
- StartWaitingThread([&](pthread_cond_t* cond, pthread_mutex_t* mutex) {
- return pthread_cond_timedwait(cond, mutex, &ts);
- });
- progress = SIGNALED;
- ASSERT_EQ(0, pthread_cond_signal(&cond));
+ RunTimedTest(CLOCK_REALTIME, pthread_cond_timedwait);
}
TEST_F(pthread_CondWakeupTest, signal_timedwait_CLOCK_MONOTONIC) {
InitCond(CLOCK_MONOTONIC);
- timespec ts;
- ASSERT_EQ(0, clock_gettime(CLOCK_MONOTONIC, &ts));
- ts.tv_sec += 1;
- StartWaitingThread([&](pthread_cond_t* cond, pthread_mutex_t* mutex) {
- return pthread_cond_timedwait(cond, mutex, &ts);
- });
- progress = SIGNALED;
- ASSERT_EQ(0, pthread_cond_signal(&cond));
+ RunTimedTest(CLOCK_MONOTONIC, pthread_cond_timedwait);
}
TEST_F(pthread_CondWakeupTest, signal_timedwait_CLOCK_MONOTONIC_np) {
#if defined(__BIONIC__)
InitCond(CLOCK_REALTIME);
- timespec ts;
- ASSERT_EQ(0, clock_gettime(CLOCK_MONOTONIC, &ts));
- ts.tv_sec += 1;
- StartWaitingThread([&](pthread_cond_t* cond, pthread_mutex_t* mutex) {
- return pthread_cond_timedwait_monotonic_np(cond, mutex, &ts);
- });
- progress = SIGNALED;
- ASSERT_EQ(0, pthread_cond_signal(&cond));
+ RunTimedTest(CLOCK_MONOTONIC, pthread_cond_timedwait_monotonic_np);
#else // __BIONIC__
GTEST_SKIP() << "pthread_cond_timedwait_monotonic_np not available";
#endif // __BIONIC__
}
-static void pthread_cond_timedwait_timeout_helper(clockid_t clock,
+TEST_F(pthread_CondWakeupTest, signal_clockwait_monotonic_monotonic) {
+#if defined(__BIONIC__)
+ InitCond(CLOCK_MONOTONIC);
+ RunTimedTest(CLOCK_MONOTONIC, pthread_cond_clockwait);
+#else // __BIONIC__
+ GTEST_SKIP() << "pthread_cond_clockwait not available";
+#endif // __BIONIC__
+}
+
+TEST_F(pthread_CondWakeupTest, signal_clockwait_monotonic_realtime) {
+#if defined(__BIONIC__)
+ InitCond(CLOCK_MONOTONIC);
+ RunTimedTest(CLOCK_REALTIME, pthread_cond_clockwait);
+#else // __BIONIC__
+ GTEST_SKIP() << "pthread_cond_clockwait not available";
+#endif // __BIONIC__
+}
+
+TEST_F(pthread_CondWakeupTest, signal_clockwait_realtime_monotonic) {
+#if defined(__BIONIC__)
+ InitCond(CLOCK_REALTIME);
+ RunTimedTest(CLOCK_MONOTONIC, pthread_cond_clockwait);
+#else // __BIONIC__
+ GTEST_SKIP() << "pthread_cond_clockwait not available";
+#endif // __BIONIC__
+}
+
+TEST_F(pthread_CondWakeupTest, signal_clockwait_realtime_realtime) {
+#if defined(__BIONIC__)
+ InitCond(CLOCK_REALTIME);
+ RunTimedTest(CLOCK_REALTIME, pthread_cond_clockwait);
+#else // __BIONIC__
+ GTEST_SKIP() << "pthread_cond_clockwait not available";
+#endif // __BIONIC__
+}
+
+static void pthread_cond_timedwait_timeout_helper(bool init_monotonic, clockid_t clock,
int (*wait_function)(pthread_cond_t* __cond,
pthread_mutex_t* __mutex,
const timespec* __timeout)) {
pthread_mutex_t mutex;
ASSERT_EQ(0, pthread_mutex_init(&mutex, nullptr));
pthread_cond_t cond;
- ASSERT_EQ(0, pthread_cond_init(&cond, nullptr));
+
+ if (init_monotonic) {
+ pthread_condattr_t attr;
+ pthread_condattr_init(&attr);
+
+ ASSERT_EQ(0, pthread_condattr_setclock(&attr, CLOCK_MONOTONIC));
+ clockid_t clock;
+ ASSERT_EQ(0, pthread_condattr_getclock(&attr, &clock));
+ ASSERT_EQ(CLOCK_MONOTONIC, clock);
+
+ ASSERT_EQ(0, pthread_cond_init(&cond, &attr));
+ } else {
+ ASSERT_EQ(0, pthread_cond_init(&cond, nullptr));
+ }
ASSERT_EQ(0, pthread_mutex_lock(&mutex));
timespec ts;
@@ -1504,17 +1661,57 @@
}
TEST(pthread, pthread_cond_timedwait_timeout) {
- pthread_cond_timedwait_timeout_helper(CLOCK_REALTIME, pthread_cond_timedwait);
+ pthread_cond_timedwait_timeout_helper(false, CLOCK_REALTIME, pthread_cond_timedwait);
}
TEST(pthread, pthread_cond_timedwait_monotonic_np_timeout) {
#if defined(__BIONIC__)
- pthread_cond_timedwait_timeout_helper(CLOCK_MONOTONIC, pthread_cond_timedwait_monotonic_np);
+ pthread_cond_timedwait_timeout_helper(false, CLOCK_MONOTONIC, pthread_cond_timedwait_monotonic_np);
+ pthread_cond_timedwait_timeout_helper(true, CLOCK_MONOTONIC, pthread_cond_timedwait_monotonic_np);
#else // __BIONIC__
GTEST_SKIP() << "pthread_cond_timedwait_monotonic_np not available";
#endif // __BIONIC__
}
+TEST(pthread, pthread_cond_clockwait_timeout) {
+#if defined(__BIONIC__)
+ pthread_cond_timedwait_timeout_helper(
+ false, CLOCK_MONOTONIC,
+ [](pthread_cond_t* __cond, pthread_mutex_t* __mutex, const timespec* __timeout) {
+ return pthread_cond_clockwait(__cond, __mutex, CLOCK_MONOTONIC, __timeout);
+ });
+ pthread_cond_timedwait_timeout_helper(
+ true, CLOCK_MONOTONIC,
+ [](pthread_cond_t* __cond, pthread_mutex_t* __mutex, const timespec* __timeout) {
+ return pthread_cond_clockwait(__cond, __mutex, CLOCK_MONOTONIC, __timeout);
+ });
+ pthread_cond_timedwait_timeout_helper(
+ false, CLOCK_REALTIME,
+ [](pthread_cond_t* __cond, pthread_mutex_t* __mutex, const timespec* __timeout) {
+ return pthread_cond_clockwait(__cond, __mutex, CLOCK_REALTIME, __timeout);
+ });
+ pthread_cond_timedwait_timeout_helper(
+ true, CLOCK_REALTIME,
+ [](pthread_cond_t* __cond, pthread_mutex_t* __mutex, const timespec* __timeout) {
+ return pthread_cond_clockwait(__cond, __mutex, CLOCK_REALTIME, __timeout);
+ });
+#else // __BIONIC__
+ GTEST_SKIP() << "pthread_cond_clockwait not available";
+#endif // __BIONIC__
+}
+
+TEST(pthread, pthread_cond_clockwait_invalid) {
+#if defined(__BIONIC__)
+ pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
+ pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+ timespec ts;
+ EXPECT_EQ(EINVAL, pthread_cond_clockwait(&cond, &mutex, CLOCK_PROCESS_CPUTIME_ID, &ts));
+
+#else // __BIONIC__
+ GTEST_SKIP() << "pthread_cond_clockwait not available";
+#endif // __BIONIC__
+}
+
TEST(pthread, pthread_attr_getstack__main_thread) {
// This test is only meaningful for the main thread, so make sure we're running on it!
ASSERT_EQ(getpid(), syscall(__NR_gettid));
@@ -2180,6 +2377,21 @@
#endif // __BIONIC__
}
+TEST(pthread, pthread_mutex_clocklock) {
+#if defined(__BIONIC__)
+ pthread_mutex_timedlock_helper(
+ CLOCK_MONOTONIC, [](pthread_mutex_t* __mutex, const timespec* __timeout) {
+ return pthread_mutex_clocklock(__mutex, CLOCK_MONOTONIC, __timeout);
+ });
+ pthread_mutex_timedlock_helper(
+ CLOCK_REALTIME, [](pthread_mutex_t* __mutex, const timespec* __timeout) {
+ return pthread_mutex_clocklock(__mutex, CLOCK_REALTIME, __timeout);
+ });
+#else // __BIONIC__
+ GTEST_SKIP() << "pthread_mutex_clocklock not available";
+#endif // __BIONIC__
+}
+
static void pthread_mutex_timedlock_pi_helper(clockid_t clock,
int (*lock_function)(pthread_mutex_t* __mutex,
const timespec* __timeout)) {
@@ -2231,6 +2443,31 @@
#endif // __BIONIC__
}
+TEST(pthread, pthread_mutex_clocklock_pi) {
+#if defined(__BIONIC__)
+ pthread_mutex_timedlock_pi_helper(
+ CLOCK_MONOTONIC, [](pthread_mutex_t* __mutex, const timespec* __timeout) {
+ return pthread_mutex_clocklock(__mutex, CLOCK_MONOTONIC, __timeout);
+ });
+ pthread_mutex_timedlock_pi_helper(
+ CLOCK_REALTIME, [](pthread_mutex_t* __mutex, const timespec* __timeout) {
+ return pthread_mutex_clocklock(__mutex, CLOCK_REALTIME, __timeout);
+ });
+#else // __BIONIC__
+ GTEST_SKIP() << "pthread_mutex_clocklock not available";
+#endif // __BIONIC__
+}
+
+TEST(pthread, pthread_mutex_clocklock_invalid) {
+#if defined(__BIONIC__)
+ pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+ timespec ts;
+ EXPECT_EQ(EINVAL, pthread_mutex_clocklock(&mutex, CLOCK_PROCESS_CPUTIME_ID, &ts));
+#else // __BIONIC__
+ GTEST_SKIP() << "pthread_mutex_clocklock not available";
+#endif // __BIONIC__
+}
+
TEST(pthread, pthread_mutex_using_destroyed_mutex) {
#if defined(__BIONIC__)
pthread_mutex_t m;
@@ -2247,6 +2484,13 @@
"pthread_mutex_timedlock called on a destroyed mutex");
ASSERT_EXIT(pthread_mutex_timedlock_monotonic_np(&m, &ts), ::testing::KilledBySignal(SIGABRT),
"pthread_mutex_timedlock_monotonic_np called on a destroyed mutex");
+ ASSERT_EXIT(pthread_mutex_clocklock(&m, CLOCK_MONOTONIC, &ts), ::testing::KilledBySignal(SIGABRT),
+ "pthread_mutex_clocklock called on a destroyed mutex");
+ ASSERT_EXIT(pthread_mutex_clocklock(&m, CLOCK_REALTIME, &ts), ::testing::KilledBySignal(SIGABRT),
+ "pthread_mutex_clocklock called on a destroyed mutex");
+ ASSERT_EXIT(pthread_mutex_clocklock(&m, CLOCK_PROCESS_CPUTIME_ID, &ts),
+ ::testing::KilledBySignal(SIGABRT),
+ "pthread_mutex_clocklock called on a destroyed mutex");
ASSERT_EXIT(pthread_mutex_destroy(&m), ::testing::KilledBySignal(SIGABRT),
"pthread_mutex_destroy called on a destroyed mutex");
#else
diff --git a/tests/semaphore_test.cpp b/tests/semaphore_test.cpp
index 7addf6d..5a23b96 100644
--- a/tests/semaphore_test.cpp
+++ b/tests/semaphore_test.cpp
@@ -145,6 +145,19 @@
#endif // __BIONIC__
}
+TEST(semaphore, sem_clockwait) {
+#if defined(__BIONIC__)
+ sem_timedwait_helper(CLOCK_MONOTONIC, [](sem_t* __sem, const timespec* __ts) {
+ return sem_clockwait(__sem, CLOCK_MONOTONIC, __ts);
+ });
+ sem_timedwait_helper(CLOCK_REALTIME, [](sem_t* __sem, const timespec* __ts) {
+ return sem_clockwait(__sem, CLOCK_REALTIME, __ts);
+ });
+#else // __BIONIC__
+ GTEST_SKIP() << "sem_clockwait is only supported on bionic";
+#endif // __BIONIC__
+}
+
TEST(semaphore_DeathTest, sem_timedwait_null_timeout) {
sem_t s;
ASSERT_EQ(0, sem_init(&s, 0, 0));