Add `sigset64_t` and accompanying functions.

This doesn't address `struct sigaction` and `sigaction`. That will
come later.

Bug: http://b/72493232
Test: ran tests
Change-Id: I4134346757ce3a4dac6feae413361cec16223386
diff --git a/tests/Android.bp b/tests/Android.bp
index 25377df..443fe8e 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -140,6 +140,7 @@
         "sys_sem_test.cpp",
         "sys_sendfile_test.cpp",
         "sys_shm_test.cpp",
+        "sys_signalfd_test.cpp",
         "sys_socket_test.cpp",
         "sys_stat_test.cpp",
         "sys_statvfs_test.cpp",
diff --git a/tests/ScopedSignalHandler.h b/tests/ScopedSignalHandler.h
index 71f22dc..85c41a8 100644
--- a/tests/ScopedSignalHandler.h
+++ b/tests/ScopedSignalHandler.h
@@ -20,6 +20,26 @@
 #include <signal.h>
 #include <string.h>
 
+#if defined(__GLIBC__)
+#define posix_spawnattr_getsigdefault64 posix_spawnattr_getsigdefault
+#define posix_spawnattr_getsigmask64 posix_spawnattr_getsigmask
+#define posix_spawnattr_setsigdefault64 posix_spawnattr_setsigdefault
+#define posix_spawnattr_setsigmask64 posix_spawnattr_setsigmask
+#define pthread_sigmask64 pthread_sigmask
+#define sigaddset64 sigaddset
+#define sigdelset64 sigdelset
+#define sigemptyset64 sigemptyset
+#define sigfillset64 sigfillset
+#define sigismember64 sigismember
+#define sigpending64 sigpending
+#define sigprocmask64 sigprocmask
+#define sigset64_t sigset_t
+#define sigsuspend64 sigsuspend
+#define sigtimedwait64 sigtimedwait
+#define sigwait64 sigwait
+#define sigwaitinfo64 sigwaitinfo
+#endif
+
 class ScopedSignalHandler {
  public:
   ScopedSignalHandler(int signal_number, void (*handler)(int), int sa_flags = 0)
@@ -56,15 +76,15 @@
 class SignalMaskRestorer {
  public:
   SignalMaskRestorer() {
-    sigprocmask(SIG_SETMASK, nullptr, &old_mask_);
+    sigprocmask64(SIG_SETMASK, nullptr, &old_mask_);
   }
 
   ~SignalMaskRestorer() {
-    sigprocmask(SIG_SETMASK, &old_mask_, nullptr);
+    sigprocmask64(SIG_SETMASK, &old_mask_, nullptr);
   }
 
  private:
-  sigset_t old_mask_;
+  sigset64_t old_mask_;
 };
 
 #endif // _BIONIC_TESTS_SCOPED_SIGNAL_HANDLER_H
diff --git a/tests/pthread_test.cpp b/tests/pthread_test.cpp
index 9ecb10c..f812df5 100644
--- a/tests/pthread_test.cpp
+++ b/tests/pthread_test.cpp
@@ -356,9 +356,9 @@
 }
 
 static void* SignalHandlerFn(void* arg) {
-  sigset_t wait_set;
-  sigfillset(&wait_set);
-  return reinterpret_cast<void*>(sigwait(&wait_set, reinterpret_cast<int*>(arg)));
+  sigset64_t wait_set;
+  sigfillset64(&wait_set);
+  return reinterpret_cast<void*>(sigwait64(&wait_set, reinterpret_cast<int*>(arg)));
 }
 
 TEST(pthread, pthread_sigmask) {
@@ -402,6 +402,47 @@
   ASSERT_EQ(0, pthread_sigmask(SIG_SETMASK, &original_set, NULL));
 }
 
+TEST(pthread, pthread_sigmask64_SIGTRMIN) {
+  // Check that SIGRTMIN isn't blocked.
+  sigset64_t original_set;
+  sigemptyset64(&original_set);
+  ASSERT_EQ(0, pthread_sigmask64(SIG_BLOCK, NULL, &original_set));
+  ASSERT_FALSE(sigismember64(&original_set, SIGRTMIN));
+
+  // Block SIGRTMIN.
+  sigset64_t set;
+  sigemptyset64(&set);
+  sigaddset64(&set, SIGRTMIN);
+  ASSERT_EQ(0, pthread_sigmask64(SIG_BLOCK, &set, NULL));
+
+  // Check that SIGRTMIN is blocked.
+  sigset64_t final_set;
+  sigemptyset64(&final_set);
+  ASSERT_EQ(0, pthread_sigmask64(SIG_BLOCK, NULL, &final_set));
+  ASSERT_TRUE(sigismember64(&final_set, SIGRTMIN));
+  // ...and that sigprocmask64 agrees with pthread_sigmask64.
+  sigemptyset64(&final_set);
+  ASSERT_EQ(0, sigprocmask64(SIG_BLOCK, NULL, &final_set));
+  ASSERT_TRUE(sigismember64(&final_set, SIGRTMIN));
+
+  // Spawn a thread that calls sigwait64 and tells us what it received.
+  pthread_t signal_thread;
+  int received_signal = -1;
+  ASSERT_EQ(0, pthread_create(&signal_thread, NULL, SignalHandlerFn, &received_signal));
+
+  // Send that thread SIGRTMIN.
+  pthread_kill(signal_thread, SIGRTMIN);
+
+  // See what it got.
+  void* join_result;
+  ASSERT_EQ(0, pthread_join(signal_thread, &join_result));
+  ASSERT_EQ(SIGRTMIN, received_signal);
+  ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(join_result));
+
+  // Restore the original signal mask.
+  ASSERT_EQ(0, pthread_sigmask64(SIG_SETMASK, &original_set, NULL));
+}
+
 static void test_pthread_setname_np__pthread_getname_np(pthread_t t) {
   ASSERT_EQ(0, pthread_setname_np(t, "short"));
   char name[32];
diff --git a/tests/signal_test.cpp b/tests/signal_test.cpp
index 5cbec88..ebc079e 100644
--- a/tests/signal_test.cpp
+++ b/tests/signal_test.cpp
@@ -20,57 +20,45 @@
 #include <sys/types.h>
 #include <unistd.h>
 
+#include <thread>
+
 #include <gtest/gtest.h>
 
 #include "ScopedSignalHandler.h"
 
-static size_t SIGNAL_MIN() {
+static int SIGNAL_MIN() {
   return 1; // Signals start at 1 (SIGHUP), not 0.
 }
 
-static size_t SIGNAL_MAX() {
-  size_t result = SIGRTMAX;
-
-#if defined(__BIONIC__) && !defined(__mips__) && !defined(__LP64__)
-  // 32-bit bionic's sigset_t is too small for ARM and x86: 32 bits instead of 64.
-  // This means you can't refer to any of the real-time signals.
-  // See http://b/3038348 and http://b/5828899.
-  result = 32;
-#else
-  // Otherwise, C libraries should be perfectly capable of using their largest signal.
-  if (sizeof(sigset_t) * 8 < static_cast<size_t>(SIGRTMAX)) {
-    abort();
-  }
-#endif
-
-  return result;
+template <typename SigSetT>
+static int SIGNAL_MAX(SigSetT* set) {
+  return sizeof(*set) * 8;
 }
 
-template <typename Fn>
-static void TestSigSet1(Fn fn) {
-  // NULL sigset_t*.
-  sigset_t* set_ptr = NULL;
+template <typename SigSetT>
+static void TestSigSet1(int (fn)(SigSetT*)) {
+  // NULL sigset_t*/sigset64_t*.
+  SigSetT* set_ptr = NULL;
   errno = 0;
   ASSERT_EQ(-1, fn(set_ptr));
   ASSERT_EQ(EINVAL, errno);
 
   // Non-NULL.
-  sigset_t set;
+  SigSetT set = {};
   errno = 0;
   ASSERT_EQ(0, fn(&set));
   ASSERT_EQ(0, errno);
 }
 
-template <typename Fn>
-static void TestSigSet2(Fn fn) {
-  // NULL sigset_t*.
-  sigset_t* set_ptr = NULL;
+template <typename SigSetT>
+static void TestSigSet2(int (fn)(SigSetT*, int)) {
+  // NULL sigset_t*/sigset64_t*.
+  SigSetT* set_ptr = NULL;
   errno = 0;
   ASSERT_EQ(-1, fn(set_ptr, SIGSEGV));
   ASSERT_EQ(EINVAL, errno);
 
-  sigset_t set;
-  sigemptyset(&set);
+  SigSetT set = {};
 
   // Bad signal number: too small.
   errno = 0;
@@ -79,37 +67,67 @@
 
   // Bad signal number: too high.
   errno = 0;
-  ASSERT_EQ(-1, fn(&set, SIGNAL_MAX() + 1));
+  ASSERT_EQ(-1, fn(&set, SIGNAL_MAX(&set) + 1));
   ASSERT_EQ(EINVAL, errno);
 
   // Good signal numbers, low and high ends of range.
   errno = 0;
   ASSERT_EQ(0, fn(&set, SIGNAL_MIN()));
   ASSERT_EQ(0, errno);
-  ASSERT_EQ(0, fn(&set, SIGNAL_MAX()));
+  ASSERT_EQ(0, fn(&set, SIGNAL_MAX(&set)));
   ASSERT_EQ(0, errno);
 }
 
-TEST(signal, sigismember_invalid) {
-  TestSigSet2(sigismember);
-}
-
 TEST(signal, sigaddset_invalid) {
   TestSigSet2(sigaddset);
 }
 
+TEST(signal, sigaddset64_invalid) {
+#if defined(__BIONIC__)
+  TestSigSet2(sigaddset64);
+#endif
+}
+
 TEST(signal, sigdelset_invalid) {
   TestSigSet2(sigdelset);
 }
 
+TEST(signal, sigdelset64_invalid) {
+#if defined(__BIONIC__)
+  TestSigSet2(sigdelset64);
+#endif
+}
+
 TEST(signal, sigemptyset_invalid) {
   TestSigSet1(sigemptyset);
 }
 
+TEST(signal, sigemptyset64_invalid) {
+#if defined(__BIONIC__)
+  TestSigSet1(sigemptyset64);
+#endif
+}
+
 TEST(signal, sigfillset_invalid) {
   TestSigSet1(sigfillset);
 }
 
+TEST(signal, sigfillset64_invalid) {
+#if defined(__BIONIC__)
+  TestSigSet1(sigfillset64);
+#endif
+}
+
+TEST(signal, sigismember_invalid) {
+  TestSigSet2(sigismember);
+}
+
+TEST(signal, sigismember64_invalid) {
+#if defined(__BIONIC__)
+  TestSigSet2(sigismember64);
+#endif
+}
+
 TEST(signal, raise_invalid) {
   errno = 0;
   ASSERT_EQ(-1, raise(-1));
@@ -129,12 +147,8 @@
   raise(SIGALRM);
 }
 
-static void HandleSIGALRM(int signal_number) {
-  ASSERT_EQ(SIGALRM, signal_number);
-}
-
-TEST(signal, sigwait) {
-  ScopedSignalHandler ssh(SIGALRM, HandleSIGALRM);
+TEST(signal, sigwait_SIGALRM) {
+  ScopedSignalHandler ssh(SIGALRM, [](int sig) { ASSERT_EQ(SIGALRM, sig); });
 
   sigset_t wait_set;
   sigemptyset(&wait_set);
@@ -149,38 +163,57 @@
   ASSERT_EQ(SIGALRM, received_signal);
 }
 
-static int g_sigsuspend_test_helper_call_count = 0;
+TEST(signal, sigwait64_SIGRTMIN) {
+  ScopedSignalHandler ssh(SIGRTMIN, [](int sig) { ASSERT_EQ(SIGRTMIN, sig); });
 
-static void SigSuspendTestHelper(int) {
-  ++g_sigsuspend_test_helper_call_count;
+  sigset64_t wait_set;
+  sigemptyset64(&wait_set);
+  sigaddset64(&wait_set, SIGRTMIN);
+
+  pid_t pid = getpid();
+  std::thread thread([&pid]() {
+    usleep(5000);
+    kill(pid, SIGRTMIN);
+  });
+
+  int received_signal;
+  errno = 0;
+  ASSERT_EQ(0, sigwait64(&wait_set, &received_signal));
+  ASSERT_EQ(0, errno);
+  ASSERT_EQ(SIGRTMIN, received_signal);
+
+  thread.join();
 }
 
+static int g_sigsuspend_signal_handler_call_count = 0;
+
 TEST(signal, sigsuspend_sigpending) {
+  SignalMaskRestorer smr;
+
   // Block SIGALRM.
   sigset_t just_SIGALRM;
   sigemptyset(&just_SIGALRM);
   sigaddset(&just_SIGALRM, SIGALRM);
-  sigset_t original_set;
-  ASSERT_EQ(0, sigprocmask(SIG_BLOCK, &just_SIGALRM, &original_set));
+  ASSERT_EQ(0, sigprocmask(SIG_BLOCK, &just_SIGALRM, nullptr));
 
-  ScopedSignalHandler ssh(SIGALRM, SigSuspendTestHelper);
+  ScopedSignalHandler ssh(SIGALRM, [](int) { ++g_sigsuspend_signal_handler_call_count; });
 
   // There should be no pending signals.
   sigset_t pending;
   sigemptyset(&pending);
   ASSERT_EQ(0, sigpending(&pending));
-  for (size_t i = SIGNAL_MIN(); i <= SIGNAL_MAX(); ++i) {
+  for (int i = SIGNAL_MIN(); i <= SIGNAL_MAX(&pending); ++i) {
     EXPECT_FALSE(sigismember(&pending, i)) << i;
   }
 
   // Raise SIGALRM and check our signal handler wasn't called.
   raise(SIGALRM);
-  ASSERT_EQ(0, g_sigsuspend_test_helper_call_count);
+  ASSERT_EQ(0, g_sigsuspend_signal_handler_call_count);
 
   // We should now have a pending SIGALRM but nothing else.
   sigemptyset(&pending);
   ASSERT_EQ(0, sigpending(&pending));
-  for (size_t i = SIGNAL_MIN(); i <= SIGNAL_MAX(); ++i) {
+  for (int i = SIGNAL_MIN(); i <= SIGNAL_MAX(&pending); ++i) {
     EXPECT_EQ((i == SIGALRM), sigismember(&pending, i));
   }
 
@@ -191,10 +224,49 @@
   ASSERT_EQ(-1, sigsuspend(&not_SIGALRM));
   ASSERT_EQ(EINTR, errno);
   // ...and check that we now receive our pending SIGALRM.
-  ASSERT_EQ(1, g_sigsuspend_test_helper_call_count);
+  ASSERT_EQ(1, g_sigsuspend_signal_handler_call_count);
+}
 
-  // Restore the original set.
-  ASSERT_EQ(0, sigprocmask(SIG_SETMASK, &original_set, NULL));
+static int g_sigsuspend64_signal_handler_call_count = 0;
+
+TEST(signal, sigsuspend64_sigpending64) {
+  SignalMaskRestorer smr;
+
+  // Block SIGRTMIN.
+  sigset64_t just_SIGRTMIN;
+  sigemptyset64(&just_SIGRTMIN);
+  sigaddset64(&just_SIGRTMIN, SIGRTMIN);
+  ASSERT_EQ(0, sigprocmask64(SIG_BLOCK, &just_SIGRTMIN, nullptr));
+
+  ScopedSignalHandler ssh(SIGRTMIN, [](int) { ++g_sigsuspend64_signal_handler_call_count; });
+
+  // There should be no pending signals.
+  sigset64_t pending;
+  sigemptyset64(&pending);
+  ASSERT_EQ(0, sigpending64(&pending));
+  for (int i = SIGNAL_MIN(); i <= SIGNAL_MAX(&pending); ++i) {
+    EXPECT_FALSE(sigismember64(&pending, i)) << i;
+  }
+
+  // Raise SIGRTMIN and check our signal handler wasn't called.
+  raise(SIGRTMIN);
+  ASSERT_EQ(0, g_sigsuspend64_signal_handler_call_count);
+
+  // We should now have a pending SIGRTMIN but nothing else.
+  sigemptyset64(&pending);
+  ASSERT_EQ(0, sigpending64(&pending));
+  for (int i = SIGNAL_MIN(); i <= SIGNAL_MAX(&pending); ++i) {
+    EXPECT_EQ((i == SIGRTMIN), sigismember64(&pending, i));
+  }
+
+  // Use sigsuspend64 to block everything except SIGRTMIN...
+  sigset64_t not_SIGRTMIN;
+  sigfillset64(&not_SIGRTMIN);
+  sigdelset64(&not_SIGRTMIN, SIGRTMIN);
+  ASSERT_EQ(-1, sigsuspend64(&not_SIGRTMIN));
+  ASSERT_EQ(EINTR, errno);
+  // ...and check that we now receive our pending SIGRTMIN.
+  ASSERT_EQ(1, g_sigsuspend64_signal_handler_call_count);
 }
 
 static void EmptySignalHandler(int) {}
@@ -301,12 +373,13 @@
 }
 
 TEST(signal, sigwaitinfo) {
+  SignalMaskRestorer smr;
+
   // Block SIGALRM.
   sigset_t just_SIGALRM;
   sigemptyset(&just_SIGALRM);
   sigaddset(&just_SIGALRM, SIGALRM);
-  sigset_t original_set;
-  ASSERT_EQ(0, sigprocmask(SIG_BLOCK, &just_SIGALRM, &original_set));
+  ASSERT_EQ(0, sigprocmask(SIG_BLOCK, &just_SIGALRM, nullptr));
 
   // Raise SIGALRM.
   sigval_t sigval;
@@ -320,38 +393,75 @@
   ASSERT_EQ(0, errno);
   ASSERT_EQ(SIGALRM, info.si_signo);
   ASSERT_EQ(1, info.si_value.sival_int);
+}
 
-  ASSERT_EQ(0, sigprocmask(SIG_SETMASK, &original_set, NULL));
+TEST(signal, sigwaitinfo64_SIGRTMIN) {
+  SignalMaskRestorer smr;
+
+  // Block SIGRTMIN.
+  sigset64_t just_SIGRTMIN;
+  sigemptyset64(&just_SIGRTMIN);
+  sigaddset64(&just_SIGRTMIN, SIGRTMIN);
+  ASSERT_EQ(0, sigprocmask64(SIG_BLOCK, &just_SIGRTMIN, nullptr));
+
+  // Raise SIGRTMIN.
+  sigval_t sigval;
+  sigval.sival_int = 1;
+  ASSERT_EQ(0, sigqueue(getpid(), SIGRTMIN, sigval));
+
+  // Get pending SIGRTMIN.
+  siginfo_t info;
+  errno = 0;
+  ASSERT_EQ(SIGRTMIN, sigwaitinfo64(&just_SIGRTMIN, &info));
+  ASSERT_EQ(0, errno);
+  ASSERT_EQ(SIGRTMIN, info.si_signo);
+  ASSERT_EQ(1, info.si_value.sival_int);
 }
 
 TEST(signal, sigtimedwait) {
+  SignalMaskRestorer smr;
+
   // Block SIGALRM.
   sigset_t just_SIGALRM;
   sigemptyset(&just_SIGALRM);
   sigaddset(&just_SIGALRM, SIGALRM);
-  sigset_t original_set;
-  ASSERT_EQ(0, sigprocmask(SIG_BLOCK, &just_SIGALRM, &original_set));
+  ASSERT_EQ(0, sigprocmask(SIG_BLOCK, &just_SIGALRM, nullptr));
 
   // Raise SIGALRM.
-  sigval_t sigval;
-  sigval.sival_int = 1;
+  sigval_t sigval = { .sival_int = 1 };
   ASSERT_EQ(0, sigqueue(getpid(), SIGALRM, sigval));
 
   // Get pending SIGALRM.
   siginfo_t info;
-  struct timespec timeout;
-  timeout.tv_sec = 2;
-  timeout.tv_nsec = 0;
+  timespec timeout = { .tv_sec = 2, .tv_nsec = 0 };
   errno = 0;
   ASSERT_EQ(SIGALRM, sigtimedwait(&just_SIGALRM, &info, &timeout));
   ASSERT_EQ(0, errno);
+}
 
-  ASSERT_EQ(0, sigprocmask(SIG_SETMASK, &original_set, NULL));
+TEST(signal, sigtimedwait64_SIGRTMIN) {
+  SignalMaskRestorer smr;
+
+  // Block SIGRTMIN.
+  sigset64_t just_SIGRTMIN;
+  sigemptyset64(&just_SIGRTMIN);
+  sigaddset64(&just_SIGRTMIN, SIGRTMIN);
+  ASSERT_EQ(0, sigprocmask64(SIG_BLOCK, &just_SIGRTMIN, nullptr));
+
+  // Raise SIGALRM.
+  sigval_t sigval = { .sival_int = 1 };
+  ASSERT_EQ(0, sigqueue(getpid(), SIGRTMIN, sigval));
+
+  // Get pending SIGALRM.
+  siginfo_t info;
+  timespec timeout = { .tv_sec = 2, .tv_nsec = 0 };
+  errno = 0;
+  ASSERT_EQ(SIGRTMIN, sigtimedwait64(&just_SIGRTMIN, &info, &timeout));
+  ASSERT_EQ(0, errno);
 }
 
 static int64_t NanoTime() {
-  struct timespec t;
-  t.tv_sec = t.tv_nsec = 0;
+  timespec t;
   clock_gettime(CLOCK_MONOTONIC, &t);
   return static_cast<int64_t>(t.tv_sec) * 1000000000LL + t.tv_nsec;
 }
@@ -367,9 +477,7 @@
   // Wait timeout.
   int64_t start_time = NanoTime();
   siginfo_t info;
-  struct timespec timeout;
-  timeout.tv_sec = 0;
-  timeout.tv_nsec = 1000000;
+  timespec timeout = { .tv_sec = 0, .tv_nsec = 1000000 };
   errno = 0;
   ASSERT_EQ(-1, sigtimedwait(&just_SIGALRM, &info, &timeout));
   ASSERT_EQ(EAGAIN, errno);
@@ -411,18 +519,20 @@
                                             << sent.si_code << ", received " << received.si_code
                                             << error_msg;
 }
+#endif
 
-#if defined(__arm__) || defined(__aarch64__) || defined(__i386__) || defined(__x86_64__)
 TEST(signal, sigset_size) {
   // The setjmp implementations for ARM, AArch64, x86, and x86_64 assume that sigset_t can fit in a
   // long. This is true because ARM and x86 have broken rt signal support, and AArch64 and x86_64
   // both have a SIGRTMAX defined as 64.
+#if defined(__arm__) || defined(__aarch64__) || defined(__i386__) || defined(__x86_64__)
+#if defined(__BIONIC__)
   static_assert(sizeof(sigset_t) <= sizeof(long), "sigset_t doesn't fit in a long");
+#endif
+  static_assert(sizeof(sigset64_t)*8 >= 64, "sigset64_t too small for real-time signals");
+#endif
 }
 
-#endif
-#endif
-
 TEST(signal, sigignore_EINVAL) {
   errno = 0;
   ASSERT_EQ(-1, sigignore(99999));
diff --git a/tests/spawn_test.cpp b/tests/spawn_test.cpp
index dfce0dc..84df16d 100644
--- a/tests/spawn_test.cpp
+++ b/tests/spawn_test.cpp
@@ -96,6 +96,25 @@
   ASSERT_EQ(0, posix_spawnattr_destroy(&sa));
 }
 
+TEST(spawn, posix_spawnattr_setsigmask64_posix_spawnattr_getsigmask64) {
+  posix_spawnattr_t sa;
+  ASSERT_EQ(0, posix_spawnattr_init(&sa));
+
+  sigset64_t sigs;
+  ASSERT_EQ(0, posix_spawnattr_getsigmask64(&sa, &sigs));
+  ASSERT_FALSE(sigismember64(&sigs, SIGRTMIN));
+
+  sigset64_t just_SIGRTMIN;
+  sigemptyset64(&just_SIGRTMIN);
+  sigaddset64(&just_SIGRTMIN, SIGRTMIN);
+  ASSERT_EQ(0, posix_spawnattr_setsigmask64(&sa, &just_SIGRTMIN));
+
+  ASSERT_EQ(0, posix_spawnattr_getsigmask64(&sa, &sigs));
+  ASSERT_TRUE(sigismember64(&sigs, SIGRTMIN));
+
+  ASSERT_EQ(0, posix_spawnattr_destroy(&sa));
+}
+
 TEST(spawn, posix_spawnattr_setsigdefault_posix_spawnattr_getsigdefault) {
   posix_spawnattr_t sa;
   ASSERT_EQ(0, posix_spawnattr_init(&sa));
@@ -115,6 +134,25 @@
   ASSERT_EQ(0, posix_spawnattr_destroy(&sa));
 }
 
+TEST(spawn, posix_spawnattr_setsigdefault64_posix_spawnattr_getsigdefault64) {
+  posix_spawnattr_t sa;
+  ASSERT_EQ(0, posix_spawnattr_init(&sa));
+
+  sigset64_t sigs;
+  ASSERT_EQ(0, posix_spawnattr_getsigdefault64(&sa, &sigs));
+  ASSERT_FALSE(sigismember64(&sigs, SIGRTMIN));
+
+  sigset64_t just_SIGRTMIN;
+  sigemptyset64(&just_SIGRTMIN);
+  sigaddset64(&just_SIGRTMIN, SIGRTMIN);
+  ASSERT_EQ(0, posix_spawnattr_setsigdefault64(&sa, &just_SIGRTMIN));
+
+  ASSERT_EQ(0, posix_spawnattr_getsigdefault64(&sa, &sigs));
+  ASSERT_TRUE(sigismember64(&sigs, SIGRTMIN));
+
+  ASSERT_EQ(0, posix_spawnattr_destroy(&sa));
+}
+
 TEST(spawn, posix_spawnattr_setsschedparam_posix_spawnattr_getsschedparam) {
   posix_spawnattr_t sa;
   ASSERT_EQ(0, posix_spawnattr_init(&sa));
diff --git a/tests/sys_epoll_test.cpp b/tests/sys_epoll_test.cpp
index d1b411a..7233ccc 100644
--- a/tests/sys_epoll_test.cpp
+++ b/tests/sys_epoll_test.cpp
@@ -35,6 +35,11 @@
   // epoll_pwait without a sigset (which is equivalent to epoll_wait).
   ASSERT_EQ(0, epoll_pwait(epoll_fd, events, 1, 1, NULL));
 
+#if defined(__BIONIC__)
+  // epoll_pwait64 without a sigset (which is equivalent to epoll_wait).
+  ASSERT_EQ(0, epoll_pwait64(epoll_fd, events, 1, 1, NULL));
+#endif
+
   // epoll_pwait with a sigset.
   sigset_t ss;
   sigemptyset(&ss);
diff --git a/tests/sys_signalfd_test.cpp b/tests/sys_signalfd_test.cpp
new file mode 100644
index 0000000..67a72e0
--- /dev/null
+++ b/tests/sys_signalfd_test.cpp
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2018 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 <gtest/gtest.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <sys/signalfd.h>
+#include <unistd.h>
+
+#include <thread>
+
+#include "ScopedSignalHandler.h"
+
+static void TestSignalFd(int fd, int signal) {
+  ASSERT_NE(-1, fd) << strerror(errno);
+
+  ASSERT_EQ(0, raise(signal));
+
+  signalfd_siginfo sfd_si;
+  ASSERT_EQ(static_cast<ssize_t>(sizeof(sfd_si)), read(fd, &sfd_si, sizeof(sfd_si)));
+
+  ASSERT_EQ(signal, static_cast<int>(sfd_si.ssi_signo));
+
+  close(fd);
+}
+
+TEST(sys_signalfd, signalfd) {
+  SignalMaskRestorer smr;
+
+  sigset_t mask = {};
+  sigaddset(&mask, SIGALRM);
+  ASSERT_EQ(0, sigprocmask(SIG_SETMASK, &mask, nullptr));
+
+  TestSignalFd(signalfd(-1, &mask, SFD_CLOEXEC), SIGALRM);
+}
+
+TEST(sys_signalfd, signalfd64) {
+#if defined(__BIONIC__)
+  SignalMaskRestorer smr;
+
+  sigset64_t mask = {};
+  sigaddset64(&mask, SIGRTMIN);
+  ASSERT_EQ(0, sigprocmask64(SIG_SETMASK, &mask, nullptr));
+
+  TestSignalFd(signalfd64(-1, &mask, SFD_CLOEXEC), SIGRTMIN);
+#endif
+}