The Linux Kernel Mailing List
 help / color / mirror / Atom feed
* [PATCH v8 0/2] selftests/futex: fix the failed futex_requeue test issue
@ 2026-05-18  2:15 Yuwen Chen
  2026-05-18  2:16 ` [PATCH v8 1/2] selftests/futex: implement the interfaces related to threads Yuwen Chen
  2026-05-18  2:16 ` [PATCH v8 2/2] selftests/futex: fix the failed futex_requeue test issue Yuwen Chen
  0 siblings, 2 replies; 11+ messages in thread
From: Yuwen Chen @ 2026-05-18  2:15 UTC (permalink / raw)
  To: akpm
  Cc: andrealmeid, bigeasy, colin.i.king, dave, dvhart, edliaw,
	justinstitt, kernel-team, licayy, linux-kernel, linux-kselftest,
	luto, mingo, morbo, nathan, ndesaulniers, peterz, shuah, tglx,
	usama.anjum, wakel

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.

An attempt is made to avoid this problem by checking whether the child
thread is in a sleeping state in the main thread.

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.

v4->v5: https://lore.kernel.org/all/tencent_204540DCC2E303AEB6E77679C05F5C5D3808@qq.com/
    1. Split the patch into two.
    2. Modify the thread interface to support returning error codes.
    3. In the test cases, check the return values of the threads.
    4. Modify the macro definitions to more understandable names.
    5. When failing to open the /proc/%d/wchan file, delay for 100 ms.
    6. Modify the parameter description of the interface.

v5->v6: https://lore.kernel.org/all/tencent_35CFB8AE9D4BE7917D95763D15B972638C0A@qq.com/
    1. Add parameters to the futex_wait_for_thread function to support custom timeout periods.
    2. Even when the proc file system is not mounted, the test case can still pass.
    3. Add timeout time comments to the usleep function.
    4. Reduce the time of FUTEX_WAIT_TIMEOUT_SECS to 1 second.
    5. Add the necessary header files to futex_thread.h.

v6->v7: https://lore.kernel.org/all/tencent_D6D5FA3C2F6FE52BA6ABA1A88C1B6E1CC605@qq.com/
    1. Changed `static` to `static inline` for all functions in futex_thread.h.
    2. Added `sleep_time_us` variable with zero-guard in __wait_for_thread() to prevent
       tight loop when timeout_us < WAIT_THREAD_RETRIES.
    3. Removed fallback usleep(100ms) from futex_wait_for_thread(); moved error handling to callers.
    4. Added return value check for pthread_barrier_init() in futex_thread_create().
    5. Added pthread_barrier_destroy() cleanup on pthread_create() failure path.
    6. Unified error checking to `if (ret < 0)` in both requeue_single and requeue_multiple.
    7. Added comment for the break logic in requeue_multiple when /proc is not available.

v7->v8: https://lore.kernel.org/all/tencent_0C775F885D7D4560DC59E359AE7DE74C7908@qq.com/
    1. Increase FUTEX_WAIT_TIMEOUT_SECS to 2 seconds to avoid timeouts.

Yuwen Chen (2):
  selftests/futex: implement the interfaces related to threads
  selftests/futex: fix the failed futex_requeue test issue

 .../selftests/futex/functional/Makefile       |   3 +-
 .../futex/functional/futex_requeue.c          |  46 ++++---
 .../selftests/futex/include/futex_thread.h    | 114 ++++++++++++++++++
 3 files changed, 148 insertions(+), 15 deletions(-)
 create mode 100644 tools/testing/selftests/futex/include/futex_thread.h

-- 
2.34.1


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH v8 1/2] selftests/futex: implement the interfaces related to threads
  2026-05-18  2:15 [PATCH v8 0/2] selftests/futex: fix the failed futex_requeue test issue Yuwen Chen
@ 2026-05-18  2:16 ` Yuwen Chen
  2026-07-05 19:54   ` [tip: locking/futex] selftests/futex: Provide thread creation and synchronization helpers tip-bot2 for Yuwen Chen
  2026-05-18  2:16 ` [PATCH v8 2/2] selftests/futex: fix the failed futex_requeue test issue Yuwen Chen
  1 sibling, 1 reply; 11+ messages in thread
From: Yuwen Chen @ 2026-05-18  2:16 UTC (permalink / raw)
  To: ywen.chen
  Cc: akpm, andrealmeid, bigeasy, colin.i.king, dave, dvhart, edliaw,
	justinstitt, kernel-team, licayy, linux-kernel, linux-kselftest,
	luto, mingo, morbo, nathan, ndesaulniers, peterz, shuah, tglx,
	usama.anjum, wakel

There are timing issues in the use of threads in some unit test cases
for futex. A potentially good solution is to check whether the thread
is in the sleep state after creating it.

A file named futex_thread.h is added, in which several thread-related
functions are implemented to facilitate the solution of this problem.

Signed-off-by: Yuwen Chen <ywen.chen@foxmail.com>
---
 .../selftests/futex/functional/Makefile       |   3 +-
 .../selftests/futex/include/futex_thread.h    | 114 ++++++++++++++++++
 2 files changed, 116 insertions(+), 1 deletion(-)
 create mode 100644 tools/testing/selftests/futex/include/futex_thread.h

diff --git a/tools/testing/selftests/futex/functional/Makefile b/tools/testing/selftests/futex/functional/Makefile
index 5c1c824f97400..724e8216e41b1 100644
--- a/tools/testing/selftests/futex/functional/Makefile
+++ b/tools/testing/selftests/futex/functional/Makefile
@@ -11,7 +11,8 @@ endif
 
 LOCAL_HDRS := \
 	../include/futextest.h \
-	../include/atomic.h
+	../include/atomic.h \
+	../include/futex_thread.h
 TEST_GEN_PROGS := \
 	futex_wait_timeout \
 	futex_wait_wouldblock \
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..49ae687012fe5
--- /dev/null
+++ b/tools/testing/selftests/futex/include/futex_thread.h
@@ -0,0 +1,114 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#ifndef _FUTEX_THREAD_H
+#define _FUTEX_THREAD_H
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <pthread.h>
+#include <unistd.h>
+
+#define USEC_PER_SEC 1000000L
+#define WAIT_THREAD_RETRIES 100
+
+struct futex_thread {
+	pthread_t		thread;
+	pthread_barrier_t	barrier;
+	pid_t			tid;
+	int			(*threadfn)(void *arg);
+	void			*arg;
+	int			retval;
+};
+
+static inline int __wait_for_thread(FILE *fp, int timeout_us)
+{
+	char buf[80] = "";
+	int i;
+	int sleep_time_us = timeout_us / WAIT_THREAD_RETRIES;
+
+	if (sleep_time_us <= 0)
+		sleep_time_us = 1;
+
+	for (i = 0; i < WAIT_THREAD_RETRIES; i++) {
+		if (!fgets(buf, sizeof(buf), fp))
+			return -EIO;
+		if (!strncmp(buf, "futex", 5))
+			return 0;
+		usleep(sleep_time_us);
+		rewind(fp);
+	}
+	return -ETIMEDOUT;
+}
+
+static void *__futex_thread_fn(void *arg)
+{
+	struct futex_thread *t = arg;
+
+	t->tid = gettid();
+	pthread_barrier_wait(&t->barrier);
+	t->retval = t->threadfn(t->arg);
+	return NULL;
+}
+
+/**
+ * futex_wait_for_thread - Wait for the child thread to sleep in the futex context
+ * @t:          Thread handle.
+ * @timeout_us: The timeout for waiting for the thread to enter the sleep state.
+ */
+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_thread_create - Create a new thread for testing.
+ * @t:        The handle of the newly created thread.
+ * @threadfn: The new thread starts execution by invoking threadfn
+ * @arg:      The parameters passed to threadfn.
+ */
+static inline int futex_thread_create(struct futex_thread *t, int (*threadfn)(void *), void *arg)
+{
+	int ret;
+
+	ret = pthread_barrier_init(&t->barrier, NULL, 2);
+	if (ret)
+		return ret;
+
+	t->tid = 0;
+	t->threadfn = threadfn;
+	t->arg = arg;
+
+	ret = pthread_create(&t->thread, NULL, __futex_thread_fn, t);
+	if (ret) {
+		pthread_barrier_destroy(&t->barrier);
+		return ret;
+	}
+
+	pthread_barrier_wait(&t->barrier);
+	return 0;
+}
+
+/**
+ * futex_thread_destroy - Wait for and reclaim the resources of the thread.
+ * @t:      Thread handle.
+ */
+static inline int futex_thread_destroy(struct futex_thread *t)
+{
+	pthread_join(t->thread, NULL);
+	pthread_barrier_destroy(&t->barrier);
+	return t->retval;
+}
+
+#endif
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH v8 2/2] selftests/futex: fix the failed futex_requeue test issue
  2026-05-18  2:15 [PATCH v8 0/2] selftests/futex: fix the failed futex_requeue test issue Yuwen Chen
  2026-05-18  2:16 ` [PATCH v8 1/2] selftests/futex: implement the interfaces related to threads Yuwen Chen
@ 2026-05-18  2:16 ` Yuwen Chen
  2026-05-19  2:06   ` Yuwen Chen
                     ` (2 more replies)
  1 sibling, 3 replies; 11+ messages in thread
From: Yuwen Chen @ 2026-05-18  2:16 UTC (permalink / raw)
  To: ywen.chen
  Cc: akpm, andrealmeid, bigeasy, colin.i.king, dave, dvhart, edliaw,
	justinstitt, kernel-team, licayy, linux-kernel, linux-kselftest,
	luto, mingo, morbo, nathan, ndesaulniers, peterz, shuah, tglx,
	usama.anjum, wakel

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.

An attempt is made to avoid 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@foxmail.com>
Co-developed-by: Edward Liaw <edliaw@google.com>
Signed-off-by: Edward Liaw <edliaw@google.com>
---
v7->v8:
    1. Increase FUTEX_WAIT_TIMEOUT_SECS to 2 seconds to avoid timeouts.

 .../futex/functional/futex_requeue.c          | 46 +++++++++++++------
 1 file changed, 32 insertions(+), 14 deletions(-)

diff --git a/tools/testing/selftests/futex/functional/futex_requeue.c b/tools/testing/selftests/futex/functional/futex_requeue.c
index dcf0d5f2f3122..5c849ccf16e26 100644
--- a/tools/testing/selftests/futex/functional/futex_requeue.c
+++ b/tools/testing/selftests/futex/functional/futex_requeue.c
@@ -9,51 +9,59 @@
 #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_SECS 2
+#define WAIT_THREAD_CREATE_TIMEOUT_USECS (USEC_PER_SEC / 2) /* 500ms */
 
 volatile futex_t *f1;
 
-void *waiterfn(void *arg)
+static int waiterfn(void *arg)
 {
 	struct timespec to;
 
-	to.tv_sec = 0;
-	to.tv_nsec = timeout_ns;
+	to.tv_sec = FUTEX_WAIT_TIMEOUT_SECS;
+	to.tv_nsec = 0;
 
-	if (futex_wait(f1, *f1, &to, 0))
+	if (futex_wait(f1, *f1, &to, 0)) {
 		printf("waiter failed errno %d\n", errno);
+		return -errno;
+	}
 
-	return NULL;
+	return 0;
 }
 
 TEST(requeue_single)
 {
+	struct futex_thread waiter;
 	volatile futex_t _f1 = 0;
 	volatile futex_t f2 = 0;
-	pthread_t waiter[10];
+	int ret;
 
 	f1 = &_f1;
 
 	/*
 	 * Requeue a waiter from f1 to f2, and wake f2.
 	 */
-	ASSERT_EQ(0, pthread_create(&waiter[0], NULL, waiterfn, NULL));
+	ASSERT_EQ(0, futex_thread_create(&waiter, waiterfn, NULL));
 
-	usleep(WAKE_WAIT_US);
+	ret = futex_wait_for_thread(&waiter, WAIT_THREAD_CREATE_TIMEOUT_USECS);
+	if (ret < 0)
+		usleep(WAIT_THREAD_CREATE_TIMEOUT_USECS);
 
 	EXPECT_EQ(1, futex_cmp_requeue(f1, 0, &f2, 0, 1, 0));
 	EXPECT_EQ(1, futex_wake(&f2, 1, 0));
+
+	EXPECT_EQ(0, futex_thread_destroy(&waiter));
 }
 
 TEST(requeue_multiple)
 {
+	struct futex_thread waiter[10];
 	volatile futex_t _f1 = 0;
 	volatile futex_t f2 = 0;
-	pthread_t waiter[10];
-	int i;
+	int i, ret;
 
 	f1 = &_f1;
 
@@ -62,12 +70,22 @@ TEST(requeue_multiple)
 	 * 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));
+		ASSERT_EQ(0, futex_thread_create(&waiter[i], waiterfn, NULL));
 
-	usleep(WAKE_WAIT_US);
+	for (i = 0; i < 10; i++) {
+		ret = futex_wait_for_thread(&waiter[i], WAIT_THREAD_CREATE_TIMEOUT_USECS / 10);
+		if (ret < 0) {
+			/* /proc not available, give all threads time to enter futex wait */
+			usleep(WAIT_THREAD_CREATE_TIMEOUT_USECS);
+			break;
+		}
+	}
 
 	EXPECT_EQ(10, futex_cmp_requeue(f1, 0, &f2, 3, 7, 0));
 	EXPECT_EQ(7, futex_wake(&f2, INT_MAX, 0));
+
+	for (i = 0; i < 10; i++)
+		EXPECT_EQ(0, futex_thread_destroy(&waiter[i]));
 }
 
 TEST_HARNESS_MAIN
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH v8 2/2] selftests/futex: fix the failed futex_requeue test issue
  2026-05-18  2:16 ` [PATCH v8 2/2] selftests/futex: fix the failed futex_requeue test issue Yuwen Chen
@ 2026-05-19  2:06   ` Yuwen Chen
  2026-07-05 19:54   ` [tip: locking/futex] selftests/futex: Use thread synchronization helpers instead of usleep() tip-bot2 for Yuwen Chen
  2026-07-07 22:28   ` [PATCH v8 2/2] selftests/futex: fix the failed futex_requeue test issue Mark Brown
  2 siblings, 0 replies; 11+ messages in thread
From: Yuwen Chen @ 2026-05-19  2:06 UTC (permalink / raw)
  To: ywen.chen
  Cc: akpm, andrealmeid, bigeasy, colin.i.king, dave, dvhart, edliaw,
	justinstitt, kernel-team, licayy, linux-kernel, linux-kselftest,
	luto, mingo, morbo, nathan, ndesaulniers, peterz, shuah, tglx,
	usama.anjum, wakel

on 5/18/2026, 10:15:21 AM, gemini/gemini-3.1-pro-preview wrote:
> > diff --git a/tools/testing/selftests/futex/functional/futex_requeue.c b/tools/testing/selftests/futex/functional/futex_requeue.c
> > index dcf0d5f2f3122..246404b73ad86 100644
> > --- a/tools/testing/selftests/futex/functional/futex_requeue.c
> > +++ b/tools/testing/selftests/futex/functional/futex_requeue.c
> [ ... ]
> > @@ -62,12 +70,22 @@ TEST(requeue_multiple)
> >  	 * 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));
> > +		ASSERT_EQ(0, futex_thread_create(&waiter[i], waiterfn, NULL));
> >  
> > -	usleep(WAKE_WAIT_US);
> > +	for (i = 0; i < 10; i++) {
> > +		ret = futex_wait_for_thread(&waiter[i], WAIT_THREAD_CREATE_TIMEOUT_USECS / 10);
> > +		if (ret < 0) {
> Could this error handling reintroduce the race condition?
> futex_wait_for_thread() returns -ETIMEDOUT if the thread does not enter the
> futex sleep state within the specified timeout, and -EIO if the /proc entry
> cannot be read.
> Because this condition catches both errors indiscriminately, a slightly
> delayed thread that returns -ETIMEDOUT will be treated as if /proc is
> unavailable.

Personally, I don't think it's necessary to handle these two states separately
at this time. When a timeout occurs, the delay is at least 500ms + 50ms. If the
processing requirements still can't be met at this point, then this test item
should fail.

> +			/* /proc not available, give all threads time to enter futex wait */
> +			usleep(WAIT_THREAD_CREATE_TIMEOUT_USECS);
> +			break;
> If the loop is broken here, the code skips verifying the wait state for any
> remaining threads.
> If those remaining threads take longer than 500ms to reach futex_wait(),
> the main thread will prematurely execute futex_cmp_requeue() and cause the
> test to fail.
> Should the check specifically verify if ret is -EIO before breaking the
> loop and falling back to usleep?

The reason is the same as above. I believe that waiting for 500ms is long enough
for the child threads to enter the test state.

> > +		}
> > +	}
> >  
> >  	EXPECT_EQ(10, futex_cmp_requeue(f1, 0, &f2, 3, 7, 0));
> >  	EXPECT_EQ(7, futex_wake(&f2, INT_MAX, 0));


^ permalink raw reply	[flat|nested] 11+ messages in thread

* [tip: locking/futex] selftests/futex: Use thread synchronization helpers instead of usleep()
  2026-05-18  2:16 ` [PATCH v8 2/2] selftests/futex: fix the failed futex_requeue test issue Yuwen Chen
  2026-05-19  2:06   ` Yuwen Chen
@ 2026-07-05 19:54   ` tip-bot2 for Yuwen Chen
  2026-07-07 22:28   ` [PATCH v8 2/2] selftests/futex: fix the failed futex_requeue test issue Mark Brown
  2 siblings, 0 replies; 11+ messages in thread
From: tip-bot2 for Yuwen Chen @ 2026-07-05 19:54 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Yuwen Chen, Edward Liaw, Thomas Gleixner, x86, linux-kernel

The following commit has been merged into the locking/futex branch of tip:

Commit-ID:     157a9b22ff769e1a657aec6210df3ea896600eec
Gitweb:        https://git.kernel.org/tip/157a9b22ff769e1a657aec6210df3ea896600eec
Author:        Yuwen Chen <ywen.chen@foxmail.com>
AuthorDate:    Mon, 18 May 2026 10:16:54 +08:00
Committer:     Thomas Gleixner <tglx@kernel.org>
CommitterDate: Sun, 05 Jul 2026 21:49:18 +02:00

selftests/futex: Use thread synchronization helpers instead of usleep()

This test uses usleep() to delay the main thread after creating the test
thread[s] under the assumption that they already are blocked on the futex
when the main thread continues.

That "works" on otherwise idle systems, but fails under load resulting in
failed selftests because the requeue operation starts before the waiters
reached the kernel.

Replace the usleep() waits by the new thread synchronization helpers to cure that.

[ tglx: Adapted to test harness changes, fixed coding style, sanitized the
	timeout handling and rewrote change log.

Co-developed-by: Edward Liaw <edliaw@google.com>
Signed-off-by: Yuwen Chen <ywen.chen@foxmail.com>
Signed-off-by: Edward Liaw <edliaw@google.com>
Signed-off-by: Thomas Gleixner <tglx@kernel.org>
Link: https://patch.msgid.link/tencent_76B9DE9C9FE5C57F6D74B5149970DF8CCF0A@qq.com
---
 tools/testing/selftests/futex/functional/futex_requeue.c | 38 +++----
 1 file changed, 19 insertions(+), 19 deletions(-)

diff --git a/tools/testing/selftests/futex/functional/futex_requeue.c b/tools/testing/selftests/futex/functional/futex_requeue.c
index f4b8dc1..22e7046 100644
--- a/tools/testing/selftests/futex/functional/futex_requeue.c
+++ b/tools/testing/selftests/futex/functional/futex_requeue.c
@@ -10,59 +10,56 @@
 #include <string.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_SECS			2
 
 volatile futex_t *f1;
 
-void *waiterfn(void *arg)
+static int waiterfn(void *arg)
 {
 	struct __test_metadata *_metadata = (struct __test_metadata *)arg;
-	struct timespec to;
+	struct timespec to = { .tv_sec = FUTEX_WAIT_TIMEOUT_SECS };
 	int res;
 
-	to.tv_sec = 0;
-	to.tv_nsec = timeout_ns;
-
 	res = futex_wait(f1, *f1, &to, 0);
 	if (res) {
 		EXPECT_EQ(res, 0)
 			TH_LOG("waiter failed errno %d: %s", errno, strerror(errno));
 	}
 
-	return NULL;
+	return 0;
 }
 
 TEST(requeue_single)
 {
+	struct futex_thread waiter;
 	volatile futex_t _f1 = 0;
 	volatile futex_t f2 = 0;
-	pthread_t waiter[10];
 
 	f1 = &_f1;
 
 	/*
 	 * Requeue a waiter from f1 to f2, and wake f2.
 	 */
-	ASSERT_EQ(pthread_create(&waiter[0], NULL, waiterfn, _metadata), 0)
+	ASSERT_EQ(futex_thread_create(&waiter, waiterfn, _metadata), 0)
 		TH_LOG("pthread_create failed");
 
-	usleep(WAKE_WAIT_US);
+	ASSERT_EQ(futex_wait_for_thread(&waiter, _metadata), 0)
+		TH_LOG("Wait for thread failed");
 
 	EXPECT_EQ(futex_cmp_requeue(f1, 0, &f2, 0, 1, 0), 1);
 	EXPECT_EQ(futex_wake(&f2, 1, 0), 1);
 
-	pthread_join(waiter[0], NULL);
+	EXPECT_EQ(futex_thread_destroy(&waiter), 0);
 }
 
 TEST(requeue_multiple)
 {
+	struct futex_thread waiter[10];
 	volatile futex_t _f1 = 0;
 	volatile futex_t f2 = 0;
-	pthread_t waiter[10];
-	int i;
 
 	f1 = &_f1;
 
@@ -70,18 +67,21 @@ 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(pthread_create(&waiter[i], NULL, waiterfn, _metadata), 0)
+	for (int i = 0; i < 10; i++) {
+		ASSERT_EQ(futex_thread_create(&waiter[i], waiterfn, _metadata), 0)
 			TH_LOG("pthread_create failed for waiter %d", i);
 	}
 
-	usleep(WAKE_WAIT_US);
+	for (int i = 0; i < 10; i++) {
+		ASSERT_EQ(futex_wait_for_thread(&waiter[i], _metadata), 0)
+			TH_LOG("Wait for waiter thread %d failed", i);
+	}
 
 	EXPECT_EQ(futex_cmp_requeue(f1, 0, &f2, 3, 7, 0), 10);
 	EXPECT_EQ(futex_wake(&f2, INT_MAX, 0), 7);
 
-	for (i = 0; i < 10; i++)
-		pthread_join(waiter[i], NULL);
+	for (int i = 0; i < 10; i++)
+		EXPECT_EQ(futex_thread_destroy(&waiter[i]), 0);
 }
 
 TEST_HARNESS_MAIN

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [tip: locking/futex] selftests/futex: Provide thread creation and synchronization helpers
  2026-05-18  2:16 ` [PATCH v8 1/2] selftests/futex: implement the interfaces related to threads Yuwen Chen
@ 2026-07-05 19:54   ` tip-bot2 for Yuwen Chen
  0 siblings, 0 replies; 11+ messages in thread
From: tip-bot2 for Yuwen Chen @ 2026-07-05 19:54 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: Yuwen Chen, Thomas Gleixner, x86, linux-kernel

The following commit has been merged into the locking/futex branch of tip:

Commit-ID:     86620fb9d37b9f5aaae7c7cb27a173463d961cdc
Gitweb:        https://git.kernel.org/tip/86620fb9d37b9f5aaae7c7cb27a173463d961cdc
Author:        Yuwen Chen <ywen.chen@foxmail.com>
AuthorDate:    Mon, 18 May 2026 10:16:40 +08:00
Committer:     Thomas Gleixner <tglx@kernel.org>
CommitterDate: Sun, 05 Jul 2026 21:49:18 +02:00

selftests/futex: Provide thread creation and synchronization helpers

There are timing issues in the use of threads in some selftests for futexes
as the tests rely on timed waits to ensure that the other test thread[s]
reached the lock wait function in the kernel.

That "works" on halfways idle systems, but fails under load which results
in tests failing.

Provide a set of helper functions to create test threads and to wait for
them to reach the lock wait by monitoring /proc/$PID/wchan.

[ tglx: Fixup coding style, move the timeout into the helper, adapt to test
  	harness changes and massage change log ]

Signed-off-by: Yuwen Chen <ywen.chen@foxmail.com>
Signed-off-by: Thomas Gleixner <tglx@kernel.org>
Link: https://patch.msgid.link/tencent_4C90BE98BBC48B38B9FBC6A95C45CF49F309@qq.com
---
 tools/testing/selftests/futex/functional/Makefile    |   3 +-
 tools/testing/selftests/futex/include/futex_thread.h | 115 ++++++++++-
 2 files changed, 117 insertions(+), 1 deletion(-)
 create mode 100644 tools/testing/selftests/futex/include/futex_thread.h

diff --git a/tools/testing/selftests/futex/functional/Makefile b/tools/testing/selftests/futex/functional/Makefile
index d59faf7..a03bd5a 100644
--- a/tools/testing/selftests/futex/functional/Makefile
+++ b/tools/testing/selftests/futex/functional/Makefile
@@ -11,7 +11,8 @@ endif
 
 LOCAL_HDRS := \
 	../include/futextest.h \
-	../include/atomic.h
+	../include/atomic.h \
+	../include/futex_thread.h
 TEST_GEN_PROGS := \
 	futex_wait_timeout \
 	futex_wait_wouldblock \
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 0000000..f71b5b6
--- /dev/null
+++ b/tools/testing/selftests/futex/include/futex_thread.h
@@ -0,0 +1,115 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#ifndef _FUTEX_THREAD_H
+#define _FUTEX_THREAD_H
+#include <errno.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "kselftest_harness.h"
+
+#define USEC_PER_SEC		1000000L
+#define WAIT_FOR_THREAD_SECS	2
+#define WAIT_FOR_THREAD_USECS	(WAIT_FOR_THREAD_SECS * USEC_PER_SEC)
+#define WAIT_THREAD_RETRIES	100
+
+struct futex_thread {
+	pthread_t		thread;
+	pthread_barrier_t	barrier;
+	pid_t			tid;
+	int			(*threadfn)(void *arg);
+	void			*arg;
+	int			retval;
+};
+
+static inline int __wait_for_thread(FILE *fp)
+{
+	unsigned int sleep_time_us = WAIT_FOR_THREAD_USECS / WAIT_THREAD_RETRIES;
+	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(sleep_time_us);
+		rewind(fp);
+	}
+	return ETIMEDOUT;
+}
+
+static void *__futex_thread_fn(void *arg)
+{
+	struct futex_thread *t = arg;
+
+	t->tid = gettid();
+	pthread_barrier_wait(&t->barrier);
+	t->retval = t->threadfn(t->arg);
+	return NULL;
+}
+
+/**
+ * futex_wait_for_thread - Wait for the child thread to sleep in the futex context
+ * @t:          Thread handle.
+ * @_metadata:	Test metadata for TH_LOG() context
+ */
+static inline int futex_wait_for_thread(struct futex_thread *t, struct __test_metadata *_metadata)
+{
+	char fname[80];
+	FILE *fp;
+	int res;
+
+	snprintf(fname, sizeof(fname), "/proc/%d/wchan", t->tid);
+	fp = fopen(fname, "r");
+	if (!fp) {
+		/* If /proc/... is not available, sleep */
+		if (errno != ENOENT)
+			return errno;
+		TH_LOG("/proc/$PID/wchan not accessible, continue with sleep()");
+		sleep(WAIT_FOR_THREAD_SECS);
+		return 0;
+	}
+
+	res = __wait_for_thread(fp);
+	fclose(fp);
+	return res;
+}
+
+/**
+ * futex_thread_create - Create a new thread for testing.
+ * @t:        The handle of the newly created thread.
+ * @threadfn: The new thread starts execution by invoking threadfn
+ * @arg:      The parameters passed to threadfn.
+ */
+static inline int futex_thread_create(struct futex_thread *t, int (*threadfn)(void *), void *arg)
+{
+	pthread_barrier_init(&t->barrier, NULL, 2);
+
+	t->tid = 0;
+	t->threadfn = threadfn;
+	t->arg = arg;
+
+	if (pthread_create(&t->thread, NULL, __futex_thread_fn, t) < 0) {
+		int ret = errno;
+		pthread_barrier_destroy(&t->barrier);
+		return ret;
+	}
+
+	pthread_barrier_wait(&t->barrier);
+	return 0;
+}
+
+/**
+ * futex_thread_destroy - Wait for and reclaim the resources of the thread.
+ * @t:      Thread handle.
+ */
+static inline int futex_thread_destroy(struct futex_thread *t)
+{
+	pthread_join(t->thread, NULL);
+	pthread_barrier_destroy(&t->barrier);
+	return t->retval;
+}
+
+#endif

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [PATCH v8 2/2] selftests/futex: fix the failed futex_requeue test issue
  2026-05-18  2:16 ` [PATCH v8 2/2] selftests/futex: fix the failed futex_requeue test issue Yuwen Chen
  2026-05-19  2:06   ` Yuwen Chen
  2026-07-05 19:54   ` [tip: locking/futex] selftests/futex: Use thread synchronization helpers instead of usleep() tip-bot2 for Yuwen Chen
@ 2026-07-07 22:28   ` Mark Brown
  2026-07-07 23:31     ` Thomas Gleixner
  2 siblings, 1 reply; 11+ messages in thread
From: Mark Brown @ 2026-07-07 22:28 UTC (permalink / raw)
  To: Yuwen Chen
  Cc: akpm, andrealmeid, bigeasy, colin.i.king, dave, dvhart, edliaw,
	justinstitt, kernel-team, licayy, linux-kernel, linux-kselftest,
	luto, mingo, morbo, nathan, ndesaulniers, peterz, shuah, tglx,
	usama.anjum, wakel, mark.rutland

[-- Attachment #1: Type: text/plain, Size: 7481 bytes --]

On Mon, May 18, 2026 at 10:16:54AM +0800, Yuwen Chen wrote:
> 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:

...

> 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.
> 
> An attempt is made to avoid this problem by checking whether the child
> thread is in a sleeping state in the main thread.

I'm seeing failures on arm64 (running a system with 4xA53) in -next in
this test which bisect to this commit, the commit seems obviously
plausible but I didn't actually investigate:

# TAP version 13
 1..2
 # Starting 2 tests from 1 test cases.
 #  RUN           global.requeue_single ...
 # futex_requeue.c:28:requeue_single:Expected res (-1) == 0 (0)
 # futex_requeue.c:29:requeue_single:waiter failed errno 110: Connection timed out
 # futex_requeue.c:49:requeue_single:Expected futex_wait_for_thread(&waiter, _metadata) (110) == 0 (0)
 # futex_requeue.c:50:requeue_single:Wait for thread failed
 # requeue_single: Test terminated by assertion
 #          FAIL  global.requeue_single
 not ok 1 global.requeue_single
 #  RUN           global.requeue_multiple ...
 # futex_requeue.c:28:requeue_multiple:Expected res (-1) == 0 (0)
 # futex_requeue.c:29:requeue_multiple:waiter failed errno 110: Connection timed out
 # futex_requeue.c:28:requeue_multiple:Expected res (-1) == 0 (0)
 # futex_requeue.c:29:requeue_multiple:waiter failed errno 110: Connection timed out
 # futex_requeue.c:28:requeue_multiple:Expected res (-1) == 0 (0)
 # futex_requeue.c:29:requeue_multiple:waiter failed errno 110: Connection timed out
 # futex_requeue.c:28:requeue_multiple:Expected res (-1) == 0 (0)
 # futex_requeue.c:29:requeue_multiple:waiter failed errno 110: Connection timed out
 # futex_requeue.c:28:requeue_multiple:Expected res (-1) == 0 (0)
 # futex_requeue.c:29:requeue_multiple:waiter failed errno 110: Connection timed out
 # futex_requeue.c:28:requeue_multiple:Expected res (-1) == 0 (0)
 # futex_requeue.c:29:requeue_multiple:waiter failed errno 110: Connection timed out
 # futex_requeue.c:28:requeue_multiple:Expected res (-1) == 0 (0)
 # futex_requeue.c:29:requeue_multiple:waiter failed errno 110: Connection timed out
 # futex_requeue.c:28:requeue_multiple:Expected res (-1) == 0 (0)
 # futex_requeue.c:29:requeue_multiple:waiter failed errno 110: Connection timed out
 # futex_requeue.c:28:requeue_multiple:Expected res (-1) == 0 (0)
 # futex_requeue.c:29:requeue_multiple:waiter failed errno 110: Connection timed out
 # futex_requeue.c:28:requeue_multiple:Expected res (-1) == 0 (0)
 # futex_requeue.c:29:requeue_multiple:waiter failed errno 110: Connection timed out
 # futex_requeue.c:76:requeue_multiple:Expected futex_wait_for_thread(&waiter[i], _metadata) (5) == 0 (0)
 # futex_requeue.c:77:requeue_multiple:Wait for waiter thread 0 failed
 # requeue_multiple: Test terminated by assertion
 #          FAIL  global.requeue_multiple
 not ok 2 global.requeue_multiple
 # FAILED: 0 / 2 tests passed.
 # Totals: pass:0 fail:2 xfail:0 xpass:0 skip:0 error:0

Full log should be at:

   https://lava.sirena.org.uk/scheduler/job/2954705#L13289

but I'm having a terrible time with AI scrapers right now so perhaps not
usefully.

# bad: [5c73cd9f0819c1c44e373e3dabb68318b1de1a12] Add linux-next specific files for 20260707
# good: [fc5f2284ad6951ce06d6881ca8cbd6d14d5f5071] Merge branch 'for-linux-next-fixes' of https://gitlab.freedesktop.org/drm/misc/kernel.git
git bisect start '5c73cd9f0819c1c44e373e3dabb68318b1de1a12' 'fc5f2284ad6951ce06d6881ca8cbd6d14d5f5071'
# test job: [5c73cd9f0819c1c44e373e3dabb68318b1de1a12] https://lava.sirena.org.uk/scheduler/job/2954705
# bad: [5c73cd9f0819c1c44e373e3dabb68318b1de1a12] Add linux-next specific files for 20260707
git bisect bad 5c73cd9f0819c1c44e373e3dabb68318b1de1a12
# test job: [f03ff00f5fd55e2c02b44611ac65380082c46b62] https://lava.sirena.org.uk/scheduler/job/2954744
# good: [f03ff00f5fd55e2c02b44611ac65380082c46b62] Merge branch 'libcrypto-next' of https://git.kernel.org/pub/scm/linux/kernel/git/ebiggers/linux.git
git bisect good f03ff00f5fd55e2c02b44611ac65380082c46b62
# test job: [fe28d02cde5372d7f71cc6132ccdef37a98ac750] https://lava.sirena.org.uk/scheduler/job/2954790
# good: [fe28d02cde5372d7f71cc6132ccdef37a98ac750] Merge branch 'for-linux-next' of https://gitlab.freedesktop.org/drm/i915/kernel.git
git bisect good fe28d02cde5372d7f71cc6132ccdef37a98ac750
# test job: [954c3050e57c29ee3a216cda83da13f16815bbb4] https://lava.sirena.org.uk/scheduler/job/2954824
# bad: [954c3050e57c29ee3a216cda83da13f16815bbb4] Merge branch 'for-next' of https://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace.git
git bisect bad 954c3050e57c29ee3a216cda83da13f16815bbb4
# test job: [6054d7d90130d6788ec459be1bfdc14300587aac] https://lava.sirena.org.uk/scheduler/job/2954855
# good: [6054d7d90130d6788ec459be1bfdc14300587aac] Merge branch 'for-mfd-next' of https://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd.git
git bisect good 6054d7d90130d6788ec459be1bfdc14300587aac
# test job: [f705c6728b357ca8d675f9ee94191d7c900e3652] https://lava.sirena.org.uk/scheduler/job/2954897
# bad: [f705c6728b357ca8d675f9ee94191d7c900e3652] Merge branch into tip/master: 'x86/msr'
git bisect bad f705c6728b357ca8d675f9ee94191d7c900e3652
# test job: [7af7f4599923cc4e1ab60d0991b33cab17ade101] https://lava.sirena.org.uk/scheduler/job/2954940
# bad: [7af7f4599923cc4e1ab60d0991b33cab17ade101] Merge branch into tip/master: 'perf/core'
git bisect bad 7af7f4599923cc4e1ab60d0991b33cab17ade101
# test job: [c6cf5150bdb99c61d32fca8da51f5a2a80227ca2] https://lava.sirena.org.uk/scheduler/job/2954963
# bad: [c6cf5150bdb99c61d32fca8da51f5a2a80227ca2] Merge branch into tip/master: 'locking/futex'
git bisect bad c6cf5150bdb99c61d32fca8da51f5a2a80227ca2
# test job: [86620fb9d37b9f5aaae7c7cb27a173463d961cdc] https://lava.sirena.org.uk/scheduler/job/2955014
# good: [86620fb9d37b9f5aaae7c7cb27a173463d961cdc] selftests/futex: Provide thread creation and synchronization helpers
git bisect good 86620fb9d37b9f5aaae7c7cb27a173463d961cdc
# test job: [86e9ba573c353afd1a46816682f4cc3dbabeeb23] https://lava.sirena.org.uk/scheduler/job/2955047
# good: [86e9ba573c353afd1a46816682f4cc3dbabeeb23] irqchip/irq-imgpdc: Remove unused driver
git bisect good 86e9ba573c353afd1a46816682f4cc3dbabeeb23
# test job: [1cd91823008a033cc766b78ad0cd1138e96bfcd9] https://lava.sirena.org.uk/scheduler/job/2955064
# good: [1cd91823008a033cc766b78ad0cd1138e96bfcd9] Merge branch into tip/master: 'irq/core'
git bisect good 1cd91823008a033cc766b78ad0cd1138e96bfcd9
# test job: [919c6f2762254d4bcb92ea30bf473cfcc5521c9c] https://lava.sirena.org.uk/scheduler/job/2955116
# good: [919c6f2762254d4bcb92ea30bf473cfcc5521c9c] Merge branch into tip/master: 'locking/debug'
git bisect good 919c6f2762254d4bcb92ea30bf473cfcc5521c9c
# test job: [157a9b22ff769e1a657aec6210df3ea896600eec] https://lava.sirena.org.uk/scheduler/job/2955137
# bad: [157a9b22ff769e1a657aec6210df3ea896600eec] selftests/futex: Use thread synchronization helpers instead of usleep()
git bisect bad 157a9b22ff769e1a657aec6210df3ea896600eec
# first bad commit: [157a9b22ff769e1a657aec6210df3ea896600eec] selftests/futex: Use thread synchronization helpers instead of usleep()

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v8 2/2] selftests/futex: fix the failed futex_requeue test issue
  2026-07-07 22:28   ` [PATCH v8 2/2] selftests/futex: fix the failed futex_requeue test issue Mark Brown
@ 2026-07-07 23:31     ` Thomas Gleixner
  2026-07-07 23:48       ` Mark Brown
  2026-07-08  1:54       ` Yuwen Chen
  0 siblings, 2 replies; 11+ messages in thread
From: Thomas Gleixner @ 2026-07-07 23:31 UTC (permalink / raw)
  To: Mark Brown, Yuwen Chen
  Cc: akpm, andrealmeid, bigeasy, colin.i.king, dave, dvhart, edliaw,
	justinstitt, kernel-team, licayy, linux-kernel, linux-kselftest,
	luto, mingo, morbo, nathan, ndesaulniers, peterz, shuah,
	usama.anjum, wakel, mark.rutland

On Tue, Jul 07 2026 at 23:28, Mark Brown wrote:
> On Mon, May 18, 2026 at 10:16:54AM +0800, Yuwen Chen wrote:
>
> I'm seeing failures on arm64 (running a system with 4xA53) in -next in
> this test which bisect to this commit, the commit seems obviously
> plausible but I didn't actually investigate:
>
> # TAP version 13
>  1..2
>  # Starting 2 tests from 1 test cases.
>  #  RUN           global.requeue_single ...
>  # futex_requeue.c:28:requeue_single:Expected res (-1) == 0 (0)
>  # futex_requeue.c:29:requeue_single:waiter failed errno 110: Connection timed out
>  # futex_requeue.c:49:requeue_single:Expected futex_wait_for_thread(&waiter, _metadata) (110) == 0 (0)
>  # futex_requeue.c:50:requeue_single:Wait for thread failed

Do you have /proc/ disabled by chance or is it not accessible for the
test case?

> Full log should be at:
>
>    https://lava.sirena.org.uk/scheduler/job/2954705#L13289
>
> but I'm having a terrible time with AI scrapers right now so perhaps not
> usefully.

Seems to correlate with the test case failure: Connection timed out :)

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v8 2/2] selftests/futex: fix the failed futex_requeue test issue
  2026-07-07 23:31     ` Thomas Gleixner
@ 2026-07-07 23:48       ` Mark Brown
  2026-07-08  1:54       ` Yuwen Chen
  1 sibling, 0 replies; 11+ messages in thread
From: Mark Brown @ 2026-07-07 23:48 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: Yuwen Chen, akpm, andrealmeid, bigeasy, colin.i.king, dave,
	dvhart, edliaw, justinstitt, kernel-team, licayy, linux-kernel,
	linux-kselftest, luto, mingo, morbo, nathan, ndesaulniers, peterz,
	shuah, usama.anjum, wakel, mark.rutland

[-- Attachment #1: Type: text/plain, Size: 1371 bytes --]

On Wed, Jul 08, 2026 at 01:31:45AM +0200, Thomas Gleixner wrote:
> On Tue, Jul 07 2026 at 23:28, Mark Brown wrote:

> >  1..2
> >  # Starting 2 tests from 1 test cases.
> >  #  RUN           global.requeue_single ...
> >  # futex_requeue.c:28:requeue_single:Expected res (-1) == 0 (0)
> >  # futex_requeue.c:29:requeue_single:waiter failed errno 110: Connection timed out
> >  # futex_requeue.c:49:requeue_single:Expected futex_wait_for_thread(&waiter, _metadata) (110) == 0 (0)
> >  # futex_requeue.c:50:requeue_single:Wait for thread failed

> Do you have /proc/ disabled by chance or is it not accessible for the
> test case?

Not intentionally, it's an arm64 defconfig running a Debian rootfs.  The
jobs that do the futex tests actually also run the proc selftests (after
the futex ones) and those are passing, adding checks that /proc is there
seems to confirm it is:

  # mount
  sysfs on /sys type sysfs (rw,nosuid,nodev,noexec,relatime)
  proc on /proc type proc (rw,nosuid,nodev,noexec,relatime)
  ...

ls seems to work too.

> > Full log should be at:

> >    https://lava.sirena.org.uk/scheduler/job/2954705#L13289

> > but I'm having a terrible time with AI scrapers right now so perhaps not
> > usefully.

> Seems to correlate with the test case failure: Connection timed out :)

Bah.  If you've got a fixed IP or IP range I can fiddle with the
firewalling?

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v8 2/2] selftests/futex: fix the failed futex_requeue test issue
  2026-07-07 23:31     ` Thomas Gleixner
  2026-07-07 23:48       ` Mark Brown
@ 2026-07-08  1:54       ` Yuwen Chen
  2026-07-08  8:08         ` Thomas Gleixner
  1 sibling, 1 reply; 11+ messages in thread
From: Yuwen Chen @ 2026-07-08  1:54 UTC (permalink / raw)
  To: tglx
  Cc: akpm, andrealmeid, bigeasy, broonie, colin.i.king, dave, dvhart,
	edliaw, justinstitt, kernel-team, licayy, linux-kernel,
	linux-kselftest, luto, mark.rutland, mingo, morbo, nathan,
	ndesaulniers, peterz, shuah, usama.anjum, wakel, ywen.chen

On Wed, 08 Jul 2026 01:31:45 +0200, Thomas Gleixner wrote:

> Do you have /proc/ disabled by chance or is it not accessible for the
> test case?
...
> Seems to correlate with the test case failure: Connection timed out :)

I used the following patch to simulate the situation where the proc file
system is not mounted on the system. The log is very similar to that of
the current problem.

--- a/tools/testing/selftests/futex/include/futex_thread.h
+++ b/tools/testing/selftests/futex/include/futex_thread.h
@@ -62,7 +62,8 @@ static inline int futex_wait_for_thread(struct futex_thread *t, struct __test_me
        int res;
 
        snprintf(fname, sizeof(fname), "/proc/%d/wchan", t->tid);
-       fp = fopen(fname, "r");
+       errno = ENOENT;
+       fp = NULL;
        if (!fp) {
                /* If /proc/... is not available, sleep */
                if (errno != ENOENT)

The corresponding logs are as follows:

  TAP version 13
  1..2
  # Starting 2 tests from 1 test cases.
  #  RUN           global.requeue_single ...
  # ../include/futex_thread.h:71:requeue_single:/proc/$PID/wchan not accessible, continue with sleep()
  # futex_requeue.c:28:requeue_single:Expected res (-1) == 0 (0)
  # futex_requeue.c:52:requeue_single:Expected futex_cmp_requeue(f1, 0, &f2, 0, 1, 0) (0) == 1 (1)
  # futex_requeue.c:53:requeue_single:Expected futex_wake(&f2, 1, 0) (0) == 1 (1)
  # futex_requeue.c:29:requeue_single:waiter failed errno 110: Connection timed out
  # requeue_single: Test failed
  #          FAIL  global.requeue_single
  not ok 1 global.requeue_single
  #  RUN           global.requeue_multiple ...
  # ../include/futex_thread.h:71:requeue_multiple:/proc/$PID/wchan not accessible, continue with sleep()
  # futex_requeue.c:28:requeue_multiple:Expected res (-1) == 0 (0)
  # futex_requeue.c:28:requeue_multiple:Expected res (-1) == 0 (0)
  # futex_requeue.c:29:requeue_multiple:waiter failed errno 110: Connection timed out
  # futex_requeue.c:29:requeue_multiple:waiter failed errno 110: Connection timed out
  # futex_requeue.c:28:requeue_multiple:Expected res (-1) == 0 (0)
  # futex_requeue.c:29:requeue_multiple:waiter failed errno 110: Connection timed out
  # futex_requeue.c:28:requeue_multiple:Expected res (-1) == 0 (0)
  # futex_requeue.c:29:requeue_multiple:waiter failed errno 110: Connection timed out
  # futex_requeue.c:28:requeue_multiple:Expected res (-1) == 0 (0)
  # futex_requeue.c:29:requeue_multiple:waiter failed errno 110: Connection timed out
  # futex_requeue.c:28:requeue_multiple:Expected res (-1) == 0 (0)
  # futex_requeue.c:29:requeue_multiple:waiter failed errno 110: Connection timed out
  # futex_requeue.c:28:requeue_multiple:Expected res (-1) == 0 (0)
  # futex_requeue.c:29:requeue_multiple:waiter failed errno 110: Connection timed out
  # futex_requeue.c:28:requeue_multiple:Expected res (-1) == 0 (0)
  # futex_requeue.c:29:requeue_multiple:waiter failed errno 110: Connection timed out
  # futex_requeue.c:28:requeue_multiple:Expected res (-1) == 0 (0)
  # futex_requeue.c:29:requeue_multiple:waiter failed errno 110: Connection timed out
  # futex_requeue.c:28:requeue_multiple:Expected res (-1) == 0 (0)
  # futex_requeue.c:29:requeue_multiple:waiter failed errno 110: Connection timed out
  # ../include/futex_thread.h:71:requeue_multiple:/proc/$PID/wchan not accessible, continue with sleep()
  # ../include/futex_thread.h:71:requeue_multiple:/proc/$PID/wchan not accessible, continue with sleep()
  # ../include/futex_thread.h:71:requeue_multiple:/proc/$PID/wchan not accessible, continue with sleep()
  # ../include/futex_thread.h:71:requeue_multiple:/proc/$PID/wchan not accessible, continue with sleep()
  # ../include/futex_thread.h:71:requeue_multiple:/proc/$PID/wchan not accessible, continue with sleep()
  # ../include/futex_thread.h:71:requeue_multiple:/proc/$PID/wchan not accessible, continue with sleep()
  # ../include/futex_thread.h:71:requeue_multiple:/proc/$PID/wchan not accessible, continue with sleep()
  # ../include/futex_thread.h:71:requeue_multiple:/proc/$PID/wchan not accessible, continue with sleep()
  # ../include/futex_thread.h:71:requeue_multiple:/proc/$PID/wchan not accessible, continue with sleep()
  # futex_requeue.c:80:requeue_multiple:Expected futex_cmp_requeue(f1, 0, &f2, 3, 7, 0) (0) == 10 (10)
  # futex_requeue.c:81:requeue_multiple:Expected futex_wake(&f2, INT_MAX, 0) (0) == 7 (7)
  # requeue_multiple: Test failed
  #          FAIL  global.requeue_multiple
  not ok 2 global.requeue_multiple
  # FAILED: 0 / 2 tests passed.
  # Totals: pass:0 fail:2 xfail:0 xpass:0 skip:0 error:0

I suggested adding a parameter for the waiting time to the futex_wait_for_thread function.
In this way, when the proc file system is not mounted on the system, the old solution
can still be used.

Thanks.


^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH v8 2/2] selftests/futex: fix the failed futex_requeue test issue
  2026-07-08  1:54       ` Yuwen Chen
@ 2026-07-08  8:08         ` Thomas Gleixner
  0 siblings, 0 replies; 11+ messages in thread
From: Thomas Gleixner @ 2026-07-08  8:08 UTC (permalink / raw)
  To: Yuwen Chen
  Cc: akpm, andrealmeid, bigeasy, broonie, colin.i.king, dave, dvhart,
	edliaw, justinstitt, kernel-team, licayy, linux-kernel,
	linux-kselftest, luto, mark.rutland, mingo, morbo, nathan,
	ndesaulniers, peterz, shuah, usama.anjum, wakel, ywen.chen

On Wed, Jul 08 2026 at 09:54, Yuwen Chen wrote:
> On Wed, 08 Jul 2026 01:31:45 +0200, Thomas Gleixner wrote:
>
>> Do you have /proc/ disabled by chance or is it not accessible for the
>> test case?
> ...
>> Seems to correlate with the test case failure: Connection timed out :)
>
> I used the following patch to simulate the situation where the proc file
> system is not mounted on the system. The log is very similar to that of
> the current problem.
>
> --- a/tools/testing/selftests/futex/include/futex_thread.h
> +++ b/tools/testing/selftests/futex/include/futex_thread.h
> @@ -62,7 +62,8 @@ static inline int futex_wait_for_thread(struct futex_thread *t, struct __test_me
>         int res;
>  
>         snprintf(fname, sizeof(fname), "/proc/%d/wchan", t->tid);
> -       fp = fopen(fname, "r");
> +       errno = ENOENT;
> +       fp = NULL;
>         if (!fp) {
>                 /* If /proc/... is not available, sleep */
>                 if (errno != ENOENT)

Sure. But that's _NOT_ the problem. /proc/ is accessible and my tired
brain asked the wrong question yesterday. Why?

Do you see any of those messages in the log Mark provided?

>   # ../include/futex_thread.h:71:requeue_single:/proc/$PID/wchan not accessible, continue with sleep()

Obviously not.

So /proc/.../wchan _IS_ accessible, but futex does not show up there,
which makes the loop wait for the full timeout. That in turn causes the
waiter to time out because that timeout is the same and in the multi
waiter case it's even worse.

So the real question is what is read from wchan on that machine.

> I suggested adding a parameter for the waiting time to the
> futex_wait_for_thread function.  In this way, when the proc file
> system is not mounted on the system, the old solution can still be
> used.

That does not solve anything and that can be made to work in the helper
code without magic parameters. Both issues have the same root cause and
no, we are not papering over it with some magic parameters.

Mark, can you give the below a spin?

That survives when I make the strncmp fail by changing the compare
string to "futil" :) It's slow and noisy, but works.

Can you please provide the output of that run?

Thanks,

        tglx
---
--- a/tools/testing/selftests/futex/functional/futex_requeue.c
+++ b/tools/testing/selftests/futex/functional/futex_requeue.c
@@ -13,16 +13,23 @@
 #include "futex_thread.h"
 #include "kselftest_harness.h"
 
-#define FUTEX_WAIT_TIMEOUT_SECS			2
+struct waiter_args {
+	struct __test_metadata	*_metadata;
+	unsigned int		n_threads;
+};
 
 volatile futex_t *f1;
 
 static int waiterfn(void *arg)
 {
-	struct __test_metadata *_metadata = (struct __test_metadata *)arg;
-	struct timespec to = { .tv_sec = FUTEX_WAIT_TIMEOUT_SECS };
+	struct __test_metadata *_metadata;
+	struct waiter_args *wargs = arg;
+	struct timespec to = { };
 	int res;
 
+	_metadata = wargs->_metadata;
+	to.tv_sec = (wargs->n_threads + 1) * WAIT_FOR_THREAD_SECS;
+
 	res = futex_wait(f1, *f1, &to, 0);
 	if (res) {
 		EXPECT_EQ(res, 0)
@@ -34,6 +41,7 @@ static int waiterfn(void *arg)
 
 TEST(requeue_single)
 {
+	struct waiter_args wargs = { ._metadata = _metadata, .n_threads = 1 };
 	struct futex_thread waiter;
 	volatile futex_t _f1 = 0;
 	volatile futex_t f2 = 0;
@@ -43,7 +51,7 @@ TEST(requeue_single)
 	/*
 	 * Requeue a waiter from f1 to f2, and wake f2.
 	 */
-	ASSERT_EQ(futex_thread_create(&waiter, waiterfn, _metadata), 0)
+	ASSERT_EQ(futex_thread_create(&waiter, waiterfn, &wargs), 0)
 		TH_LOG("pthread_create failed");
 
 	ASSERT_EQ(futex_wait_for_thread(&waiter, _metadata), 0)
@@ -57,6 +65,7 @@ TEST(requeue_single)
 
 TEST(requeue_multiple)
 {
+	struct waiter_args wargs = { ._metadata = _metadata, .n_threads = 10 };
 	struct futex_thread waiter[10];
 	volatile futex_t _f1 = 0;
 	volatile futex_t f2 = 0;
@@ -68,7 +77,7 @@ TEST(requeue_multiple)
 	 * At futex_wake, wake INT_MAX (should be exactly 7).
 	 */
 	for (int i = 0; i < 10; i++) {
-		ASSERT_EQ(futex_thread_create(&waiter[i], waiterfn, _metadata), 0)
+		ASSERT_EQ(futex_thread_create(&waiter[i], waiterfn, &wargs), 0)
 			TH_LOG("pthread_create failed for waiter %d", i);
 	}
 
--- a/tools/testing/selftests/futex/include/futex_thread.h
+++ b/tools/testing/selftests/futex/include/futex_thread.h
@@ -11,7 +11,7 @@
 #include "kselftest_harness.h"
 
 #define USEC_PER_SEC		1000000L
-#define WAIT_FOR_THREAD_SECS	2
+#define WAIT_FOR_THREAD_SECS	1
 #define WAIT_FOR_THREAD_USECS	(WAIT_FOR_THREAD_SECS * USEC_PER_SEC)
 #define WAIT_THREAD_RETRIES	100
 
@@ -24,7 +24,7 @@ struct futex_thread {
 	int			retval;
 };
 
-static inline int __wait_for_thread(FILE *fp)
+static inline int __wait_for_thread(FILE *fp, struct __test_metadata *_metadata)
 {
 	unsigned int sleep_time_us = WAIT_FOR_THREAD_USECS / WAIT_THREAD_RETRIES;
 	char buf[80] = "";
@@ -37,7 +37,9 @@ static inline int __wait_for_thread(FILE
 		usleep(sleep_time_us);
 		rewind(fp);
 	}
-	return ETIMEDOUT;
+
+	TH_LOG("/proc/$PID/wchan contains \"%s\". Trying to continue.", buf);
+	return 0;
 }
 
 static void *__futex_thread_fn(void *arg)
@@ -72,7 +74,7 @@ static inline int futex_wait_for_thread(
 		return 0;
 	}
 
-	res = __wait_for_thread(fp);
+	res = __wait_for_thread(fp, _metadata);
 	fclose(fp);
 	return res;
 }

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2026-07-08  8:08 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-18  2:15 [PATCH v8 0/2] selftests/futex: fix the failed futex_requeue test issue Yuwen Chen
2026-05-18  2:16 ` [PATCH v8 1/2] selftests/futex: implement the interfaces related to threads Yuwen Chen
2026-07-05 19:54   ` [tip: locking/futex] selftests/futex: Provide thread creation and synchronization helpers tip-bot2 for Yuwen Chen
2026-05-18  2:16 ` [PATCH v8 2/2] selftests/futex: fix the failed futex_requeue test issue Yuwen Chen
2026-05-19  2:06   ` Yuwen Chen
2026-07-05 19:54   ` [tip: locking/futex] selftests/futex: Use thread synchronization helpers instead of usleep() tip-bot2 for Yuwen Chen
2026-07-07 22:28   ` [PATCH v8 2/2] selftests/futex: fix the failed futex_requeue test issue Mark Brown
2026-07-07 23:31     ` Thomas Gleixner
2026-07-07 23:48       ` Mark Brown
2026-07-08  1:54       ` Yuwen Chen
2026-07-08  8:08         ` Thomas Gleixner

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox