* [PATCH v2 0/5] futex: Random fixes after the private-hash series.
@ 2025-05-17 15:14 Sebastian Andrzej Siewior
2025-05-17 15:14 ` [PATCH v2 1/5] selftests/futex: Use TAP output in futex_priv_hash Sebastian Andrzej Siewior
` (4 more replies)
0 siblings, 5 replies; 11+ messages in thread
From: Sebastian Andrzej Siewior @ 2025-05-17 15:14 UTC (permalink / raw)
To: linux-kernel
Cc: André Almeida, Darren Hart, Davidlohr Bueso, Ingo Molnar,
Juri Lelli, Peter Zijlstra, Thomas Gleixner, Valentin Schneider,
Waiman Long, Sebastian Andrzej Siewior
A few things were raised after the private-hash series has been merged.
Here are the fixes for it. Nothing serious but should be merged before
it hits ht merge window.
v1…v2: https://lore.kernel.org/all/20250516160339.1022507-1-bigeasy@linutronix.de/
- Correct the introduce compile errors in while trying to use the
FH_FLAG_IMMUTABLE in the selftest.
- Use FH_FLAG_IMMUTABLE also in perf bench futex.
Sebastian Andrzej Siewior (5):
selftests/futex: Use TAP output in futex_priv_hash
selftests/futex: Use TAP output in futex_numa_mpol
futex: Use RCU_INIT_POINTER() in futex_mm_init().
tools headers: Synchronize prctl.h ABI header
futex: Correct the kernedoc return value for futex_wait_setup().
include/linux/futex.h | 9 +-
kernel/futex/waitwake.c | 3 +-
tools/include/uapi/linux/prctl.h | 1 +
tools/perf/bench/futex.c | 4 +-
.../futex/functional/futex_numa_mpol.c | 65 ++++---
.../futex/functional/futex_priv_hash.c | 169 ++++++++----------
6 files changed, 112 insertions(+), 139 deletions(-)
--
2.49.0
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH v2 1/5] selftests/futex: Use TAP output in futex_priv_hash
2025-05-17 15:14 [PATCH v2 0/5] futex: Random fixes after the private-hash series Sebastian Andrzej Siewior
@ 2025-05-17 15:14 ` Sebastian Andrzej Siewior
2025-05-21 12:06 ` [tip: locking/futex] " tip-bot2 for Sebastian Andrzej Siewior
2025-05-17 15:14 ` [PATCH v2 2/5] selftests/futex: Use TAP output in futex_numa_mpol Sebastian Andrzej Siewior
` (3 subsequent siblings)
4 siblings, 1 reply; 11+ messages in thread
From: Sebastian Andrzej Siewior @ 2025-05-17 15:14 UTC (permalink / raw)
To: linux-kernel
Cc: André Almeida, Darren Hart, Davidlohr Bueso, Ingo Molnar,
Juri Lelli, Peter Zijlstra, Thomas Gleixner, Valentin Schneider,
Waiman Long, Sebastian Andrzej Siewior
Use TAP output for easier automated testing.
Suggested-by: André Almeida <andrealmeid@igalia.com>
Reviewed-by: André Almeida <andrealmeid@igalia.com>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
.../futex/functional/futex_priv_hash.c | 150 ++++++++----------
1 file changed, 63 insertions(+), 87 deletions(-)
diff --git a/tools/testing/selftests/futex/functional/futex_priv_hash.c b/tools/testing/selftests/futex/functional/futex_priv_hash.c
index 4d37650baa192..72a621d9313f3 100644
--- a/tools/testing/selftests/futex/functional/futex_priv_hash.c
+++ b/tools/testing/selftests/futex/functional/futex_priv_hash.c
@@ -51,15 +51,16 @@ static void futex_hash_slots_set_verify(int slots)
ret = futex_hash_slots_set(slots, 0);
if (ret != 0) {
- error("Failed to set slots to %d\n", errno, slots);
- exit(1);
+ ksft_test_result_fail("Failed to set slots to %d: %m\n", slots);
+ ksft_finished();
}
ret = futex_hash_slots_get();
if (ret != slots) {
- error("Set %d slots but PR_FUTEX_HASH_GET_SLOTS returns: %d\n",
- errno, slots, ret);
- exit(1);
+ ksft_test_result_fail("Set %d slots but PR_FUTEX_HASH_GET_SLOTS returns: %d, %m\n",
+ slots, ret);
+ ksft_finished();
}
+ ksft_test_result_pass("SET and GET slots %d passed\n", slots);
}
static void futex_hash_slots_set_must_fail(int slots, int immutable)
@@ -67,12 +68,8 @@ static void futex_hash_slots_set_must_fail(int slots, int immutable)
int ret;
ret = futex_hash_slots_set(slots, immutable);
- if (ret < 0)
- return;
-
- fail("futex_hash_slots_set(%d, %d) expected to fail but succeeded.\n",
- slots, immutable);
- exit(1);
+ ksft_test_result(ret < 0, "futex_hash_slots_set(%d, %d)\n",
+ slots, immutable);
}
static void *thread_return_fn(void *arg)
@@ -97,10 +94,8 @@ static void create_max_threads(void *(*thread_fn)(void *))
for (i = 0; i < MAX_THREADS; i++) {
ret = pthread_create(&threads[i], NULL, thread_fn, NULL);
- if (ret) {
- error("pthread_create failed\n", errno);
- exit(1);
- }
+ if (ret)
+ ksft_exit_fail_msg("pthread_create failed: %m\n");
}
}
@@ -110,10 +105,8 @@ static void join_max_threads(void)
for (i = 0; i < MAX_THREADS; i++) {
ret = pthread_join(threads[i], NULL);
- if (ret) {
- error("pthread_join failed for thread %d\n", errno, i);
- exit(1);
- }
+ if (ret)
+ ksft_exit_fail_msg("pthread_join failed for thread %d\n", i);
}
}
@@ -127,6 +120,9 @@ static void usage(char *prog)
VQUIET, VCRITICAL, VINFO);
}
+static const char *test_msg_auto_create = "Automatic hash bucket init on thread creation.\n";
+static const char *test_msg_auto_inc = "Automatic increase with more than 16 CPUs\n";
+
int main(int argc, char *argv[])
{
int futex_slots1, futex_slotsn, online_cpus;
@@ -156,56 +152,50 @@ int main(int argc, char *argv[])
}
}
+ ksft_print_header();
+ ksft_set_plan(22);
ret = pthread_mutexattr_init(&mutex_attr_pi);
ret |= pthread_mutexattr_setprotocol(&mutex_attr_pi, PTHREAD_PRIO_INHERIT);
ret |= pthread_mutex_init(&global_lock, &mutex_attr_pi);
if (ret != 0) {
- fail("Failed to initialize pthread mutex.\n");
- return 1;
+ ksft_exit_fail_msg("Failed to initialize pthread mutex.\n");
}
-
/* First thread, expect to be 0, not yet initialized */
ret = futex_hash_slots_get();
- if (ret != 0) {
- error("futex_hash_slots_get() failed: %d\n", errno, ret);
- return 1;
- }
- ret = futex_hash_immutable_get();
- if (ret != 0) {
- error("futex_hash_immutable_get() failed: %d\n", errno, ret);
- return 1;
- }
+ if (ret != 0)
+ ksft_exit_fail_msg("futex_hash_slots_get() failed: %d, %m\n", ret);
+ ret = futex_hash_immutable_get();
+ if (ret != 0)
+ ksft_exit_fail_msg("futex_hash_immutable_get() failed: %d, %m\n", ret);
+
+ ksft_test_result_pass("Basic get slots and immutable status.\n");
ret = pthread_create(&threads[0], NULL, thread_return_fn, NULL);
- if (ret != 0) {
- error("pthread_create() failed: %d\n", errno, ret);
- return 1;
- }
+ if (ret != 0)
+ ksft_exit_fail_msg("pthread_create() failed: %d, %m\n", ret);
+
ret = pthread_join(threads[0], NULL);
- if (ret != 0) {
- error("pthread_join() failed: %d\n", errno, ret);
- return 1;
- }
+ if (ret != 0)
+ ksft_exit_fail_msg("pthread_join() failed: %d, %m\n", ret);
+
/* First thread, has to initialiaze private hash */
futex_slots1 = futex_hash_slots_get();
if (futex_slots1 <= 0) {
- fail("Expected > 0 hash buckets, got: %d\n", futex_slots1);
- return 1;
+ ksft_print_msg("Current hash buckets: %d\n", futex_slots1);
+ ksft_exit_fail_msg(test_msg_auto_create);
}
+ ksft_test_result_pass(test_msg_auto_create);
+
online_cpus = sysconf(_SC_NPROCESSORS_ONLN);
ret = pthread_barrier_init(&barrier_main, NULL, MAX_THREADS + 1);
- if (ret != 0) {
- error("pthread_barrier_init failed.\n", errno);
- return 1;
- }
+ if (ret != 0)
+ ksft_exit_fail_msg("pthread_barrier_init failed: %m.\n");
ret = pthread_mutex_lock(&global_lock);
- if (ret != 0) {
- error("pthread_mutex_lock failed.\n", errno);
- return 1;
- }
+ if (ret != 0)
+ ksft_exit_fail_msg("pthread_mutex_lock failed: %m.\n");
counter = 0;
create_max_threads(thread_lock_fn);
@@ -215,14 +205,17 @@ int main(int argc, char *argv[])
* The current default size of hash buckets is 16. The auto increase
* works only if more than 16 CPUs are available.
*/
+ ksft_print_msg("Online CPUs: %d\n", online_cpus);
if (online_cpus > 16) {
futex_slotsn = futex_hash_slots_get();
if (futex_slotsn < 0 || futex_slots1 == futex_slotsn) {
- fail("Expected increase of hash buckets but got: %d -> %d\n",
- futex_slots1, futex_slotsn);
- info("Online CPUs: %d\n", online_cpus);
- return 1;
+ ksft_print_msg("Expected increase of hash buckets but got: %d -> %d\n",
+ futex_slots1, futex_slotsn);
+ ksft_exit_fail_msg(test_msg_auto_inc);
}
+ ksft_test_result_pass(test_msg_auto_inc);
+ } else {
+ ksft_test_result_skip(test_msg_auto_inc);
}
ret = pthread_mutex_unlock(&global_lock);
@@ -234,17 +227,12 @@ int main(int argc, char *argv[])
futex_hash_slots_set_verify(16);
ret = futex_hash_slots_set(15, 0);
- if (ret >= 0) {
- fail("Expected to fail with 15 slots but succeeded: %d.\n", ret);
- return 1;
- }
+ ksft_test_result(ret < 0, "Use 15 slots\n");
+
futex_hash_slots_set_verify(2);
join_max_threads();
- if (counter != MAX_THREADS) {
- fail("Expected thread counter at %d but is %d\n",
- MAX_THREADS, counter);
- return 1;
- }
+ ksft_test_result(counter == MAX_THREADS, "Created of waited for %d of %d threads\n",
+ counter, MAX_THREADS);
counter = 0;
/* Once the user set something, auto reisze must be disabled */
ret = pthread_barrier_init(&barrier_main, NULL, MAX_THREADS);
@@ -253,10 +241,8 @@ int main(int argc, char *argv[])
join_max_threads();
ret = futex_hash_slots_get();
- if (ret != 2) {
- printf("Expected 2 slots, no auto-resize, got %d\n", ret);
- return 1;
- }
+ ksft_test_result(ret == 2, "No more auto-resize after manaul setting, got %d\n",
+ ret);
futex_hash_slots_set_must_fail(1 << 29, 0);
@@ -266,17 +252,13 @@ int main(int argc, char *argv[])
*/
if (use_global_hash) {
ret = futex_hash_slots_set(0, 0);
- if (ret != 0) {
- printf("Can't request global hash: %m\n");
- return 1;
- }
+ ksft_test_result(ret == 0, "Global hash request\n");
} else {
ret = futex_hash_slots_set(4, 1);
- if (ret != 0) {
- printf("Immutable resize to 4 failed: %m\n");
- return 1;
- }
+ ksft_test_result(ret == 0, "Immutable resize to 4\n");
}
+ if (ret != 0)
+ goto out;
futex_hash_slots_set_must_fail(4, 0);
futex_hash_slots_set_must_fail(4, 1);
@@ -287,7 +269,7 @@ int main(int argc, char *argv[])
ret = pthread_barrier_init(&barrier_main, NULL, MAX_THREADS);
if (ret != 0) {
- error("pthread_barrier_init failed.\n", errno);
+ ksft_exit_fail_msg("pthread_barrier_init failed: %m\n");
return 1;
}
create_max_threads(thread_lock_fn);
@@ -295,21 +277,15 @@ int main(int argc, char *argv[])
ret = futex_hash_slots_get();
if (use_global_hash) {
- if (ret != 0) {
- error("Expected global hash, got %d\n", errno, ret);
- return 1;
- }
+ ksft_test_result(ret == 0, "Continue to use global hash\n");
} else {
- if (ret != 4) {
- error("Expected 4 slots, no auto-resize, got %d\n", errno, ret);
- return 1;
- }
+ ksft_test_result(ret == 4, "Continue to use the 4 hash buckets\n");
}
ret = futex_hash_immutable_get();
- if (ret != 1) {
- fail("Expected immutable private hash, got %d\n", ret);
- return 1;
- }
+ ksft_test_result(ret == 1, "Hash reports to be immutable\n");
+
+out:
+ ksft_finished();
return 0;
}
--
2.49.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v2 2/5] selftests/futex: Use TAP output in futex_numa_mpol
2025-05-17 15:14 [PATCH v2 0/5] futex: Random fixes after the private-hash series Sebastian Andrzej Siewior
2025-05-17 15:14 ` [PATCH v2 1/5] selftests/futex: Use TAP output in futex_priv_hash Sebastian Andrzej Siewior
@ 2025-05-17 15:14 ` Sebastian Andrzej Siewior
2025-05-21 12:06 ` [tip: locking/futex] " tip-bot2 for Sebastian Andrzej Siewior
2025-05-17 15:14 ` [PATCH v2 3/5] futex: Use RCU_INIT_POINTER() in futex_mm_init() Sebastian Andrzej Siewior
` (2 subsequent siblings)
4 siblings, 1 reply; 11+ messages in thread
From: Sebastian Andrzej Siewior @ 2025-05-17 15:14 UTC (permalink / raw)
To: linux-kernel
Cc: André Almeida, Darren Hart, Davidlohr Bueso, Ingo Molnar,
Juri Lelli, Peter Zijlstra, Thomas Gleixner, Valentin Schneider,
Waiman Long, Sebastian Andrzej Siewior
Use TAP output for easier automated testing.
Suggested-by: André Almeida <andrealmeid@igalia.com>
Reviewed-by: André Almeida <andrealmeid@igalia.com>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
.../futex/functional/futex_numa_mpol.c | 65 +++++++++----------
1 file changed, 32 insertions(+), 33 deletions(-)
diff --git a/tools/testing/selftests/futex/functional/futex_numa_mpol.c b/tools/testing/selftests/futex/functional/futex_numa_mpol.c
index dd70532f293ec..d18949ea915aa 100644
--- a/tools/testing/selftests/futex/functional/futex_numa_mpol.c
+++ b/tools/testing/selftests/futex/functional/futex_numa_mpol.c
@@ -61,10 +61,8 @@ static void create_max_threads(void *futex_ptr)
thread_args[i].flags = FUTEX2_SIZE_U32 | FUTEX_PRIVATE_FLAG | FUTEX2_NUMA;
thread_args[i].result = 0;
ret = pthread_create(&threads[i], NULL, thread_lock_fn, &thread_args[i]);
- if (ret) {
- error("pthread_create failed\n", errno);
- exit(1);
- }
+ if (ret)
+ ksft_exit_fail_msg("pthread_create failed\n");
}
}
@@ -74,10 +72,8 @@ static void join_max_threads(void)
for (i = 0; i < MAX_THREADS; i++) {
ret = pthread_join(threads[i], NULL);
- if (ret) {
- error("pthread_join failed for thread %d\n", errno, i);
- exit(1);
- }
+ if (ret)
+ ksft_exit_fail_msg("pthread_join failed for thread %d\n", i);
}
}
@@ -95,12 +91,12 @@ static void __test_futex(void *futex_ptr, int must_fail, unsigned int futex_flag
if (must_fail) {
if (ret < 0)
break;
- fail("Should fail, but didn't\n");
- exit(1);
+ ksft_exit_fail_msg("futex2_wake(%d, 0x%x) should fail, but didn't\n",
+ to_wake, futex_flags);
}
if (ret < 0) {
- error("Failed futex2_wake(%d)\n", errno, to_wake);
- exit(1);
+ ksft_exit_fail_msg("Failed futex2_wake(%d, 0x%x): %m\n",
+ to_wake, futex_flags);
}
if (!ret)
usleep(50);
@@ -111,16 +107,17 @@ static void __test_futex(void *futex_ptr, int must_fail, unsigned int futex_flag
for (i = 0; i < MAX_THREADS; i++) {
if (must_fail && thread_args[i].result != -1) {
- fail("Thread %d should fail but succeeded (%d)\n", i, thread_args[i].result);
+ ksft_print_msg("Thread %d should fail but succeeded (%d)\n",
+ i, thread_args[i].result);
need_exit = 1;
}
if (!must_fail && thread_args[i].result != 0) {
- fail("Thread %d failed (%d)\n", i, thread_args[i].result);
+ ksft_print_msg("Thread %d failed (%d)\n", i, thread_args[i].result);
need_exit = 1;
}
}
if (need_exit)
- exit(1);
+ ksft_exit_fail_msg("Aborting due to earlier errors.\n");
}
static void test_futex(void *futex_ptr, int must_fail)
@@ -167,41 +164,41 @@ int main(int argc, char *argv[])
}
}
+ ksft_print_header();
+ ksft_set_plan(1);
+
mem_size = sysconf(_SC_PAGE_SIZE);
futex_ptr = mmap(NULL, mem_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
- if (futex_ptr == MAP_FAILED) {
- error("mmap() for %d bytes failed\n", errno, mem_size);
- return 1;
- }
+ if (futex_ptr == MAP_FAILED)
+ ksft_exit_fail_msg("mmap() for %d bytes failed\n", mem_size);
+
futex_numa = futex_ptr;
- info("Regular test\n");
+ ksft_print_msg("Regular test\n");
futex_numa->futex = 0;
futex_numa->numa = FUTEX_NO_NODE;
test_futex(futex_ptr, 0);
- if (futex_numa->numa == FUTEX_NO_NODE) {
- fail("NUMA node is left unitiliazed\n");
- return 1;
- }
+ if (futex_numa->numa == FUTEX_NO_NODE)
+ ksft_exit_fail_msg("NUMA node is left unitiliazed\n");
- info("Memory too small\n");
+ ksft_print_msg("Memory too small\n");
test_futex(futex_ptr + mem_size - 4, 1);
- info("Memory out of range\n");
+ ksft_print_msg("Memory out of range\n");
test_futex(futex_ptr + mem_size, 1);
futex_numa->numa = FUTEX_NO_NODE;
mprotect(futex_ptr, mem_size, PROT_READ);
- info("Memory, RO\n");
+ ksft_print_msg("Memory, RO\n");
test_futex(futex_ptr, 1);
mprotect(futex_ptr, mem_size, PROT_NONE);
- info("Memory, no access\n");
+ ksft_print_msg("Memory, no access\n");
test_futex(futex_ptr, 1);
mprotect(futex_ptr, mem_size, PROT_READ | PROT_WRITE);
- info("Memory back to RW\n");
+ ksft_print_msg("Memory back to RW\n");
test_futex(futex_ptr, 0);
/* MPOL test. Does not work as expected */
@@ -213,20 +210,22 @@ int main(int argc, char *argv[])
ret = mbind(futex_ptr, mem_size, MPOL_BIND, &nodemask,
sizeof(nodemask) * 8, 0);
if (ret == 0) {
- info("Node %d test\n", i);
+ ksft_print_msg("Node %d test\n", i);
futex_numa->futex = 0;
futex_numa->numa = FUTEX_NO_NODE;
ret = futex2_wake(futex_ptr, 0, FUTEX2_SIZE_U32 | FUTEX_PRIVATE_FLAG | FUTEX2_NUMA | FUTEX2_MPOL);
if (ret < 0)
- error("Failed to wake 0 with MPOL.\n", errno);
+ ksft_test_result_fail("Failed to wake 0 with MPOL: %m\n");
if (0)
test_futex_mpol(futex_numa, 0);
if (futex_numa->numa != i) {
- fail("Returned NUMA node is %d expected %d\n",
- futex_numa->numa, i);
+ ksft_test_result_fail("Returned NUMA node is %d expected %d\n",
+ futex_numa->numa, i);
}
}
}
+ ksft_test_result_pass("NUMA MPOL tests passed\n");
+ ksft_finished();
return 0;
}
--
2.49.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v2 3/5] futex: Use RCU_INIT_POINTER() in futex_mm_init().
2025-05-17 15:14 [PATCH v2 0/5] futex: Random fixes after the private-hash series Sebastian Andrzej Siewior
2025-05-17 15:14 ` [PATCH v2 1/5] selftests/futex: Use TAP output in futex_priv_hash Sebastian Andrzej Siewior
2025-05-17 15:14 ` [PATCH v2 2/5] selftests/futex: Use TAP output in futex_numa_mpol Sebastian Andrzej Siewior
@ 2025-05-17 15:14 ` Sebastian Andrzej Siewior
2025-05-21 12:06 ` [tip: locking/futex] " tip-bot2 for Sebastian Andrzej Siewior
2025-05-17 15:14 ` [PATCH v2 4/5] tools headers: Synchronize prctl.h ABI header Sebastian Andrzej Siewior
2025-05-17 15:14 ` [PATCH v2 5/5] futex: Correct the kernedoc return value for futex_wait_setup() Sebastian Andrzej Siewior
4 siblings, 1 reply; 11+ messages in thread
From: Sebastian Andrzej Siewior @ 2025-05-17 15:14 UTC (permalink / raw)
To: linux-kernel
Cc: André Almeida, Darren Hart, Davidlohr Bueso, Ingo Molnar,
Juri Lelli, Peter Zijlstra, Thomas Gleixner, Valentin Schneider,
Waiman Long, Sebastian Andrzej Siewior
There is no need for an explicit NULL pointer initialisation plus a
comment why it is okay. RCU_INIT_POINTER() can be used for NULL
initialisations and it is documented.
This has been build tested with gcc version 9.3.0 (Debian 9.3.0-22) on a
x86-64 defconfig.
Fixes: 094ac8cff7858 ("futex: Relax the rcu_assign_pointer() assignment of mm->futex_phash in futex_mm_init()")
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
include/linux/futex.h | 9 +--------
1 file changed, 1 insertion(+), 8 deletions(-)
diff --git a/include/linux/futex.h b/include/linux/futex.h
index 168ffd5996b48..005b040c4791b 100644
--- a/include/linux/futex.h
+++ b/include/linux/futex.h
@@ -88,14 +88,7 @@ void futex_hash_free(struct mm_struct *mm);
static inline void futex_mm_init(struct mm_struct *mm)
{
- /*
- * No need for rcu_assign_pointer() here, as we can rely on
- * tasklist_lock write-ordering in copy_process(), before
- * the task's MM becomes visible and the ->futex_phash
- * becomes externally observable:
- */
- mm->futex_phash = NULL;
-
+ RCU_INIT_POINTER(mm->futex_phash, NULL);
mutex_init(&mm->futex_hash_lock);
}
--
2.49.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v2 4/5] tools headers: Synchronize prctl.h ABI header
2025-05-17 15:14 [PATCH v2 0/5] futex: Random fixes after the private-hash series Sebastian Andrzej Siewior
` (2 preceding siblings ...)
2025-05-17 15:14 ` [PATCH v2 3/5] futex: Use RCU_INIT_POINTER() in futex_mm_init() Sebastian Andrzej Siewior
@ 2025-05-17 15:14 ` Sebastian Andrzej Siewior
2025-05-21 12:06 ` [tip: locking/futex] " tip-bot2 for Sebastian Andrzej Siewior
2025-05-17 15:14 ` [PATCH v2 5/5] futex: Correct the kernedoc return value for futex_wait_setup() Sebastian Andrzej Siewior
4 siblings, 1 reply; 11+ messages in thread
From: Sebastian Andrzej Siewior @ 2025-05-17 15:14 UTC (permalink / raw)
To: linux-kernel
Cc: André Almeida, Darren Hart, Davidlohr Bueso, Ingo Molnar,
Juri Lelli, Peter Zijlstra, Thomas Gleixner, Valentin Schneider,
Waiman Long, Sebastian Andrzej Siewior
The prctl.h ABI header was slightly updated during the development of
the interface. In particular the "immutable" parameter became a bit in
the option argument.
Synchronize prctl.h ABI header again and make use of the definition in
the testsuite and "perf bench futex".
Reviewed-by: André Almeida <andrealmeid@igalia.com>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
tools/include/uapi/linux/prctl.h | 1 +
tools/perf/bench/futex.c | 4 +++-
.../futex/functional/futex_priv_hash.c | 21 ++++++++++---------
3 files changed, 15 insertions(+), 11 deletions(-)
diff --git a/tools/include/uapi/linux/prctl.h b/tools/include/uapi/linux/prctl.h
index 21f30b3ded74b..43dec6eed559a 100644
--- a/tools/include/uapi/linux/prctl.h
+++ b/tools/include/uapi/linux/prctl.h
@@ -367,6 +367,7 @@ struct prctl_mm_map {
/* FUTEX hash management */
#define PR_FUTEX_HASH 78
# define PR_FUTEX_HASH_SET_SLOTS 1
+# define FH_FLAG_IMMUTABLE (1ULL << 0)
# define PR_FUTEX_HASH_GET_SLOTS 2
# define PR_FUTEX_HASH_GET_IMMUTABLE 3
diff --git a/tools/perf/bench/futex.c b/tools/perf/bench/futex.c
index 02ae6c52ba881..26382e4d8d4ce 100644
--- a/tools/perf/bench/futex.c
+++ b/tools/perf/bench/futex.c
@@ -9,12 +9,14 @@
void futex_set_nbuckets_param(struct bench_futex_parameters *params)
{
+ unsigned long flags;
int ret;
if (params->nbuckets < 0)
return;
- ret = prctl(PR_FUTEX_HASH, PR_FUTEX_HASH_SET_SLOTS, params->nbuckets, params->buckets_immutable);
+ flags = params->buckets_immutable ? FH_FLAG_IMMUTABLE : 0;
+ ret = prctl(PR_FUTEX_HASH, PR_FUTEX_HASH_SET_SLOTS, params->nbuckets, flags);
if (ret) {
printf("Requesting %d hash buckets failed: %d/%m\n",
params->nbuckets, ret);
diff --git a/tools/testing/selftests/futex/functional/futex_priv_hash.c b/tools/testing/selftests/futex/functional/futex_priv_hash.c
index 72a621d9313f3..2dca18fefedcd 100644
--- a/tools/testing/selftests/futex/functional/futex_priv_hash.c
+++ b/tools/testing/selftests/futex/functional/futex_priv_hash.c
@@ -26,13 +26,14 @@ static int counter;
#ifndef PR_FUTEX_HASH
#define PR_FUTEX_HASH 78
# define PR_FUTEX_HASH_SET_SLOTS 1
+# define FH_FLAG_IMMUTABLE (1ULL << 0)
# define PR_FUTEX_HASH_GET_SLOTS 2
# define PR_FUTEX_HASH_GET_IMMUTABLE 3
#endif
-static int futex_hash_slots_set(unsigned int slots, int immutable)
+static int futex_hash_slots_set(unsigned int slots, int flags)
{
- return prctl(PR_FUTEX_HASH, PR_FUTEX_HASH_SET_SLOTS, slots, immutable);
+ return prctl(PR_FUTEX_HASH, PR_FUTEX_HASH_SET_SLOTS, slots, flags);
}
static int futex_hash_slots_get(void)
@@ -63,13 +64,13 @@ static void futex_hash_slots_set_verify(int slots)
ksft_test_result_pass("SET and GET slots %d passed\n", slots);
}
-static void futex_hash_slots_set_must_fail(int slots, int immutable)
+static void futex_hash_slots_set_must_fail(int slots, int flags)
{
int ret;
- ret = futex_hash_slots_set(slots, immutable);
+ ret = futex_hash_slots_set(slots, flags);
ksft_test_result(ret < 0, "futex_hash_slots_set(%d, %d)\n",
- slots, immutable);
+ slots, flags);
}
static void *thread_return_fn(void *arg)
@@ -254,18 +255,18 @@ int main(int argc, char *argv[])
ret = futex_hash_slots_set(0, 0);
ksft_test_result(ret == 0, "Global hash request\n");
} else {
- ret = futex_hash_slots_set(4, 1);
+ ret = futex_hash_slots_set(4, FH_FLAG_IMMUTABLE);
ksft_test_result(ret == 0, "Immutable resize to 4\n");
}
if (ret != 0)
goto out;
futex_hash_slots_set_must_fail(4, 0);
- futex_hash_slots_set_must_fail(4, 1);
+ futex_hash_slots_set_must_fail(4, FH_FLAG_IMMUTABLE);
futex_hash_slots_set_must_fail(8, 0);
- futex_hash_slots_set_must_fail(8, 1);
- futex_hash_slots_set_must_fail(0, 1);
- futex_hash_slots_set_must_fail(6, 1);
+ futex_hash_slots_set_must_fail(8, FH_FLAG_IMMUTABLE);
+ futex_hash_slots_set_must_fail(0, FH_FLAG_IMMUTABLE);
+ futex_hash_slots_set_must_fail(6, FH_FLAG_IMMUTABLE);
ret = pthread_barrier_init(&barrier_main, NULL, MAX_THREADS);
if (ret != 0) {
--
2.49.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH v2 5/5] futex: Correct the kernedoc return value for futex_wait_setup().
2025-05-17 15:14 [PATCH v2 0/5] futex: Random fixes after the private-hash series Sebastian Andrzej Siewior
` (3 preceding siblings ...)
2025-05-17 15:14 ` [PATCH v2 4/5] tools headers: Synchronize prctl.h ABI header Sebastian Andrzej Siewior
@ 2025-05-17 15:14 ` Sebastian Andrzej Siewior
2025-05-21 12:06 ` [tip: locking/futex] " tip-bot2 for Sebastian Andrzej Siewior
4 siblings, 1 reply; 11+ messages in thread
From: Sebastian Andrzej Siewior @ 2025-05-17 15:14 UTC (permalink / raw)
To: linux-kernel
Cc: André Almeida, Darren Hart, Davidlohr Bueso, Ingo Molnar,
Juri Lelli, Peter Zijlstra, Thomas Gleixner, Valentin Schneider,
Waiman Long, Sebastian Andrzej Siewior
The kerneldoc for futex_wait_setup() states it can return "0" or "<1".
This isn't true because the error case is "<0" not less than 1.
Document that <0 is returned on error. Drop the possible return values
and state possible reasons.
Reviewed-by: André Almeida <andrealmeid@igalia.com>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
kernel/futex/waitwake.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/kernel/futex/waitwake.c b/kernel/futex/waitwake.c
index b3738fbe83c62..e2bbe5509ec27 100644
--- a/kernel/futex/waitwake.c
+++ b/kernel/futex/waitwake.c
@@ -585,7 +585,8 @@ int futex_wait_multiple(struct futex_vector *vs, unsigned int count,
*
* Return:
* - 0 - uaddr contains val and hb has been locked;
- * - <1 - -EFAULT or -EWOULDBLOCK (uaddr does not contain val) and hb is unlocked
+ * - <0 - On error and the hb is unlocked. A possible reason: the uaddr can not
+ * be read, does not contain the expected value or is not properly aligned.
*/
int futex_wait_setup(u32 __user *uaddr, u32 val, unsigned int flags,
struct futex_q *q, union futex_key *key2,
--
2.49.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [tip: locking/futex] futex: Correct the kernedoc return value for futex_wait_setup().
2025-05-17 15:14 ` [PATCH v2 5/5] futex: Correct the kernedoc return value for futex_wait_setup() Sebastian Andrzej Siewior
@ 2025-05-21 12:06 ` tip-bot2 for Sebastian Andrzej Siewior
0 siblings, 0 replies; 11+ messages in thread
From: tip-bot2 for Sebastian Andrzej Siewior @ 2025-05-21 12:06 UTC (permalink / raw)
To: linux-tip-commits
Cc: Sebastian Andrzej Siewior, Peter Zijlstra (Intel), andrealmeid,
x86, linux-kernel
The following commit has been merged into the locking/futex branch of tip:
Commit-ID: 73c6c02b4febbb2c2761e559f31af8c7b87e81a5
Gitweb: https://git.kernel.org/tip/73c6c02b4febbb2c2761e559f31af8c7b87e81a5
Author: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
AuthorDate: Sat, 17 May 2025 17:14:55 +02:00
Committer: Peter Zijlstra <peterz@infradead.org>
CommitterDate: Wed, 21 May 2025 13:57:41 +02:00
futex: Correct the kernedoc return value for futex_wait_setup().
The kerneldoc for futex_wait_setup() states it can return "0" or "<1".
This isn't true because the error case is "<0" not less than 1.
Document that <0 is returned on error. Drop the possible return values
and state possible reasons.
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: André Almeida <andrealmeid@igalia.com>
Link: https://lore.kernel.org/r/20250517151455.1065363-6-bigeasy@linutronix.de
---
kernel/futex/waitwake.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/kernel/futex/waitwake.c b/kernel/futex/waitwake.c
index b3738fb..e2bbe55 100644
--- a/kernel/futex/waitwake.c
+++ b/kernel/futex/waitwake.c
@@ -585,7 +585,8 @@ int futex_wait_multiple(struct futex_vector *vs, unsigned int count,
*
* Return:
* - 0 - uaddr contains val and hb has been locked;
- * - <1 - -EFAULT or -EWOULDBLOCK (uaddr does not contain val) and hb is unlocked
+ * - <0 - On error and the hb is unlocked. A possible reason: the uaddr can not
+ * be read, does not contain the expected value or is not properly aligned.
*/
int futex_wait_setup(u32 __user *uaddr, u32 val, unsigned int flags,
struct futex_q *q, union futex_key *key2,
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [tip: locking/futex] tools headers: Synchronize prctl.h ABI header
2025-05-17 15:14 ` [PATCH v2 4/5] tools headers: Synchronize prctl.h ABI header Sebastian Andrzej Siewior
@ 2025-05-21 12:06 ` tip-bot2 for Sebastian Andrzej Siewior
0 siblings, 0 replies; 11+ messages in thread
From: tip-bot2 for Sebastian Andrzej Siewior @ 2025-05-21 12:06 UTC (permalink / raw)
To: linux-tip-commits
Cc: Sebastian Andrzej Siewior, Peter Zijlstra (Intel), andrealmeid,
x86, linux-kernel
The following commit has been merged into the locking/futex branch of tip:
Commit-ID: 4140e2b31bedd87bfc53362441165979aa4fc5d8
Gitweb: https://git.kernel.org/tip/4140e2b31bedd87bfc53362441165979aa4fc5d8
Author: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
AuthorDate: Sat, 17 May 2025 17:14:54 +02:00
Committer: Peter Zijlstra <peterz@infradead.org>
CommitterDate: Wed, 21 May 2025 13:57:41 +02:00
tools headers: Synchronize prctl.h ABI header
The prctl.h ABI header was slightly updated during the development of
the interface. In particular the "immutable" parameter became a bit in
the option argument.
Synchronize prctl.h ABI header again and make use of the definition in
the testsuite and "perf bench futex".
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: André Almeida <andrealmeid@igalia.com>
Link: https://lore.kernel.org/r/20250517151455.1065363-5-bigeasy@linutronix.de
---
tools/include/uapi/linux/prctl.h | 1 +-
tools/perf/bench/futex.c | 4 +-
tools/testing/selftests/futex/functional/futex_priv_hash.c | 21 +++----
3 files changed, 15 insertions(+), 11 deletions(-)
diff --git a/tools/include/uapi/linux/prctl.h b/tools/include/uapi/linux/prctl.h
index 21f30b3..43dec6e 100644
--- a/tools/include/uapi/linux/prctl.h
+++ b/tools/include/uapi/linux/prctl.h
@@ -367,6 +367,7 @@ struct prctl_mm_map {
/* FUTEX hash management */
#define PR_FUTEX_HASH 78
# define PR_FUTEX_HASH_SET_SLOTS 1
+# define FH_FLAG_IMMUTABLE (1ULL << 0)
# define PR_FUTEX_HASH_GET_SLOTS 2
# define PR_FUTEX_HASH_GET_IMMUTABLE 3
diff --git a/tools/perf/bench/futex.c b/tools/perf/bench/futex.c
index 02ae6c5..26382e4 100644
--- a/tools/perf/bench/futex.c
+++ b/tools/perf/bench/futex.c
@@ -9,12 +9,14 @@
void futex_set_nbuckets_param(struct bench_futex_parameters *params)
{
+ unsigned long flags;
int ret;
if (params->nbuckets < 0)
return;
- ret = prctl(PR_FUTEX_HASH, PR_FUTEX_HASH_SET_SLOTS, params->nbuckets, params->buckets_immutable);
+ flags = params->buckets_immutable ? FH_FLAG_IMMUTABLE : 0;
+ ret = prctl(PR_FUTEX_HASH, PR_FUTEX_HASH_SET_SLOTS, params->nbuckets, flags);
if (ret) {
printf("Requesting %d hash buckets failed: %d/%m\n",
params->nbuckets, ret);
diff --git a/tools/testing/selftests/futex/functional/futex_priv_hash.c b/tools/testing/selftests/futex/functional/futex_priv_hash.c
index 72a621d..2dca18f 100644
--- a/tools/testing/selftests/futex/functional/futex_priv_hash.c
+++ b/tools/testing/selftests/futex/functional/futex_priv_hash.c
@@ -26,13 +26,14 @@ static int counter;
#ifndef PR_FUTEX_HASH
#define PR_FUTEX_HASH 78
# define PR_FUTEX_HASH_SET_SLOTS 1
+# define FH_FLAG_IMMUTABLE (1ULL << 0)
# define PR_FUTEX_HASH_GET_SLOTS 2
# define PR_FUTEX_HASH_GET_IMMUTABLE 3
#endif
-static int futex_hash_slots_set(unsigned int slots, int immutable)
+static int futex_hash_slots_set(unsigned int slots, int flags)
{
- return prctl(PR_FUTEX_HASH, PR_FUTEX_HASH_SET_SLOTS, slots, immutable);
+ return prctl(PR_FUTEX_HASH, PR_FUTEX_HASH_SET_SLOTS, slots, flags);
}
static int futex_hash_slots_get(void)
@@ -63,13 +64,13 @@ static void futex_hash_slots_set_verify(int slots)
ksft_test_result_pass("SET and GET slots %d passed\n", slots);
}
-static void futex_hash_slots_set_must_fail(int slots, int immutable)
+static void futex_hash_slots_set_must_fail(int slots, int flags)
{
int ret;
- ret = futex_hash_slots_set(slots, immutable);
+ ret = futex_hash_slots_set(slots, flags);
ksft_test_result(ret < 0, "futex_hash_slots_set(%d, %d)\n",
- slots, immutable);
+ slots, flags);
}
static void *thread_return_fn(void *arg)
@@ -254,18 +255,18 @@ int main(int argc, char *argv[])
ret = futex_hash_slots_set(0, 0);
ksft_test_result(ret == 0, "Global hash request\n");
} else {
- ret = futex_hash_slots_set(4, 1);
+ ret = futex_hash_slots_set(4, FH_FLAG_IMMUTABLE);
ksft_test_result(ret == 0, "Immutable resize to 4\n");
}
if (ret != 0)
goto out;
futex_hash_slots_set_must_fail(4, 0);
- futex_hash_slots_set_must_fail(4, 1);
+ futex_hash_slots_set_must_fail(4, FH_FLAG_IMMUTABLE);
futex_hash_slots_set_must_fail(8, 0);
- futex_hash_slots_set_must_fail(8, 1);
- futex_hash_slots_set_must_fail(0, 1);
- futex_hash_slots_set_must_fail(6, 1);
+ futex_hash_slots_set_must_fail(8, FH_FLAG_IMMUTABLE);
+ futex_hash_slots_set_must_fail(0, FH_FLAG_IMMUTABLE);
+ futex_hash_slots_set_must_fail(6, FH_FLAG_IMMUTABLE);
ret = pthread_barrier_init(&barrier_main, NULL, MAX_THREADS);
if (ret != 0) {
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [tip: locking/futex] futex: Use RCU_INIT_POINTER() in futex_mm_init().
2025-05-17 15:14 ` [PATCH v2 3/5] futex: Use RCU_INIT_POINTER() in futex_mm_init() Sebastian Andrzej Siewior
@ 2025-05-21 12:06 ` tip-bot2 for Sebastian Andrzej Siewior
0 siblings, 0 replies; 11+ messages in thread
From: tip-bot2 for Sebastian Andrzej Siewior @ 2025-05-21 12:06 UTC (permalink / raw)
To: linux-tip-commits
Cc: Sebastian Andrzej Siewior, Peter Zijlstra (Intel), x86,
linux-kernel
The following commit has been merged into the locking/futex branch of tip:
Commit-ID: 279f2c2c8e2169403d01190f042efa6e41731578
Gitweb: https://git.kernel.org/tip/279f2c2c8e2169403d01190f042efa6e41731578
Author: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
AuthorDate: Sat, 17 May 2025 17:14:53 +02:00
Committer: Peter Zijlstra <peterz@infradead.org>
CommitterDate: Wed, 21 May 2025 13:57:41 +02:00
futex: Use RCU_INIT_POINTER() in futex_mm_init().
There is no need for an explicit NULL pointer initialisation plus a
comment why it is okay. RCU_INIT_POINTER() can be used for NULL
initialisations and it is documented.
This has been build tested with gcc version 9.3.0 (Debian 9.3.0-22) on a
x86-64 defconfig.
Fixes: 094ac8cff7858 ("futex: Relax the rcu_assign_pointer() assignment of mm->futex_phash in futex_mm_init()")
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://lore.kernel.org/r/20250517151455.1065363-4-bigeasy@linutronix.de
---
include/linux/futex.h | 9 +--------
1 file changed, 1 insertion(+), 8 deletions(-)
diff --git a/include/linux/futex.h b/include/linux/futex.h
index 168ffd5..005b040 100644
--- a/include/linux/futex.h
+++ b/include/linux/futex.h
@@ -88,14 +88,7 @@ void futex_hash_free(struct mm_struct *mm);
static inline void futex_mm_init(struct mm_struct *mm)
{
- /*
- * No need for rcu_assign_pointer() here, as we can rely on
- * tasklist_lock write-ordering in copy_process(), before
- * the task's MM becomes visible and the ->futex_phash
- * becomes externally observable:
- */
- mm->futex_phash = NULL;
-
+ RCU_INIT_POINTER(mm->futex_phash, NULL);
mutex_init(&mm->futex_hash_lock);
}
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [tip: locking/futex] selftests/futex: Use TAP output in futex_numa_mpol
2025-05-17 15:14 ` [PATCH v2 2/5] selftests/futex: Use TAP output in futex_numa_mpol Sebastian Andrzej Siewior
@ 2025-05-21 12:06 ` tip-bot2 for Sebastian Andrzej Siewior
0 siblings, 0 replies; 11+ messages in thread
From: tip-bot2 for Sebastian Andrzej Siewior @ 2025-05-21 12:06 UTC (permalink / raw)
To: linux-tip-commits
Cc: andrealmeid, Sebastian Andrzej Siewior, Peter Zijlstra (Intel),
x86, linux-kernel
The following commit has been merged into the locking/futex branch of tip:
Commit-ID: 7d4f494767918c80f2a99831728159b2aa398872
Gitweb: https://git.kernel.org/tip/7d4f494767918c80f2a99831728159b2aa398872
Author: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
AuthorDate: Sat, 17 May 2025 17:14:52 +02:00
Committer: Peter Zijlstra <peterz@infradead.org>
CommitterDate: Wed, 21 May 2025 13:57:40 +02:00
selftests/futex: Use TAP output in futex_numa_mpol
Use TAP output for easier automated testing.
Suggested-by: André Almeida <andrealmeid@igalia.com>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: André Almeida <andrealmeid@igalia.com>
Link: https://lore.kernel.org/r/20250517151455.1065363-3-bigeasy@linutronix.de
---
tools/testing/selftests/futex/functional/futex_numa_mpol.c | 65 +++----
1 file changed, 32 insertions(+), 33 deletions(-)
diff --git a/tools/testing/selftests/futex/functional/futex_numa_mpol.c b/tools/testing/selftests/futex/functional/futex_numa_mpol.c
index dd70532..d18949e 100644
--- a/tools/testing/selftests/futex/functional/futex_numa_mpol.c
+++ b/tools/testing/selftests/futex/functional/futex_numa_mpol.c
@@ -61,10 +61,8 @@ static void create_max_threads(void *futex_ptr)
thread_args[i].flags = FUTEX2_SIZE_U32 | FUTEX_PRIVATE_FLAG | FUTEX2_NUMA;
thread_args[i].result = 0;
ret = pthread_create(&threads[i], NULL, thread_lock_fn, &thread_args[i]);
- if (ret) {
- error("pthread_create failed\n", errno);
- exit(1);
- }
+ if (ret)
+ ksft_exit_fail_msg("pthread_create failed\n");
}
}
@@ -74,10 +72,8 @@ static void join_max_threads(void)
for (i = 0; i < MAX_THREADS; i++) {
ret = pthread_join(threads[i], NULL);
- if (ret) {
- error("pthread_join failed for thread %d\n", errno, i);
- exit(1);
- }
+ if (ret)
+ ksft_exit_fail_msg("pthread_join failed for thread %d\n", i);
}
}
@@ -95,12 +91,12 @@ static void __test_futex(void *futex_ptr, int must_fail, unsigned int futex_flag
if (must_fail) {
if (ret < 0)
break;
- fail("Should fail, but didn't\n");
- exit(1);
+ ksft_exit_fail_msg("futex2_wake(%d, 0x%x) should fail, but didn't\n",
+ to_wake, futex_flags);
}
if (ret < 0) {
- error("Failed futex2_wake(%d)\n", errno, to_wake);
- exit(1);
+ ksft_exit_fail_msg("Failed futex2_wake(%d, 0x%x): %m\n",
+ to_wake, futex_flags);
}
if (!ret)
usleep(50);
@@ -111,16 +107,17 @@ static void __test_futex(void *futex_ptr, int must_fail, unsigned int futex_flag
for (i = 0; i < MAX_THREADS; i++) {
if (must_fail && thread_args[i].result != -1) {
- fail("Thread %d should fail but succeeded (%d)\n", i, thread_args[i].result);
+ ksft_print_msg("Thread %d should fail but succeeded (%d)\n",
+ i, thread_args[i].result);
need_exit = 1;
}
if (!must_fail && thread_args[i].result != 0) {
- fail("Thread %d failed (%d)\n", i, thread_args[i].result);
+ ksft_print_msg("Thread %d failed (%d)\n", i, thread_args[i].result);
need_exit = 1;
}
}
if (need_exit)
- exit(1);
+ ksft_exit_fail_msg("Aborting due to earlier errors.\n");
}
static void test_futex(void *futex_ptr, int must_fail)
@@ -167,41 +164,41 @@ int main(int argc, char *argv[])
}
}
+ ksft_print_header();
+ ksft_set_plan(1);
+
mem_size = sysconf(_SC_PAGE_SIZE);
futex_ptr = mmap(NULL, mem_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
- if (futex_ptr == MAP_FAILED) {
- error("mmap() for %d bytes failed\n", errno, mem_size);
- return 1;
- }
+ if (futex_ptr == MAP_FAILED)
+ ksft_exit_fail_msg("mmap() for %d bytes failed\n", mem_size);
+
futex_numa = futex_ptr;
- info("Regular test\n");
+ ksft_print_msg("Regular test\n");
futex_numa->futex = 0;
futex_numa->numa = FUTEX_NO_NODE;
test_futex(futex_ptr, 0);
- if (futex_numa->numa == FUTEX_NO_NODE) {
- fail("NUMA node is left unitiliazed\n");
- return 1;
- }
+ if (futex_numa->numa == FUTEX_NO_NODE)
+ ksft_exit_fail_msg("NUMA node is left unitiliazed\n");
- info("Memory too small\n");
+ ksft_print_msg("Memory too small\n");
test_futex(futex_ptr + mem_size - 4, 1);
- info("Memory out of range\n");
+ ksft_print_msg("Memory out of range\n");
test_futex(futex_ptr + mem_size, 1);
futex_numa->numa = FUTEX_NO_NODE;
mprotect(futex_ptr, mem_size, PROT_READ);
- info("Memory, RO\n");
+ ksft_print_msg("Memory, RO\n");
test_futex(futex_ptr, 1);
mprotect(futex_ptr, mem_size, PROT_NONE);
- info("Memory, no access\n");
+ ksft_print_msg("Memory, no access\n");
test_futex(futex_ptr, 1);
mprotect(futex_ptr, mem_size, PROT_READ | PROT_WRITE);
- info("Memory back to RW\n");
+ ksft_print_msg("Memory back to RW\n");
test_futex(futex_ptr, 0);
/* MPOL test. Does not work as expected */
@@ -213,20 +210,22 @@ int main(int argc, char *argv[])
ret = mbind(futex_ptr, mem_size, MPOL_BIND, &nodemask,
sizeof(nodemask) * 8, 0);
if (ret == 0) {
- info("Node %d test\n", i);
+ ksft_print_msg("Node %d test\n", i);
futex_numa->futex = 0;
futex_numa->numa = FUTEX_NO_NODE;
ret = futex2_wake(futex_ptr, 0, FUTEX2_SIZE_U32 | FUTEX_PRIVATE_FLAG | FUTEX2_NUMA | FUTEX2_MPOL);
if (ret < 0)
- error("Failed to wake 0 with MPOL.\n", errno);
+ ksft_test_result_fail("Failed to wake 0 with MPOL: %m\n");
if (0)
test_futex_mpol(futex_numa, 0);
if (futex_numa->numa != i) {
- fail("Returned NUMA node is %d expected %d\n",
- futex_numa->numa, i);
+ ksft_test_result_fail("Returned NUMA node is %d expected %d\n",
+ futex_numa->numa, i);
}
}
}
+ ksft_test_result_pass("NUMA MPOL tests passed\n");
+ ksft_finished();
return 0;
}
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [tip: locking/futex] selftests/futex: Use TAP output in futex_priv_hash
2025-05-17 15:14 ` [PATCH v2 1/5] selftests/futex: Use TAP output in futex_priv_hash Sebastian Andrzej Siewior
@ 2025-05-21 12:06 ` tip-bot2 for Sebastian Andrzej Siewior
0 siblings, 0 replies; 11+ messages in thread
From: tip-bot2 for Sebastian Andrzej Siewior @ 2025-05-21 12:06 UTC (permalink / raw)
To: linux-tip-commits
Cc: andrealmeid, Sebastian Andrzej Siewior, Peter Zijlstra (Intel),
x86, linux-kernel
The following commit has been merged into the locking/futex branch of tip:
Commit-ID: 2b7363602973d1073f0e1775698fa62477a9a495
Gitweb: https://git.kernel.org/tip/2b7363602973d1073f0e1775698fa62477a9a495
Author: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
AuthorDate: Sat, 17 May 2025 17:14:51 +02:00
Committer: Peter Zijlstra <peterz@infradead.org>
CommitterDate: Wed, 21 May 2025 13:57:40 +02:00
selftests/futex: Use TAP output in futex_priv_hash
Use TAP output for easier automated testing.
Suggested-by: André Almeida <andrealmeid@igalia.com>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: André Almeida <andrealmeid@igalia.com>
Link: https://lore.kernel.org/r/20250517151455.1065363-2-bigeasy@linutronix.de
---
tools/testing/selftests/futex/functional/futex_priv_hash.c | 148 ++-----
1 file changed, 62 insertions(+), 86 deletions(-)
diff --git a/tools/testing/selftests/futex/functional/futex_priv_hash.c b/tools/testing/selftests/futex/functional/futex_priv_hash.c
index 4d37650..72a621d 100644
--- a/tools/testing/selftests/futex/functional/futex_priv_hash.c
+++ b/tools/testing/selftests/futex/functional/futex_priv_hash.c
@@ -51,15 +51,16 @@ static void futex_hash_slots_set_verify(int slots)
ret = futex_hash_slots_set(slots, 0);
if (ret != 0) {
- error("Failed to set slots to %d\n", errno, slots);
- exit(1);
+ ksft_test_result_fail("Failed to set slots to %d: %m\n", slots);
+ ksft_finished();
}
ret = futex_hash_slots_get();
if (ret != slots) {
- error("Set %d slots but PR_FUTEX_HASH_GET_SLOTS returns: %d\n",
- errno, slots, ret);
- exit(1);
+ ksft_test_result_fail("Set %d slots but PR_FUTEX_HASH_GET_SLOTS returns: %d, %m\n",
+ slots, ret);
+ ksft_finished();
}
+ ksft_test_result_pass("SET and GET slots %d passed\n", slots);
}
static void futex_hash_slots_set_must_fail(int slots, int immutable)
@@ -67,12 +68,8 @@ static void futex_hash_slots_set_must_fail(int slots, int immutable)
int ret;
ret = futex_hash_slots_set(slots, immutable);
- if (ret < 0)
- return;
-
- fail("futex_hash_slots_set(%d, %d) expected to fail but succeeded.\n",
- slots, immutable);
- exit(1);
+ ksft_test_result(ret < 0, "futex_hash_slots_set(%d, %d)\n",
+ slots, immutable);
}
static void *thread_return_fn(void *arg)
@@ -97,10 +94,8 @@ static void create_max_threads(void *(*thread_fn)(void *))
for (i = 0; i < MAX_THREADS; i++) {
ret = pthread_create(&threads[i], NULL, thread_fn, NULL);
- if (ret) {
- error("pthread_create failed\n", errno);
- exit(1);
- }
+ if (ret)
+ ksft_exit_fail_msg("pthread_create failed: %m\n");
}
}
@@ -110,10 +105,8 @@ static void join_max_threads(void)
for (i = 0; i < MAX_THREADS; i++) {
ret = pthread_join(threads[i], NULL);
- if (ret) {
- error("pthread_join failed for thread %d\n", errno, i);
- exit(1);
- }
+ if (ret)
+ ksft_exit_fail_msg("pthread_join failed for thread %d\n", i);
}
}
@@ -127,6 +120,9 @@ static void usage(char *prog)
VQUIET, VCRITICAL, VINFO);
}
+static const char *test_msg_auto_create = "Automatic hash bucket init on thread creation.\n";
+static const char *test_msg_auto_inc = "Automatic increase with more than 16 CPUs\n";
+
int main(int argc, char *argv[])
{
int futex_slots1, futex_slotsn, online_cpus;
@@ -156,56 +152,50 @@ int main(int argc, char *argv[])
}
}
+ ksft_print_header();
+ ksft_set_plan(22);
ret = pthread_mutexattr_init(&mutex_attr_pi);
ret |= pthread_mutexattr_setprotocol(&mutex_attr_pi, PTHREAD_PRIO_INHERIT);
ret |= pthread_mutex_init(&global_lock, &mutex_attr_pi);
if (ret != 0) {
- fail("Failed to initialize pthread mutex.\n");
- return 1;
+ ksft_exit_fail_msg("Failed to initialize pthread mutex.\n");
}
-
/* First thread, expect to be 0, not yet initialized */
ret = futex_hash_slots_get();
- if (ret != 0) {
- error("futex_hash_slots_get() failed: %d\n", errno, ret);
- return 1;
- }
+ if (ret != 0)
+ ksft_exit_fail_msg("futex_hash_slots_get() failed: %d, %m\n", ret);
+
ret = futex_hash_immutable_get();
- if (ret != 0) {
- error("futex_hash_immutable_get() failed: %d\n", errno, ret);
- return 1;
- }
+ if (ret != 0)
+ ksft_exit_fail_msg("futex_hash_immutable_get() failed: %d, %m\n", ret);
+ ksft_test_result_pass("Basic get slots and immutable status.\n");
ret = pthread_create(&threads[0], NULL, thread_return_fn, NULL);
- if (ret != 0) {
- error("pthread_create() failed: %d\n", errno, ret);
- return 1;
- }
+ if (ret != 0)
+ ksft_exit_fail_msg("pthread_create() failed: %d, %m\n", ret);
+
ret = pthread_join(threads[0], NULL);
- if (ret != 0) {
- error("pthread_join() failed: %d\n", errno, ret);
- return 1;
- }
+ if (ret != 0)
+ ksft_exit_fail_msg("pthread_join() failed: %d, %m\n", ret);
+
/* First thread, has to initialiaze private hash */
futex_slots1 = futex_hash_slots_get();
if (futex_slots1 <= 0) {
- fail("Expected > 0 hash buckets, got: %d\n", futex_slots1);
- return 1;
+ ksft_print_msg("Current hash buckets: %d\n", futex_slots1);
+ ksft_exit_fail_msg(test_msg_auto_create);
}
+ ksft_test_result_pass(test_msg_auto_create);
+
online_cpus = sysconf(_SC_NPROCESSORS_ONLN);
ret = pthread_barrier_init(&barrier_main, NULL, MAX_THREADS + 1);
- if (ret != 0) {
- error("pthread_barrier_init failed.\n", errno);
- return 1;
- }
+ if (ret != 0)
+ ksft_exit_fail_msg("pthread_barrier_init failed: %m.\n");
ret = pthread_mutex_lock(&global_lock);
- if (ret != 0) {
- error("pthread_mutex_lock failed.\n", errno);
- return 1;
- }
+ if (ret != 0)
+ ksft_exit_fail_msg("pthread_mutex_lock failed: %m.\n");
counter = 0;
create_max_threads(thread_lock_fn);
@@ -215,14 +205,17 @@ int main(int argc, char *argv[])
* The current default size of hash buckets is 16. The auto increase
* works only if more than 16 CPUs are available.
*/
+ ksft_print_msg("Online CPUs: %d\n", online_cpus);
if (online_cpus > 16) {
futex_slotsn = futex_hash_slots_get();
if (futex_slotsn < 0 || futex_slots1 == futex_slotsn) {
- fail("Expected increase of hash buckets but got: %d -> %d\n",
- futex_slots1, futex_slotsn);
- info("Online CPUs: %d\n", online_cpus);
- return 1;
+ ksft_print_msg("Expected increase of hash buckets but got: %d -> %d\n",
+ futex_slots1, futex_slotsn);
+ ksft_exit_fail_msg(test_msg_auto_inc);
}
+ ksft_test_result_pass(test_msg_auto_inc);
+ } else {
+ ksft_test_result_skip(test_msg_auto_inc);
}
ret = pthread_mutex_unlock(&global_lock);
@@ -234,17 +227,12 @@ int main(int argc, char *argv[])
futex_hash_slots_set_verify(16);
ret = futex_hash_slots_set(15, 0);
- if (ret >= 0) {
- fail("Expected to fail with 15 slots but succeeded: %d.\n", ret);
- return 1;
- }
+ ksft_test_result(ret < 0, "Use 15 slots\n");
+
futex_hash_slots_set_verify(2);
join_max_threads();
- if (counter != MAX_THREADS) {
- fail("Expected thread counter at %d but is %d\n",
- MAX_THREADS, counter);
- return 1;
- }
+ ksft_test_result(counter == MAX_THREADS, "Created of waited for %d of %d threads\n",
+ counter, MAX_THREADS);
counter = 0;
/* Once the user set something, auto reisze must be disabled */
ret = pthread_barrier_init(&barrier_main, NULL, MAX_THREADS);
@@ -253,10 +241,8 @@ int main(int argc, char *argv[])
join_max_threads();
ret = futex_hash_slots_get();
- if (ret != 2) {
- printf("Expected 2 slots, no auto-resize, got %d\n", ret);
- return 1;
- }
+ ksft_test_result(ret == 2, "No more auto-resize after manaul setting, got %d\n",
+ ret);
futex_hash_slots_set_must_fail(1 << 29, 0);
@@ -266,17 +252,13 @@ int main(int argc, char *argv[])
*/
if (use_global_hash) {
ret = futex_hash_slots_set(0, 0);
- if (ret != 0) {
- printf("Can't request global hash: %m\n");
- return 1;
- }
+ ksft_test_result(ret == 0, "Global hash request\n");
} else {
ret = futex_hash_slots_set(4, 1);
- if (ret != 0) {
- printf("Immutable resize to 4 failed: %m\n");
- return 1;
- }
+ ksft_test_result(ret == 0, "Immutable resize to 4\n");
}
+ if (ret != 0)
+ goto out;
futex_hash_slots_set_must_fail(4, 0);
futex_hash_slots_set_must_fail(4, 1);
@@ -287,7 +269,7 @@ int main(int argc, char *argv[])
ret = pthread_barrier_init(&barrier_main, NULL, MAX_THREADS);
if (ret != 0) {
- error("pthread_barrier_init failed.\n", errno);
+ ksft_exit_fail_msg("pthread_barrier_init failed: %m\n");
return 1;
}
create_max_threads(thread_lock_fn);
@@ -295,21 +277,15 @@ int main(int argc, char *argv[])
ret = futex_hash_slots_get();
if (use_global_hash) {
- if (ret != 0) {
- error("Expected global hash, got %d\n", errno, ret);
- return 1;
- }
+ ksft_test_result(ret == 0, "Continue to use global hash\n");
} else {
- if (ret != 4) {
- error("Expected 4 slots, no auto-resize, got %d\n", errno, ret);
- return 1;
- }
+ ksft_test_result(ret == 4, "Continue to use the 4 hash buckets\n");
}
ret = futex_hash_immutable_get();
- if (ret != 1) {
- fail("Expected immutable private hash, got %d\n", ret);
- return 1;
- }
+ ksft_test_result(ret == 1, "Hash reports to be immutable\n");
+
+out:
+ ksft_finished();
return 0;
}
^ permalink raw reply related [flat|nested] 11+ messages in thread
end of thread, other threads:[~2025-05-21 12:06 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-05-17 15:14 [PATCH v2 0/5] futex: Random fixes after the private-hash series Sebastian Andrzej Siewior
2025-05-17 15:14 ` [PATCH v2 1/5] selftests/futex: Use TAP output in futex_priv_hash Sebastian Andrzej Siewior
2025-05-21 12:06 ` [tip: locking/futex] " tip-bot2 for Sebastian Andrzej Siewior
2025-05-17 15:14 ` [PATCH v2 2/5] selftests/futex: Use TAP output in futex_numa_mpol Sebastian Andrzej Siewior
2025-05-21 12:06 ` [tip: locking/futex] " tip-bot2 for Sebastian Andrzej Siewior
2025-05-17 15:14 ` [PATCH v2 3/5] futex: Use RCU_INIT_POINTER() in futex_mm_init() Sebastian Andrzej Siewior
2025-05-21 12:06 ` [tip: locking/futex] " tip-bot2 for Sebastian Andrzej Siewior
2025-05-17 15:14 ` [PATCH v2 4/5] tools headers: Synchronize prctl.h ABI header Sebastian Andrzej Siewior
2025-05-21 12:06 ` [tip: locking/futex] " tip-bot2 for Sebastian Andrzej Siewior
2025-05-17 15:14 ` [PATCH v2 5/5] futex: Correct the kernedoc return value for futex_wait_setup() Sebastian Andrzej Siewior
2025-05-21 12:06 ` [tip: locking/futex] " tip-bot2 for Sebastian Andrzej Siewior
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).