#define __LIBC12_SOURCE__
#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();
}