[PATCH v2 2/5] syscalls: Add epoll_wait13
Cyril Hrubis <[email protected]>
| Newsgroups | gmane.linux.ltp |
|---|---|
| Message-ID | <[email protected]> |
That checks that subsequent calls to epoll() return all events if there were more events than the size of the events array passed to epoll. Signed-off-by: Cyril Hrubis <[email protected]> --- runtest/syscalls | 1 + .../kernel/syscalls/epoll_wait/.gitignore | 1 + .../kernel/syscalls/epoll_wait/epoll_wait13.c | 143 ++++++++++++++++++ 3 files changed, 145 insertions(+) create mode 100644 testcases/kernel/syscalls/epoll_wait/epoll_wait13.c diff --git a/runtest/syscalls b/runtest/syscalls index 9f46e28de..1cbc13c82 100644 --- a/runtest/syscalls +++ b/runtest/syscalls @@ -202,6 +202,7 @@ epoll_wait09 epoll_wait09 epoll_wait10 epoll_wait10 epoll_wait11 epoll_wait11 epoll_wait12 epoll_wait12 +epoll_wait13 epoll_wait13 epoll_pwait01 epoll_pwait01 epoll_pwait02 epoll_pwait02 diff --git a/testcases/kernel/syscalls/epoll_wait/.gitignore b/testcases/kernel/syscalls/epoll_wait/.gitignore index ad890d077..145e7a0bd 100644 --- a/testcases/kernel/syscalls/epoll_wait/.gitignore +++ b/testcases/kernel/syscalls/epoll_wait/.gitignore @@ -10,3 +10,4 @@ epoll_wait09 epoll_wait10 epoll_wait11 epoll_wait12 +epoll_wait13 diff --git a/testcases/kernel/syscalls/epoll_wait/epoll_wait13.c b/testcases/kernel/syscalls/epoll_wait/epoll_wait13.c new file mode 100644 index 000000000..8a8446baa --- /dev/null +++ b/testcases/kernel/syscalls/epoll_wait/epoll_wait13.c @@ -0,0 +1,143 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2026 Cyril Hrubis <[email protected]> + */ + +/*\ + * Verify that :manpage:`epoll_wait(2)` caps the number of reported events at + * ``maxevents`` and eventually reports every ready file descriptor while + * ignoring the registered descriptors that are not ready. + * + * When more file descriptors are ready than the ``maxevents`` limit passed to + * :manpage:`epoll_wait(2)`, a single call must return at most ``maxevents`` + * events. The remaining ready descriptors have to be reported by subsequent + * calls. Descriptors that are registered but have no data ready must never be + * reported, so the test also registers a set of quiet descriptors and checks + * that none of them show up in the results. + */ + +#include <sys/epoll.h> + +#include "tst_test.h" +#include "tst_epoll.h" +#include "tst_minmax.h" + +/* NREADY is deliberately not a multiple of MAXEVENTS. */ +#define NREADY 13 +#define NQUIET 5 +#define MAXEVENTS 3 + +/* + * Ready fds are registered with data.u64 in the range [0, NREADY), quiet fds + * with data.u64 >= NREADY, so any reported quiet fd is trivially detected. + */ +#define QUIET_TAG NREADY + +static int epfd = -1; +static int ready_fds[NREADY][2]; +static int quiet_fds[NQUIET][2]; +static struct epoll_event *events; + +static void register_fds(int fds[][2], int n, uint64_t tag) +{ + struct epoll_event ev = {.events = EPOLLIN}; + int i; + + for (i = 0; i < n; i++) { + SAFE_PIPE(fds[i]); + + ev.data.u64 = tag + i; + SAFE_EPOLL_CTL(epfd, EPOLL_CTL_ADD, fds[i][0], &ev); + } +} + +static void close_fds(int fds[][2], int n) +{ + int i; + + for (i = 0; i < n; i++) { + if (fds[i][0] > 0) { + SAFE_CLOSE(fds[i][0]); + SAFE_CLOSE(fds[i][1]); + } + } +} + +static void setup(void) +{ + epfd = SAFE_EPOLL_CREATE1(0); + + register_fds(ready_fds, NREADY, 0); + register_fds(quiet_fds, NQUIET, QUIET_TAG); +} + +static void cleanup(void) +{ + if (epfd != -1) + SAFE_CLOSE(epfd); + + close_fds(ready_fds, NREADY); + close_fds(quiet_fds, NQUIET); +} + +static void run(void) +{ + int seen[NREADY] = {}; + int total = 0, calls = 0; + int i, ret, remaining, exp_events; + char c; + + for (i = 0; i < NREADY; i++) + SAFE_WRITE(SAFE_WRITE_ALL, ready_fds[i][1], "x", 1); + + while (total < NREADY) { + ret = SAFE_EPOLL_WAIT(epfd, events, MAXEVENTS, 0); + calls++; + + remaining = NREADY - total; + exp_events = MIN(remaining, MAXEVENTS); + + if (ret != exp_events) { + tst_res(TFAIL, + "epoll_wait() returned %d events, expected %d", + ret, exp_events); + return; + } + + for (i = 0; i < ret; i++) { + uint64_t idx = events[i].data.u64; + + if (idx >= NREADY) { + tst_res(TFAIL, + "epoll_wait() reported quiet fd (tag %llu)", + (unsigned long long)idx); + return; + } + + if (seen[idx]) { + tst_res(TFAIL, + "epoll_wait() reported ready fd %llu twice", + (unsigned long long)idx); + return; + } + + seen[idx] = 1; + total++; + + SAFE_READ(1, ready_fds[idx][0], &c, 1); + } + } + + tst_res(TPASS, "epoll_wait() reported all %d ready fds in %d calls", + NREADY, calls); +} + +static struct tst_test test = { + .setup = setup, + .cleanup = cleanup, + .test_all = run, + .bufs = (struct tst_buffers []) { + {&events, .size = MAXEVENTS * sizeof(struct epoll_event)}, + {}, + }, +}; -- 2.54.0 -- Mailing list info: https://lists.linux.it/listinfo/ltp