[PATCH v2 3/5] syscalls: Add epoll_wait14
Cyril Hrubis <[email protected]>
| Newsgroups | gmane.linux.ltp |
|---|---|
| Message-ID | <[email protected]> |
This is another test for maxevents cap, but in this case we do not drain the fds so they are never removed from the ready set. We loop over the epoll_wait() and make sure that the fds are reported round robin i.e. no fd is starved. Signed-off-by: Cyril Hrubis <[email protected]> --- runtest/syscalls | 1 + .../kernel/syscalls/epoll_wait/.gitignore | 1 + .../kernel/syscalls/epoll_wait/epoll_wait14.c | 114 ++++++++++++++++++ 3 files changed, 116 insertions(+) create mode 100644 testcases/kernel/syscalls/epoll_wait/epoll_wait14.c diff --git a/runtest/syscalls b/runtest/syscalls index 1cbc13c82..7c7e4b6f6 100644 --- a/runtest/syscalls +++ b/runtest/syscalls @@ -203,6 +203,7 @@ epoll_wait10 epoll_wait10 epoll_wait11 epoll_wait11 epoll_wait12 epoll_wait12 epoll_wait13 epoll_wait13 +epoll_wait14 epoll_wait14 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 145e7a0bd..fadaf4faa 100644 --- a/testcases/kernel/syscalls/epoll_wait/.gitignore +++ b/testcases/kernel/syscalls/epoll_wait/.gitignore @@ -11,3 +11,4 @@ epoll_wait10 epoll_wait11 epoll_wait12 epoll_wait13 +epoll_wait14 diff --git a/testcases/kernel/syscalls/epoll_wait/epoll_wait14.c b/testcases/kernel/syscalls/epoll_wait/epoll_wait14.c new file mode 100644 index 000000000..192db87b5 --- /dev/null +++ b/testcases/kernel/syscalls/epoll_wait/epoll_wait14.c @@ -0,0 +1,114 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2026 Cyril Hrubis <[email protected]> + */ + +/*\ + * Verify that :manpage:`epoll_wait(2)` rotates its ready list fairly. + * + * When more file descriptors are ready than the ``maxevents`` limit and the + * descriptors are kept ready (never drained), the kernel has to rotate the + * ready list so that all of them are reported in a round-robin fashion. Over + * several full rotations every descriptor must therefore be reported the same + * number of times, none may be starved and none may be favoured. + */ + +#include <sys/epoll.h> + +#include "tst_test.h" +#include "tst_epoll.h" + +/* NREADY is deliberately not a multiple of MAXEVENTS. */ +#define NREADY 13 +#define MAXEVENTS 3 +#define ROUNDS 4 + +static int epfd = -1; +static int ready_fds[NREADY][2]; +static struct epoll_event *events; + +static void setup(void) +{ + struct epoll_event ev = {.events = EPOLLIN}; + int i; + + epfd = SAFE_EPOLL_CREATE1(0); + + for (i = 0; i < NREADY; i++) { + SAFE_PIPE(ready_fds[i]); + SAFE_WRITE(SAFE_WRITE_ALL, ready_fds[i][1], "x", 1); + + ev.data.u64 = i; + SAFE_EPOLL_CTL(epfd, EPOLL_CTL_ADD, ready_fds[i][0], &ev); + } +} + +static void cleanup(void) +{ + int i; + + if (epfd != -1) + SAFE_CLOSE(epfd); + + for (i = 0; i < NREADY; i++) { + if (ready_fds[i][0] > 0) { + SAFE_CLOSE(ready_fds[i][0]); + SAFE_CLOSE(ready_fds[i][1]); + } + } +} + +static void run(void) +{ + int count[NREADY] = {}; + int collected = 0, target = ROUNDS * NREADY; + int i, ret; + + while (collected < target) { + ret = SAFE_EPOLL_WAIT(epfd, events, MAXEVENTS, 0); + + if (ret != MAXEVENTS) { + tst_res(TFAIL, + "epoll_wait() returned %d events, expected %d", + ret, MAXEVENTS); + return; + } + + for (i = 0; i < ret && collected < target; i++) { + uint64_t idx = events[i].data.u64; + + if (idx >= NREADY) { + tst_res(TFAIL, + "epoll_wait() returned bogus index %llu", + (unsigned long long)idx); + return; + } + + count[idx]++; + collected++; + } + } + + for (i = 0; i < NREADY; i++) { + if (count[i] != ROUNDS) { + tst_res(TFAIL, + "fd %d reported %d times, expected %d", + i, count[i], ROUNDS); + return; + } + } + + tst_res(TPASS, + "epoll_wait() reported each of %d fds exactly %d times", + NREADY, ROUNDS); +} + +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