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/libc/Android.bp b/libc/Android.bp
index 2ea8514..0f58204 100644
--- a/libc/Android.bp
+++ b/libc/Android.bp
@@ -1248,9 +1248,6 @@
         "bionic/dirent.cpp",
         "bionic/dup2.cpp",
         "bionic/environ.cpp",
-        "bionic/epoll_create.cpp",
-        "bionic/epoll_pwait.cpp",
-        "bionic/epoll_wait.cpp",
         "bionic/error.cpp",
         "bionic/eventfd_read.cpp",
         "bionic/eventfd_write.cpp",
@@ -1350,6 +1347,7 @@
         "bionic/swab.cpp",
         "bionic/symlink.cpp",
         "bionic/sync_file_range.cpp",
+        "bionic/sys_epoll.cpp",
         "bionic/sys_msg.cpp",
         "bionic/sys_sem.cpp",
         "bionic/sys_shm.cpp",
@@ -1431,7 +1429,6 @@
         "bionic/pthread_self.cpp",
         "bionic/pthread_setname_np.cpp",
         "bionic/pthread_setschedparam.cpp",
-        "bionic/pthread_sigmask.cpp",
         "bionic/pthread_spinlock.cpp",
 
         // The following implementations depend on pthread data or implementation,
diff --git a/libc/SYSCALLS.TXT b/libc/SYSCALLS.TXT
index 5c9a284..5c63c0f 100644
--- a/libc/SYSCALLS.TXT
+++ b/libc/SYSCALLS.TXT
@@ -229,12 +229,12 @@
 # signals
 int     __sigaction:sigaction(int, const struct sigaction*, struct sigaction*)  arm,mips,x86
 int     __rt_sigaction:rt_sigaction(int, const struct sigaction*, struct sigaction*, size_t)  all
-int     __rt_sigpending:rt_sigpending(sigset_t*, size_t)  all
-int     __rt_sigprocmask:rt_sigprocmask(int, const sigset_t*, sigset_t*, size_t)  all
-int     __rt_sigsuspend:rt_sigsuspend(const sigset_t*, size_t)  all
-int     __rt_sigtimedwait:rt_sigtimedwait(const sigset_t*, siginfo_t*, const timespec*, size_t)  all
+int     __rt_sigpending:rt_sigpending(sigset64_t*, size_t)  all
+int     __rt_sigprocmask:rt_sigprocmask(int, const sigset64_t*, sigset64_t*, size_t)  all
+int     __rt_sigsuspend:rt_sigsuspend(const sigset64_t*, size_t)  all
+int     __rt_sigtimedwait:rt_sigtimedwait(const sigset64_t*, siginfo_t*, const timespec*, size_t)  all
 int     ___rt_sigqueueinfo:rt_sigqueueinfo(pid_t, int, siginfo_t*)  all
-int     __signalfd4:signalfd4(int, const sigset_t*, size_t, int)  all
+int     __signalfd4:signalfd4(int, const sigset64_t*, size_t, int)  all
 
 # sockets
 int           __socket:socket(int, int, int)              arm,arm64,mips,mips64,x86_64
@@ -305,7 +305,7 @@
 
 int epoll_create1(int)  all
 int epoll_ctl(int, int op, int, struct epoll_event*)  all
-int __epoll_pwait:epoll_pwait(int, struct epoll_event*, int, int, const sigset_t*, size_t)  all
+int __epoll_pwait:epoll_pwait(int, struct epoll_event*, int, int, const sigset64_t*, size_t)  all
 
 int eventfd:eventfd2(unsigned int, int)  all
 
@@ -317,7 +317,7 @@
 int inotify_rm_watch(int, unsigned int)  all
 
 int __pselect6:pselect6(int, fd_set*, fd_set*, fd_set*, timespec*, void*)  all
-int __ppoll:ppoll(pollfd*, unsigned int, timespec*, const sigset_t*, size_t)  all
+int __ppoll:ppoll(pollfd*, unsigned int, timespec*, const sigset64_t*, size_t)  all
 
 ssize_t process_vm_readv(pid_t, const struct iovec*, unsigned long, const struct iovec*, unsigned long, unsigned long)  all
 ssize_t process_vm_writev(pid_t, const struct iovec*, unsigned long, const struct iovec*, unsigned long, unsigned long)  all
diff --git a/libc/bionic/abort.cpp b/libc/bionic/abort.cpp
index 9f1c31f..ec26a50 100644
--- a/libc/bionic/abort.cpp
+++ b/libc/bionic/abort.cpp
@@ -32,8 +32,6 @@
 #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) {
@@ -62,11 +60,11 @@
 
   // Don't block SIGABRT to give any signal handler a chance; we ignore
   // any errors -- X311J doesn't allow abort to return anyway.
-  kernel_sigset_t mask;
-  mask.fill();
-  mask.clear(SIGABRT);
-  __rt_sigprocmask(SIG_SETMASK, &mask, nullptr, sizeof(mask));
+  sigset64_t mask;
+  sigfillset64(&mask);
+  sigdelset64(&mask, SIGABRT);
 
+  sigprocmask64(SIG_SETMASK, &mask, nullptr);
   inline_tgkill(pid, tid, SIGABRT);
 
   // If SIGABRT ignored, or caught and the handler returns,
@@ -76,8 +74,8 @@
   sa.sa_flags   = SA_RESTART;
   sigemptyset(&sa.sa_mask);
   sigaction(SIGABRT, &sa, &sa);
-  __rt_sigprocmask(SIG_SETMASK, &mask, nullptr, sizeof(mask));
 
+  sigprocmask64(SIG_SETMASK, &mask, nullptr);
   inline_tgkill(pid, tid, SIGABRT);
 
   // If we get this far, just exit.
diff --git a/libc/bionic/epoll_wait.cpp b/libc/bionic/epoll_wait.cpp
deleted file mode 100644
index deb19da..0000000
--- a/libc/bionic/epoll_wait.cpp
+++ /dev/null
@@ -1,33 +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 <sys/epoll.h>
-
-int epoll_wait(int fd, struct epoll_event* events, int max_events, int timeout) {
-  return epoll_pwait(fd, events, max_events, timeout, NULL);
-}
diff --git a/libc/bionic/pause.cpp b/libc/bionic/pause.cpp
index 2a0779a..534a804 100644
--- a/libc/bionic/pause.cpp
+++ b/libc/bionic/pause.cpp
@@ -26,12 +26,10 @@
  * SUCH DAMAGE.
  */
 
+#include <signal.h>
 #include <unistd.h>
 
-#include "private/kernel_sigset_t.h"
-
 int pause() {
-  kernel_sigset_t mask;
-  if (__rt_sigprocmask(SIG_SETMASK, nullptr, &mask, sizeof(mask)) == -1) return -1;
-  return __rt_sigsuspend(&mask, sizeof(mask));
+  sigset64_t mask = {};
+  return sigsuspend64(&mask);
 }
diff --git a/libc/bionic/poll.cpp b/libc/bionic/poll.cpp
index dbc9584..1d72fe5 100644
--- a/libc/bionic/poll.cpp
+++ b/libc/bionic/poll.cpp
@@ -31,51 +31,56 @@
 #include <sys/select.h>
 
 #include "private/bionic_time_conversions.h"
-#include "private/kernel_sigset_t.h"
+#include "private/SigSetConverter.h"
 
-extern "C" int __ppoll(pollfd*, unsigned int, timespec*, const kernel_sigset_t*, size_t);
+extern "C" int __ppoll(pollfd*, unsigned int, timespec*, const sigset64_t*, size_t);
 extern "C" int __pselect6(int, fd_set*, fd_set*, fd_set*, timespec*, void*);
 
 int poll(pollfd* fds, nfds_t fd_count, int ms) __overloadable {
   timespec ts;
-  timespec* ts_ptr = NULL;
+  timespec* ts_ptr = nullptr;
   if (ms >= 0) {
     timespec_from_ms(ts, ms);
     ts_ptr = &ts;
   }
-  return __ppoll(fds, fd_count, ts_ptr, NULL, 0);
+  return __ppoll(fds, fd_count, ts_ptr, nullptr, 0);
 }
 
 int ppoll(pollfd* fds, nfds_t fd_count, const timespec* ts, const sigset_t* ss) __overloadable {
+  // The underlying `__ppoll` system call only takes `sigset64_t`.
+  SigSetConverter set;
+  sigset64_t* ss_ptr = nullptr;
+  if (ss != nullptr) {
+    set = {};
+    set.sigset = *ss;
+    ss_ptr = &set.sigset64;
+  }
+  return ppoll64(fds, fd_count, ts, ss_ptr);
+}
+
+int ppoll64(pollfd* fds, nfds_t fd_count, const timespec* ts, const sigset64_t* ss) {
+  // The underlying __ppoll system call modifies its `struct timespec` argument.
   timespec mutable_ts;
-  timespec* mutable_ts_ptr = NULL;
-  if (ts != NULL) {
+  timespec* mutable_ts_ptr = nullptr;
+  if (ts != nullptr) {
     mutable_ts = *ts;
     mutable_ts_ptr = &mutable_ts;
   }
-
-  kernel_sigset_t kernel_ss;
-  kernel_sigset_t* kernel_ss_ptr = NULL;
-  if (ss != NULL) {
-    kernel_ss.set(ss);
-    kernel_ss_ptr = &kernel_ss;
-  }
-
-  return __ppoll(fds, fd_count, mutable_ts_ptr, kernel_ss_ptr, sizeof(kernel_ss));
+  return __ppoll(fds, fd_count, mutable_ts_ptr, ss, sizeof(*ss));
 }
 
 int select(int fd_count, fd_set* read_fds, fd_set* write_fds, fd_set* error_fds, timeval* tv) {
   timespec ts;
-  timespec* ts_ptr = NULL;
-  if (tv != NULL) {
+  timespec* ts_ptr = nullptr;
+  if (tv != nullptr) {
     if (!timespec_from_timeval(ts, *tv)) {
       errno = EINVAL;
       return -1;
     }
     ts_ptr = &ts;
   }
-  int result = __pselect6(fd_count, read_fds, write_fds, error_fds, ts_ptr, NULL);
-  if (tv != NULL) {
+  int result = __pselect6(fd_count, read_fds, write_fds, error_fds, ts_ptr, nullptr);
+  if (tv != nullptr) {
     timeval_from_timespec(*tv, ts);
   }
   return result;
@@ -83,20 +88,27 @@
 
 int pselect(int fd_count, fd_set* read_fds, fd_set* write_fds, fd_set* error_fds,
             const timespec* ts, const sigset_t* ss) {
+  // The underlying `__pselect6` system call only takes `sigset64_t`.
+  SigSetConverter set;
+  sigset64_t* ss_ptr = nullptr;
+  if (ss != nullptr) {
+    set = {};
+    set.sigset = *ss;
+    ss_ptr = &set.sigset64;
+  }
+  return pselect64(fd_count, read_fds, write_fds, error_fds, ts, ss_ptr);
+}
+
+int pselect64(int fd_count, fd_set* read_fds, fd_set* write_fds, fd_set* error_fds,
+              const timespec* ts, const sigset64_t* ss) {
+  // The underlying __pselect6 system call modifies its `struct timespec` argument.
   timespec mutable_ts;
-  timespec* mutable_ts_ptr = NULL;
-  if (ts != NULL) {
+  timespec* mutable_ts_ptr = nullptr;
+  if (ts != nullptr) {
     mutable_ts = *ts;
     mutable_ts_ptr = &mutable_ts;
   }
 
-  kernel_sigset_t kernel_ss;
-  kernel_sigset_t* kernel_ss_ptr = NULL;
-  if (ss != NULL) {
-    kernel_ss.set(ss);
-    kernel_ss_ptr = &kernel_ss;
-  }
-
   // The Linux kernel only handles 6 arguments and this system call really needs 7,
   // so the last argument is a void* pointing to:
   struct pselect6_extra_data_t {
@@ -104,8 +116,8 @@
     size_t ss_len;
   };
   pselect6_extra_data_t extra_data;
-  extra_data.ss_addr = reinterpret_cast<uintptr_t>(kernel_ss_ptr);
-  extra_data.ss_len = sizeof(kernel_ss);
+  extra_data.ss_addr = reinterpret_cast<uintptr_t>(ss);
+  extra_data.ss_len = sizeof(*ss);
 
   return __pselect6(fd_count, read_fds, write_fds, error_fds, mutable_ts_ptr, &extra_data);
 }
diff --git a/libc/bionic/posix_timers.cpp b/libc/bionic/posix_timers.cpp
index e3bb112..2edfe97 100644
--- a/libc/bionic/posix_timers.cpp
+++ b/libc/bionic/posix_timers.cpp
@@ -26,8 +26,6 @@
  * SUCH DAMAGE.
  */
 
-#include "private/kernel_sigset_t.h"
-
 #include <errno.h>
 #include <malloc.h>
 #include <pthread.h>
@@ -37,7 +35,6 @@
 #include <time.h>
 
 // System calls.
-extern "C" int __rt_sigtimedwait(const sigset_t*, siginfo_t*, const timespec*, size_t);
 extern "C" int __timer_create(clockid_t, sigevent*, __kernel_timer_t*);
 extern "C" int __timer_delete(__kernel_timer_t);
 extern "C" int __timer_getoverrun(__kernel_timer_t);
@@ -74,16 +71,13 @@
 static void* __timer_thread_start(void* arg) {
   PosixTimer* timer = reinterpret_cast<PosixTimer*>(arg);
 
-  kernel_sigset_t sigset{TIMER_SIGNAL};
+  sigset64_t sigset = {};
+  sigaddset64(&sigset, TIMER_SIGNAL);
 
   while (true) {
     // Wait for a signal...
-    siginfo_t si;
-    memset(&si, 0, sizeof(si));
-    int rc = __rt_sigtimedwait(sigset.get(), &si, NULL, sizeof(sigset));
-    if (rc == -1) {
-      continue;
-    }
+    siginfo_t si = {};
+    if (sigtimedwait64(&sigset, &si, nullptr) == -1) continue;
 
     if (si.si_code == SI_TIMER) {
       // This signal was sent because a timer fired, so call the callback.
@@ -149,13 +143,14 @@
 
   // 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{TIMER_SIGNAL};
-  kernel_sigset_t old_sigset;
-  __rt_sigprocmask(SIG_BLOCK, &sigset, &old_sigset, sizeof(sigset));
+  sigset64_t sigset = {};
+  sigaddset64(&sigset, TIMER_SIGNAL);
+  sigset64_t old_sigset;
+  sigprocmask64(SIG_BLOCK, &sigset, &old_sigset);
 
   int rc = pthread_create(&timer->callback_thread, &thread_attributes, __timer_thread_start, timer);
 
-  __rt_sigprocmask(SIG_SETMASK, &old_sigset, nullptr, sizeof(sigset));
+  sigprocmask64(SIG_SETMASK, &old_sigset, nullptr);
 
   if (rc != 0) {
     free(timer);
diff --git a/libc/bionic/pthread_sigmask.cpp b/libc/bionic/pthread_sigmask.cpp
deleted file mode 100644
index 79f31a1..0000000
--- a/libc/bionic/pthread_sigmask.cpp
+++ /dev/null
@@ -1,39 +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 <pthread.h>
-#include <signal.h>
-
-#include "private/ErrnoRestorer.h"
-
-int pthread_sigmask(int how, const sigset_t* new_set, sigset_t* old_set) {
-  ErrnoRestorer errno_restorer;
-  int result = sigprocmask(how, new_set, old_set);
-  return (result == -1) ? errno : 0;
-}
diff --git a/libc/bionic/signal.cpp b/libc/bionic/signal.cpp
index 9a23416..099944a 100644
--- a/libc/bionic/signal.cpp
+++ b/libc/bionic/signal.cpp
@@ -30,19 +30,36 @@
 #include <pthread.h>
 #include <signal.h>
 #include <string.h>
+#include <sys/epoll.h>
+#include <sys/signalfd.h>
 #include <sys/types.h>
 #include <time.h>
 #include <unistd.h>
 
-#include "private/kernel_sigset_t.h"
+#include "private/ErrnoRestorer.h"
+#include "private/SigSetConverter.h"
 
+extern "C" int __rt_sigpending(const sigset64_t*, size_t);
+extern "C" int __rt_sigprocmask(int, const sigset64_t*, sigset64_t*, size_t);
 extern "C" int ___rt_sigqueueinfo(pid_t, int, siginfo_t*);
-extern "C" int __rt_sigtimedwait(const sigset_t*, siginfo_t*, const timespec*, size_t);
+extern "C" int __rt_sigsuspend(const sigset64_t*, size_t);
+extern "C" int __rt_sigtimedwait(const sigset64_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.
+int pthread_sigmask(int how, const sigset_t* new_set, sigset_t* old_set) {
+  ErrnoRestorer errno_restorer;
+  return (sigprocmask(how, new_set, old_set) == -1) ? errno : 0;
+}
+
+int pthread_sigmask64(int how, const sigset64_t* new_set, sigset64_t* old_set) {
+  ErrnoRestorer errno_restorer;
+  return (sigprocmask64(how, new_set, old_set) == -1) ? errno : 0;
+}
+
+template <typename SigSetT>
+int SigAddSet(SigSetT* set, int sig) {
+  int bit = sig - 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))) {
+  if (set == nullptr || bit < 0 || bit >= static_cast<int>(8*sizeof(*set))) {
     errno = EINVAL;
     return -1;
   }
@@ -50,24 +67,28 @@
   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 sigaddset(sigset_t* set, int sig) {
+  return SigAddSet(set, sig);
 }
 
-int sigdelset(sigset_t* set, int signum) {
-  int bit = signum - 1; // Signal numbers start at 1, but bit positions start at 0.
+int sigaddset64(sigset64_t* set, int sig) {
+  return SigAddSet(set, sig);
+}
+
+// This isn't in our header files, but is exposed on all architectures.
+extern "C" int sigblock(int mask) {
+  SigSetConverter in, out;
+  sigemptyset(&in.sigset);
+  in.bsd = mask;
+  if (sigprocmask(SIG_BLOCK, &in.sigset, &out.sigset) == -1) return -1;
+  return out.bsd;
+}
+
+template <typename SigSetT>
+int SigDelSet(SigSetT* set, int sig) {
+  int bit = sig - 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))) {
+  if (set == nullptr || bit < 0 || bit >= static_cast<int>(8*sizeof(*set))) {
     errno = EINVAL;
     return -1;
   }
@@ -75,29 +96,54 @@
   return 0;
 }
 
-int sigemptyset(sigset_t* set) {
-  if (set == NULL) {
+int sigdelset(sigset_t* set, int sig) {
+  return SigDelSet(set, sig);
+}
+
+int sigdelset64(sigset64_t* set, int sig) {
+  return SigDelSet(set, sig);
+}
+
+template <typename SigSetT>
+int SigEmptySet(SigSetT* set) {
+  if (set == nullptr) {
     errno = EINVAL;
     return -1;
   }
-  memset(set, 0, sizeof(sigset_t));
+  memset(set, 0, sizeof(*set));
+  return 0;
+}
+
+int sigemptyset(sigset_t* set) {
+  return SigEmptySet(set);
+}
+
+int sigemptyset64(sigset64_t* set) {
+  return SigEmptySet(set);
+}
+
+template <typename SigSetT>
+int SigFillSet(SigSetT* set) {
+  if (set == nullptr) {
+    errno = EINVAL;
+    return -1;
+  }
+  memset(set, 0xff, sizeof(*set));
   return 0;
 }
 
 int sigfillset(sigset_t* set) {
-  if (set == NULL) {
-    errno = EINVAL;
-    return -1;
-  }
-  memset(set, ~0, sizeof(sigset_t));
-  return 0;
+  return SigFillSet(set);
+}
+
+int sigfillset64(sigset64_t* set) {
+  return SigFillSet(set);
 }
 
 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));
+  sigset64_t set = {};
+  if (sigaddset64(&set, sig) == -1) return -1;
+  return sigprocmask64(SIG_BLOCK, &set, nullptr);
 }
 
 int sigignore(int sig) {
@@ -119,87 +165,100 @@
   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.
+template <typename SigSetT>
+int SigIsMember(const SigSetT* set, int sig) {
+  int bit = sig - 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))) {
+  if (set == nullptr || bit < 0 || bit >= static_cast<int>(8*sizeof(*set))) {
     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) {
+int sigismember(const sigset_t* set, int sig) {
+  return SigIsMember(set, sig);
+}
+
+int sigismember64(const sigset64_t* set, int sig) {
+  return SigIsMember(set, sig);
+}
+
+__LIBC_HIDDEN__ sighandler_t _signal(int sig, sighandler_t handler, int flags) {
   struct sigaction sa;
   sigemptyset(&sa.sa_mask);
   sa.sa_handler = handler;
   sa.sa_flags = flags;
 
-  if (sigaction(signum, &sa, &sa) == -1) {
+  if (sigaction(sig, &sa, &sa) == -1) {
     return SIG_ERR;
   }
 
   return sa.sa_handler;
 }
 
-sighandler_t signal(int signum, sighandler_t handler) {
-  return _signal(signum, handler, SA_RESTART);
+sighandler_t signal(int sig, sighandler_t handler) {
+  return _signal(sig, 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));
+  sigset64_t set = {};
+  if (sigprocmask64(SIG_SETMASK, nullptr, &set) == -1 || sigdelset64(&set, sig) == -1) return -1;
+  return sigsuspend64(&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;
+  SigSetConverter set = {};
+  set.sigset = *bionic_set;
+  if (__rt_sigpending(&set.sigset64, sizeof(set.sigset64)) == -1) return -1;
+  *bionic_set = set.sigset;
+  return 0;
+}
+
+int sigpending64(sigset64_t* set) {
+  return __rt_sigpending(set, sizeof(*set));
 }
 
 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;
+  SigSetConverter new_set;
+  sigset64_t* new_set_ptr = nullptr;
+  if (bionic_new_set != nullptr) {
+    sigemptyset64(&new_set.sigset64);
+    new_set.sigset = *bionic_new_set;
+    new_set_ptr = &new_set.sigset64;
   }
 
-  kernel_sigset_t old_set;
-  if (__rt_sigprocmask(how, new_set_ptr, &old_set, sizeof(old_set)) == -1) {
+  SigSetConverter old_set;
+  if (sigprocmask64(how, new_set_ptr, &old_set.sigset64) == -1) {
     return -1;
   }
 
-  if (bionic_old_set != NULL) {
-    *bionic_old_set = old_set.bionic;
+  if (bionic_old_set != nullptr) {
+    *bionic_old_set = old_set.sigset;
   }
 
   return 0;
 }
 
-int sigqueue(pid_t pid, int signo, const sigval value) {
+int sigprocmask64(int how, const sigset64_t* new_set, sigset64_t* old_set) {
+  return __rt_sigprocmask(how, new_set, old_set, sizeof(*new_set));
+}
+
+int sigqueue(pid_t pid, int sig, const sigval value) {
   siginfo_t info;
   memset(&info, 0, sizeof(siginfo_t));
-  info.si_signo = signo;
+  info.si_signo = sig;
   info.si_code = SI_QUEUE;
   info.si_pid = getpid();
   info.si_uid = getuid();
   info.si_value = value;
-
-  return ___rt_sigqueueinfo(pid, signo, &info);
+  return ___rt_sigqueueinfo(pid, sig, &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));
+  sigset64_t set = {};
+  if (sigaddset64(&set, sig) == -1) return -1;
+  return sigprocmask64(SIG_UNBLOCK, &set, nullptr);
 }
 
 sighandler_t sigset(int sig, sighandler_t disp) {
@@ -215,57 +274,68 @@
     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) {
+  sigset64_t new_mask = {};
+  sigaddset64(&new_mask, sig);
+  sigset64_t old_mask;
+  if (sigprocmask64(disp == SIG_HOLD ? SIG_BLOCK : SIG_UNBLOCK, &new_mask, &old_mask) == -1) {
     return SIG_ERR;
   }
 
-  return old_mask.is_set(sig) ? SIG_HOLD : old_sa.sa_handler;
+  return sigismember64(&old_mask, 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;
+  SigSetConverter in, out;
+  sigemptyset(&in.sigset);
+  in.bsd = mask;
+  if (sigprocmask(SIG_SETMASK, &in.sigset, &out.sigset) == -1) return -1;
+  return out.bsd;
 }
 
 int sigsuspend(const sigset_t* bionic_set) {
-  kernel_sigset_t set(bionic_set);
-  return __rt_sigsuspend(&set, sizeof(set));
+  SigSetConverter set = {};
+  set.sigset = *bionic_set;
+  return __rt_sigsuspend(&set.sigset64, sizeof(set.sigset64));
 }
 
-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 sigsuspend64(const sigset64_t* set) {
+  return __rt_sigsuspend(set, sizeof(*set));
 }
 
-int sigwait(const sigset_t* set, int* sig) {
-  kernel_sigset_t sigset(set);
+int sigtimedwait(const sigset_t* bionic_set, siginfo_t* info, const timespec* timeout) {
+  SigSetConverter set = {};
+  set.sigset = *bionic_set;
+  return __rt_sigtimedwait(&set.sigset64, info, timeout, sizeof(set.sigset64));
+}
+
+int sigtimedwait64(const sigset64_t* set, siginfo_t* info, const timespec* timeout) {
+  return __rt_sigtimedwait(set, info, timeout, sizeof(*set));
+}
+
+int sigwait(const sigset_t* bionic_set, int* sig) {
+  SigSetConverter set = {};
+  set.sigset = *bionic_set;
+  return sigwait64(&set.sigset64, sig);
+}
+
+int sigwait64(const sigset64_t* set, int* sig) {
   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));
+    int result = sigtimedwait64(set, nullptr, nullptr);
     if (result >= 0) {
       *sig = result;
       return 0;
     }
-
-    if (errno != EAGAIN && errno != EINTR) {
-      return errno;
-    }
+    if (errno != EAGAIN && errno != EINTR) return errno;
   }
 }
 
 int sigwaitinfo(const sigset_t* set, siginfo_t* info) {
-  return sigtimedwait(set, info, NULL);
+  return sigtimedwait(set, info, nullptr);
+}
+
+int sigwaitinfo64(const sigset64_t* set, siginfo_t* info) {
+  return sigtimedwait64(set, info, nullptr);
 }
diff --git a/libc/bionic/spawn.cpp b/libc/bionic/spawn.cpp
index e5075f5..7422a0b 100644
--- a/libc/bionic/spawn.cpp
+++ b/libc/bionic/spawn.cpp
@@ -36,6 +36,7 @@
 #include <unistd.h>
 
 #include "private/ScopedSignalBlocker.h"
+#include "private/SigSetConverter.h"
 
 enum Action {
   kOpen,
@@ -87,8 +88,8 @@
   pid_t pgroup;
   sched_param schedparam;
   int schedpolicy;
-  sigset_t sigmask;
-  sigset_t sigdefault;
+  SigSetConverter sigmask;
+  SigSetConverter sigdefault;
 };
 
 static void ApplyAttrs(short flags, const posix_spawnattr_t* attr) {
@@ -100,7 +101,7 @@
   const struct sigaction default_sa = { .sa_handler = SIG_DFL };
   for (int s = 1; s < _NSIG; ++s) {
     bool reset = false;
-    if (use_sigdefault && sigismember(&(*attr)->sigdefault, s)) {
+    if (use_sigdefault && sigismember64(&(*attr)->sigdefault.sigset64, s)) {
       reset = true;
     } else {
       struct sigaction current;
@@ -126,7 +127,7 @@
   }
 
   if ((flags & POSIX_SPAWN_SETSIGMASK) != 0) {
-    if (sigprocmask(SIG_SETMASK, &(*attr)->sigmask, nullptr)) _exit(127);
+    if (sigprocmask64(SIG_SETMASK, &(*attr)->sigmask.sigset64, nullptr)) _exit(127);
   }
 }
 
@@ -209,22 +210,42 @@
 }
 
 int posix_spawnattr_setsigmask(posix_spawnattr_t* attr, const sigset_t* mask) {
-  (*attr)->sigmask = *mask;
+  (*attr)->sigmask.sigset = *mask;
+  return 0;
+}
+
+int posix_spawnattr_setsigmask64(posix_spawnattr_t* attr, const sigset64_t* mask) {
+  (*attr)->sigmask.sigset64 = *mask;
   return 0;
 }
 
 int posix_spawnattr_getsigmask(const posix_spawnattr_t* attr, sigset_t* mask) {
-  *mask = (*attr)->sigmask;
+  *mask = (*attr)->sigmask.sigset;
+  return 0;
+}
+
+int posix_spawnattr_getsigmask64(const posix_spawnattr_t* attr, sigset64_t* mask) {
+  *mask = (*attr)->sigmask.sigset64;
   return 0;
 }
 
 int posix_spawnattr_setsigdefault(posix_spawnattr_t* attr, const sigset_t* mask) {
-  (*attr)->sigdefault = *mask;
+  (*attr)->sigdefault.sigset = *mask;
+  return 0;
+}
+
+int posix_spawnattr_setsigdefault64(posix_spawnattr_t* attr, const sigset64_t* mask) {
+  (*attr)->sigdefault.sigset64 = *mask;
   return 0;
 }
 
 int posix_spawnattr_getsigdefault(const posix_spawnattr_t* attr, sigset_t* mask) {
-  *mask = (*attr)->sigdefault;
+  *mask = (*attr)->sigdefault.sigset;
+  return 0;
+}
+
+int posix_spawnattr_getsigdefault64(const posix_spawnattr_t* attr, sigset64_t* mask) {
+  *mask = (*attr)->sigdefault.sigset64;
   return 0;
 }
 
diff --git a/libc/bionic/epoll_pwait.cpp b/libc/bionic/sys_epoll.cpp
similarity index 68%
rename from libc/bionic/epoll_pwait.cpp
rename to libc/bionic/sys_epoll.cpp
index f3af93e..9f82912 100644
--- a/libc/bionic/epoll_pwait.cpp
+++ b/libc/bionic/sys_epoll.cpp
@@ -26,18 +26,36 @@
  * SUCH DAMAGE.
  */
 
+#include <errno.h>
 #include <sys/epoll.h>
 
-#include "private/kernel_sigset_t.h"
+#include "private/SigSetConverter.h"
 
-extern "C" int __epoll_pwait(int, epoll_event*, int, int, const kernel_sigset_t*, size_t);
+extern "C" int __epoll_pwait(int, epoll_event*, int, int, const sigset64_t*, size_t);
+
+int epoll_create(int size) {
+  if (size <= 0) {
+    errno = EINVAL;
+    return -1;
+  }
+  return epoll_create1(0);
+}
 
 int epoll_pwait(int fd, epoll_event* events, int max_events, int timeout, const sigset_t* ss) {
-  kernel_sigset_t kernel_ss;
-  kernel_sigset_t* kernel_ss_ptr = NULL;
-  if (ss != NULL) {
-    kernel_ss.set(ss);
-    kernel_ss_ptr = &kernel_ss;
+  SigSetConverter set;
+  sigset64_t* ss_ptr = nullptr;
+  if (ss != nullptr) {
+    set = {};
+    set.sigset = *ss;
+    ss_ptr = &set.sigset64;
   }
-  return __epoll_pwait(fd, events, max_events, timeout, kernel_ss_ptr, sizeof(kernel_ss));
+  return epoll_pwait64(fd, events, max_events, timeout, ss_ptr);
+}
+
+int epoll_pwait64(int fd, epoll_event* events, int max_events, int timeout, const sigset64_t* ss) {
+  return __epoll_pwait(fd, events, max_events, timeout, ss, sizeof(*ss));
+}
+
+int epoll_wait(int fd, struct epoll_event* events, int max_events, int timeout) {
+  return epoll_pwait64(fd, events, max_events, timeout, nullptr);
 }
diff --git a/libc/bionic/sys_signalfd.cpp b/libc/bionic/sys_signalfd.cpp
index 63e1db4..53d1f25 100644
--- a/libc/bionic/sys_signalfd.cpp
+++ b/libc/bionic/sys_signalfd.cpp
@@ -28,11 +28,16 @@
 
 #include <sys/signalfd.h>
 
-#include "private/kernel_sigset_t.h"
+#include "private/SigSetConverter.h"
 
-extern "C" int __signalfd4(int fd, kernel_sigset_t* mask, size_t sizemask, int flags);
+extern "C" int __signalfd4(int, const sigset64_t*, size_t, int);
 
 int signalfd(int fd, const sigset_t* mask, int flags) {
-  kernel_sigset_t in_set(mask);
-  return __signalfd4(fd, &in_set, sizeof(in_set), flags);
+  SigSetConverter set = {};
+  set.sigset = *mask;
+  return signalfd64(fd, &set.sigset64, flags);
+}
+
+int signalfd64(int fd, const sigset64_t* mask, int flags) {
+  return __signalfd4(fd, mask, sizeof(*mask), flags);
 }
diff --git a/libc/include/poll.h b/libc/include/poll.h
index 8517dc6..9ca1cf8 100644
--- a/libc/include/poll.h
+++ b/libc/include/poll.h
@@ -40,6 +40,7 @@
 
 int poll(struct pollfd* __fds, nfds_t __count, int __timeout_ms) __overloadable __RENAME_CLANG(poll);
 int ppoll(struct pollfd* __fds, nfds_t __count, const struct timespec* __timeout, const sigset_t* __mask) __overloadable __RENAME_CLANG(ppoll) __INTRODUCED_IN(21);
+int ppoll64(struct pollfd* __fds, nfds_t __count, const struct timespec* __timeout, const sigset64_t* __mask) __INTRODUCED_IN(28);
 
 #if defined(__BIONIC_INCLUDE_FORTIFY_HEADERS)
 #include <bits/fortify/poll.h>
diff --git a/libc/include/signal.h b/libc/include/signal.h
index d9c9ee2..61bb395 100644
--- a/libc/include/signal.h
+++ b/libc/include/signal.h
@@ -80,6 +80,13 @@
 
 #define si_timerid si_tid /* glibc compatibility. */
 
+/* sigset_t is already large enough on LP64, but LP32's sigset_t is just `unsigned long`. */
+#if defined(__LP64__)
+typedef sigset_t sigset64_t;
+#else
+typedef struct { unsigned long __bits[_KERNEL__NSIG/LONG_BIT]; } sigset64_t;
+#endif
+
 #if defined(__LP64__)
 
 struct sigaction {
@@ -117,6 +124,7 @@
 
 #endif
 
+// TODO: sigaction contains a sigset_t that's too small on LP32.
 int sigaction(int __signal, const struct sigaction* __new_action, struct sigaction* __old_action);
 
 int siginterrupt(int __signal, int __flag);
@@ -124,18 +132,27 @@
 #if __ANDROID_API__ >= __ANDROID_API_L__
 sighandler_t signal(int __signal, sighandler_t __handler) __INTRODUCED_IN(21);
 int sigaddset(sigset_t* __set, int __signal) __INTRODUCED_IN(21);
+int sigaddset64(sigset64_t* __set, int __signal) __INTRODUCED_IN(28);
 int sigdelset(sigset_t* __set, int __signal) __INTRODUCED_IN(21);
+int sigdelset64(sigset64_t* __set, int __signal) __INTRODUCED_IN(28);
 int sigemptyset(sigset_t* __set) __INTRODUCED_IN(21);
+int sigemptyset64(sigset64_t* __set) __INTRODUCED_IN(28);
 int sigfillset(sigset_t* __set) __INTRODUCED_IN(21);
+int sigfillset64(sigset64_t* __set) __INTRODUCED_IN(28);
 int sigismember(const sigset_t* __set, int __signal) __INTRODUCED_IN(21);
+int sigismember64(const sigset64_t* __set, int __signal) __INTRODUCED_IN(28);
 #else
 // Implemented as static inlines before 21.
 #endif
 
 int sigpending(sigset_t* __set);
+int sigpending64(sigset64_t* __set) __INTRODUCED_IN(28);
 int sigprocmask(int __how, const sigset_t* __new_set, sigset_t* __old_set);
+int sigprocmask64(int __how, const sigset64_t* __new_set, sigset64_t* __old_set) __INTRODUCED_IN(28);
 int sigsuspend(const sigset_t* __mask);
+int sigsuspend64(const sigset64_t* __mask) __INTRODUCED_IN(28);
 int sigwait(const sigset_t* __set, int* __signal);
+int sigwait64(const sigset64_t* __set, int* __signal) __INTRODUCED_IN(28);
 
 int sighold(int __signal)
   __attribute__((deprecated("use sigprocmask() or pthread_sigmask() instead")))
@@ -162,10 +179,13 @@
 
 int pthread_kill(pthread_t __pthread, int __signal);
 int pthread_sigmask(int __how, const sigset_t* __new_set, sigset_t* __old_set);
+int pthread_sigmask64(int __how, const sigset64_t* __new_set, sigset64_t* __old_set) __INTRODUCED_IN(28);
 
 int sigqueue(pid_t __pid, int __signal, const union sigval __value) __INTRODUCED_IN(23);
 int sigtimedwait(const sigset_t* __set, siginfo_t* __info, const struct timespec* __timeout) __INTRODUCED_IN(23);
+int sigtimedwait64(const sigset64_t* __set, siginfo_t* __info, const struct timespec* __timeout) __INTRODUCED_IN(28);
 int sigwaitinfo(const sigset_t* __set, siginfo_t* __info) __INTRODUCED_IN(23);
+int sigwaitinfo64(const sigset64_t* __set, siginfo_t* __info) __INTRODUCED_IN(28);
 
 __END_DECLS
 
diff --git a/libc/include/spawn.h b/libc/include/spawn.h
index b5ac586..2e239bf 100644
--- a/libc/include/spawn.h
+++ b/libc/include/spawn.h
@@ -63,10 +63,14 @@
 int posix_spawnattr_getpgroup(const posix_spawnattr_t* __attr, pid_t* __pgroup) __INTRODUCED_IN(28);
 
 int posix_spawnattr_setsigmask(posix_spawnattr_t* __attr, const sigset_t* __mask) __INTRODUCED_IN(28);
+int posix_spawnattr_setsigmask64(posix_spawnattr_t* __attr, const sigset64_t* __mask) __INTRODUCED_IN(28);
 int posix_spawnattr_getsigmask(const posix_spawnattr_t* __attr, sigset_t* __mask) __INTRODUCED_IN(28);
+int posix_spawnattr_getsigmask64(const posix_spawnattr_t* __attr, sigset64_t* __mask) __INTRODUCED_IN(28);
 
 int posix_spawnattr_setsigdefault(posix_spawnattr_t* __attr, const sigset_t* __mask) __INTRODUCED_IN(28);
+int posix_spawnattr_setsigdefault64(posix_spawnattr_t* __attr, const sigset64_t* __mask) __INTRODUCED_IN(28);
 int posix_spawnattr_getsigdefault(const posix_spawnattr_t* __attr, sigset_t* __mask) __INTRODUCED_IN(28);
+int posix_spawnattr_getsigdefault64(const posix_spawnattr_t* __attr, sigset64_t* __mask) __INTRODUCED_IN(28);
 
 int posix_spawnattr_setschedparam(posix_spawnattr_t* __attr, const struct sched_param* __param) __INTRODUCED_IN(28);
 int posix_spawnattr_getschedparam(const posix_spawnattr_t* __attr, struct sched_param* __param) __INTRODUCED_IN(28);
diff --git a/libc/include/sys/epoll.h b/libc/include/sys/epoll.h
index 2bc16f5..a213a90 100644
--- a/libc/include/sys/epoll.h
+++ b/libc/include/sys/epoll.h
@@ -58,6 +58,7 @@
 int epoll_ctl(int __epoll_fd, int __op, int __fd, struct epoll_event* __event);
 int epoll_wait(int __epoll_fd, struct epoll_event* __events, int __event_count, int __timeout_ms);
 int epoll_pwait(int __epoll_fd, struct epoll_event* __events, int __event_count, int __timeout_ms, const sigset_t* __mask) __INTRODUCED_IN(21);
+int epoll_pwait64(int __epoll_fd, struct epoll_event* __events, int __event_count, int __timeout_ms, const sigset64_t* __mask) __INTRODUCED_IN(28);
 
 __END_DECLS
 
diff --git a/libc/include/sys/select.h b/libc/include/sys/select.h
index ac51d3f..603a5a6 100644
--- a/libc/include/sys/select.h
+++ b/libc/include/sys/select.h
@@ -75,6 +75,7 @@
 
 int select(int __fd_count, fd_set* __read_fds, fd_set* __write_fds, fd_set* __exception_fds, struct timeval* __timeout);
 int pselect(int __fd_count, fd_set* __read_fds, fd_set* __write_fds, fd_set* __exception_fds, const struct timespec* __timeout, const sigset_t* __mask);
+int pselect64(int __fd_count, fd_set* __read_fds, fd_set* __write_fds, fd_set* __exception_fds, const struct timespec* __timeout, const sigset64_t* __mask);
 
 __END_DECLS
 
diff --git a/libc/include/sys/signalfd.h b/libc/include/sys/signalfd.h
index 315622c..2337cd7 100644
--- a/libc/include/sys/signalfd.h
+++ b/libc/include/sys/signalfd.h
@@ -37,6 +37,7 @@
 __BEGIN_DECLS
 
 int signalfd(int __fd, const sigset_t* __mask, int __flags) __INTRODUCED_IN(18);
+int signalfd64(int __fd, const sigset64_t* __mask, int __flags) __INTRODUCED_IN(28);
 
 __END_DECLS
 
diff --git a/libc/libc.arm.map b/libc/libc.arm.map
index 1ed4ec6..c345ba6 100644
--- a/libc/libc.arm.map
+++ b/libc/libc.arm.map
@@ -1325,6 +1325,7 @@
     endhostent;
     endnetent;
     endprotoent;
+    epoll_pwait64;
     fexecve;
     fflush_unlocked;
     fgetc_unlocked;
@@ -1356,28 +1357,47 @@
     posix_spawnattr_getschedparam;
     posix_spawnattr_getschedpolicy;
     posix_spawnattr_getsigdefault;
+    posix_spawnattr_getsigdefault64;
     posix_spawnattr_getsigmask;
+    posix_spawnattr_getsigmask64;
     posix_spawnattr_init;
     posix_spawnattr_setflags;
     posix_spawnattr_setpgroup;
     posix_spawnattr_setschedparam;
     posix_spawnattr_setschedpolicy;
     posix_spawnattr_setsigdefault;
+    posix_spawnattr_setsigdefault64;
     posix_spawnattr_setsigmask;
+    posix_spawnattr_setsigmask64;
     posix_spawn_file_actions_addclose;
     posix_spawn_file_actions_adddup2;
     posix_spawn_file_actions_addopen;
     posix_spawn_file_actions_destroy;
     posix_spawn_file_actions_init;
     posix_spawnp;
+    ppoll64;
+    pselect64;
     pthread_attr_getinheritsched;
     pthread_attr_setinheritsched;
     pthread_mutexattr_getprotocol;
     pthread_mutexattr_setprotocol;
     pthread_setschedprio;
+    pthread_sigmask64;
     sethostent;
     setnetent;
     setprotoent;
+    sigaddset64;
+    sigdelset64;
+    sigemptyset64;
+    sigfillset64;
+    sigismember64;
+    signalfd64;
+    sigpending64;
+    sigprocmask64;
+    sigsuspend64;
+    sigtimedwait64;
+    sigwait64;
+    sigwaitinfo64;
     swab;
     syncfs;
 } LIBC_O;
diff --git a/libc/libc.arm64.map b/libc/libc.arm64.map
index f511707..3af0d42 100644
--- a/libc/libc.arm64.map
+++ b/libc/libc.arm64.map
@@ -1245,6 +1245,7 @@
     endhostent;
     endnetent;
     endprotoent;
+    epoll_pwait64;
     fexecve;
     fflush_unlocked;
     fgetc_unlocked;
@@ -1276,28 +1277,47 @@
     posix_spawnattr_getschedparam;
     posix_spawnattr_getschedpolicy;
     posix_spawnattr_getsigdefault;
+    posix_spawnattr_getsigdefault64;
     posix_spawnattr_getsigmask;
+    posix_spawnattr_getsigmask64;
     posix_spawnattr_init;
     posix_spawnattr_setflags;
     posix_spawnattr_setpgroup;
     posix_spawnattr_setschedparam;
     posix_spawnattr_setschedpolicy;
     posix_spawnattr_setsigdefault;
+    posix_spawnattr_setsigdefault64;
     posix_spawnattr_setsigmask;
+    posix_spawnattr_setsigmask64;
     posix_spawn_file_actions_addclose;
     posix_spawn_file_actions_adddup2;
     posix_spawn_file_actions_addopen;
     posix_spawn_file_actions_destroy;
     posix_spawn_file_actions_init;
     posix_spawnp;
+    ppoll64;
+    pselect64;
     pthread_attr_getinheritsched;
     pthread_attr_setinheritsched;
     pthread_mutexattr_getprotocol;
     pthread_mutexattr_setprotocol;
     pthread_setschedprio;
+    pthread_sigmask64;
     sethostent;
     setnetent;
     setprotoent;
+    sigaddset64;
+    sigdelset64;
+    sigemptyset64;
+    sigfillset64;
+    sigismember64;
+    signalfd64;
+    sigpending64;
+    sigprocmask64;
+    sigsuspend64;
+    sigtimedwait64;
+    sigwait64;
+    sigwaitinfo64;
     swab;
     syncfs;
 } LIBC_O;
diff --git a/libc/libc.map.txt b/libc/libc.map.txt
index 0960560..5c54ba1 100644
--- a/libc/libc.map.txt
+++ b/libc/libc.map.txt
@@ -1350,6 +1350,7 @@
     endhostent;
     endnetent;
     endprotoent;
+    epoll_pwait64;
     fexecve;
     fflush_unlocked;
     fgetc_unlocked;
@@ -1381,28 +1382,47 @@
     posix_spawnattr_getschedparam;
     posix_spawnattr_getschedpolicy;
     posix_spawnattr_getsigdefault;
+    posix_spawnattr_getsigdefault64;
     posix_spawnattr_getsigmask;
+    posix_spawnattr_getsigmask64;
     posix_spawnattr_init;
     posix_spawnattr_setflags;
     posix_spawnattr_setpgroup;
     posix_spawnattr_setschedparam;
     posix_spawnattr_setschedpolicy;
     posix_spawnattr_setsigdefault;
+    posix_spawnattr_setsigdefault64;
     posix_spawnattr_setsigmask;
+    posix_spawnattr_setsigmask64;
     posix_spawn_file_actions_addclose;
     posix_spawn_file_actions_adddup2;
     posix_spawn_file_actions_addopen;
     posix_spawn_file_actions_destroy;
     posix_spawn_file_actions_init;
     posix_spawnp;
+    ppoll64;
+    pselect64;
     pthread_attr_getinheritsched;
     pthread_attr_setinheritsched;
     pthread_mutexattr_getprotocol;
     pthread_mutexattr_setprotocol;
     pthread_setschedprio;
+    pthread_sigmask64;
     sethostent;
     setnetent;
     setprotoent;
+    sigaddset64;
+    sigdelset64;
+    sigemptyset64;
+    sigfillset64;
+    sigismember64;
+    signalfd64;
+    sigpending64;
+    sigprocmask64;
+    sigsuspend64;
+    sigtimedwait64;
+    sigwait64;
+    sigwaitinfo64;
     swab;
     syncfs;
 } LIBC_O;
diff --git a/libc/libc.mips.map b/libc/libc.mips.map
index 1160f87..c364608 100644
--- a/libc/libc.mips.map
+++ b/libc/libc.mips.map
@@ -1309,6 +1309,7 @@
     endhostent;
     endnetent;
     endprotoent;
+    epoll_pwait64;
     fexecve;
     fflush_unlocked;
     fgetc_unlocked;
@@ -1340,28 +1341,47 @@
     posix_spawnattr_getschedparam;
     posix_spawnattr_getschedpolicy;
     posix_spawnattr_getsigdefault;
+    posix_spawnattr_getsigdefault64;
     posix_spawnattr_getsigmask;
+    posix_spawnattr_getsigmask64;
     posix_spawnattr_init;
     posix_spawnattr_setflags;
     posix_spawnattr_setpgroup;
     posix_spawnattr_setschedparam;
     posix_spawnattr_setschedpolicy;
     posix_spawnattr_setsigdefault;
+    posix_spawnattr_setsigdefault64;
     posix_spawnattr_setsigmask;
+    posix_spawnattr_setsigmask64;
     posix_spawn_file_actions_addclose;
     posix_spawn_file_actions_adddup2;
     posix_spawn_file_actions_addopen;
     posix_spawn_file_actions_destroy;
     posix_spawn_file_actions_init;
     posix_spawnp;
+    ppoll64;
+    pselect64;
     pthread_attr_getinheritsched;
     pthread_attr_setinheritsched;
     pthread_mutexattr_getprotocol;
     pthread_mutexattr_setprotocol;
     pthread_setschedprio;
+    pthread_sigmask64;
     sethostent;
     setnetent;
     setprotoent;
+    sigaddset64;
+    sigdelset64;
+    sigemptyset64;
+    sigfillset64;
+    sigismember64;
+    signalfd64;
+    sigpending64;
+    sigprocmask64;
+    sigsuspend64;
+    sigtimedwait64;
+    sigwait64;
+    sigwaitinfo64;
     swab;
     syncfs;
 } LIBC_O;
diff --git a/libc/libc.mips64.map b/libc/libc.mips64.map
index f511707..3af0d42 100644
--- a/libc/libc.mips64.map
+++ b/libc/libc.mips64.map
@@ -1245,6 +1245,7 @@
     endhostent;
     endnetent;
     endprotoent;
+    epoll_pwait64;
     fexecve;
     fflush_unlocked;
     fgetc_unlocked;
@@ -1276,28 +1277,47 @@
     posix_spawnattr_getschedparam;
     posix_spawnattr_getschedpolicy;
     posix_spawnattr_getsigdefault;
+    posix_spawnattr_getsigdefault64;
     posix_spawnattr_getsigmask;
+    posix_spawnattr_getsigmask64;
     posix_spawnattr_init;
     posix_spawnattr_setflags;
     posix_spawnattr_setpgroup;
     posix_spawnattr_setschedparam;
     posix_spawnattr_setschedpolicy;
     posix_spawnattr_setsigdefault;
+    posix_spawnattr_setsigdefault64;
     posix_spawnattr_setsigmask;
+    posix_spawnattr_setsigmask64;
     posix_spawn_file_actions_addclose;
     posix_spawn_file_actions_adddup2;
     posix_spawn_file_actions_addopen;
     posix_spawn_file_actions_destroy;
     posix_spawn_file_actions_init;
     posix_spawnp;
+    ppoll64;
+    pselect64;
     pthread_attr_getinheritsched;
     pthread_attr_setinheritsched;
     pthread_mutexattr_getprotocol;
     pthread_mutexattr_setprotocol;
     pthread_setschedprio;
+    pthread_sigmask64;
     sethostent;
     setnetent;
     setprotoent;
+    sigaddset64;
+    sigdelset64;
+    sigemptyset64;
+    sigfillset64;
+    sigismember64;
+    signalfd64;
+    sigpending64;
+    sigprocmask64;
+    sigsuspend64;
+    sigtimedwait64;
+    sigwait64;
+    sigwaitinfo64;
     swab;
     syncfs;
 } LIBC_O;
diff --git a/libc/libc.x86.map b/libc/libc.x86.map
index b0b4b16..eec2c19 100644
--- a/libc/libc.x86.map
+++ b/libc/libc.x86.map
@@ -1307,6 +1307,7 @@
     endhostent;
     endnetent;
     endprotoent;
+    epoll_pwait64;
     fexecve;
     fflush_unlocked;
     fgetc_unlocked;
@@ -1338,28 +1339,47 @@
     posix_spawnattr_getschedparam;
     posix_spawnattr_getschedpolicy;
     posix_spawnattr_getsigdefault;
+    posix_spawnattr_getsigdefault64;
     posix_spawnattr_getsigmask;
+    posix_spawnattr_getsigmask64;
     posix_spawnattr_init;
     posix_spawnattr_setflags;
     posix_spawnattr_setpgroup;
     posix_spawnattr_setschedparam;
     posix_spawnattr_setschedpolicy;
     posix_spawnattr_setsigdefault;
+    posix_spawnattr_setsigdefault64;
     posix_spawnattr_setsigmask;
+    posix_spawnattr_setsigmask64;
     posix_spawn_file_actions_addclose;
     posix_spawn_file_actions_adddup2;
     posix_spawn_file_actions_addopen;
     posix_spawn_file_actions_destroy;
     posix_spawn_file_actions_init;
     posix_spawnp;
+    ppoll64;
+    pselect64;
     pthread_attr_getinheritsched;
     pthread_attr_setinheritsched;
     pthread_mutexattr_getprotocol;
     pthread_mutexattr_setprotocol;
     pthread_setschedprio;
+    pthread_sigmask64;
     sethostent;
     setnetent;
     setprotoent;
+    sigaddset64;
+    sigdelset64;
+    sigemptyset64;
+    sigfillset64;
+    sigismember64;
+    signalfd64;
+    sigpending64;
+    sigprocmask64;
+    sigsuspend64;
+    sigtimedwait64;
+    sigwait64;
+    sigwaitinfo64;
     swab;
     syncfs;
 } LIBC_O;
diff --git a/libc/libc.x86_64.map b/libc/libc.x86_64.map
index f511707..3af0d42 100644
--- a/libc/libc.x86_64.map
+++ b/libc/libc.x86_64.map
@@ -1245,6 +1245,7 @@
     endhostent;
     endnetent;
     endprotoent;
+    epoll_pwait64;
     fexecve;
     fflush_unlocked;
     fgetc_unlocked;
@@ -1276,28 +1277,47 @@
     posix_spawnattr_getschedparam;
     posix_spawnattr_getschedpolicy;
     posix_spawnattr_getsigdefault;
+    posix_spawnattr_getsigdefault64;
     posix_spawnattr_getsigmask;
+    posix_spawnattr_getsigmask64;
     posix_spawnattr_init;
     posix_spawnattr_setflags;
     posix_spawnattr_setpgroup;
     posix_spawnattr_setschedparam;
     posix_spawnattr_setschedpolicy;
     posix_spawnattr_setsigdefault;
+    posix_spawnattr_setsigdefault64;
     posix_spawnattr_setsigmask;
+    posix_spawnattr_setsigmask64;
     posix_spawn_file_actions_addclose;
     posix_spawn_file_actions_adddup2;
     posix_spawn_file_actions_addopen;
     posix_spawn_file_actions_destroy;
     posix_spawn_file_actions_init;
     posix_spawnp;
+    ppoll64;
+    pselect64;
     pthread_attr_getinheritsched;
     pthread_attr_setinheritsched;
     pthread_mutexattr_getprotocol;
     pthread_mutexattr_setprotocol;
     pthread_setschedprio;
+    pthread_sigmask64;
     sethostent;
     setnetent;
     setprotoent;
+    sigaddset64;
+    sigdelset64;
+    sigemptyset64;
+    sigfillset64;
+    sigismember64;
+    signalfd64;
+    sigpending64;
+    sigprocmask64;
+    sigsuspend64;
+    sigtimedwait64;
+    sigwait64;
+    sigwaitinfo64;
     swab;
     syncfs;
 } LIBC_O;
diff --git a/libc/private/ScopedSignalBlocker.h b/libc/private/ScopedSignalBlocker.h
index c3ab307..7582068 100644
--- a/libc/private/ScopedSignalBlocker.h
+++ b/libc/private/ScopedSignalBlocker.h
@@ -20,14 +20,13 @@
 #include <signal.h>
 
 #include "bionic_macros.h"
-#include "kernel_sigset_t.h"
 
 class ScopedSignalBlocker {
  public:
   explicit ScopedSignalBlocker() {
-    kernel_sigset_t set;
-    set.fill();
-    __rt_sigprocmask(SIG_SETMASK, &set, &old_set_, sizeof(set));
+    sigset64_t set;
+    sigfillset64(&set);
+    sigprocmask64(SIG_SETMASK, &set, &old_set_);
   }
 
   ~ScopedSignalBlocker() {
@@ -35,11 +34,11 @@
   }
 
   void reset() {
-    __rt_sigprocmask(SIG_SETMASK, &old_set_, nullptr, sizeof(old_set_));
+    sigprocmask64(SIG_SETMASK, &old_set_, nullptr);
   }
 
  private:
-  kernel_sigset_t old_set_;
+  sigset64_t old_set_;
 
   DISALLOW_COPY_AND_ASSIGN(ScopedSignalBlocker);
 };
diff --git a/libc/bionic/epoll_create.cpp b/libc/private/SigSetConverter.h
similarity index 85%
rename from libc/bionic/epoll_create.cpp
rename to libc/private/SigSetConverter.h
index 74f664f..7d0b215 100644
--- a/libc/bionic/epoll_create.cpp
+++ b/libc/private/SigSetConverter.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 The Android Open Source Project
+ * Copyright (C) 2018 The Android Open Source Project
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -26,13 +26,10 @@
  * SUCH DAMAGE.
  */
 
-#include <errno.h>
-#include <sys/epoll.h>
+#pragma once
 
-int epoll_create(int size) {
-  if (size <= 0) {
-    errno = EINVAL;
-    return -1;
-  }
-  return epoll_create1(0);
-}
+union SigSetConverter {
+  int bsd;
+  sigset_t sigset;
+  sigset64_t sigset64;
+};
diff --git a/libc/private/kernel_sigset_t.h b/libc/private/kernel_sigset_t.h
deleted file mode 100644
index bdfb729..0000000
--- a/libc/private/kernel_sigset_t.h
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#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 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 when
-// initializing from a sigset_t on LP32.
-union kernel_sigset_t {
- public:
-  kernel_sigset_t() {
-  }
-
-  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);
-  }
-
-  void clear() {
-    __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;
-  }
-
-  sigset_t* get() {
-    return &bionic;
-  }
-
-  sigset_t bionic;
-  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