Merge "Move static variable out of should_trace()."
diff --git a/docs/status.md b/docs/status.md
index d4ca913..8cef5b7 100644
--- a/docs/status.md
+++ b/docs/status.md
@@ -48,10 +48,12 @@
   * `hcreate`/`hcreate_r`/`hdestroy`/`hdestroy_r`/`hsearch`/`hsearch_r` (completing <search.h>)
   * `iconv`/`iconv_close`/`iconv_open` (adding <iconv.h>)
   * `pthread_attr_getinheritsched`/`pthread_attr_setinheritsched`/`pthread_setschedprio`
+  * `pthread_mutexattr_getprotocol`/`pthread_mutexattr_setprotocol` (mutex priority inheritance)
   * <spawn.h>
   * `swab`
   * `syncfs`
-  * %C and %S support in the printf family (previously only the wprintf family supported these).
+  * `%C` and `%S` support in the printf family (previously only the wprintf family supported these).
+  * `%mc`/`%ms`/`%m[` support in the scanf family.
 
 New libc functions in O:
   * `sendto` FORTIFY support
diff --git a/libc/Android.bp b/libc/Android.bp
index a8c518d..2ea8514 100644
--- a/libc/Android.bp
+++ b/libc/Android.bp
@@ -10,9 +10,6 @@
     "bionic/pututline.c",
     "bionic/sched_cpualloc.c",
     "bionic/sched_cpucount.c",
-    "bionic/sigblock.c",
-    "bionic/siginterrupt.c",
-    "bionic/sigsetmask.c",
     "stdio/fmemopen.cpp",
     "stdio/parsefloat.c",
     "stdio/refill.c",
@@ -1336,25 +1333,7 @@
         "bionic/seteuid.cpp",
         "bionic/setpgrp.cpp",
         "bionic/sigaction.cpp",
-        "bionic/sigaddset.cpp",
-        "bionic/sigdelset.cpp",
-        "bionic/sigemptyset.cpp",
-        "bionic/sigfillset.cpp",
-        "bionic/sighold.cpp",
-        "bionic/sigignore.cpp",
-        "bionic/sigismember.cpp",
         "bionic/signal.cpp",
-        "bionic/signalfd.cpp",
-        "bionic/sigpause.cpp",
-        "bionic/sigpending.cpp",
-        "bionic/sigprocmask.cpp",
-        "bionic/sigqueue.cpp",
-        "bionic/sigrelse.cpp",
-        "bionic/sigset.cpp",
-        "bionic/sigsuspend.cpp",
-        "bionic/sigtimedwait.cpp",
-        "bionic/sigwait.cpp",
-        "bionic/sigwaitinfo.cpp",
         "bionic/socket.cpp",
         "bionic/spawn.cpp",
         "bionic/stat.cpp",
@@ -1375,6 +1354,7 @@
         "bionic/sys_sem.cpp",
         "bionic/sys_shm.cpp",
         "bionic/sys_siglist.c",
+        "bionic/sys_signalfd.cpp",
         "bionic/sys_signame.c",
         "bionic/sys_time.cpp",
         "bionic/sysinfo.cpp",
diff --git a/libc/arch-arm/bionic/setjmp.S b/libc/arch-arm/bionic/setjmp.S
index b814124..c10bd3e 100644
--- a/libc/arch-arm/bionic/setjmp.S
+++ b/libc/arch-arm/bionic/setjmp.S
@@ -218,8 +218,10 @@
   beq 1f
 
   // Restore the signal mask.
-  ldr r0, [r0, #(_JB_SIGMASK * 4)]
-  bl sigsetmask
+  mov r2, #0
+  add r1, r0, #(_JB_SIGMASK * 4)
+  mov r0, #2 // SIG_SETMASK
+  bl sigprocmask
 
 1:
   ldmfd sp!, {r0, r1, lr}
diff --git a/libc/arch-x86/bionic/setjmp.S b/libc/arch-x86/bionic/setjmp.S
index 6e6c365..f9f7cd7 100644
--- a/libc/arch-x86/bionic/setjmp.S
+++ b/libc/arch-x86/bionic/setjmp.S
@@ -110,16 +110,17 @@
   testl $1,%eax
   jz 1f
 
-  // Get the current signal mask.
+  // Save the current signal mask.
+  pushl %ecx
   PIC_PROLOGUE
-  pushl $0
-  call PIC_PLT(sigblock)
-  addl $4,%esp
+  leal (_JB_SIGMASK * 4)(%ecx),%eax
+  pushl %eax
+  pushl $0 // NULL
+  pushl $2 // SIG_SETMASK
+  call PIC_PLT(sigprocmask)
+  addl $12,%esp
   PIC_EPILOGUE
-
-  // Save the signal mask.
-  movl 4(%esp),%ecx
-  movl %eax,(_JB_SIGMASK * 4)(%ecx)
+  popl %ecx
 
 1:
   // Fetch the setjmp cookie and clear the signal flag bit.
@@ -159,10 +160,13 @@
   jz 1f
 
   // Restore the signal mask.
+  leal (_JB_SIGMASK * 4)(%edx),%eax
   PIC_PROLOGUE
-  pushl (_JB_SIGMASK * 4)(%edx)
-  call PIC_PLT(sigsetmask)
-  addl $4,%esp
+  pushl $0 // NULL
+  pushl %eax
+  pushl $2 // SIG_SETMASK
+  call PIC_PLT(sigprocmask)
+  addl $12,%esp
   PIC_EPILOGUE
 
 1:
diff --git a/libc/bionic/abort.cpp b/libc/bionic/abort.cpp
index f401cab..9f1c31f 100644
--- a/libc/bionic/abort.cpp
+++ b/libc/bionic/abort.cpp
@@ -32,6 +32,8 @@
 #include <sys/syscall.h>
 #include <unistd.h>
 
+#include "private/kernel_sigset_t.h"
+
 // We call tgkill(2) directly instead of raise (or even the libc tgkill wrapper), to reduce the
 // number of uninteresting stack frames at the top of a crash.
 static inline __always_inline void inline_tgkill(pid_t pid, pid_t tid, int sig) {
@@ -60,10 +62,10 @@
 
   // Don't block SIGABRT to give any signal handler a chance; we ignore
   // any errors -- X311J doesn't allow abort to return anyway.
-  sigset_t mask;
-  sigfillset(&mask);
-  sigdelset(&mask, SIGABRT);
-  sigprocmask(SIG_SETMASK, &mask, NULL);
+  kernel_sigset_t mask;
+  mask.fill();
+  mask.clear(SIGABRT);
+  __rt_sigprocmask(SIG_SETMASK, &mask, nullptr, sizeof(mask));
 
   inline_tgkill(pid, tid, SIGABRT);
 
@@ -74,7 +76,7 @@
   sa.sa_flags   = SA_RESTART;
   sigemptyset(&sa.sa_mask);
   sigaction(SIGABRT, &sa, &sa);
-  sigprocmask(SIG_SETMASK, &mask, NULL);
+  __rt_sigprocmask(SIG_SETMASK, &mask, nullptr, sizeof(mask));
 
   inline_tgkill(pid, tid, SIGABRT);
 
diff --git a/libc/bionic/pause.cpp b/libc/bionic/pause.cpp
index 94a16fb..2a0779a 100644
--- a/libc/bionic/pause.cpp
+++ b/libc/bionic/pause.cpp
@@ -30,13 +30,8 @@
 
 #include "private/kernel_sigset_t.h"
 
-extern "C" int __rt_sigprocmask(int, const kernel_sigset_t*, kernel_sigset_t*, size_t);
-extern "C" int __rt_sigsuspend(const kernel_sigset_t*, size_t);
-
 int pause() {
   kernel_sigset_t mask;
-  if (__rt_sigprocmask(SIG_SETMASK, NULL, &mask, sizeof(mask)) == -1) {
-    return -1;
-  }
+  if (__rt_sigprocmask(SIG_SETMASK, nullptr, &mask, sizeof(mask)) == -1) return -1;
   return __rt_sigsuspend(&mask, sizeof(mask));
 }
diff --git a/libc/bionic/posix_timers.cpp b/libc/bionic/posix_timers.cpp
index c46965f..e3bb112 100644
--- a/libc/bionic/posix_timers.cpp
+++ b/libc/bionic/posix_timers.cpp
@@ -74,8 +74,7 @@
 static void* __timer_thread_start(void* arg) {
   PosixTimer* timer = reinterpret_cast<PosixTimer*>(arg);
 
-  kernel_sigset_t sigset;
-  sigaddset(sigset.get(), TIMER_SIGNAL);
+  kernel_sigset_t sigset{TIMER_SIGNAL};
 
   while (true) {
     // Wait for a signal...
@@ -150,14 +149,13 @@
 
   // We start the thread with TIMER_SIGNAL blocked by blocking the signal here and letting it
   // inherit. If it tried to block the signal itself, there would be a race.
-  kernel_sigset_t sigset;
-  sigaddset(sigset.get(), TIMER_SIGNAL);
+  kernel_sigset_t sigset{TIMER_SIGNAL};
   kernel_sigset_t old_sigset;
-  pthread_sigmask(SIG_BLOCK, sigset.get(), old_sigset.get());
+  __rt_sigprocmask(SIG_BLOCK, &sigset, &old_sigset, sizeof(sigset));
 
   int rc = pthread_create(&timer->callback_thread, &thread_attributes, __timer_thread_start, timer);
 
-  pthread_sigmask(SIG_SETMASK, old_sigset.get(), NULL);
+  __rt_sigprocmask(SIG_SETMASK, &old_sigset, nullptr, sizeof(sigset));
 
   if (rc != 0) {
     free(timer);
diff --git a/libc/bionic/pthread_exit.cpp b/libc/bionic/pthread_exit.cpp
index 8b4c44e..f1b65fd 100644
--- a/libc/bionic/pthread_exit.cpp
+++ b/libc/bionic/pthread_exit.cpp
@@ -34,6 +34,7 @@
 #include <sys/mman.h>
 
 #include "private/bionic_defs.h"
+#include "private/ScopedSignalBlocker.h"
 #include "pthread_internal.h"
 
 extern "C" __noreturn void _exit_with_stack_teardown(void*, size_t);
@@ -63,6 +64,12 @@
   }
 }
 
+static void __pthread_unmap_tls(pthread_internal_t* thread) {
+  // Unmap the bionic TLS, including guard pages.
+  void* allocation = reinterpret_cast<char*>(thread->bionic_tls) - PTHREAD_GUARD_SIZE;
+  munmap(allocation, BIONIC_TLS_SIZE + 2 * PTHREAD_GUARD_SIZE);
+}
+
 __BIONIC_WEAK_FOR_NATIVE_BRIDGE
 void pthread_exit(void* return_value) {
   // Call dtors for thread_local objects first.
@@ -96,10 +103,6 @@
     thread->alternate_signal_stack = NULL;
   }
 
-  // Unmap the bionic TLS, including guard pages.
-  void* allocation = reinterpret_cast<char*>(thread->bionic_tls) - PTHREAD_GUARD_SIZE;
-  munmap(allocation, BIONIC_TLS_SIZE + 2 * PTHREAD_GUARD_SIZE);
-
   ThreadJoinState old_state = THREAD_NOT_JOINED;
   while (old_state == THREAD_NOT_JOINED &&
          !atomic_compare_exchange_weak(&thread->join_state, &old_state, THREAD_EXITED_NOT_JOINED)) {
@@ -120,16 +123,15 @@
       // That's not something we can do in C.
 
       // We don't want to take a signal after we've unmapped the stack.
-      // That's one last thing we can handle in C.
-      sigset_t mask;
-      sigfillset(&mask);
-      sigprocmask(SIG_SETMASK, &mask, NULL);
-
+      // That's one last thing we can do before dropping to assembler.
+      ScopedSignalBlocker ssb;
+      __pthread_unmap_tls(thread);
       _exit_with_stack_teardown(thread->attr.stack_base, thread->mmap_size);
     }
   }
 
   // No need to free mapped space. Either there was no space mapped, or it is left for
   // the pthread_join caller to clean up.
+  __pthread_unmap_tls(thread);
   __exit(0);
 }
diff --git a/libc/bionic/sigaddset.cpp b/libc/bionic/sigaddset.cpp
deleted file mode 100644
index ca6b982..0000000
--- a/libc/bionic/sigaddset.cpp
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <errno.h>
-#include <signal.h>
-
-int sigaddset(sigset_t* set, int signum) {
-  int bit = signum - 1; // Signal numbers start at 1, but bit positions start at 0.
-  unsigned long* local_set = reinterpret_cast<unsigned long*>(set);
-  if (set == NULL || bit < 0 || bit >= static_cast<int>(8*sizeof(sigset_t))) {
-    errno = EINVAL;
-    return -1;
-  }
-  local_set[bit / LONG_BIT] |= 1UL << (bit % LONG_BIT);
-  return 0;
-}
diff --git a/libc/bionic/sigblock.c b/libc/bionic/sigblock.c
deleted file mode 100644
index 176bc13..0000000
--- a/libc/bionic/sigblock.c
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-#include <signal.h>
-
-/* this function is called from the ARM assembly setjmp fragments */
-int
-sigblock(int mask)
-{
-    int  n;
-    union {
-        int       the_mask;
-        sigset_t  the_sigset;
-    } in, out;
-
-    sigemptyset(&in.the_sigset);
-    in.the_mask = mask;
-
-    n = sigprocmask(SIG_BLOCK, &in.the_sigset, &out.the_sigset);
-    if (n)
-        return n;
-
-    return out.the_mask;
-}
-
-
diff --git a/libc/bionic/sigdelset.cpp b/libc/bionic/sigdelset.cpp
deleted file mode 100644
index 48363d3..0000000
--- a/libc/bionic/sigdelset.cpp
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <errno.h>
-#include <signal.h>
-
-int sigdelset(sigset_t* set, int signum) {
-  int bit = signum - 1; // Signal numbers start at 1, but bit positions start at 0.
-  unsigned long* local_set = reinterpret_cast<unsigned long*>(set);
-  if (set == NULL || bit < 0 || bit >= static_cast<int>(8*sizeof(sigset_t))) {
-    errno = EINVAL;
-    return -1;
-  }
-  local_set[bit / LONG_BIT] &= ~(1UL << (bit % LONG_BIT));
-  return 0;
-}
diff --git a/libc/bionic/sigemptyset.cpp b/libc/bionic/sigemptyset.cpp
deleted file mode 100644
index 58166a1..0000000
--- a/libc/bionic/sigemptyset.cpp
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <errno.h>
-#include <signal.h>
-#include <string.h>
-
-int sigemptyset(sigset_t* set) {
-  if (set == NULL) {
-    errno = EINVAL;
-    return -1;
-  }
-  memset(set, 0, sizeof(sigset_t));
-  return 0;
-}
diff --git a/libc/bionic/sigfillset.cpp b/libc/bionic/sigfillset.cpp
deleted file mode 100644
index cb67394..0000000
--- a/libc/bionic/sigfillset.cpp
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <errno.h>
-#include <signal.h>
-#include <string.h>
-
-int sigfillset(sigset_t* set) {
-  if (set == NULL) {
-    errno = EINVAL;
-    return -1;
-  }
-  memset(set, ~0, sizeof(sigset_t));
-  return 0;
-}
diff --git a/libc/bionic/sighold.cpp b/libc/bionic/sighold.cpp
deleted file mode 100644
index e9c8ca1..0000000
--- a/libc/bionic/sighold.cpp
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <signal.h>
-
-int sighold(int sig) {
-  sigset_t set;
-  if (sigemptyset(&set) == -1) return -1;
-  if (sigaddset(&set, sig) == -1) return -1;
-  return sigprocmask(SIG_BLOCK, &set, nullptr);
-}
diff --git a/libc/bionic/sigignore.cpp b/libc/bionic/sigignore.cpp
deleted file mode 100644
index 06f458e..0000000
--- a/libc/bionic/sigignore.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <signal.h>
-#include <string.h>
-
-int sigignore(int sig) {
-  struct sigaction sa;
-  memset(&sa, 0, sizeof(sa));
-  if (sigemptyset(&sa.sa_mask) == -1) return -1;
-  sa.sa_handler = SIG_IGN;
-  return sigaction(sig, &sa, nullptr);
-}
diff --git a/libc/bionic/siginterrupt.c b/libc/bionic/siginterrupt.c
deleted file mode 100644
index 4e91edb..0000000
--- a/libc/bionic/siginterrupt.c
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <signal.h>
-
-/* this is only useful for legacy programs */
-int siginterrupt(int sig, int flag) 
-{
-    struct sigaction act;
-
-    (void) sigaction(sig, NULL, &act);
-
-    if (flag)
-        act.sa_flags &= ~SA_RESTART;
-    else
-        act.sa_flags |= SA_RESTART;
-
-    return sigaction(sig, &act, NULL);
-}
-
diff --git a/libc/bionic/sigismember.cpp b/libc/bionic/sigismember.cpp
deleted file mode 100644
index 9d1fc3c..0000000
--- a/libc/bionic/sigismember.cpp
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <errno.h>
-#include <signal.h>
-
-int sigismember(const sigset_t* set, int signum) {
-  int bit = signum - 1; // Signal numbers start at 1, but bit positions start at 0.
-  const unsigned long* local_set = reinterpret_cast<const unsigned long*>(set);
-  if (set == NULL || bit < 0 || bit >= static_cast<int>(8*sizeof(sigset_t))) {
-    errno = EINVAL;
-    return -1;
-  }
-  return static_cast<int>((local_set[bit / LONG_BIT] >> (bit % LONG_BIT)) & 1);
-}
diff --git a/libc/bionic/signal.cpp b/libc/bionic/signal.cpp
index 13d1882..9a23416 100644
--- a/libc/bionic/signal.cpp
+++ b/libc/bionic/signal.cpp
@@ -26,7 +26,108 @@
  * SUCH DAMAGE.
  */
 
+#include <errno.h>
+#include <pthread.h>
 #include <signal.h>
+#include <string.h>
+#include <sys/types.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "private/kernel_sigset_t.h"
+
+extern "C" int ___rt_sigqueueinfo(pid_t, int, siginfo_t*);
+extern "C" int __rt_sigtimedwait(const sigset_t*, siginfo_t*, const timespec*, size_t);
+
+int sigaddset(sigset_t* set, int signum) {
+  int bit = signum - 1; // Signal numbers start at 1, but bit positions start at 0.
+  unsigned long* local_set = reinterpret_cast<unsigned long*>(set);
+  if (set == NULL || bit < 0 || bit >= static_cast<int>(8*sizeof(sigset_t))) {
+    errno = EINVAL;
+    return -1;
+  }
+  local_set[bit / LONG_BIT] |= 1UL << (bit % LONG_BIT);
+  return 0;
+}
+
+// This isn't in our header files, but is exposed on all architectures.
+extern "C" int sigblock(int mask) {
+  union {
+    int mask;
+    sigset_t set;
+  } in, out;
+
+  sigemptyset(&in.set);
+  in.mask = mask;
+
+  if (sigprocmask(SIG_BLOCK, &in.set, &out.set) == -1) return -1;
+  return out.mask;
+}
+
+int sigdelset(sigset_t* set, int signum) {
+  int bit = signum - 1; // Signal numbers start at 1, but bit positions start at 0.
+  unsigned long* local_set = reinterpret_cast<unsigned long*>(set);
+  if (set == NULL || bit < 0 || bit >= static_cast<int>(8*sizeof(sigset_t))) {
+    errno = EINVAL;
+    return -1;
+  }
+  local_set[bit / LONG_BIT] &= ~(1UL << (bit % LONG_BIT));
+  return 0;
+}
+
+int sigemptyset(sigset_t* set) {
+  if (set == NULL) {
+    errno = EINVAL;
+    return -1;
+  }
+  memset(set, 0, sizeof(sigset_t));
+  return 0;
+}
+
+int sigfillset(sigset_t* set) {
+  if (set == NULL) {
+    errno = EINVAL;
+    return -1;
+  }
+  memset(set, ~0, sizeof(sigset_t));
+  return 0;
+}
+
+int sighold(int sig) {
+  kernel_sigset_t set;
+  set.clear();
+  if (!set.set(sig)) return -1;
+  return __rt_sigprocmask(SIG_BLOCK, &set, nullptr, sizeof(set));
+}
+
+int sigignore(int sig) {
+  struct sigaction sa;
+  memset(&sa, 0, sizeof(sa));
+  if (sigemptyset(&sa.sa_mask) == -1) return -1;
+  sa.sa_handler = SIG_IGN;
+  return sigaction(sig, &sa, nullptr);
+}
+
+int siginterrupt(int sig, int flag) {
+  struct sigaction act;
+  sigaction(sig, nullptr, &act);
+  if (flag) {
+    act.sa_flags &= ~SA_RESTART;
+  } else {
+    act.sa_flags |= SA_RESTART;
+  }
+  return sigaction(sig, &act, nullptr);
+}
+
+int sigismember(const sigset_t* set, int signum) {
+  int bit = signum - 1; // Signal numbers start at 1, but bit positions start at 0.
+  const unsigned long* local_set = reinterpret_cast<const unsigned long*>(set);
+  if (set == NULL || bit < 0 || bit >= static_cast<int>(8*sizeof(sigset_t))) {
+    errno = EINVAL;
+    return -1;
+  }
+  return static_cast<int>((local_set[bit / LONG_BIT] >> (bit % LONG_BIT)) & 1);
+}
 
 __LIBC_HIDDEN__ sighandler_t _signal(int signum, sighandler_t handler, int flags) {
   struct sigaction sa;
@@ -44,3 +145,127 @@
 sighandler_t signal(int signum, sighandler_t handler) {
   return _signal(signum, handler, SA_RESTART);
 }
+
+int sigpause(int sig) {
+  kernel_sigset_t set;
+  set.clear();
+  if (__rt_sigprocmask(SIG_SETMASK, nullptr, &set, sizeof(set)) == -1) return -1;
+  if (!set.clear(sig)) return -1;
+  return __rt_sigsuspend(&set, sizeof(set));
+}
+
+int sigpending(sigset_t* bionic_set) {
+  kernel_sigset_t set;
+  int result = __rt_sigpending(&set, sizeof(set));
+  if (result != -1) {
+    *bionic_set = set.bionic;
+  }
+  return result;
+}
+
+int sigprocmask(int how, const sigset_t* bionic_new_set, sigset_t* bionic_old_set) {
+  kernel_sigset_t new_set;
+  kernel_sigset_t* new_set_ptr = NULL;
+  if (bionic_new_set != NULL) {
+    new_set.set(bionic_new_set);
+    new_set_ptr = &new_set;
+  }
+
+  kernel_sigset_t old_set;
+  if (__rt_sigprocmask(how, new_set_ptr, &old_set, sizeof(old_set)) == -1) {
+    return -1;
+  }
+
+  if (bionic_old_set != NULL) {
+    *bionic_old_set = old_set.bionic;
+  }
+
+  return 0;
+}
+
+int sigqueue(pid_t pid, int signo, const sigval value) {
+  siginfo_t info;
+  memset(&info, 0, sizeof(siginfo_t));
+  info.si_signo = signo;
+  info.si_code = SI_QUEUE;
+  info.si_pid = getpid();
+  info.si_uid = getuid();
+  info.si_value = value;
+
+  return ___rt_sigqueueinfo(pid, signo, &info);
+}
+
+int sigrelse(int sig) {
+  kernel_sigset_t set;
+  set.clear();
+  if (!set.set(sig)) return -1;
+  return __rt_sigprocmask(SIG_UNBLOCK, &set, nullptr, sizeof(set));
+}
+
+sighandler_t sigset(int sig, sighandler_t disp) {
+  struct sigaction new_sa;
+  if (disp != SIG_HOLD) {
+    memset(&new_sa, 0, sizeof(new_sa));
+    new_sa.sa_handler = disp;
+    sigemptyset(&new_sa.sa_mask);
+  }
+
+  struct sigaction old_sa;
+  if (sigaction(sig, (disp == SIG_HOLD) ? nullptr : &new_sa, &old_sa) == -1) {
+    return SIG_ERR;
+  }
+
+  kernel_sigset_t new_mask{sig};
+  kernel_sigset_t old_mask;
+  if (__rt_sigprocmask(disp == SIG_HOLD ? SIG_BLOCK : SIG_UNBLOCK, &new_mask, &old_mask,
+                       sizeof(new_mask)) == -1) {
+    return SIG_ERR;
+  }
+
+  return old_mask.is_set(sig) ? SIG_HOLD : old_sa.sa_handler;
+}
+
+// This isn't in our header files, but is exposed on all architectures.
+extern "C" int sigsetmask(int mask) {
+  union {
+    int mask;
+    sigset_t set;
+  } in, out;
+
+  sigemptyset(&in.set);
+  in.mask = mask;
+
+  if (sigprocmask(SIG_SETMASK, &in.set, &out.set) == -1) return -1;
+  return out.mask;
+}
+
+int sigsuspend(const sigset_t* bionic_set) {
+  kernel_sigset_t set(bionic_set);
+  return __rt_sigsuspend(&set, sizeof(set));
+}
+
+int sigtimedwait(const sigset_t* set, siginfo_t* info, const timespec* timeout) {
+  kernel_sigset_t sigset(set);
+  return __rt_sigtimedwait(sigset.get(), info, timeout, sizeof(sigset));
+}
+
+int sigwait(const sigset_t* set, int* sig) {
+  kernel_sigset_t sigset(set);
+  while (true) {
+    // __rt_sigtimedwait can return EAGAIN or EINTR, we need to loop
+    // around them since sigwait is only allowed to return EINVAL.
+    int result = __rt_sigtimedwait(sigset.get(), NULL, NULL, sizeof(sigset));
+    if (result >= 0) {
+      *sig = result;
+      return 0;
+    }
+
+    if (errno != EAGAIN && errno != EINTR) {
+      return errno;
+    }
+  }
+}
+
+int sigwaitinfo(const sigset_t* set, siginfo_t* info) {
+  return sigtimedwait(set, info, NULL);
+}
diff --git a/libc/bionic/sigpause.cpp b/libc/bionic/sigpause.cpp
deleted file mode 100644
index 8ba42d4..0000000
--- a/libc/bionic/sigpause.cpp
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <signal.h>
-
-int sigpause(int sig) {
-  sigset_t set;
-  if (sigprocmask(SIG_SETMASK, nullptr, &set) == -1) return -1;
-  if (sigdelset(&set, sig) == -1) return -1;
-  return sigsuspend(&set);
-}
diff --git a/libc/bionic/sigpending.cpp b/libc/bionic/sigpending.cpp
deleted file mode 100644
index b6e503c..0000000
--- a/libc/bionic/sigpending.cpp
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <signal.h>
-
-#include "private/kernel_sigset_t.h"
-
-extern "C" int __rt_sigpending(const kernel_sigset_t*, size_t);
-
-int sigpending(sigset_t* bionic_set) {
-  kernel_sigset_t set;
-  int result = __rt_sigpending(&set, sizeof(set));
-  if (result != -1) {
-    *bionic_set = set.bionic;
-  }
-  return result;
-}
diff --git a/libc/bionic/sigprocmask.cpp b/libc/bionic/sigprocmask.cpp
deleted file mode 100644
index 61e2c63..0000000
--- a/libc/bionic/sigprocmask.cpp
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <errno.h>
-#include <pthread.h>
-#include <signal.h>
-
-#include "private/kernel_sigset_t.h"
-
-extern "C" int __rt_sigprocmask(int, const kernel_sigset_t*, kernel_sigset_t*, size_t);
-
-int sigprocmask(int how, const sigset_t* bionic_new_set, sigset_t* bionic_old_set) {
-  kernel_sigset_t new_set;
-  kernel_sigset_t* new_set_ptr = NULL;
-  if (bionic_new_set != NULL) {
-    new_set.set(bionic_new_set);
-    new_set_ptr = &new_set;
-  }
-
-  kernel_sigset_t old_set;
-  if (__rt_sigprocmask(how, new_set_ptr, &old_set, sizeof(old_set)) == -1) {
-    return -1;
-  }
-
-  if (bionic_old_set != NULL) {
-    *bionic_old_set = old_set.bionic;
-  }
-
-  return 0;
-}
diff --git a/libc/bionic/sigqueue.cpp b/libc/bionic/sigqueue.cpp
deleted file mode 100644
index 8741460..0000000
--- a/libc/bionic/sigqueue.cpp
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2014 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 <signal.h>
-#include <string.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-extern "C" int ___rt_sigqueueinfo(pid_t, int, siginfo_t*);
-
-int sigqueue(pid_t pid, int signo, const sigval value) {
-  siginfo_t info;
-  memset(&info, 0, sizeof(siginfo_t));
-  info.si_signo = signo;
-  info.si_code = SI_QUEUE;
-  info.si_pid = getpid();
-  info.si_uid = getuid();
-  info.si_value = value;
-
-  return ___rt_sigqueueinfo(pid, signo, &info);
-}
diff --git a/libc/bionic/sigrelse.cpp b/libc/bionic/sigrelse.cpp
deleted file mode 100644
index ab5554e..0000000
--- a/libc/bionic/sigrelse.cpp
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <signal.h>
-
-int sigrelse(int sig) {
-  sigset_t set;
-  if (sigemptyset(&set) == -1) return -1;
-  if (sigaddset(&set, sig) == -1) return -1;
-  return sigprocmask(SIG_UNBLOCK, &set, nullptr);
-}
diff --git a/libc/bionic/sigset.cpp b/libc/bionic/sigset.cpp
deleted file mode 100644
index e3f3e72..0000000
--- a/libc/bionic/sigset.cpp
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <signal.h>
-#include <string.h>
-
-sighandler_t sigset(int sig, sighandler_t disp) {
-  struct sigaction new_sa;
-  if (disp != SIG_HOLD) {
-    memset(&new_sa, 0, sizeof(new_sa));
-    new_sa.sa_handler = disp;
-    sigemptyset(&new_sa.sa_mask);
-  }
-
-  struct sigaction old_sa;
-  if (sigaction(sig, disp == SIG_HOLD ? nullptr : &new_sa, &old_sa) == -1) {
-    return SIG_ERR;
-  }
-
-  sigset_t new_proc_mask;
-  sigemptyset(&new_proc_mask);
-  sigaddset(&new_proc_mask, sig);
-
-  sigset_t old_proc_mask;
-  if (sigprocmask(disp == SIG_HOLD ? SIG_BLOCK : SIG_UNBLOCK,
-                  &new_proc_mask, &old_proc_mask) == -1) {
-    return SIG_ERR;
-  }
-
-  return sigismember(&old_proc_mask, sig) ? SIG_HOLD : old_sa.sa_handler;
-}
diff --git a/libc/bionic/sigsetmask.c b/libc/bionic/sigsetmask.c
deleted file mode 100644
index 7842bf1..0000000
--- a/libc/bionic/sigsetmask.c
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-#include <signal.h>
-
-/* called from setjmp assembly fragment */
-int
-sigsetmask(int mask)
-{
-    int  n;
-
-    union {
-        int       the_mask;
-        sigset_t  the_sigset;
-    } in, out;
-
-    sigemptyset(&in.the_sigset);
-    in.the_mask = mask;
-
-    n = sigprocmask(SIG_SETMASK, &in.the_sigset, &out.the_sigset);
-    if (n)
-        return n;
-
-    return out.the_mask;
-}
-
diff --git a/libc/bionic/sigsuspend.cpp b/libc/bionic/sigsuspend.cpp
deleted file mode 100644
index fb846b8..0000000
--- a/libc/bionic/sigsuspend.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <signal.h>
-
-#include "private/kernel_sigset_t.h"
-
-extern "C" int __rt_sigsuspend(const kernel_sigset_t*, size_t);
-
-int sigsuspend(const sigset_t* bionic_set) {
-  kernel_sigset_t set(bionic_set);
-  return __rt_sigsuspend(&set, sizeof(set));
-}
diff --git a/libc/bionic/sigtimedwait.cpp b/libc/bionic/sigtimedwait.cpp
deleted file mode 100644
index c29f806..0000000
--- a/libc/bionic/sigtimedwait.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2014 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 <signal.h>
-
-#include "private/kernel_sigset_t.h"
-
-extern "C" int __rt_sigtimedwait(const sigset_t*, siginfo_t*, const timespec*, size_t);
-
-int sigtimedwait(const sigset_t* set, siginfo_t* info, const timespec* timeout) {
-  kernel_sigset_t sigset(set);
-  return __rt_sigtimedwait(sigset.get(), info, timeout, sizeof(sigset));
-}
diff --git a/libc/bionic/sigwait.cpp b/libc/bionic/sigwait.cpp
deleted file mode 100644
index 2534b89..0000000
--- a/libc/bionic/sigwait.cpp
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <errno.h>
-#include <signal.h>
-#include <string.h>
-#include <time.h>
-
-#include "private/kernel_sigset_t.h"
-
-extern "C" int __rt_sigtimedwait(const sigset_t*, siginfo_t*, const timespec*, size_t);
-
-int sigwait(const sigset_t* set, int* sig) {
-  kernel_sigset_t sigset(set);
-  while (true) {
-    // __rt_sigtimedwait can return EAGAIN or EINTR, we need to loop
-    // around them since sigwait is only allowed to return EINVAL.
-    int result = __rt_sigtimedwait(sigset.get(), NULL, NULL, sizeof(sigset));
-    if (result >= 0) {
-      *sig = result;
-      return 0;
-    }
-
-    if (errno != EAGAIN && errno != EINTR) {
-      return errno;
-    }
-  }
-}
diff --git a/libc/bionic/sigwaitinfo.cpp b/libc/bionic/sigwaitinfo.cpp
deleted file mode 100644
index 43e2395..0000000
--- a/libc/bionic/sigwaitinfo.cpp
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2014 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 <signal.h>
-
-int sigwaitinfo(const sigset_t* set, siginfo_t* info) {
-  return sigtimedwait(set, info, NULL);
-}
diff --git a/libc/bionic/signalfd.cpp b/libc/bionic/sys_signalfd.cpp
similarity index 100%
rename from libc/bionic/signalfd.cpp
rename to libc/bionic/sys_signalfd.cpp
diff --git a/libc/include/android/dlext.h b/libc/include/android/dlext.h
index c824544..2b4169e 100644
--- a/libc/include/android/dlext.h
+++ b/libc/include/android/dlext.h
@@ -23,88 +23,116 @@
 #include <sys/cdefs.h>
 #include <sys/types.h>  /* for off64_t */
 
+/**
+ * \file
+ * Advanced dynamic library opening support. Most users will want to use
+ * the standard [dlopen(3)](http://man7.org/linux/man-pages/man3/dlopen.3.html)
+ * functionality in `<dlfcn.h>` instead.
+ */
+
 __BEGIN_DECLS
 
-/* bitfield definitions for android_dlextinfo.flags */
+/** Bitfield definitions for `android_dlextinfo::flags`. */
 enum {
-  /* When set, the reserved_addr and reserved_size fields must point to an
+  /**
+   * When set, the `reserved_addr` and `reserved_size` fields must point to an
    * already-reserved region of address space which will be used to load the
-   * library if it fits. If the reserved region is not large enough, the load
-   * will fail.
+   * library if it fits.
+   *
+   * If the reserved region is not large enough, loading will fail.
    */
   ANDROID_DLEXT_RESERVED_ADDRESS      = 0x1,
 
-  /* As DLEXT_RESERVED_ADDRESS, but if the reserved region is not large enough,
+  /**
+   * Like `ANDROID_DLEXT_RESERVED_ADDRESS`, but if the reserved region is not large enough,
    * the linker will choose an available address instead.
    */
   ANDROID_DLEXT_RESERVED_ADDRESS_HINT = 0x2,
 
-  /* When set, write the GNU RELRO section of the mapped library to relro_fd
+  /**
+   * When set, write the GNU RELRO section of the mapped library to `relro_fd`
    * after relocation has been performed, to allow it to be reused by another
    * process loading the same library at the same address. This implies
-   * ANDROID_DLEXT_USE_RELRO.
+   * `ANDROID_DLEXT_USE_RELRO`.
+   *
+   * This is mainly useful for the system WebView implementation.
    */
   ANDROID_DLEXT_WRITE_RELRO           = 0x4,
 
-  /* When set, compare the GNU RELRO section of the mapped library to relro_fd
+  /**
+   * When set, compare the GNU RELRO section of the mapped library to `relro_fd`
    * after relocation has been performed, and replace any relocated pages that
    * are identical with a version mapped from the file.
+   *
+   * This is mainly useful for the system WebView implementation.
    */
   ANDROID_DLEXT_USE_RELRO             = 0x8,
 
-  /* Instruct dlopen to use library_fd instead of opening file by name.
+  /**
+   * Use `library_fd` instead of opening the file by name.
    * The filename parameter is still used to identify the library.
    */
   ANDROID_DLEXT_USE_LIBRARY_FD        = 0x10,
 
-  /* If opening a library using library_fd read it starting at library_fd_offset.
-   * This flag is only valid when ANDROID_DLEXT_USE_LIBRARY_FD is set.
+  /**
+   * If opening a library using `library_fd` read it starting at `library_fd_offset`.
+   * This is mainly useful for loading a library stored within another file (such as uncompressed
+   * inside a ZIP archive).
+   * This flag is only valid when `ANDROID_DLEXT_USE_LIBRARY_FD` is set.
    */
   ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET    = 0x20,
 
-  /* When set, do not check if the library has already been loaded by file stat(2)s.
+  /**
+   * When set, do not use `stat(2)` to check if the library has already been loaded.
    *
    * This flag allows forced loading of the library in the case when for some
    * reason multiple ELF files share the same filename (because the already-loaded
    * library has been removed and overwritten, for example).
    *
-   * Note that if the library has the same dt_soname as an old one and some other
-   * library has the soname in DT_NEEDED list, the first one will be used to resolve any
+   * Note that if the library has the same `DT_SONAME` as an old one and some other
+   * library has the soname in its `DT_NEEDED` list, the first one will be used to resolve any
    * dependencies.
    */
   ANDROID_DLEXT_FORCE_LOAD = 0x40,
 
-  /* When set, if the minimum p_vaddr of the ELF file's PT_LOAD segments is non-zero,
+  /**
+   * When set, if the minimum `p_vaddr` of the ELF file's `PT_LOAD` segments is non-zero,
    * the dynamic linker will load it at that address.
    *
    * This flag is for ART internal use only.
    */
   ANDROID_DLEXT_FORCE_FIXED_VADDR = 0x80,
 
-  /* Instructs dlopen to load the library at the address specified by reserved_addr.
+  /**
+   * Instructs dlopen to load the library at the address specified by reserved_addr.
    *
-   * The difference between ANDROID_DLEXT_LOAD_AT_FIXED_ADDRESS and ANDROID_DLEXT_RESERVED_ADDRESS
-   * is that for ANDROID_DLEXT_LOAD_AT_FIXED_ADDRESS the linker reserves memory at reserved_addr
-   * whereas for ANDROID_DLEXT_RESERVED_ADDRESS the linker relies on the caller to reserve the memory.
+   * The difference between `ANDROID_DLEXT_LOAD_AT_FIXED_ADDRESS` and
+   * `ANDROID_DLEXT_RESERVED_ADDRESS` is that for `ANDROID_DLEXT_LOAD_AT_FIXED_ADDRESS` the linker
+   * reserves memory at `reserved_addr` whereas for `ANDROID_DLEXT_RESERVED_ADDRESS` the linker
+   * relies on the caller to reserve the memory.
    *
-   * This flag can be used with ANDROID_DLEXT_FORCE_FIXED_VADDR; when ANDROID_DLEXT_FORCE_FIXED_VADDR
-   * is set and load_bias is not 0 (load_bias is min(p_vaddr) of PT_LOAD segments) this flag is ignored.
-   * This is implemented this way because the linker has to pick one address over the other and this
-   * way is more convenient for art. Note that ANDROID_DLEXT_FORCE_FIXED_VADDR does not generate
-   * an error when min(p_vaddr) is 0.
+   * This flag can be used with `ANDROID_DLEXT_FORCE_FIXED_VADDR`. When
+   * `ANDROID_DLEXT_FORCE_FIXED_VADDR` is set and `load_bias` is not 0 (`load_bias` is the
+   * minimum `p_vaddr` of all `PT_LOAD` segments) this flag is ignored because the linker has to
+   * pick one address over the other and this way is more convenient for ART.
+   * Note that `ANDROID_DLEXT_FORCE_FIXED_VADDR` does not generate an error when the minimum
+   * `p_vaddr` is 0.
    *
-   * Cannot be used with ANDROID_DLEXT_RESERVED_ADDRESS or ANDROID_DLEXT_RESERVED_ADDRESS_HINT.
+   * Cannot be used with `ANDROID_DLEXT_RESERVED_ADDRESS` or `ANDROID_DLEXT_RESERVED_ADDRESS_HINT`.
    *
    * This flag is for ART internal use only.
    */
   ANDROID_DLEXT_LOAD_AT_FIXED_ADDRESS = 0x100,
 
-  /* This flag used to load library in a different namespace. The namespace is
-   * specified in library_namespace.
+  /**
+   * This flag used to load library in a different namespace. The namespace is
+   * specified in `library_namespace`.
+   *
+   * This flag is for internal use only (since there is no NDK API for namespaces).
    */
   ANDROID_DLEXT_USE_NAMESPACE = 0x200,
 
-  /* Mask of valid bits */
+  /** Mask of valid bits. */
   ANDROID_DLEXT_VALID_FLAG_BITS       = ANDROID_DLEXT_RESERVED_ADDRESS |
                                         ANDROID_DLEXT_RESERVED_ADDRESS_HINT |
                                         ANDROID_DLEXT_WRITE_RELRO |
@@ -119,19 +147,36 @@
 
 struct android_namespace_t;
 
+/** Used to pass Android-specific arguments to `android_dlopen_ext`. */
 typedef struct {
+  /** A bitmask of `ANDROID_DLEXT_` enum values. */
   uint64_t flags;
+
+  /** Used by `ANDROID_DLEXT_RESERVED_ADDRESS` and `ANDROID_DLEXT_RESERVED_ADDRESS_HINT`. */
   void*   reserved_addr;
+  /** Used by `ANDROID_DLEXT_RESERVED_ADDRESS` and `ANDROID_DLEXT_RESERVED_ADDRESS_HINT`. */
   size_t  reserved_size;
+
+  /** Used by `ANDROID_DLEXT_WRITE_RELRO` and `ANDROID_DLEXT_USE_RELRO`. */
   int     relro_fd;
+
+  /** Used by `ANDROID_DLEXT_USE_LIBRARY_FD`. */
   int     library_fd;
+  /** Used by `ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET` */
   off64_t library_fd_offset;
+
+  /** Used by `ANDROID_DLEXT_USE_NAMESPACE`. */
   struct android_namespace_t* library_namespace;
 } android_dlextinfo;
 
+/**
+ * Opens the given library. The `__filename` and `__flags` arguments are
+ * the same as for [dlopen(3)](http://man7.org/linux/man-pages/man3/dlopen.3.html),
+ * with the Android-specific flags supplied via the `flags` member of `__info`.
+ */
 void* android_dlopen_ext(const char* __filename, int __flags, const android_dlextinfo* __info)
   __INTRODUCED_IN(21);
 
 __END_DECLS
 
-#endif /* __ANDROID_DLEXT_H__ */
+#endif
diff --git a/libc/include/bits/fortify/fcntl.h b/libc/include/bits/fortify/fcntl.h
index 6d90341..75cd4f2 100644
--- a/libc/include/bits/fortify/fcntl.h
+++ b/libc/include/bits/fortify/fcntl.h
@@ -98,7 +98,7 @@
 __errordecl(__creat_too_many_args, __open_too_many_args_error);
 
 #if __ANDROID_API__ >= __ANDROID_API_J_MR1__
-__BIONIC_FORTIFY_INLINE
+__BIONIC_FORTIFY_VARIADIC
 int open(const char* pathname, int flags, ...) {
     if (__builtin_constant_p(flags)) {
         if (__open_modes_useful(flags) && __builtin_va_arg_pack_len() == 0) {
@@ -117,7 +117,7 @@
     return __open_real(pathname, flags, __builtin_va_arg_pack());
 }
 
-__BIONIC_FORTIFY_INLINE
+__BIONIC_FORTIFY_VARIADIC
 int openat(int dirfd, const char* pathname, int flags, ...) {
     if (__builtin_constant_p(flags)) {
         if (__open_modes_useful(flags) && __builtin_va_arg_pack_len() == 0) {
diff --git a/libc/include/bits/fortify/stdio.h b/libc/include/bits/fortify/stdio.h
index cfc78d7..6a6b433 100644
--- a/libc/include/bits/fortify/stdio.h
+++ b/libc/include/bits/fortify/stdio.h
@@ -63,8 +63,7 @@
                 "format string will always overflow destination buffer")
     __errorattr("format string will always overflow destination buffer");
 
-__BIONIC_FORTIFY_INLINE
-__printflike(3, 4)
+__BIONIC_FORTIFY_VARIADIC __printflike(3, 4)
 int snprintf(char* const __pass_object_size dest, size_t size, const char* format, ...)
         __overloadable {
     va_list va;
@@ -82,8 +81,7 @@
                 "format string will always overflow destination buffer")
     __errorattr("format string will always overflow destination buffer");
 
-__BIONIC_FORTIFY_INLINE
-__printflike(2, 3)
+__BIONIC_FORTIFY_VARIADIC __printflike(2, 3)
 int sprintf(char* const __pass_object_size dest, const char* format, ...) __overloadable {
     va_list va;
     va_start(va, format);
@@ -159,12 +157,12 @@
 
 
 #if __ANDROID_API__ >= __ANDROID_API_J_MR1__
-__BIONIC_FORTIFY_INLINE __printflike(3, 4)
+__BIONIC_FORTIFY_VARIADIC __printflike(3, 4)
 int snprintf(char* dest, size_t size, const char* format, ...) {
     return __builtin___snprintf_chk(dest, size, 0, __bos(dest), format, __builtin_va_arg_pack());
 }
 
-__BIONIC_FORTIFY_INLINE __printflike(2, 3)
+__BIONIC_FORTIFY_VARIADIC __printflike(2, 3)
 int sprintf(char* dest, const char* format, ...) {
     return __builtin___sprintf_chk(dest, 0, __bos(dest), format, __builtin_va_arg_pack());
 }
diff --git a/libc/include/elf.h b/libc/include/elf.h
index bda11f5..a8d62db 100644
--- a/libc/include/elf.h
+++ b/libc/include/elf.h
@@ -194,13 +194,9 @@
   Elf64_Word vna_next;
 } Elf64_Vernaux;
 
-/* Relocation table entry for relative (in section of type SHT_RELR).  */
+/* Relocation table entry for relative (in section of type SHT_RELR). */
 typedef Elf32_Word Elf32_Relr;
 typedef Elf64_Xword Elf64_Relr;
-#define ELF32_R_JUMP(val) ((val) >> 24)
-#define ELF32_R_BITS(val) ((val) & 0xffffff)
-#define ELF64_R_JUMP(val) ((val) >> 56)
-#define ELF64_R_BITS(val) ((val) & 0xffffffffffffff)
 
 /* http://www.sco.com/developers/gabi/latest/ch5.dynamic.html */
 #define DF_ORIGIN     0x00000001
diff --git a/libc/include/sys/cdefs.h b/libc/include/sys/cdefs.h
index 3cf6723..be07007 100644
--- a/libc/include/sys/cdefs.h
+++ b/libc/include/sys/cdefs.h
@@ -300,6 +300,13 @@
  * inline` without making them available externally.
  */
 #    define __BIONIC_FORTIFY_INLINE static __inline__ __always_inline
+/*
+ * We should use __BIONIC_FORTIFY_VARIADIC instead of __BIONIC_FORTIFY_INLINE
+ * for variadic functions because compilers cannot inline them.
+ * The __always_inline attribute is useless, misleading, and could trigger
+ * clang compiler bug to incorrectly inline variadic functions.
+ */
+#    define __BIONIC_FORTIFY_VARIADIC static __inline__
 /* Error functions don't have bodies, so they can just be static. */
 #    define __BIONIC_ERROR_FUNCTION_VISIBILITY static
 #  else
@@ -311,6 +318,8 @@
 #    define __call_bypassing_fortify(fn) (fn)
 /* __BIONIC_FORTIFY_NONSTATIC_INLINE is pointless in GCC's FORTIFY */
 #    define __BIONIC_FORTIFY_INLINE extern __inline__ __always_inline __attribute__((gnu_inline)) __attribute__((__artificial__))
+/* __always_inline is probably okay and ignored by gcc in __BIONIC_FORTIFY_VARIADIC */
+#    define __BIONIC_FORTIFY_VARIADIC __BIONIC_FORTIFY_INLINE
 #  endif
 #else
 /* Further increase sharing for some inline functions */
diff --git a/libc/include/sys/ioctl.h b/libc/include/sys/ioctl.h
index 76dc1ff..b48b7f9 100644
--- a/libc/include/sys/ioctl.h
+++ b/libc/include/sys/ioctl.h
@@ -36,8 +36,6 @@
  * terminal-related ioctl data structures such as struct winsize.
  */
 #include <linux/termios.h>
-#include <asm/ioctls.h>
-#include <asm/termbits.h>
 #include <linux/tty.h>
 
 #include <bits/ioctl.h>
diff --git a/libc/private/ScopedSignalBlocker.h b/libc/private/ScopedSignalBlocker.h
index 35d1c58..c3ab307 100644
--- a/libc/private/ScopedSignalBlocker.h
+++ b/libc/private/ScopedSignalBlocker.h
@@ -20,13 +20,14 @@
 #include <signal.h>
 
 #include "bionic_macros.h"
+#include "kernel_sigset_t.h"
 
 class ScopedSignalBlocker {
  public:
   explicit ScopedSignalBlocker() {
-    sigset_t set;
-    sigfillset(&set);
-    sigprocmask(SIG_BLOCK, &set, &old_set_);
+    kernel_sigset_t set;
+    set.fill();
+    __rt_sigprocmask(SIG_SETMASK, &set, &old_set_, sizeof(set));
   }
 
   ~ScopedSignalBlocker() {
@@ -34,11 +35,11 @@
   }
 
   void reset() {
-    sigprocmask(SIG_SETMASK, &old_set_, nullptr);
+    __rt_sigprocmask(SIG_SETMASK, &old_set_, nullptr, sizeof(old_set_));
   }
 
  private:
-  sigset_t old_set_;
+  kernel_sigset_t old_set_;
 
   DISALLOW_COPY_AND_ASSIGN(ScopedSignalBlocker);
 };
diff --git a/libc/private/kernel_sigset_t.h b/libc/private/kernel_sigset_t.h
index 9415fcf..bdfb729 100644
--- a/libc/private/kernel_sigset_t.h
+++ b/libc/private/kernel_sigset_t.h
@@ -17,18 +17,27 @@
 #ifndef LIBC_PRIVATE_KERNEL_SIGSET_T_H_
 #define LIBC_PRIVATE_KERNEL_SIGSET_T_H_
 
+#include <errno.h>
 #include <signal.h>
 
+#include <async_safe/log.h>
+
 // Our sigset_t is wrong for ARM and x86. It's 32-bit but the kernel expects 64 bits.
-// This means we can't support real-time signals correctly until we can change the ABI.
+// This means we can't support real-time signals correctly without breaking the ABI.
 // In the meantime, we can use this union to pass an appropriately-sized block of memory
-// to the kernel, at the cost of not being able to refer to real-time signals.
+// to the kernel, at the cost of not being able to refer to real-time signals when
+// initializing from a sigset_t on LP32.
 union kernel_sigset_t {
+ public:
   kernel_sigset_t() {
-    clear();
   }
 
-  kernel_sigset_t(const sigset_t* value) {
+  explicit kernel_sigset_t(int signal_number) {
+    clear();
+    if (!set(signal_number)) async_safe_fatal("kernel_sigset_t(%d)", signal_number);
+  }
+
+  explicit kernel_sigset_t(const sigset_t* value) {
     clear();
     set(value);
   }
@@ -37,7 +46,32 @@
     __builtin_memset(this, 0, sizeof(*this));
   }
 
+  bool clear(int signal_number) {
+    int bit = bit_of(signal_number);
+    if (bit == -1) return false;
+    bits[bit / LONG_BIT] &= ~(1UL << (bit % LONG_BIT));
+    return true;
+  }
+
+  void fill() {
+    __builtin_memset(this, 0xff, sizeof(*this));
+  }
+
+  bool is_set(int signal_number) {
+    int bit = bit_of(signal_number);
+    if (bit == -1) return false;
+    return ((bits[bit / LONG_BIT] >> (bit % LONG_BIT)) & 1) == 1;
+  }
+
+  bool set(int signal_number) {
+    int bit = bit_of(signal_number);
+    if (bit == -1) return false;
+    bits[bit / LONG_BIT] |= 1UL << (bit % LONG_BIT);
+    return true;
+  }
+
   void set(const sigset_t* value) {
+    clear();
     bionic = *value;
   }
 
@@ -46,9 +80,21 @@
   }
 
   sigset_t bionic;
-#ifndef __mips__
-  uint32_t kernel[2];
-#endif
+  unsigned long bits[_KERNEL__NSIG/LONG_BIT];
+
+ private:
+  int bit_of(int signal_number) {
+    int bit = signal_number - 1; // Signal numbers start at 1, but bit positions start at 0.
+    if (bit < 0 || bit >= static_cast<int>(8*sizeof(*this))) {
+      errno = EINVAL;
+      return -1;
+    }
+    return bit;
+  }
 };
 
+extern "C" int __rt_sigpending(const kernel_sigset_t*, size_t);
+extern "C" int __rt_sigprocmask(int, const kernel_sigset_t*, kernel_sigset_t*, size_t);
+extern "C" int __rt_sigsuspend(const kernel_sigset_t*, size_t);
+
 #endif
diff --git a/libdl/libdl.arm.map b/libdl/libdl.arm.map
index 7ed9503..1fcfc58 100644
--- a/libdl/libdl.arm.map
+++ b/libdl/libdl.arm.map
@@ -41,11 +41,6 @@
     __cfi_slowpath_diag;
 } LIBC_N;
 
-LIBC_PRIVATE {
-  global:
-    android_link_namespaces_all_libs;
-} LIBC_OMR1;
-
 LIBC_PLATFORM {
   global:
     __cfi_init;
diff --git a/libdl/libdl.arm64.map b/libdl/libdl.arm64.map
index 199f2e3..8d4019c 100644
--- a/libdl/libdl.arm64.map
+++ b/libdl/libdl.arm64.map
@@ -40,11 +40,6 @@
     __cfi_slowpath_diag;
 } LIBC_N;
 
-LIBC_PRIVATE {
-  global:
-    android_link_namespaces_all_libs;
-} LIBC_OMR1;
-
 LIBC_PLATFORM {
   global:
     __cfi_init;
diff --git a/libdl/libdl.cpp b/libdl/libdl.cpp
index 4c2415f..c834088 100644
--- a/libdl/libdl.cpp
+++ b/libdl/libdl.cpp
@@ -93,11 +93,6 @@
                                 const char* shared_libs_sonames);
 
 __attribute__((__weak__, visibility("default")))
-bool __loader_android_link_namespaces_all_libs(
-                                struct android_namespace_t* namespace_from,
-                                struct android_namespace_t* namespace_to);
-
-__attribute__((__weak__, visibility("default")))
 void __loader_android_dlwarning(void* obj, void (*f)(void*, const char*));
 
 __attribute__((__weak__, visibility("default")))
@@ -210,12 +205,6 @@
 }
 
 __attribute__((__weak__))
-bool android_link_namespaces_all_libs(struct android_namespace_t* namespace_from,
-                                      struct android_namespace_t* namespace_to) {
-  return __loader_android_link_namespaces_all_libs(namespace_from, namespace_to);
-}
-
-__attribute__((__weak__))
 void android_dlwarning(void* obj, void (*f)(void*, const char*)) {
   __loader_android_dlwarning(obj, f);
 }
diff --git a/libdl/libdl.map.txt b/libdl/libdl.map.txt
index 579ffa7..002e9f8 100644
--- a/libdl/libdl.map.txt
+++ b/libdl/libdl.map.txt
@@ -40,11 +40,6 @@
     __cfi_slowpath_diag;
 } LIBC_N;
 
-LIBC_PRIVATE {
-  global:
-    android_link_namespaces_all_libs;
-} LIBC_OMR1;
-
 LIBC_PLATFORM {
   global:
     __cfi_init;
diff --git a/libdl/libdl.mips.map b/libdl/libdl.mips.map
index 199f2e3..8d4019c 100644
--- a/libdl/libdl.mips.map
+++ b/libdl/libdl.mips.map
@@ -40,11 +40,6 @@
     __cfi_slowpath_diag;
 } LIBC_N;
 
-LIBC_PRIVATE {
-  global:
-    android_link_namespaces_all_libs;
-} LIBC_OMR1;
-
 LIBC_PLATFORM {
   global:
     __cfi_init;
diff --git a/libdl/libdl.mips64.map b/libdl/libdl.mips64.map
index 199f2e3..8d4019c 100644
--- a/libdl/libdl.mips64.map
+++ b/libdl/libdl.mips64.map
@@ -40,11 +40,6 @@
     __cfi_slowpath_diag;
 } LIBC_N;
 
-LIBC_PRIVATE {
-  global:
-    android_link_namespaces_all_libs;
-} LIBC_OMR1;
-
 LIBC_PLATFORM {
   global:
     __cfi_init;
diff --git a/libdl/libdl.x86.map b/libdl/libdl.x86.map
index 199f2e3..8d4019c 100644
--- a/libdl/libdl.x86.map
+++ b/libdl/libdl.x86.map
@@ -40,11 +40,6 @@
     __cfi_slowpath_diag;
 } LIBC_N;
 
-LIBC_PRIVATE {
-  global:
-    android_link_namespaces_all_libs;
-} LIBC_OMR1;
-
 LIBC_PLATFORM {
   global:
     __cfi_init;
diff --git a/libdl/libdl.x86_64.map b/libdl/libdl.x86_64.map
index 199f2e3..8d4019c 100644
--- a/libdl/libdl.x86_64.map
+++ b/libdl/libdl.x86_64.map
@@ -40,11 +40,6 @@
     __cfi_slowpath_diag;
 } LIBC_N;
 
-LIBC_PRIVATE {
-  global:
-    android_link_namespaces_all_libs;
-} LIBC_OMR1;
-
 LIBC_PLATFORM {
   global:
     __cfi_init;
diff --git a/linker/ld_android.cpp b/linker/ld_android.cpp
index 4a05772..e2499b3 100644
--- a/linker/ld_android.cpp
+++ b/linker/ld_android.cpp
@@ -29,14 +29,6 @@
 #include <stdlib.h>
 #include <sys/cdefs.h>
 
-extern "C" void __somehow_you_managed_to_not_get_the_actual_symbols_from_the_linker();
-
-extern "C" void __ld_android_init() __attribute__((constructor));
-
-void __ld_android_init() {
-  __somehow_you_managed_to_not_get_the_actual_symbols_from_the_linker();
-}
-
 extern "C" void __internal_linker_error() {
   abort();
 }
diff --git a/linker/linker.cpp b/linker/linker.cpp
index 0b8d5ee..3f898ba 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -2614,31 +2614,46 @@
   return true;
 }
 
+void soinfo::apply_relr_reloc(ElfW(Addr) offset) {
+  ElfW(Addr) address = offset + load_bias;
+  *reinterpret_cast<ElfW(Addr)*>(address) += load_bias;
+}
+
 // Process relocations in SHT_RELR section (experimental).
-// See the original proposal for details of the encoding:
-// - https://groups.google.com/forum/#!topic/generic-abi/bX460iggiKg
+// Details of the encoding are described in this post:
+//   https://groups.google.com/d/msg/generic-abi/bX460iggiKg/Pi9aSwwABgAJ
 bool soinfo::relocate_relr() {
   ElfW(Relr)* begin = relr_;
   ElfW(Relr)* end = relr_ + relr_count_;
+  constexpr size_t wordsize = sizeof(ElfW(Addr));
 
-  ElfW(Addr) offset = 0;
+  ElfW(Addr) base = 0;
   for (ElfW(Relr)* current = begin; current < end; ++current) {
-    ElfW(Addr) jump = ELFW(R_JUMP)(*current);
-    ElfW(Addr) bits = ELFW(R_BITS)(*current);
-    offset += jump * sizeof(ElfW(Addr));
-    if (jump == 0) {
-      ++current;
-      offset = *current;
+    ElfW(Relr) entry = *current;
+    ElfW(Addr) offset;
+
+    if ((entry&1) == 0) {
+      // Even entry: encodes the offset for next relocation.
+      offset = static_cast<ElfW(Addr)>(entry);
+      apply_relr_reloc(offset);
+      // Set base offset for subsequent bitmap entries.
+      base = offset + wordsize;
+      continue;
     }
-    ElfW(Addr) r_offset = offset;
-    for (; bits != 0; bits >>= 1) {
-      if ((bits&1) != 0) {
-        ElfW(Addr) reloc = static_cast<ElfW(Addr)>(r_offset + load_bias);
-        ElfW(Addr) addend = *reinterpret_cast<ElfW(Addr)*>(reloc);
-        *reinterpret_cast<ElfW(Addr)*>(reloc) = (load_bias + addend);
+
+    // Odd entry: encodes bitmap for relocations starting at base.
+    offset = base;
+    while (entry != 0) {
+      entry >>= 1;
+      if ((entry&1) != 0) {
+        apply_relr_reloc(offset);
       }
-      r_offset += sizeof(ElfW(Addr));
+      offset += wordsize;
     }
+
+    // Advance base offset by 63 words for 64-bit platforms,
+    // or 31 words for 32-bit platforms.
+    base += (8*wordsize - 1) * wordsize;
   }
   return true;
 }
diff --git a/linker/linker_soinfo.h b/linker/linker_soinfo.h
index cb607a9..447c7c3 100644
--- a/linker/linker_soinfo.h
+++ b/linker/linker_soinfo.h
@@ -310,6 +310,7 @@
   bool relocate(const VersionTracker& version_tracker, ElfRelIteratorT&& rel_iterator,
                 const soinfo_list_t& global_group, const soinfo_list_t& local_group);
   bool relocate_relr();
+  void apply_relr_reloc(ElfW(Addr) offset);
 
  private:
   // This part of the structure is only available
diff --git a/tests/Android.bp b/tests/Android.bp
index 1521b73..25377df 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -413,6 +413,7 @@
     target: {
         android: {
             shared_libs: [
+                "ld-android",
                 "libdl",
                 "libdl_preempt_test_1",
                 "libdl_preempt_test_2",
diff --git a/tests/ScopedSignalHandler.h b/tests/ScopedSignalHandler.h
index 8998d0d..71f22dc 100644
--- a/tests/ScopedSignalHandler.h
+++ b/tests/ScopedSignalHandler.h
@@ -53,13 +53,13 @@
   const int signal_number_;
 };
 
-class ScopedSignalMask {
+class SignalMaskRestorer {
  public:
-  ScopedSignalMask() {
+  SignalMaskRestorer() {
     sigprocmask(SIG_SETMASK, nullptr, &old_mask_);
   }
 
-  ~ScopedSignalMask() {
+  ~SignalMaskRestorer() {
     sigprocmask(SIG_SETMASK, &old_mask_, nullptr);
   }
 
diff --git a/tests/dlext_test.cpp b/tests/dlext_test.cpp
index bb2d8a3..9ed1a56 100644
--- a/tests/dlext_test.cpp
+++ b/tests/dlext_test.cpp
@@ -1737,6 +1737,9 @@
   ASSERT_EQ(expected_dlerror, dlerror());
 }
 
+extern "C" bool __loader_android_link_namespaces_all_libs(android_namespace_t* namespace_from,
+                                                          android_namespace_t* namespace_to);
+
 TEST(dlext, ns_link_namespaces_invalid_arguments) {
   ASSERT_TRUE(android_init_anonymous_namespace(g_core_shared_libs.c_str(), nullptr));
 
@@ -1764,16 +1767,16 @@
                "error linking namespaces \"private\"->\"(default)\": "
                "the list of shared libraries is empty.", dlerror());
 
-  // Test android_link_namespaces_all_libs()
-  ASSERT_FALSE(android_link_namespaces_all_libs(nullptr, nullptr));
+  // Test __loader_android_link_namespaces_all_libs()
+  ASSERT_FALSE(__loader_android_link_namespaces_all_libs(nullptr, nullptr));
   ASSERT_STREQ("android_link_namespaces_all_libs failed: "
                "error linking namespaces: namespace_from is null.", dlerror());
 
-  ASSERT_FALSE(android_link_namespaces_all_libs(nullptr, ns));
+  ASSERT_FALSE(__loader_android_link_namespaces_all_libs(nullptr, ns));
   ASSERT_STREQ("android_link_namespaces_all_libs failed: "
                "error linking namespaces: namespace_from is null.", dlerror());
 
-  ASSERT_FALSE(android_link_namespaces_all_libs(ns, nullptr));
+  ASSERT_FALSE(__loader_android_link_namespaces_all_libs(ns, nullptr));
   ASSERT_STREQ("android_link_namespaces_all_libs failed: "
                "error linking namespaces: namespace_to is null.", dlerror());
 }
@@ -1802,7 +1805,7 @@
   ASSERT_TRUE(android_link_namespaces(ns_b, nullptr, g_core_shared_libs.c_str())) << dlerror();
 
   ASSERT_TRUE(android_link_namespaces(ns_b, ns_a, "libnstest_ns_a_public1.so")) << dlerror();
-  ASSERT_TRUE(android_link_namespaces_all_libs(ns_a, ns_b)) << dlerror();
+  ASSERT_TRUE(__loader_android_link_namespaces_all_libs(ns_a, ns_b)) << dlerror();
 
   // Load libs with android_dlopen_ext() from namespace b
   android_dlextinfo extinfo;
diff --git a/tests/headers/posix/pthread_h.c b/tests/headers/posix/pthread_h.c
index 4fa5b9d..4be822c 100644
--- a/tests/headers/posix/pthread_h.c
+++ b/tests/headers/posix/pthread_h.c
@@ -57,9 +57,9 @@
 
   MACRO(PTHREAD_ONCE_INIT);
 
-#if !defined(__BIONIC__) // No robust mutexes on Android.
   MACRO(PTHREAD_PRIO_INHERIT);
   MACRO(PTHREAD_PRIO_NONE);
+#if !defined(__BIONIC__)
   MACRO(PTHREAD_PRIO_PROTECT);
 #endif
 
@@ -158,8 +158,8 @@
   FUNCTION(pthread_mutexattr_destroy, int (*f)(pthread_mutexattr_t*));
 #if !defined(__BIONIC__) // No robust mutexes on Android.
   FUNCTION(pthread_mutexattr_getprioceiling, int (*f)(const pthread_mutexattr_t*, int*));
-  FUNCTION(pthread_mutexattr_getprotocol, int (*f)(const pthread_mutexattr_t*, int*));
 #endif
+  FUNCTION(pthread_mutexattr_getprotocol, int (*f)(const pthread_mutexattr_t*, int*));
   FUNCTION(pthread_mutexattr_getpshared, int (*f)(const pthread_mutexattr_t*, int*));
 #if !defined(__BIONIC__) // No robust mutexes on Android.
   FUNCTION(pthread_mutexattr_getrobust, int (*f)(const pthread_mutexattr_t*, int*));
@@ -168,8 +168,8 @@
   FUNCTION(pthread_mutexattr_init, int (*f)(pthread_mutexattr_t*));
 #if !defined(__BIONIC__) // No robust mutexes on Android.
   FUNCTION(pthread_mutexattr_setprioceiling, int (*f)(pthread_mutexattr_t*, int));
-  FUNCTION(pthread_mutexattr_setprotocol, int (*f)(pthread_mutexattr_t*, int));
 #endif
+  FUNCTION(pthread_mutexattr_setprotocol, int (*f)(pthread_mutexattr_t*, int));
   FUNCTION(pthread_mutexattr_setpshared, int (*f)(pthread_mutexattr_t*, int));
 #if !defined(__BIONIC__) // No robust mutexes on Android.
   FUNCTION(pthread_mutexattr_setrobust, int (*f)(pthread_mutexattr_t*, int));
diff --git a/tests/signal_test.cpp b/tests/signal_test.cpp
index 207c156..5cbec88 100644
--- a/tests/signal_test.cpp
+++ b/tests/signal_test.cpp
@@ -464,33 +464,45 @@
   ASSERT_EQ(EINVAL, errno);
 }
 
-TEST(signal, sighold_sigpause_sigrelse) {
-  static int sigalrm_handler_call_count;
-  auto sigalrm_handler = [](int) { sigalrm_handler_call_count++; };
-  ScopedSignalHandler sigalrm{SIGALRM, sigalrm_handler};
-  ScopedSignalMask mask;
+static void TestSigholdSigpauseSigrelse(int sig) {
+  static int signal_handler_call_count = 0;
+  ScopedSignalHandler ssh{sig, [](int) { signal_handler_call_count++; }};
+  SignalMaskRestorer mask_restorer;
   sigset_t set;
 
-  // sighold(SIGALRM) should add SIGALRM to the signal mask ...
-  ASSERT_EQ(0, sighold(SIGALRM));
+  // sighold(SIGALRM/SIGRTMIN) should add SIGALRM/SIGRTMIN to the signal mask ...
+  ASSERT_EQ(0, sighold(sig));
   ASSERT_EQ(0, sigprocmask(SIG_SETMASK, 0, &set));
-  EXPECT_TRUE(sigismember(&set, SIGALRM));
+  EXPECT_TRUE(sigismember(&set, sig));
 
-  // ... preventing our SIGALRM handler from running ...
-  raise(SIGALRM);
-  ASSERT_EQ(0, sigalrm_handler_call_count);
-  // ... until sigpause(SIGALRM) temporarily unblocks it.
-  ASSERT_EQ(-1, sigpause(SIGALRM));
+  // ... preventing our SIGALRM/SIGRTMIN handler from running ...
+  raise(sig);
+  ASSERT_EQ(0, signal_handler_call_count);
+  // ... until sigpause(SIGALRM/SIGRTMIN) temporarily unblocks it.
+  ASSERT_EQ(-1, sigpause(sig));
   ASSERT_EQ(EINTR, errno);
-  ASSERT_EQ(1, sigalrm_handler_call_count);
+  ASSERT_EQ(1, signal_handler_call_count);
 
-  // But sigpause(SIGALRM) shouldn't permanently unblock SIGALRM.
-  ASSERT_EQ(0, sigprocmask(SIG_SETMASK, 0, &set));
-  EXPECT_TRUE(sigismember(&set, SIGALRM));
+  if (sig >= SIGRTMIN && sizeof(void*) == 8) {
+    // But sigpause(SIGALRM/SIGRTMIN) shouldn't permanently unblock SIGALRM/SIGRTMIN.
+    ASSERT_EQ(0, sigprocmask(SIG_SETMASK, 0, &set));
+    EXPECT_TRUE(sigismember(&set, sig));
 
-  ASSERT_EQ(0, sigrelse(SIGALRM));
-  ASSERT_EQ(0, sigprocmask(SIG_SETMASK, 0, &set));
-  EXPECT_FALSE(sigismember(&set, SIGALRM));
+    // Whereas sigrelse(SIGALRM/SIGRTMIN) should.
+    ASSERT_EQ(0, sigrelse(sig));
+    ASSERT_EQ(0, sigprocmask(SIG_SETMASK, 0, &set));
+    EXPECT_FALSE(sigismember(&set, sig));
+  } else {
+    // sigismember won't work for SIGRTMIN on LP32.
+  }
+}
+
+TEST(signal, sighold_sigpause_sigrelse) {
+  TestSigholdSigpauseSigrelse(SIGALRM);
+}
+
+TEST(signal, sighold_sigpause_sigrelse_RT) {
+  TestSigholdSigpauseSigrelse(SIGRTMIN);
 }
 
 TEST(signal, sigset_EINVAL) {
@@ -499,23 +511,48 @@
   ASSERT_EQ(EINVAL, errno);
 }
 
-TEST(signal, sigset) {
-  auto sigalrm_handler = [](int) { };
-  ScopedSignalHandler sigalrm{SIGALRM, sigalrm_handler};
-  ScopedSignalMask mask;
+TEST(signal, sigset_RT) {
+  static int signal_handler_call_count = 0;
+  auto signal_handler = [](int) { signal_handler_call_count++; };
+  ScopedSignalHandler ssh{SIGRTMIN, signal_handler};
+  SignalMaskRestorer mask_restorer;
 
-  // block SIGALRM so the next sigset(SIGARLM) call will return SIG_HOLD
-  sigset_t sigalrm_set;
-  sigemptyset(&sigalrm_set);
-  sigaddset(&sigalrm_set, SIGALRM);
-  ASSERT_EQ(0, sigprocmask(SIG_BLOCK, &sigalrm_set, nullptr));
-
+  ASSERT_EQ(signal_handler, sigset(SIGRTMIN, SIG_HOLD));
+#if defined(__LP64__)
   sigset_t set;
-  ASSERT_EQ(SIG_HOLD, sigset(SIGALRM, sigalrm_handler));
+  ASSERT_EQ(0, sigprocmask(SIG_BLOCK, nullptr, &set));
+  ASSERT_TRUE(sigismember(&set, SIGRTMIN));
+#endif
+
+  ASSERT_EQ(SIG_HOLD, sigset(SIGRTMIN, signal_handler));
+  ASSERT_EQ(signal_handler, sigset(SIGRTMIN, signal_handler));
+  ASSERT_EQ(0, signal_handler_call_count);
+  raise(SIGRTMIN);
+  ASSERT_EQ(1, signal_handler_call_count);
+}
+
+TEST(signal, sigset) {
+  static int signal_handler_call_count = 0;
+  auto signal_handler = [](int) { signal_handler_call_count++; };
+  ScopedSignalHandler ssh{SIGALRM, signal_handler};
+  SignalMaskRestorer mask_restorer;
+
+  ASSERT_EQ(0, signal_handler_call_count);
+  raise(SIGALRM);
+  ASSERT_EQ(1, signal_handler_call_count);
+
+  // Block SIGALRM so the next sigset(SIGARLM) call will return SIG_HOLD.
+  sigset_t set;
+  sigemptyset(&set);
+  sigaddset(&set, SIGALRM);
+  ASSERT_EQ(0, sigprocmask(SIG_BLOCK, &set, nullptr));
+
+  sigemptyset(&set);
+  ASSERT_EQ(SIG_HOLD, sigset(SIGALRM, signal_handler));
   ASSERT_EQ(0, sigprocmask(SIG_BLOCK, nullptr, &set));
   EXPECT_FALSE(sigismember(&set, SIGALRM));
 
-  ASSERT_EQ(sigalrm_handler, sigset(SIGALRM, SIG_IGN));
+  ASSERT_EQ(signal_handler, sigset(SIGALRM, SIG_IGN));
   ASSERT_EQ(0, sigprocmask(SIG_BLOCK, nullptr, &set));
   EXPECT_FALSE(sigismember(&set, SIGALRM));
 
diff --git a/tests/spawn_test.cpp b/tests/spawn_test.cpp
index d2e4ea1..dfce0dc 100644
--- a/tests/spawn_test.cpp
+++ b/tests/spawn_test.cpp
@@ -376,6 +376,7 @@
   sigset_t just_SIGALRM;
   sigemptyset(&just_SIGALRM);
   sigaddset(&just_SIGALRM, SIGALRM);
+
   ASSERT_EQ(0, posix_spawnattr_setsigdefault(&sa, &just_SIGALRM));
   ASSERT_EQ(0, posix_spawnattr_setflags(&sa, POSIX_SPAWN_SETSIGDEF));
 
@@ -393,15 +394,18 @@
   // child without first defaulting any caught signals (http://b/68707996).
   static pid_t parent = getpid();
 
+  setpgid(0, 0);
+
   pid_t pid = fork();
   ASSERT_NE(-1, pid);
 
   if (pid == 0) {
+    signal(SIGRTMIN, SIG_IGN);
     for (size_t i = 0; i < 1024; ++i) {
-      kill(0, SIGWINCH);
+      kill(0, SIGRTMIN);
       usleep(10);
     }
-    return;
+    _exit(99);
   }
 
   // We test both with and without attributes, because they used to be
@@ -417,11 +421,15 @@
 
   posix_spawnattr_t* attrs[] = { nullptr, &attr1, &attr2 };
 
-  ScopedSignalHandler ssh(SIGWINCH, [](int) { ASSERT_EQ(getpid(), parent); });
+  // We use a real-time signal because that's a tricky case for LP32
+  // because our sigset_t was too small.
+  ScopedSignalHandler ssh(SIGRTMIN, [](int) { ASSERT_EQ(getpid(), parent); });
 
   ExecTestHelper eth;
   eth.SetArgs({"true", nullptr});
   for (size_t i = 0; i < 128; ++i) {
     posix_spawn(nullptr, "true", nullptr, attrs[i % 3], eth.GetArgs(), nullptr);
   }
+
+  AssertChildExited(pid, 99);
 }