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));