Only have one copy of the kernel_sigset_t hack, and add more tests.
Change-Id: I377522fcba6fb4b5fd2754ab15b091014bd7c16f
diff --git a/libc/bionic/pthread.c b/libc/bionic/pthread.c
index b685f2d..92ee4aa 100644
--- a/libc/bionic/pthread.c
+++ b/libc/bionic/pthread.c
@@ -2099,58 +2099,6 @@
return ret;
}
-/* Despite the fact that our kernel headers define sigset_t explicitly
- * as a 32-bit integer, the kernel system call really expects a 64-bit
- * bitmap for the signal set, or more exactly an array of two-32-bit
- * values (see $KERNEL/arch/$ARCH/include/asm/signal.h for details).
- *
- * Unfortunately, we cannot fix the sigset_t definition without breaking
- * the C library ABI, so perform a little runtime translation here.
- */
-typedef union {
- sigset_t bionic;
- uint32_t kernel[2];
-} kernel_sigset_t;
-
-/* this is a private syscall stub */
-extern int __rt_sigprocmask(int, const kernel_sigset_t *, kernel_sigset_t *, size_t);
-
-int pthread_sigmask(int how, const sigset_t *set, sigset_t *oset)
-{
- /* pthread_sigmask must return the error code, but the syscall
- * will set errno instead and return 0/-1
- */
- int ret, old_errno = errno;
-
- /* We must convert *set into a kernel_sigset_t */
- kernel_sigset_t in_set, *in_set_ptr;
- kernel_sigset_t out_set;
-
- in_set.kernel[0] = in_set.kernel[1] = 0;
- out_set.kernel[0] = out_set.kernel[1] = 0;
-
- /* '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'.
- */
- if (set == NULL) {
- in_set_ptr = NULL;
- } else {
- in_set.bionic = *set;
- in_set_ptr = &in_set;
- }
-
- ret = __rt_sigprocmask(how, in_set_ptr, &out_set, sizeof(kernel_sigset_t));
- if (ret < 0)
- ret = errno;
-
- if (oset)
- *oset = out_set.bionic;
-
- errno = old_errno;
- return ret;
-}
-
int pthread_getcpuclockid(pthread_t tid, clockid_t *clockid)
{
diff --git a/libc/bionic/pthread_sigmask.cpp b/libc/bionic/pthread_sigmask.cpp
new file mode 100644
index 0000000..9c9dc3e
--- /dev/null
+++ b/libc/bionic/pthread_sigmask.cpp
@@ -0,0 +1,62 @@
+/*
+ * 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/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 old_errno = errno;
+
+ // '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;
+ int result = __rt_sigprocmask(how, in_set_ptr, &out_set, sizeof(out_set));
+ if (result < 0) {
+ result = errno;
+ }
+
+ if (oset != NULL) {
+ *oset = out_set.bionic;
+ }
+
+ errno = old_errno;
+ return result;
+}
diff --git a/libc/bionic/signalfd.cpp b/libc/bionic/signalfd.cpp
index 51fae83..b7e6474 100644
--- a/libc/bionic/signalfd.cpp
+++ b/libc/bionic/signalfd.cpp
@@ -28,27 +28,11 @@
#include <sys/signalfd.h>
-/* Despite the fact that our kernel headers define sigset_t explicitly
- * as a 32-bit integer, the kernel system call really expects a 64-bit
- * bitmap for the signal set, or more exactly an array of two-32-bit
- * values (see $KERNEL/arch/$ARCH/include/asm/signal.h for details).
- *
- * Unfortunately, we cannot fix the sigset_t definition without breaking
- * the C library ABI, so perform a little runtime translation here.
- */
-typedef union {
- sigset_t bionic;
- uint32_t kernel[2];
-} kernel_sigset_t;
+#include <private/kernel_sigset_t.h>
-extern "C" int signalfd4(int fd, kernel_sigset_t *mask, size_t sizemask, int flags);
+extern "C" int signalfd4(int fd, kernel_sigset_t* mask, size_t sizemask, int flags);
-int signalfd(int fd, const sigset_t *mask, int flags)
-{
- kernel_sigset_t in_set;
- in_set.kernel[0] = in_set.kernel[1] = 0;
-
- in_set.bionic = *mask;
-
- return signalfd4(fd, &in_set, sizeof(in_set), flags);
+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);
}
diff --git a/libc/bionic/sigwait.c b/libc/bionic/sigwait.c
deleted file mode 100644
index 1e90c41..0000000
--- a/libc/bionic/sigwait.c
+++ /dev/null
@@ -1,83 +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>
-
-int __rt_sigtimedwait(const sigset_t *uthese, siginfo_t *uinfo, const struct timespec *uts, size_t sigsetsize);
-
-/* ok, this is really subtle: <asm/signal.h> defines sigset_t differently
- * when you're in the kernel or in the C library.
- *
- * in the kernel, this is an array of 2 32-bit unsigned longs
- * in the C library, this is a single 32-bit unsigned long
- *
- * moreover, the kernel implementation of rt_sigtimedwait doesn't
- * accept anything except kernel-sized signal sets (probably a bug !)
- *
- * we thus need to create a fake kernel sigset !!
- */
-
-int sigwait(const sigset_t *set, int *sig)
-{
- int ret;
-#ifdef __mips__
- /* use a union to get rid of aliasing warnings. On MIPS sigset_t is 128 bits */
- union {
- sigset_t kernel_sigset;
- sigset_t dummy_sigset;
- } u;
- u.dummy_sigset = *set;
-#else
- /* use a union to get rid of aliasing warnings */
- union {
- unsigned long kernel_sigset[2];
- sigset_t dummy_sigset;
- } u;
-
- u.kernel_sigset[0] = *set;
- u.kernel_sigset[1] = 0; /* no real-time signals supported ? */
-#endif
- for (;;)
- {
- /* __rt_sigtimedwait can return EAGAIN or EINTR, we need to loop
- * around them since sigwait is only allowed to return EINVAL
- */
- ret = __rt_sigtimedwait ( &u.dummy_sigset, NULL, NULL, sizeof(u.kernel_sigset));
- if (ret >= 0)
- break;
-
- if (errno != EAGAIN && errno != EINTR)
- return errno;
- }
-
- *sig = ret;
- return 0;
-}
-
diff --git a/libc/bionic/sigwait.cpp b/libc/bionic/sigwait.cpp
new file mode 100644
index 0000000..1546fd6
--- /dev/null
+++ b/libc/bionic/sigwait.cpp
@@ -0,0 +1,53 @@
+/*
+ * 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* uthese, siginfo_t* uinfo, const struct timespec* uts, size_t sigsetsize);
+
+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;
+ }
+ }
+}