Clean up the sigprocmask/pthread_sigmask implementation.

Let's have both use rt_sigprocmask, like in glibc. The 64-bit ABIs
can share the same code as the 32-bit ABIs.

Also, let's test the return side of these calls, not just the
setting.

Bug: 11069919
Change-Id: I11da99f85b5b481870943c520d05ec929b15eddb
diff --git a/libc/Android.mk b/libc/Android.mk
index 340228b..b9db201 100644
--- a/libc/Android.mk
+++ b/libc/Android.mk
@@ -247,6 +247,7 @@
     bionic/seteuid.cpp \
     bionic/setlocale.cpp \
     bionic/signalfd.cpp \
+    bionic/sigprocmask.cpp \
     bionic/sigwait.cpp \
     bionic/statvfs.cpp \
     bionic/strerror.cpp \
diff --git a/libc/SYSCALLS.TXT b/libc/SYSCALLS.TXT
index 0902357..cea1878 100644
--- a/libc/SYSCALLS.TXT
+++ b/libc/SYSCALLS.TXT
@@ -233,7 +233,6 @@
 
 # signals
 int     sigaction(int, const struct sigaction*, struct sigaction*)  arm,x86,mips
-int     sigprocmask(int, const sigset_t*, sigset_t*)  arm,x86,mips
 int     __sigsuspend:sigsuspend(int unused1, int unused2, unsigned mask)  arm,x86
 int     __sigsuspend:sigsuspend(const sigset_t* mask)  mips
 int     __rt_sigsuspend:rt_sigsuspend(const sigset_t *unewset, size_t sigset_size)  x86_64
diff --git a/libc/arch-arm/syscalls.mk b/libc/arch-arm/syscalls.mk
index d28c975..3a66c1b 100644
--- a/libc/arch-arm/syscalls.mk
+++ b/libc/arch-arm/syscalls.mk
@@ -152,7 +152,6 @@
 syscall_src += arch-arm/syscalls/timerfd_settime.S
 syscall_src += arch-arm/syscalls/timerfd_gettime.S
 syscall_src += arch-arm/syscalls/sigaction.S
-syscall_src += arch-arm/syscalls/sigprocmask.S
 syscall_src += arch-arm/syscalls/__sigsuspend.S
 syscall_src += arch-arm/syscalls/__rt_sigaction.S
 syscall_src += arch-arm/syscalls/__rt_sigprocmask.S
diff --git a/libc/arch-arm/syscalls/sigprocmask.S b/libc/arch-arm/syscalls/sigprocmask.S
deleted file mode 100644
index f935340..0000000
--- a/libc/arch-arm/syscalls/sigprocmask.S
+++ /dev/null
@@ -1,15 +0,0 @@
-/* autogenerated by gensyscalls.py */
-#include <asm/unistd.h>
-#include <linux/err.h>
-#include <machine/asm.h>
-
-ENTRY(sigprocmask)
-    mov     ip, r7
-    ldr     r7, =__NR_sigprocmask
-    swi     #0
-    mov     r7, ip
-    cmn     r0, #(MAX_ERRNO + 1)
-    bxls    lr
-    neg     r0, r0
-    b       __set_errno
-END(sigprocmask)
diff --git a/libc/arch-mips/syscalls.mk b/libc/arch-mips/syscalls.mk
index 4611cd8..740f91c 100644
--- a/libc/arch-mips/syscalls.mk
+++ b/libc/arch-mips/syscalls.mk
@@ -155,7 +155,6 @@
 syscall_src += arch-mips/syscalls/timerfd_settime.S
 syscall_src += arch-mips/syscalls/timerfd_gettime.S
 syscall_src += arch-mips/syscalls/sigaction.S
-syscall_src += arch-mips/syscalls/sigprocmask.S
 syscall_src += arch-mips/syscalls/__sigsuspend.S
 syscall_src += arch-mips/syscalls/__rt_sigaction.S
 syscall_src += arch-mips/syscalls/__rt_sigprocmask.S
diff --git a/libc/arch-mips/syscalls/sigprocmask.S b/libc/arch-mips/syscalls/sigprocmask.S
deleted file mode 100644
index a4049bb..0000000
--- a/libc/arch-mips/syscalls/sigprocmask.S
+++ /dev/null
@@ -1,22 +0,0 @@
-/* autogenerated by gensyscalls.py */
-#include <asm/unistd.h>
-    .text
-    .globl sigprocmask
-    .align 4
-    .ent sigprocmask
-
-sigprocmask:
-    .set noreorder
-    .cpload $t9
-    li $v0, __NR_sigprocmask
-    syscall
-    bnez $a3, 1f
-    move $a0, $v0
-    j $ra
-    nop
-1:
-    la $t9,__set_errno
-    j $t9
-    nop
-    .set reorder
-    .end sigprocmask
diff --git a/libc/arch-x86/syscalls.mk b/libc/arch-x86/syscalls.mk
index 79b4f2c..a704905 100644
--- a/libc/arch-x86/syscalls.mk
+++ b/libc/arch-x86/syscalls.mk
@@ -156,7 +156,6 @@
 syscall_src += arch-x86/syscalls/timerfd_settime.S
 syscall_src += arch-x86/syscalls/timerfd_gettime.S
 syscall_src += arch-x86/syscalls/sigaction.S
-syscall_src += arch-x86/syscalls/sigprocmask.S
 syscall_src += arch-x86/syscalls/__sigsuspend.S
 syscall_src += arch-x86/syscalls/__rt_sigaction.S
 syscall_src += arch-x86/syscalls/__rt_sigprocmask.S
diff --git a/libc/arch-x86/syscalls/sigprocmask.S b/libc/arch-x86/syscalls/sigprocmask.S
deleted file mode 100644
index 0ac052e..0000000
--- a/libc/arch-x86/syscalls/sigprocmask.S
+++ /dev/null
@@ -1,27 +0,0 @@
-/* autogenerated by gensyscalls.py */
-#include <asm/unistd.h>
-#include <linux/err.h>
-#include <machine/asm.h>
-
-ENTRY(sigprocmask)
-    pushl   %ebx
-    pushl   %ecx
-    pushl   %edx
-    mov     16(%esp), %ebx
-    mov     20(%esp), %ecx
-    mov     24(%esp), %edx
-    movl    $__NR_sigprocmask, %eax
-    int     $0x80
-    cmpl    $-MAX_ERRNO, %eax
-    jb      1f
-    negl    %eax
-    pushl   %eax
-    call    __set_errno
-    addl    $4, %esp
-    orl     $-1, %eax
-1:
-    popl    %edx
-    popl    %ecx
-    popl    %ebx
-    ret
-END(sigprocmask)
diff --git a/libc/arch-x86_64/x86_64.mk b/libc/arch-x86_64/x86_64.mk
index a1c1705..f293b2d 100644
--- a/libc/arch-x86_64/x86_64.mk
+++ b/libc/arch-x86_64/x86_64.mk
@@ -8,7 +8,6 @@
     arch-x86_64/bionic/setjmp.S \
     arch-x86_64/bionic/__set_tls.c \
     arch-x86_64/bionic/sigaction.c \
-    arch-x86_64/bionic/sigprocmask.c \
     arch-x86_64/bionic/sigsetjmp.S \
     arch-x86_64/bionic/sigsuspend.c \
     arch-x86_64/bionic/syscall.S \
diff --git a/libc/bionic/pthread_sigmask.cpp b/libc/bionic/pthread_sigmask.cpp
index e4e1b2b..79f31a1 100644
--- a/libc/bionic/pthread_sigmask.cpp
+++ b/libc/bionic/pthread_sigmask.cpp
@@ -31,31 +31,9 @@
 #include <signal.h>
 
 #include "private/ErrnoRestorer.h"
-#include "private/kernel_sigset_t.h"
 
-extern "C" int __rt_sigprocmask(int, const kernel_sigset_t*, kernel_sigset_t*, size_t);
-
-int pthread_sigmask(int how, const sigset_t* iset, sigset_t* oset) {
+int pthread_sigmask(int how, const sigset_t* new_set, sigset_t* old_set) {
   ErrnoRestorer errno_restorer;
-
-  // 'in_set_ptr' is the second parameter to __rt_sigprocmask. It must be NULL
-  // if 'set' is NULL to ensure correct semantics (which in this case would
-  // be to ignore 'how' and return the current signal set into 'oset').
-  kernel_sigset_t in_set;
-  kernel_sigset_t* in_set_ptr = NULL;
-  if (iset != NULL) {
-    in_set.set(iset);
-    in_set_ptr = &in_set;
-  }
-
-  kernel_sigset_t out_set;
-  if (__rt_sigprocmask(how, in_set_ptr, &out_set, sizeof(out_set)) == -1) {
-    return errno;
-  }
-
-  if (oset != NULL) {
-    *oset = out_set.bionic;
-  }
-
-  return 0;
+  int result = sigprocmask(how, new_set, old_set);
+  return (result == -1) ? errno : 0;
 }
diff --git a/libc/arch-x86_64/bionic/sigprocmask.c b/libc/bionic/sigprocmask.cpp
similarity index 68%
rename from libc/arch-x86_64/bionic/sigprocmask.c
rename to libc/bionic/sigprocmask.cpp
index cdafa08..61e2c63 100644
--- a/libc/arch-x86_64/bionic/sigprocmask.c
+++ b/libc/bionic/sigprocmask.cpp
@@ -26,10 +26,30 @@
  * SUCH DAMAGE.
  */
 
+#include <errno.h>
+#include <pthread.h>
 #include <signal.h>
 
-extern int __rt_sigprocmask(int, const sigset_t*, sigset_t*, size_t);
+#include "private/kernel_sigset_t.h"
 
-int sigprocmask(int how, const sigset_t* set, sigset_t* old_set) {
-  return __rt_sigprocmask(how, set, old_set, sizeof(sigset_t));
+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/tests/pthread_test.cpp b/tests/pthread_test.cpp
index d82921b..4a7c155 100644
--- a/tests/pthread_test.cpp
+++ b/tests/pthread_test.cpp
@@ -173,12 +173,28 @@
 }
 
 TEST(pthread, pthread_sigmask) {
+  // Check that SIGUSR1 isn't blocked.
+  sigset_t original_set;
+  sigemptyset(&original_set);
+  ASSERT_EQ(0, pthread_sigmask(SIG_BLOCK, NULL, &original_set));
+  ASSERT_FALSE(sigismember(&original_set, SIGUSR1));
+
   // Block SIGUSR1.
   sigset_t set;
   sigemptyset(&set);
   sigaddset(&set, SIGUSR1);
   ASSERT_EQ(0, pthread_sigmask(SIG_BLOCK, &set, NULL));
 
+  // Check that SIGUSR1 is blocked.
+  sigset_t final_set;
+  sigemptyset(&final_set);
+  ASSERT_EQ(0, pthread_sigmask(SIG_BLOCK, NULL, &final_set));
+  ASSERT_TRUE(sigismember(&final_set, SIGUSR1));
+  // ...and that sigprocmask agrees with pthread_sigmask.
+  sigemptyset(&final_set);
+  ASSERT_EQ(0, sigprocmask(SIG_BLOCK, NULL, &final_set));
+  ASSERT_TRUE(sigismember(&final_set, SIGUSR1));
+
   // Spawn a thread that calls sigwait and tells us what it received.
   pthread_t signal_thread;
   int received_signal = -1;
@@ -192,6 +208,9 @@
   ASSERT_EQ(0, pthread_join(signal_thread, &join_result));
   ASSERT_EQ(SIGUSR1, received_signal);
   ASSERT_EQ(0U, reinterpret_cast<uintptr_t>(join_result));
+
+  // Restore the original signal mask.
+  ASSERT_EQ(0, pthread_sigmask(SIG_SETMASK, &original_set, NULL));
 }
 
 #if __BIONIC__