|
| 1 | +/* |
| 2 | + * Copyright (C) 2026 Greg Burd |
| 3 | + * |
| 4 | + * This work is open source software, licensed under the terms of the |
| 5 | + * BSD license as described in the LICENSE file in the top-level directory. |
| 6 | + */ |
| 7 | + |
| 8 | +// Exercises epoll_pwait2(2) via the raw syscall. Built and run on the OSv |
| 9 | +// test image. |
| 10 | + |
| 11 | +#include <sys/epoll.h> |
| 12 | +#include <sys/eventfd.h> |
| 13 | +#include <sys/syscall.h> |
| 14 | +#include <unistd.h> |
| 15 | +#include <time.h> |
| 16 | +#include <errno.h> |
| 17 | +#include <stdint.h> |
| 18 | + |
| 19 | +#include <cassert> |
| 20 | +#include <iostream> |
| 21 | + |
| 22 | +static int epoll_pwait2_(int epfd, struct epoll_event *ev, int maxev, |
| 23 | + const struct timespec *to, const sigset_t *sig) |
| 24 | +{ |
| 25 | + return syscall(SYS_epoll_pwait2, epfd, ev, maxev, to, sig); |
| 26 | +} |
| 27 | + |
| 28 | +int main() |
| 29 | +{ |
| 30 | + std::cerr << "Running epoll_pwait2 tests\n"; |
| 31 | + |
| 32 | + int ep = epoll_create1(0); |
| 33 | + assert(ep >= 0); |
| 34 | + int efd = eventfd(0, EFD_NONBLOCK); |
| 35 | + assert(efd >= 0); |
| 36 | + |
| 37 | + struct epoll_event ev {}; |
| 38 | + ev.events = EPOLLIN; |
| 39 | + ev.data.fd = efd; |
| 40 | + assert(epoll_ctl(ep, EPOLL_CTL_ADD, efd, &ev) == 0); |
| 41 | + |
| 42 | + struct epoll_event out[4]; |
| 43 | + |
| 44 | + // Nothing ready: a zero timespec returns immediately with 0 events. |
| 45 | + struct timespec zero { 0, 0 }; |
| 46 | + assert(epoll_pwait2_(ep, out, 4, &zero, nullptr) == 0); |
| 47 | + |
| 48 | + // Nothing ready: a short timeout returns 0 after roughly that long. |
| 49 | + struct timespec ts { 0, 100 * 1000 * 1000 }; // 100 ms |
| 50 | + struct timespec before, after; |
| 51 | + clock_gettime(CLOCK_MONOTONIC, &before); |
| 52 | + assert(epoll_pwait2_(ep, out, 4, &ts, nullptr) == 0); |
| 53 | + clock_gettime(CLOCK_MONOTONIC, &after); |
| 54 | + long long elapsed_ms = (after.tv_sec - before.tv_sec) * 1000 + |
| 55 | + (after.tv_nsec - before.tv_nsec) / 1000000; |
| 56 | + assert(elapsed_ms >= 90); // waited about 100 ms, not returned instantly |
| 57 | + |
| 58 | + // Make the eventfd readable: pwait2 reports it. |
| 59 | + uint64_t one = 1; |
| 60 | + assert(write(efd, &one, sizeof(one)) == sizeof(one)); |
| 61 | + int n = epoll_pwait2_(ep, out, 4, &ts, nullptr); |
| 62 | + assert(n == 1); |
| 63 | + assert(out[0].data.fd == efd); |
| 64 | + assert(out[0].events & EPOLLIN); |
| 65 | + |
| 66 | + // NULL timeout with a ready fd returns immediately (does not block forever). |
| 67 | + n = epoll_pwait2_(ep, out, 4, nullptr, nullptr); |
| 68 | + assert(n == 1); |
| 69 | + |
| 70 | + close(efd); |
| 71 | + close(ep); |
| 72 | + std::cerr << "epoll_pwait2 tests PASSED\n"; |
| 73 | + return 0; |
| 74 | +} |
0 commit comments