All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/3] selftests/futex: Migrate wait functional tests to harness
@ 2026-05-25  9:19 Wake Liu
  2026-05-25  9:20 ` [PATCH 1/3] selftests/futex: Migrate futex_wait " Wake Liu
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Wake Liu @ 2026-05-25  9:19 UTC (permalink / raw)
  To: Thomas Gleixner, Ingo Molnar, Shuah Khan, linux-kselftest
  Cc: Peter Zijlstra, Darren Hart, Davidlohr Bueso, André Almeida,
	Carlos Llamas, linux-kernel, wakel

This series refactors the wait-related futex functional tests (futex_wait,
futex_wait_private_mapped_file, and futex_wait_uninitialized_heap) to
exclusively use the kselftest_harness.h framework.

This eliminates mixed usage of legacy ksft_* APIs and high-level harness
asserts, preventing crashes on older kernels, and ensures proper thread
joining.

Patch 1 migrates futex_wait.
Patch 2 migrates futex_wait_private_mapped_file.
Patch 3 migrates futex_wait_uninitialized_heap.

Wake Liu (3):
  selftests/futex: Migrate futex_wait to harness
  selftests/futex: Migrate futex_wait_private_mapped_file to harness
  selftests/futex: Migrate futex_wait_uninitialized_heap to harness

 .../selftests/futex/functional/futex_wait.c   | 125 +++++++++++-------
 .../futex_wait_private_mapped_file.c          |  26 ++--
 .../futex_wait_uninitialized_heap.c           |  22 +--
 3 files changed, 100 insertions(+), 73 deletions(-)

-- 
2.54.0.746.g67dd491aae-goog


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

* [PATCH 1/3] selftests/futex: Migrate futex_wait to harness
  2026-05-25  9:19 [PATCH 0/3] selftests/futex: Migrate wait functional tests to harness Wake Liu
@ 2026-05-25  9:20 ` Wake Liu
  2026-05-25 18:51   ` André Almeida
  2026-05-25  9:20 ` [PATCH 2/3] selftests/futex: Migrate futex_wait_private_mapped_file " Wake Liu
  2026-05-25  9:20 ` [PATCH 3/3] selftests/futex: Migrate futex_wait_uninitialized_heap " Wake Liu
  2 siblings, 1 reply; 6+ messages in thread
From: Wake Liu @ 2026-05-25  9:20 UTC (permalink / raw)
  To: Thomas Gleixner, Ingo Molnar, Shuah Khan, linux-kselftest
  Cc: Peter Zijlstra, Darren Hart, Davidlohr Bueso, André Almeida,
	Carlos Llamas, linux-kernel, wakel

Migrate futex_wait test to the kselftest harness framework,
removing mixed legacy ksft_* API usages and ensuring proper thread joining.

Signed-off-by: Wake Liu <wakel@google.com>
---
 .../selftests/futex/functional/futex_wait.c   | 125 +++++++++++-------
 1 file changed, 77 insertions(+), 48 deletions(-)

diff --git a/tools/testing/selftests/futex/functional/futex_wait.c b/tools/testing/selftests/futex/functional/futex_wait.c
index 7b8879409007..ed4b040600b8 100644
--- a/tools/testing/selftests/futex/functional/futex_wait.c
+++ b/tools/testing/selftests/futex/functional/futex_wait.c
@@ -9,6 +9,7 @@
 #include <sys/shm.h>
 #include <sys/mman.h>
 #include <fcntl.h>
+#include <stdlib.h>
 
 #include "futextest.h"
 #include "kselftest_harness.h"
@@ -19,125 +20,153 @@
 
 void *futex;
 
+struct waiter_args {
+	struct __test_metadata *_metadata;
+	unsigned int flags;
+};
+
 static void *waiterfn(void *arg)
 {
+	struct waiter_args *args = (struct waiter_args *)arg;
+	struct __test_metadata *_metadata = args->_metadata;
 	struct timespec to;
-	unsigned int flags = 0;
-
-	if (arg)
-		flags = *((unsigned int *) arg);
+	int res;
 
 	to.tv_sec = 0;
 	to.tv_nsec = timeout_ns;
 
-	if (futex_wait(futex, 0, &to, flags))
-		printf("waiter failed errno %d\n", errno);
+	res = futex_wait(futex, 0, &to, args->flags);
+	if (res) {
+		EXPECT_EQ(res, 0)
+			TH_LOG("waiter failed errno %d: %s", errno, strerror(errno));
+	}
 
+	free(args);
 	return NULL;
 }
 
 TEST(private_futex)
 {
-	unsigned int flags = FUTEX_PRIVATE_FLAG;
+	struct waiter_args *args = malloc(sizeof(*args));
 	u_int32_t f_private = 0;
 	pthread_t waiter;
 	int res;
 
+	args->_metadata = _metadata;
+	args->flags = FUTEX_PRIVATE_FLAG;
 	futex = &f_private;
 
 	/* Testing a private futex */
-	ksft_print_dbg_msg("Calling private futex_wait on futex: %p\n", futex);
-	if (pthread_create(&waiter, NULL, waiterfn, (void *) &flags))
-		ksft_exit_fail_msg("pthread_create failed\n");
+	TH_LOG("Calling private futex_wait on futex: %p", futex);
+	ASSERT_EQ(pthread_create(&waiter, NULL, waiterfn, args), 0)
+		TH_LOG("pthread_create failed");
 
 	usleep(WAKE_WAIT_US);
 
-	ksft_print_dbg_msg("Calling private futex_wake on futex: %p\n", futex);
+	TH_LOG("Calling private futex_wake on futex: %p", futex);
 	res = futex_wake(futex, 1, FUTEX_PRIVATE_FLAG);
-	if (res != 1) {
-		ksft_test_result_fail("futex_wake private returned: %d %s\n",
-				      errno, strerror(errno));
-	} else {
-		ksft_test_result_pass("futex_wake private succeeds\n");
-	}
+	EXPECT_EQ(res, 1)
+		TH_LOG("futex_wake private returned: %d %s", res, res < 0 ? strerror(errno) : "");
+
+	pthread_join(waiter, NULL);
 }
 
 TEST(anon_page)
 {
+	struct waiter_args *args = malloc(sizeof(*args));
 	u_int32_t *shared_data;
 	pthread_t waiter;
 	int res, shm_id;
 
+	args->_metadata = _metadata;
+	args->flags = 0;
+
 	/* Testing an anon page shared memory */
 	shm_id = shmget(IPC_PRIVATE, 4096, IPC_CREAT | 0666);
 	if (shm_id < 0) {
-		if (errno == ENOSYS)
-			ksft_exit_skip("shmget syscall not supported\n");
-		perror("shmget");
-		exit(1);
+		if (errno == ENOSYS) {
+			free(args);
+			SKIP(return, "shmget syscall not supported");
+		}
+		ASSERT_GE(shm_id, 0)
+			TH_LOG("shmget failed: %s", strerror(errno));
 	}
 
 	shared_data = shmat(shm_id, NULL, 0);
+	if (shared_data == (void *)-1) {
+		free(args);
+		ASSERT_NE(shared_data, (void *)-1)
+			TH_LOG("shmat failed: %s", strerror(errno));
+	}
 
 	*shared_data = 0;
 	futex = shared_data;
 
-	ksft_print_dbg_msg("Calling shared (page anon) futex_wait on futex: %p\n", futex);
-	if (pthread_create(&waiter, NULL, waiterfn, NULL))
-		ksft_exit_fail_msg("pthread_create failed\n");
+	TH_LOG("Calling shared (page anon) futex_wait on futex: %p", futex);
+	ASSERT_EQ(pthread_create(&waiter, NULL, waiterfn, args), 0)
+		TH_LOG("pthread_create failed");
 
 	usleep(WAKE_WAIT_US);
 
-	ksft_print_dbg_msg("Calling shared (page anon) futex_wake on futex: %p\n", futex);
+	TH_LOG("Calling shared (page anon) futex_wake on futex: %p", futex);
 	res = futex_wake(futex, 1, 0);
-	if (res != 1) {
-		ksft_test_result_fail("futex_wake shared (page anon) returned: %d %s\n",
-				      errno, strerror(errno));
-	} else {
-		ksft_test_result_pass("futex_wake shared (page anon) succeeds\n");
-	}
+	EXPECT_EQ(res, 1)
+		TH_LOG("futex_wake shared (page anon) returned: %d %s", res, res < 0 ? strerror(errno) : "");
 
+	pthread_join(waiter, NULL);
 	shmdt(shared_data);
 }
 
 TEST(file_backed)
 {
+	struct waiter_args *args = malloc(sizeof(*args));
 	u_int32_t f_private = 0;
 	pthread_t waiter;
 	int res, fd;
 	void *shm;
 
+	args->_metadata = _metadata;
+	args->flags = 0;
+
 	/* Testing a file backed shared memory */
-	fd = open(SHM_PATH, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
-	if (fd < 0)
-		ksft_exit_fail_msg("open\n");
+	fd = open(SHM_PATH, O_RDWR | O_CREAT, 0600);
+	if (fd < 0) {
+		free(args);
+		ASSERT_GE(fd, 0)
+			TH_LOG("open failed: %s", strerror(errno));
+	}
 
-	if (ftruncate(fd, sizeof(f_private)))
-		ksft_exit_fail_msg("ftruncate\n");
+	if (ftruncate(fd, sizeof(f_private))) {
+		free(args);
+		close(fd);
+		ASSERT_TRUE(0)
+			TH_LOG("ftruncate failed: %s", strerror(errno));
+	}
 
 	shm = mmap(NULL, sizeof(f_private), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
-	if (shm == MAP_FAILED)
-		ksft_exit_fail_msg("mmap\n");
+	if (shm == MAP_FAILED) {
+		free(args);
+		close(fd);
+		ASSERT_NE(shm, MAP_FAILED)
+			TH_LOG("mmap failed: %s", strerror(errno));
+	}
 
 	memcpy(shm, &f_private, sizeof(f_private));
 
 	futex = shm;
 
-	ksft_print_dbg_msg("Calling shared (file backed) futex_wait on futex: %p\n", futex);
-	if (pthread_create(&waiter, NULL, waiterfn, NULL))
-		ksft_exit_fail_msg("pthread_create failed\n");
+	TH_LOG("Calling shared (file backed) futex_wait on futex: %p", futex);
+	ASSERT_EQ(pthread_create(&waiter, NULL, waiterfn, args), 0)
+		TH_LOG("pthread_create failed");
 
 	usleep(WAKE_WAIT_US);
 
-	ksft_print_dbg_msg("Calling shared (file backed) futex_wake on futex: %p\n", futex);
+	TH_LOG("Calling shared (file backed) futex_wake on futex: %p", futex);
 	res = futex_wake(shm, 1, 0);
-	if (res != 1) {
-		ksft_test_result_fail("futex_wake shared (file backed) returned: %d %s\n",
-				      errno, strerror(errno));
-	} else {
-		ksft_test_result_pass("futex_wake shared (file backed) succeeds\n");
-	}
+	EXPECT_EQ(res, 1)
+		TH_LOG("futex_wake shared (file backed) returned: %d %s", res, res < 0 ? strerror(errno) : "");
 
+	pthread_join(waiter, NULL);
 	munmap(shm, sizeof(f_private));
 	remove(SHM_PATH);
 	close(fd);
-- 
2.54.0.746.g67dd491aae-goog


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

* [PATCH 2/3] selftests/futex: Migrate futex_wait_private_mapped_file to harness
  2026-05-25  9:19 [PATCH 0/3] selftests/futex: Migrate wait functional tests to harness Wake Liu
  2026-05-25  9:20 ` [PATCH 1/3] selftests/futex: Migrate futex_wait " Wake Liu
@ 2026-05-25  9:20 ` Wake Liu
  2026-05-25  9:20 ` [PATCH 3/3] selftests/futex: Migrate futex_wait_uninitialized_heap " Wake Liu
  2 siblings, 0 replies; 6+ messages in thread
From: Wake Liu @ 2026-05-25  9:20 UTC (permalink / raw)
  To: Thomas Gleixner, Ingo Molnar, Shuah Khan, linux-kselftest
  Cc: Peter Zijlstra, Darren Hart, Davidlohr Bueso, André Almeida,
	Carlos Llamas, linux-kernel, wakel

Migrate futex_wait_private_mapped_file test to the kselftest harness framework,
removing mixed legacy ksft_* API usages and passing test metadata to helper thread.

Signed-off-by: Wake Liu <wakel@google.com>
---
 .../futex_wait_private_mapped_file.c          | 26 +++++++++----------
 1 file changed, 12 insertions(+), 14 deletions(-)

diff --git a/tools/testing/selftests/futex/functional/futex_wait_private_mapped_file.c b/tools/testing/selftests/futex/functional/futex_wait_private_mapped_file.c
index 2a749f9b14eb..b4d0502a6611 100644
--- a/tools/testing/selftests/futex/functional/futex_wait_private_mapped_file.c
+++ b/tools/testing/selftests/futex/functional/futex_wait_private_mapped_file.c
@@ -26,6 +26,7 @@
 #include <pthread.h>
 #include <libgen.h>
 #include <signal.h>
+#include <string.h>
 
 #include "futextest.h"
 #include "kselftest_harness.h"
@@ -41,17 +42,18 @@ struct timespec wait_timeout = { .tv_sec = 5, .tv_nsec = 0};
 
 void *thr_futex_wait(void *arg)
 {
+	struct __test_metadata *_metadata = (struct __test_metadata *)arg;
 	int ret;
 
-	ksft_print_dbg_msg("futex wait\n");
+	TH_LOG("futex wait");
 	ret = futex_wait(&val, 1, &wait_timeout, 0);
 	if (ret && errno != EWOULDBLOCK && errno != ETIMEDOUT)
-		ksft_exit_fail_msg("futex error.\n");
+		ASSERT_TRUE(0) TH_LOG("futex error: %s", strerror(errno));
 
 	if (ret && errno == ETIMEDOUT)
-		ksft_exit_fail_msg("waiter timedout\n");
+		ASSERT_TRUE(0) TH_LOG("waiter timedout");
 
-	ksft_print_dbg_msg("futex_wait: ret = %d, errno = %d\n", ret, errno);
+	TH_LOG("futex_wait: ret = %d, errno = %d", ret, errno);
 
 	return NULL;
 }
@@ -61,22 +63,18 @@ TEST(wait_private_mapped_file)
 	pthread_t thr;
 	int res;
 
-	res = pthread_create(&thr, NULL, thr_futex_wait, NULL);
-	if (res < 0)
-		ksft_exit_fail_msg("pthread_create error\n");
+	res = pthread_create(&thr, NULL, thr_futex_wait, _metadata);
+	ASSERT_EQ(res, 0) TH_LOG("pthread_create error");
 
-	ksft_print_dbg_msg("wait a while\n");
+	TH_LOG("wait a while");
 	usleep(WAKE_WAIT_US);
 	val = 2;
 	res = futex_wake(&val, 1, 0);
-	ksft_print_dbg_msg("futex_wake %d\n", res);
-	if (res != 1)
-		ksft_exit_fail_msg("FUTEX_WAKE didn't find the waiting thread.\n");
+	TH_LOG("futex_wake %d", res);
+	EXPECT_EQ(res, 1) TH_LOG("FUTEX_WAKE didn't find the waiting thread");
 
-	ksft_print_dbg_msg("join\n");
+	TH_LOG("join");
 	pthread_join(thr, NULL);
-
-	ksft_test_result_pass("wait_private_mapped_file");
 }
 
 TEST_HARNESS_MAIN
-- 
2.54.0.746.g67dd491aae-goog


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

* [PATCH 3/3] selftests/futex: Migrate futex_wait_uninitialized_heap to harness
  2026-05-25  9:19 [PATCH 0/3] selftests/futex: Migrate wait functional tests to harness Wake Liu
  2026-05-25  9:20 ` [PATCH 1/3] selftests/futex: Migrate futex_wait " Wake Liu
  2026-05-25  9:20 ` [PATCH 2/3] selftests/futex: Migrate futex_wait_private_mapped_file " Wake Liu
@ 2026-05-25  9:20 ` Wake Liu
  2 siblings, 0 replies; 6+ messages in thread
From: Wake Liu @ 2026-05-25  9:20 UTC (permalink / raw)
  To: Thomas Gleixner, Ingo Molnar, Shuah Khan, linux-kselftest
  Cc: Peter Zijlstra, Darren Hart, Davidlohr Bueso, André Almeida,
	Carlos Llamas, linux-kernel, wakel

Migrate futex_wait_uninitialized_heap test to the kselftest harness framework,
removing mixed legacy ksft_* API usages and ensuring proper thread joining.

Signed-off-by: Wake Liu <wakel@google.com>
---
 .../futex_wait_uninitialized_heap.c           | 22 +++++++++----------
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/tools/testing/selftests/futex/functional/futex_wait_uninitialized_heap.c b/tools/testing/selftests/futex/functional/futex_wait_uninitialized_heap.c
index b07d68a67f31..ae1da2c6c8ad 100644
--- a/tools/testing/selftests/futex/functional/futex_wait_uninitialized_heap.c
+++ b/tools/testing/selftests/futex/functional/futex_wait_uninitialized_heap.c
@@ -28,6 +28,7 @@
 #include <errno.h>
 #include <linux/futex.h>
 #include <libgen.h>
+#include <string.h>
 
 #include "futextest.h"
 #include "kselftest_harness.h"
@@ -40,6 +41,7 @@ void *buf;
 
 void *wait_thread(void *arg)
 {
+	struct __test_metadata *_metadata = (struct __test_metadata *)arg;
 	int res;
 
 	child_ret = true;
@@ -47,7 +49,7 @@ void *wait_thread(void *arg)
 	child_blocked = 0;
 
 	if (res != 0 && errno != EWOULDBLOCK) {
-		ksft_exit_fail_msg("futex failure\n");
+		EXPECT_EQ(res, 0) TH_LOG("futex failure: %s", strerror(errno));
 		child_ret = false;
 	}
 	pthread_exit(NULL);
@@ -63,21 +65,19 @@ TEST(futex_wait_uninitialized_heap)
 
 	buf = mmap(NULL, page_size, PROT_READ|PROT_WRITE,
 		   MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
-	if (buf == (void *)-1)
-		ksft_exit_fail_msg("mmap\n");
+	ASSERT_NE(buf, MAP_FAILED) TH_LOG("mmap failed: %s", strerror(errno));
 
-	ret = pthread_create(&thr, NULL, wait_thread, NULL);
-	if (ret)
-		ksft_exit_fail_msg("pthread_create\n");
+	ret = pthread_create(&thr, NULL, wait_thread, _metadata);
+	ASSERT_EQ(ret, 0) TH_LOG("pthread_create failed");
 
-	ksft_print_dbg_msg("waiting %dus for child to return\n", WAIT_US);
+	TH_LOG("waiting %dus for child to return", WAIT_US);
 	usleep(WAIT_US);
 
-	if (child_blocked)
-		ksft_test_result_fail("child blocked in kernel\n");
+	EXPECT_EQ(child_blocked, 0) TH_LOG("child blocked in kernel");
+	EXPECT_TRUE(child_ret) TH_LOG("child error");
 
-	if (!child_ret)
-		ksft_test_result_fail("child error\n");
+	pthread_join(thr, NULL);
+	munmap(buf, page_size);
 }
 
 TEST_HARNESS_MAIN
-- 
2.54.0.746.g67dd491aae-goog


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

* Re: [PATCH 1/3] selftests/futex: Migrate futex_wait to harness
  2026-05-25  9:20 ` [PATCH 1/3] selftests/futex: Migrate futex_wait " Wake Liu
@ 2026-05-25 18:51   ` André Almeida
  2026-05-26  1:25     ` Wake Liu
  0 siblings, 1 reply; 6+ messages in thread
From: André Almeida @ 2026-05-25 18:51 UTC (permalink / raw)
  To: Wake Liu
  Cc: Shuah Khan, Thomas Gleixner, Peter Zijlstra, Darren Hart,
	linux-kselftest, Ingo Molnar, Davidlohr Bueso, Carlos Llamas,
	linux-kernel, kernel-dev

Em 25/05/2026 06:20, Wake Liu escreveu:
> Migrate futex_wait test to the kselftest harness framework,
> removing mixed legacy ksft_* API usages and ensuring proper thread joining.
> 

Why is this patchset not part of the same series that you just sent?

> Signed-off-by: Wake Liu <wakel@google.com>
> ---
>   .../selftests/futex/functional/futex_wait.c   | 125 +++++++++++-------
>   1 file changed, 77 insertions(+), 48 deletions(-)
> 
> diff --git a/tools/testing/selftests/futex/functional/futex_wait.c b/tools/testing/selftests/futex/functional/futex_wait.c
> index 7b8879409007..ed4b040600b8 100644
> --- a/tools/testing/selftests/futex/functional/futex_wait.c
> +++ b/tools/testing/selftests/futex/functional/futex_wait.c
> @@ -9,6 +9,7 @@
>   #include <sys/shm.h>
>   #include <sys/mman.h>
>   #include <fcntl.h>
> +#include <stdlib.h>
>   
>   #include "futextest.h"
>   #include "kselftest_harness.h"
> @@ -19,125 +20,153 @@
>   
>   void *futex;
>   
> +struct waiter_args {
> +	struct __test_metadata *_metadata;
> +	unsigned int flags;
> +};
> +
>   static void *waiterfn(void *arg)
>   {
> +	struct waiter_args *args = (struct waiter_args *)arg;
> +	struct __test_metadata *_metadata = args->_metadata;

As much as I like the benefits of being able to properly use the harness 
macros in threads, I fell like we are touching private structs here. Are 
they safe to be used concurrently? If a child thread an the main thread 
fails, does that counts as two fails?

Perhaps we should have a look to create a kselftest wrapper for 
pthread_create().

>   	struct timespec to;
> -	unsigned int flags = 0;
> -
> -	if (arg)
> -		flags = *((unsigned int *) arg);
> +	int res;
>   
>   	to.tv_sec = 0;
>   	to.tv_nsec = timeout_ns;
>   
> -	if (futex_wait(futex, 0, &to, flags))
> -		printf("waiter failed errno %d\n", errno);
> +	res = futex_wait(futex, 0, &to, args->flags);
> +	if (res) {
> +		EXPECT_EQ(res, 0)

I have changed it to ASSERT_EQ(res, -1) just to see what happens when a 
child thread fails, but the test still reported PASSED: 3 / 3

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

* Re: [PATCH 1/3] selftests/futex: Migrate futex_wait to harness
  2026-05-25 18:51   ` André Almeida
@ 2026-05-26  1:25     ` Wake Liu
  0 siblings, 0 replies; 6+ messages in thread
From: Wake Liu @ 2026-05-26  1:25 UTC (permalink / raw)
  To: André Almeida
  Cc: Shuah Khan, Thomas Gleixner, Peter Zijlstra, Darren Hart,
	linux-kselftest, Ingo Molnar, Davidlohr Bueso, Carlos Llamas,
	linux-kernel, kernel-dev

On Tue, May 26, 2026 at 2:51 AM André Almeida <andrealmeid@igalia.com> wrote:
>
> Em 25/05/2026 06:20, Wake Liu escreveu:
> > Migrate futex_wait test to the kselftest harness framework,
> > removing mixed legacy ksft_* API usages and ensuring proper thread joining.
> >
>
> Why is this patchset not part of the same series that you just sent?
>

The overall scope of migrating all the remaining futex functional
tests to the harness is quite large (I still have 2 series planned for
requeue tests, just not finish yet lol).

To keep the review process manageable and incremental, I prefer
splitting them into smaller, logically grouped topic-based series
(e.g., wait-related vs. requeue-related).

> > Signed-off-by: Wake Liu <wakel@google.com>
> > ---
> >   .../selftests/futex/functional/futex_wait.c   | 125 +++++++++++-------
> >   1 file changed, 77 insertions(+), 48 deletions(-)
> >
> > diff --git a/tools/testing/selftests/futex/functional/futex_wait.c b/tools/testing/selftests/futex/functional/futex_wait.c
> > index 7b8879409007..ed4b040600b8 100644
> > --- a/tools/testing/selftests/futex/functional/futex_wait.c
> > +++ b/tools/testing/selftests/futex/functional/futex_wait.c
> > @@ -9,6 +9,7 @@
> >   #include <sys/shm.h>
> >   #include <sys/mman.h>
> >   #include <fcntl.h>
> > +#include <stdlib.h>
> >
> >   #include "futextest.h"
> >   #include "kselftest_harness.h"
> > @@ -19,125 +20,153 @@
> >
> >   void *futex;
> >
> > +struct waiter_args {
> > +     struct __test_metadata *_metadata;
> > +     unsigned int flags;
> > +};
> > +
> >   static void *waiterfn(void *arg)
> >   {
> > +     struct waiter_args *args = (struct waiter_args *)arg;
> > +     struct __test_metadata *_metadata = args->_metadata;
>
> As much as I like the benefits of being able to properly use the harness
> macros in threads, I fell like we are touching private structs here. Are
> they safe to be used concurrently? If a child thread an the main thread
> fails, does that counts as two fails?
>
> Perhaps we should have a look to create a kselftest wrapper for
> pthread_create().
>

Regarding concurrency safety: _metadata is allocated via MAP_SHARED in
the harness, so it is shared across forks. For pthread threads, they
share the same address space, so they naturally access the exact same
_metadata pointer.

While concurrently writing to _metadata->exit_code on failure is
technically a data race under the C standard, practically it is a
simple write of a constant value (KSFT_FAIL), which is robust enough
for test scenarios. Stdio logging (TH_LOG) is also thread-safe in
glibc (flockfile is used internally).

If a child thread and the main thread both fail, it will still
register as a single test failure since they both set
_metadata->exit_code = KSFT_FAIL.

A kselftest wrapper for pthread_create() would indeed be a great
addition to the harness for cleaner thread management in the future!


> >       struct timespec to;
> > -     unsigned int flags = 0;
> > -
> > -     if (arg)
> > -             flags = *((unsigned int *) arg);
> > +     int res;
> >
> >       to.tv_sec = 0;
> >       to.tv_nsec = timeout_ns;
> >
> > -     if (futex_wait(futex, 0, &to, flags))
> > -             printf("waiter failed errno %d\n", errno);
> > +     res = futex_wait(futex, 0, &to, args->flags);
> > +     if (res) {
> > +             EXPECT_EQ(res, 0)
>
> I have changed it to ASSERT_EQ(res, -1) just to see what happens when a
> child thread fails, but the test still reported PASSED: 3 / 3

I believe you might have hit a logical skip in the conditional check here:

if (res) {
      ASSERT_EQ(res, -1);
  }
Since futex_wait succeeds in the normal path (returning 0), the "if
(res)" condition evaluates to false, and the block is skipped
entirely. This is why your amended assertion was never evaluated, and
the test reported PASSED.

If you place the assertion outside the conditional block (e.g.,
immediately after futex_wait) or force a failure on success (res ==
0), it will correctly trigger a SIGABRT via abort() inside the child
thread, terminating the entire test process and reporting a FAILURE in
the harness.


-- 
Best Regards,
Wake Liu

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

end of thread, other threads:[~2026-05-26  1:26 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-25  9:19 [PATCH 0/3] selftests/futex: Migrate wait functional tests to harness Wake Liu
2026-05-25  9:20 ` [PATCH 1/3] selftests/futex: Migrate futex_wait " Wake Liu
2026-05-25 18:51   ` André Almeida
2026-05-26  1:25     ` Wake Liu
2026-05-25  9:20 ` [PATCH 2/3] selftests/futex: Migrate futex_wait_private_mapped_file " Wake Liu
2026-05-25  9:20 ` [PATCH 3/3] selftests/futex: Migrate futex_wait_uninitialized_heap " Wake Liu

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.