summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorChristian Brauner <brauner@kernel.org>2026-06-04 11:25:14 +0300
committerChristian Brauner <brauner@kernel.org>2026-06-04 11:25:14 +0300
commitb466bfe0ec0ff80994b0fa3ffe7bc36f0ce6be4b (patch)
tree1e65bf935c10395b928dfccc132c604f5413ee91 /tools
parent70a03a385de2b8f0fa54dbc70bdc3ed176853d1c (diff)
parent0c4aefe3c2d0f272a2ad73699a12d4446ffdbe7b (diff)
downloadlinux-b466bfe0ec0ff80994b0fa3ffe7bc36f0ce6be4b.tar.xz
Merge patch series "eventpoll: Fix epoll_wait() report false negative"
Nam Cao <namcao@linutronix.de> says: While staring at epoll, I noticed ep_events_available() looks wrong. I wrote a small program to confirm, and yes it is definitely wrong. This series adds a reproducer to kselftest, and fix the bug. * patches from https://patch.msgid.link/cover.1780422137.git.namcao@linutronix.de: eventpoll: Fix epoll_wait() report false negative selftests/eventpoll: Add test for multiple waiters Link: https://patch.msgid.link/cover.1780422137.git.namcao@linutronix.de Signed-off-by: Christian Brauner <brauner@kernel.org>
Diffstat (limited to 'tools')
-rw-r--r--tools/testing/selftests/filesystems/epoll/epoll_wakeup_test.c45
1 files changed, 45 insertions, 0 deletions
diff --git a/tools/testing/selftests/filesystems/epoll/epoll_wakeup_test.c b/tools/testing/selftests/filesystems/epoll/epoll_wakeup_test.c
index 8bc57a2ef966..f6f1a7ff01b0 100644
--- a/tools/testing/selftests/filesystems/epoll/epoll_wakeup_test.c
+++ b/tools/testing/selftests/filesystems/epoll/epoll_wakeup_test.c
@@ -3493,4 +3493,49 @@ TEST(epoll64)
close(ctx.sfd[1]);
}
+static void *epoll65_wait(void *ctx_)
+{
+ struct epoll_mtcontext *ctx = ctx_;
+ struct epoll_event event;
+
+ for (int i = 0; i < 100000; ++i) {
+ if (!epoll_wait(ctx->efd[0], &event, 1, 0))
+ return (void *)ENODATA;
+ }
+
+ return (void *)0;
+}
+
+TEST(epoll65)
+{
+ struct epoll_mtcontext ctx;
+ struct epoll_event event;
+ int64_t dummy_data = 99;
+ pthread_t threads[64];
+ uintptr_t ret;
+ int i, err;
+
+ ctx.efd[0] = epoll_create(1);
+ ASSERT_GE(ctx.efd[0], 0);
+ ctx.efd[1] = eventfd(0, 0);
+ ASSERT_GE(ctx.efd[1], 0);
+
+ event.events = EPOLLIN;
+ err = epoll_ctl(ctx.efd[0], EPOLL_CTL_ADD, ctx.efd[1], &event);
+ ASSERT_EQ(err, 0);
+
+ write(ctx.efd[1], &dummy_data, sizeof(dummy_data));
+
+ for (i = 0; i < ARRAY_SIZE(threads); ++i)
+ ASSERT_EQ(pthread_create(&threads[i], NULL, epoll65_wait, &ctx), 0);
+
+ for (i = 0; i < ARRAY_SIZE(threads); ++i) {
+ ASSERT_EQ(pthread_join(threads[i], (void **)&ret), 0);
+ ASSERT_EQ(ret, 0);
+ }
+
+ close(ctx.efd[0]);
+ close(ctx.efd[1]);
+}
+
TEST_HARNESS_MAIN