lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [day] [month] [year] [list]
Message-ID: <tencent_204540DCC2E303AEB6E77679C05F5C5D3808@qq.com>
Date: Wed, 28 Jan 2026 18:24:51 +0800
From: Yuwen Chen <ywen.chen@...mail.com>
To: tglx@...nel.org
Cc: akpm@...ux-foundation.org,
	andrealmeid@...lia.com,
	bigeasy@...utronix.de,
	colin.i.king@...il.com,
	dave@...olabs.net,
	dvhart@...radead.org,
	edliaw@...gle.com,
	justinstitt@...gle.com,
	kernel-team@...roid.com,
	licayy@...mail.com,
	linux-kernel@...r.kernel.org,
	linux-kselftest@...r.kernel.org,
	luto@....edu,
	mingo@...hat.com,
	morbo@...gle.com,
	nathan@...nel.org,
	ndesaulniers@...gle.com,
	peterz@...radead.org,
	shuah@...nel.org,
	usama.anjum@...labora.com,
	wakel@...gle.com,
	ywen.chen@...mail.com
Subject: [PATCH v4] selftests/futex: fix the failed futex_requeue test issue

This test item has extremely high requirements for timing and can only
pass the test under specific conditions. The following situations will
lead to test failure:

    MainThread                  Thread1
        │
  pthread_create-------------------┐
        │                          │
 futex_cmp_requeue                 │
        │                     futex_wait
        │                          │

If the child thread is not waiting in the futex_wait function when the
main thread reaches the futex_cmp_requeue function, the test will fail.

This patch avoids this problem by checking whether the child thread is
in a sleeping state in the main thread.

Fixes: 7cb5dd8e2c8c ("selftests: futex: Add futex compare requeue test")
Signed-off-by: Yuwen Chen <ywen.chen@...mail.com>
Co-developed-by: Edward Liaw <edliaw@...gle.com>
Signed-off-by: Edward Liaw <edliaw@...gle.com>
---
v1->v2:
    1. Fix the issue of abnormal use of fscanf in the get_thread_state function
    2. Add timeout logic

v2->v3: https://lore.kernel.org/all/tencent_B9DBF2ECBE56BAB68BDAB949C6935D01CE09@qq.com/
    1. Use /proc/[pid]/wchan instead of /proc/[pid]/stat to check if a process has entered the sleep state
    2. Refactor part of the logic to facilitate code reuse.
v3->v4: https://lore.kernel.org/all/tencent_FC5FB35D2545AFDCA6E377AE4DE75C79AF08@qq.com/
    1. Add a new futex_thread.h file.
    2. Add a new function named futex_thread_destroy.
    3. Fix the issue that threads are not reclaimed in futex_requeue.

 .../futex/functional/futex_requeue.c          |  31 +++---
 .../selftests/futex/include/futex_thread.h    | 100 ++++++++++++++++++
 2 files changed, 118 insertions(+), 13 deletions(-)
 create mode 100644 tools/testing/selftests/futex/include/futex_thread.h

diff --git a/tools/testing/selftests/futex/functional/futex_requeue.c b/tools/testing/selftests/futex/functional/futex_requeue.c
index dcf0d5f2f3122..38743adcfd20f 100644
--- a/tools/testing/selftests/futex/functional/futex_requeue.c
+++ b/tools/testing/selftests/futex/functional/futex_requeue.c
@@ -9,10 +9,11 @@
 #include <limits.h>
 
 #include "futextest.h"
+#include "futex_thread.h"
 #include "kselftest_harness.h"
 
-#define timeout_ns  30000000
-#define WAKE_WAIT_US 10000
+#define FUTEX_WAIT_TIMEOUT_S	3 /* 3s */
+#define WAIT_THREAD_DELAY_US	(10000 * 100) /* 1s */
 
 volatile futex_t *f1;
 
@@ -20,8 +21,8 @@ void *waiterfn(void *arg)
 {
 	struct timespec to;
 
-	to.tv_sec = 0;
-	to.tv_nsec = timeout_ns;
+	to.tv_sec = FUTEX_WAIT_TIMEOUT_S;
+	to.tv_nsec = 0;
 
 	if (futex_wait(f1, *f1, &to, 0))
 		printf("waiter failed errno %d\n", errno);
@@ -33,27 +34,27 @@ TEST(requeue_single)
 {
 	volatile futex_t _f1 = 0;
 	volatile futex_t f2 = 0;
-	pthread_t waiter[10];
+	struct futex_thread waiter;
 
 	f1 = &_f1;
 
 	/*
 	 * Requeue a waiter from f1 to f2, and wake f2.
 	 */
-	ASSERT_EQ(0, pthread_create(&waiter[0], NULL, waiterfn, NULL));
-
-	usleep(WAKE_WAIT_US);
+	ASSERT_EQ(0, futex_thread_create(&waiter, waiterfn, NULL));
+	futex_wait_for_thread(&waiter, WAIT_THREAD_DELAY_US);
 
 	EXPECT_EQ(1, futex_cmp_requeue(f1, 0, &f2, 0, 1, 0));
 	EXPECT_EQ(1, futex_wake(&f2, 1, 0));
+
+	futex_thread_destroy(&waiter);
 }
 
 TEST(requeue_multiple)
 {
 	volatile futex_t _f1 = 0;
 	volatile futex_t f2 = 0;
-	pthread_t waiter[10];
-	int i;
+	struct futex_thread waiter[10];
 
 	f1 = &_f1;
 
@@ -61,13 +62,17 @@ TEST(requeue_multiple)
 	 * Create 10 waiters at f1. At futex_requeue, wake 3 and requeue 7.
 	 * At futex_wake, wake INT_MAX (should be exactly 7).
 	 */
-	for (i = 0; i < 10; i++)
-		ASSERT_EQ(0, pthread_create(&waiter[i], NULL, waiterfn, NULL));
+	for (int i = 0; i < 10; i++)
+		ASSERT_EQ(0, futex_thread_create(&waiter[i], waiterfn, NULL));
 
-	usleep(WAKE_WAIT_US);
+	for (int i = 0; i < 10; i++)
+		futex_wait_for_thread(&waiter[i], WAIT_THREAD_DELAY_US / 10);
 
 	EXPECT_EQ(10, futex_cmp_requeue(f1, 0, &f2, 3, 7, 0));
 	EXPECT_EQ(7, futex_wake(&f2, INT_MAX, 0));
+
+	for (int i = 0; i < 10; i++)
+		futex_thread_destroy(&waiter[i]);
 }
 
 TEST_HARNESS_MAIN
diff --git a/tools/testing/selftests/futex/include/futex_thread.h b/tools/testing/selftests/futex/include/futex_thread.h
new file mode 100644
index 0000000000000..9761f67b6d30b
--- /dev/null
+++ b/tools/testing/selftests/futex/include/futex_thread.h
@@ -0,0 +1,100 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * library for futex tests
+ *
+ * Copyright 2026 Meizu Ltd.
+ */
+#ifndef _FUTEX_THREAD_H
+#define _FUTEX_THREAD_H
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#define WAIT_THREAD_RETRIES 100
+
+struct futex_thread {
+	pthread_t thread;
+	pthread_barrier_t barrier;
+	pid_t tid;
+	void *(*threadfn)(void *);
+	void *arg;
+};
+
+static int __wait_for_thread(FILE *fp, int timeout_us)
+{
+	char buf[80] = "";
+
+	for (int i = 0; i < WAIT_THREAD_RETRIES; i++) {
+		if (!fgets(buf, sizeof(buf), fp))
+			return -EIO;
+		if (!strncmp(buf, "futex", 5))
+			return 0;
+		usleep(timeout_us / WAIT_THREAD_RETRIES);
+		rewind(fp);
+	}
+	return -ETIMEDOUT;
+}
+
+static void *__futex_thread_fn(void *arg)
+{
+	struct futex_thread *t = arg;
+
+	t->tid = gettid();
+	pthread_barrier_wait(&t->barrier);
+	return t->threadfn(t->arg);
+}
+
+/**
+ * futex_wait_for_thread - Wait for the child thread to sleep in the futex context
+ * @t:          Threads for testing.
+ * @timeout_us: Optional timeout for operation
+ */
+static inline int futex_wait_for_thread(struct futex_thread *t, int timeout_us)
+{
+	char fname[80];
+	FILE *fp;
+	int res;
+
+	snprintf(fname, sizeof(fname), "/proc/%d/wchan", t->tid);
+	fp = fopen(fname, "r");
+	if (!fp)
+		return -EIO;
+	res = __wait_for_thread(fp, timeout_us);
+	fclose(fp);
+	return res;
+}
+
+/**
+ * futex_waitv - Create thread for testing.
+ * @t:        Data used for returning from the thread
+ * @threadfn: The new thread starts execution by invoking threadfn()
+ * @arg:      arg is passed as the sole argument of threadfn()
+ */
+static inline int futex_thread_create(struct futex_thread *t, void *(*threadfn)(void *), void *arg)
+{
+	int ret;
+
+	pthread_barrier_init(&t->barrier, NULL, 2);
+	t->tid = 0;
+	t->threadfn = threadfn;
+	t->arg = arg;
+
+	ret = pthread_create(&t->thread, NULL, __futex_thread_fn, t);
+	if (ret)
+		return ret;
+
+	pthread_barrier_wait(&t->barrier);
+	return 0;
+}
+
+/**
+ * futex_waitv - Destroy thread.
+ * @t: Threads for testing.
+ */
+static inline void futex_thread_destroy(struct futex_thread *t)
+{
+	pthread_join(t->thread, NULL);
+	pthread_barrier_destroy(&t->barrier);
+}
+
+#endif
-- 
2.34.1


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ