aboutsummaryrefslogtreecommitdiff
path: root/lib/libpthread/t_compat_cancel.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libpthread/t_compat_cancel.c')
-rw-r--r--lib/libpthread/t_compat_cancel.c287
1 files changed, 287 insertions, 0 deletions
diff --git a/lib/libpthread/t_compat_cancel.c b/lib/libpthread/t_compat_cancel.c
new file mode 100644
index 000000000000..280d072b3dd6
--- /dev/null
+++ b/lib/libpthread/t_compat_cancel.c
@@ -0,0 +1,287 @@
+/* $NetBSD: t_compat_cancel.c,v 1.3 2025/04/25 13:09:44 riastradh Exp $ */
+
+/*
+ * Copyright (c) 2025 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+#define __LIBC12_SOURCE__ /* expose compat declarations */
+
+#include <sys/cdefs.h>
+__RCSID("$NetBSD: t_compat_cancel.c,v 1.3 2025/04/25 13:09:44 riastradh Exp $");
+
+#include <sys/event.h>
+#include <sys/mman.h>
+
+#include <aio.h>
+#include <atf-c.h>
+#include <mqueue.h>
+#include <pthread.h>
+#include <signal.h>
+
+#include <compat/sys/event.h>
+#include <compat/sys/mman.h>
+#include <compat/sys/poll.h>
+#include <compat/sys/select.h>
+
+#include <compat/include/aio.h>
+#include <compat/include/mqueue.h>
+#include <compat/include/signal.h>
+#include <compat/include/time.h>
+
+#include "cancelpoint.h"
+#include "h_macros.h"
+
+pthread_barrier_t bar;
+bool cleanup_done;
+
+static void
+cancelpoint_compat100_kevent(void)
+{
+ int kq;
+ struct kevent100 ev;
+
+ memset(&ev, 0, sizeof(ev));
+ ev.ident = SIGUSR1;
+ ev.filter = EVFILT_SIGNAL;
+ ev.flags = EV_ADD|EV_ENABLE;
+ ev.fflags = 0;
+ ev.data = 0;
+ ev.udata = 0;
+
+ RL(kq = kqueue());
+ RL(__kevent50(kq, &ev, 1, NULL, 1, &(const struct timespec){0,0}));
+ cancelpointready();
+ RL(__kevent50(kq, NULL, 0, &ev, 1, NULL));
+}
+
+static void
+cancelpoint_compat12_msync(void)
+{
+ const unsigned long pagesize = sysconf(_SC_PAGESIZE);
+ int fd;
+ void *map;
+
+ RL(fd = open("file", O_RDWR|O_CREAT, 0666));
+ RL(ftruncate(fd, pagesize));
+ REQUIRE_LIBC(map = mmap(NULL, pagesize, PROT_READ|PROT_WRITE,
+ MAP_SHARED, fd, 0),
+ MAP_FAILED);
+ cancelpointready();
+ RL(msync(map, pagesize));
+}
+
+static void
+cancelpoint_compat50___sigtimedwait(void)
+{
+ sigset_t mask, omask;
+ siginfo_t info;
+ struct timespec50 t = {.tv_sec = 2, .tv_nsec = 0};
+
+ RL(__sigfillset14(&mask));
+ RL(__sigprocmask14(SIG_BLOCK, &mask, &omask));
+ cancelpointready();
+ RL(__sigtimedwait(&omask, &info, &t));
+}
+
+static void
+cancelpoint_compat50_aio_suspend(void)
+{
+ int fd[2];
+ char buf[32];
+ struct aiocb aio = {
+ .aio_offset = 0,
+ .aio_buf = buf,
+ .aio_nbytes = sizeof(buf),
+ .aio_fildes = -1,
+ };
+ const struct aiocb *const aiolist[] = { &aio };
+
+ RL(pipe(fd));
+ aio.aio_fildes = fd[0];
+ RL(aio_read(&aio));
+ cancelpointready();
+ RL(aio_suspend(aiolist, __arraycount(aiolist), NULL));
+}
+
+static void
+cancelpoint_compat50_kevent(void)
+{
+ int kq;
+ struct kevent100 ev;
+
+ memset(&ev, 0, sizeof(ev));
+ ev.ident = SIGUSR1;
+ ev.filter = EVFILT_SIGNAL;
+ ev.flags = EV_ADD|EV_ENABLE;
+ ev.fflags = 0;
+ ev.data = 0;
+ ev.udata = 0;
+
+ RL(kq = kqueue());
+ RL(kevent(kq, &ev, 1, NULL, 1, &(const struct timespec50){0,0}));
+ cancelpointready();
+ RL(kevent(kq, NULL, 0, &ev, 1, NULL));
+}
+
+static void
+cancelpoint_compat50_mq_timedreceive(void)
+{
+ mqd_t mq;
+ char buf[32];
+ struct timespec50 t = {.tv_sec = 2, .tv_nsec = 0};
+
+ RL(mq = mq_open("mq", O_RDWR|O_CREAT, 0666, NULL));
+ cancelpointready();
+ RL(mq_timedreceive(mq, buf, sizeof(buf), NULL, &t));
+}
+
+static void
+cancelpoint_compat50_mq_timedsend(void)
+{
+ mqd_t mq;
+ char buf[32] = {0};
+ struct timespec50 t = {.tv_sec = 2, .tv_nsec = 0};
+
+ RL(mq = mq_open("mq", O_RDWR|O_CREAT, 0666, NULL));
+ cancelpointready();
+ RL(mq_timedsend(mq, buf, sizeof(buf), 0, &t));
+}
+
+static void
+cancelpoint_compat50_nanosleep(void)
+{
+ struct timespec50 t = {.tv_sec = 2, .tv_nsec = 0};
+
+ cancelpointready();
+ RL(nanosleep(&t, NULL));
+}
+
+static void
+cancelpoint_compat50_pollts(void)
+{
+ int fd[2];
+ struct pollfd pfd;
+ struct timespec50 t = {.tv_sec = 2, .tv_nsec = 0};
+
+ RL(pipe(fd));
+ pfd.fd = fd[0];
+ pfd.events = POLLIN;
+ cancelpointready();
+ RL(pollts(&pfd, 1, &t, NULL));
+}
+
+static void
+cancelpoint_compat50_pselect(void)
+{
+ int fd[2];
+ fd_set readfd;
+ struct timespec50 t = {.tv_sec = 2, .tv_nsec = 0};
+
+ FD_ZERO(&readfd);
+
+ RL(pipe(fd));
+ FD_SET(fd[0], &readfd);
+ cancelpointready();
+ RL(pselect(fd[0] + 1, &readfd, NULL, NULL, &t, NULL));
+}
+
+static void
+cancelpoint_compat50_select(void)
+{
+ int fd[2];
+ fd_set readfd;
+ struct timeval50 t = {.tv_sec = 1, .tv_usec = 0};
+
+ FD_ZERO(&readfd);
+
+ RL(pipe(fd));
+ FD_SET(fd[0], &readfd);
+ cancelpointready();
+ RL(select(fd[0] + 1, &readfd, NULL, NULL, &t));
+}
+
+static void
+cancelpoint_compat13_sigsuspend(void)
+{
+ sigset13_t mask, omask;
+
+ RL(sigfillset(&mask));
+ RL(sigprocmask(SIG_BLOCK, &mask, &omask));
+ cancelpointready();
+ RL(sigsuspend(&omask));
+}
+
+static void
+cancelpoint_compat50_sigtimedwait(void)
+{
+ sigset_t mask, omask;
+ siginfo_t info;
+ struct timespec50 t = {.tv_sec = 2, .tv_nsec = 0};
+
+ RL(__sigfillset14(&mask));
+ RL(__sigprocmask14(SIG_BLOCK, &mask, &omask));
+ cancelpointready();
+ RL(sigtimedwait(&omask, &info, &t));
+}
+
+TEST_CANCELPOINT(cancelpoint_compat100_kevent, __nothing)
+TEST_CANCELPOINT(cancelpoint_compat12_msync, __nothing)
+TEST_CANCELPOINT(cancelpoint_compat13_sigsuspend,
+ atf_tc_expect_signal(-1, "PR lib/59240: POSIX.1-2024:"
+ " cancellation point audit"))
+TEST_CANCELPOINT(cancelpoint_compat50___sigtimedwait,
+ atf_tc_expect_signal(-1, "PR lib/59240: POSIX.1-2024:"
+ " cancellation point audit"))
+TEST_CANCELPOINT(cancelpoint_compat50_aio_suspend, __nothing)
+TEST_CANCELPOINT(cancelpoint_compat50_kevent, __nothing)
+TEST_CANCELPOINT(cancelpoint_compat50_mq_timedreceive, __nothing)
+TEST_CANCELPOINT(cancelpoint_compat50_mq_timedsend, __nothing)
+TEST_CANCELPOINT(cancelpoint_compat50_nanosleep, __nothing)
+TEST_CANCELPOINT(cancelpoint_compat50_pollts, __nothing)
+TEST_CANCELPOINT(cancelpoint_compat50_pselect, __nothing)
+TEST_CANCELPOINT(cancelpoint_compat50_select, __nothing)
+TEST_CANCELPOINT(cancelpoint_compat50_sigtimedwait,
+ atf_tc_expect_signal(-1, "PR lib/59240: POSIX.1-2024:"
+ " cancellation point audit"))
+
+ATF_TP_ADD_TCS(tp)
+{
+
+ ADD_TEST_CANCELPOINT(cancelpoint_compat100_kevent);
+ ADD_TEST_CANCELPOINT(cancelpoint_compat12_msync);
+ ADD_TEST_CANCELPOINT(cancelpoint_compat13_sigsuspend);
+ ADD_TEST_CANCELPOINT(cancelpoint_compat50___sigtimedwait);
+ ADD_TEST_CANCELPOINT(cancelpoint_compat50_aio_suspend);
+ ADD_TEST_CANCELPOINT(cancelpoint_compat50_kevent);
+ ADD_TEST_CANCELPOINT(cancelpoint_compat50_mq_timedreceive);
+ ADD_TEST_CANCELPOINT(cancelpoint_compat50_mq_timedsend);
+ ADD_TEST_CANCELPOINT(cancelpoint_compat50_nanosleep);
+ ADD_TEST_CANCELPOINT(cancelpoint_compat50_pollts);
+ ADD_TEST_CANCELPOINT(cancelpoint_compat50_pselect);
+ ADD_TEST_CANCELPOINT(cancelpoint_compat50_select);
+ ADD_TEST_CANCELPOINT(cancelpoint_compat50_sigtimedwait);
+
+ return atf_no_error();
+}