Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'locking-futex-2025-09-29' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull futex updates from Thomas Gleixner:
"A set of updates for futexes and related selftests:

- Plug the ptrace_may_access() race against a concurrent exec() which
allows to pass the check before the target's process transition in
exec() by taking a read lock on signal->ext_update_lock.

- A large set of cleanups and enhancement to the futex selftests. The
bulk of changes is the conversion to the kselftest harness"

* tag 'locking-futex-2025-09-29' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (25 commits)
selftest/futex: Fix spelling mistake "boundarie" -> "boundary"
selftests/futex: Remove logging.h file
selftests/futex: Drop logging.h include from futex_numa
selftests/futex: Refactor futex_numa_mpol with kselftest_harness.h
selftests/futex: Refactor futex_priv_hash with kselftest_harness.h
selftests/futex: Refactor futex_waitv with kselftest_harness.h
selftests/futex: Refactor futex_requeue with kselftest_harness.h
selftests/futex: Refactor futex_wait with kselftest_harness.h
selftests/futex: Refactor futex_wait_private_mapped_file with kselftest_harness.h
selftests/futex: Refactor futex_wait_unitialized_heap with kselftest_harness.h
selftests/futex: Refactor futex_wait_wouldblock with kselftest_harness.h
selftests/futex: Refactor futex_wait_timeout with kselftest_harness.h
selftests/futex: Refactor futex_requeue_pi_signal_restart with kselftest_harness.h
selftests/futex: Refactor futex_requeue_pi_mismatched_ops with kselftest_harness.h
selftests/futex: Refactor futex_requeue_pi with kselftest_harness.h
selftests: kselftest: Create ksft_print_dbg_msg()
futex: Don't leak robust_list pointer on exec race
selftest/futex: Compile also with libnuma < 2.0.16
selftest/futex: Reintroduce "Memory out of range" numa_mpol's subtest
selftest/futex: Make the error check more precise for futex_numa_mpol
...

+576 -1091
+56 -50
kernel/futex/syscalls.c
··· 39 39 return 0; 40 40 } 41 41 42 + static inline void __user *futex_task_robust_list(struct task_struct *p, bool compat) 43 + { 44 + #ifdef CONFIG_COMPAT 45 + if (compat) 46 + return p->compat_robust_list; 47 + #endif 48 + return p->robust_list; 49 + } 50 + 51 + static void __user *futex_get_robust_list_common(int pid, bool compat) 52 + { 53 + struct task_struct *p = current; 54 + void __user *head; 55 + int ret; 56 + 57 + scoped_guard(rcu) { 58 + if (pid) { 59 + p = find_task_by_vpid(pid); 60 + if (!p) 61 + return (void __user *)ERR_PTR(-ESRCH); 62 + } 63 + get_task_struct(p); 64 + } 65 + 66 + /* 67 + * Hold exec_update_lock to serialize with concurrent exec() 68 + * so ptrace_may_access() is checked against stable credentials 69 + */ 70 + ret = down_read_killable(&p->signal->exec_update_lock); 71 + if (ret) 72 + goto err_put; 73 + 74 + ret = -EPERM; 75 + if (!ptrace_may_access(p, PTRACE_MODE_READ_REALCREDS)) 76 + goto err_unlock; 77 + 78 + head = futex_task_robust_list(p, compat); 79 + 80 + up_read(&p->signal->exec_update_lock); 81 + put_task_struct(p); 82 + 83 + return head; 84 + 85 + err_unlock: 86 + up_read(&p->signal->exec_update_lock); 87 + err_put: 88 + put_task_struct(p); 89 + return (void __user *)ERR_PTR(ret); 90 + } 91 + 42 92 /** 43 93 * sys_get_robust_list() - Get the robust-futex list head of a task 44 94 * @pid: pid of the process [zero for current task] ··· 99 49 struct robust_list_head __user * __user *, head_ptr, 100 50 size_t __user *, len_ptr) 101 51 { 102 - struct robust_list_head __user *head; 103 - unsigned long ret; 104 - struct task_struct *p; 52 + struct robust_list_head __user *head = futex_get_robust_list_common(pid, false); 105 53 106 - rcu_read_lock(); 107 - 108 - ret = -ESRCH; 109 - if (!pid) 110 - p = current; 111 - else { 112 - p = find_task_by_vpid(pid); 113 - if (!p) 114 - goto err_unlock; 115 - } 116 - 117 - ret = -EPERM; 118 - if (!ptrace_may_access(p, PTRACE_MODE_READ_REALCREDS)) 119 - goto err_unlock; 120 - 121 - head = p->robust_list; 122 - rcu_read_unlock(); 54 + if (IS_ERR(head)) 55 + return PTR_ERR(head); 123 56 124 57 if (put_user(sizeof(*head), len_ptr)) 125 58 return -EFAULT; 126 59 return put_user(head, head_ptr); 127 - 128 - err_unlock: 129 - rcu_read_unlock(); 130 - 131 - return ret; 132 60 } 133 61 134 62 long do_futex(u32 __user *uaddr, int op, u32 val, ktime_t *timeout, ··· 483 455 compat_uptr_t __user *, head_ptr, 484 456 compat_size_t __user *, len_ptr) 485 457 { 486 - struct compat_robust_list_head __user *head; 487 - unsigned long ret; 488 - struct task_struct *p; 458 + struct compat_robust_list_head __user *head = futex_get_robust_list_common(pid, true); 489 459 490 - rcu_read_lock(); 491 - 492 - ret = -ESRCH; 493 - if (!pid) 494 - p = current; 495 - else { 496 - p = find_task_by_vpid(pid); 497 - if (!p) 498 - goto err_unlock; 499 - } 500 - 501 - ret = -EPERM; 502 - if (!ptrace_may_access(p, PTRACE_MODE_READ_REALCREDS)) 503 - goto err_unlock; 504 - 505 - head = p->compat_robust_list; 506 - rcu_read_unlock(); 460 + if (IS_ERR(head)) 461 + return PTR_ERR(head); 507 462 508 463 if (put_user(sizeof(*head), len_ptr)) 509 464 return -EFAULT; 510 465 return put_user(ptr_to_compat(head), head_ptr); 511 - 512 - err_unlock: 513 - rcu_read_unlock(); 514 - 515 - return ret; 516 466 } 517 467 #endif /* CONFIG_COMPAT */ 518 468
+5 -3
tools/testing/selftests/futex/functional/Makefile
··· 1 1 # SPDX-License-Identifier: GPL-2.0 2 + PKG_CONFIG ?= pkg-config 3 + LIBNUMA_TEST = $(shell sh -c "$(PKG_CONFIG) numa --atleast-version 2.0.16 > /dev/null 2>&1 && echo SUFFICIENT || echo NO") 4 + 2 5 INCLUDES := -I../include -I../../ $(KHDR_INCLUDES) 3 - CFLAGS := $(CFLAGS) -g -O2 -Wall -pthread $(INCLUDES) $(KHDR_INCLUDES) 6 + CFLAGS := $(CFLAGS) -g -O2 -Wall -pthread -D_FILE_OFFSET_BITS=64 -D_TIME_BITS=64 $(INCLUDES) $(KHDR_INCLUDES) -DLIBNUMA_VER_$(LIBNUMA_TEST)=1 4 7 LDLIBS := -lpthread -lrt -lnuma 5 8 6 9 LOCAL_HDRS := \ 7 10 ../include/futextest.h \ 8 - ../include/atomic.h \ 9 - ../include/logging.h 11 + ../include/atomic.h 10 12 TEST_GEN_PROGS := \ 11 13 futex_wait_timeout \ 12 14 futex_wait_wouldblock \
+2 -1
tools/testing/selftests/futex/functional/futex_numa.c
··· 5 5 #include <sys/mman.h> 6 6 #include <fcntl.h> 7 7 #include <stdbool.h> 8 + #include <stdio.h> 9 + #include <stdlib.h> 8 10 #include <time.h> 9 11 #include <assert.h> 10 - #include "logging.h" 11 12 #include "futextest.h" 12 13 #include "futex2test.h" 13 14
+42 -58
tools/testing/selftests/futex/functional/futex_numa_mpol.c
··· 16 16 #include <linux/futex.h> 17 17 #include <sys/mman.h> 18 18 19 - #include "logging.h" 20 19 #include "futextest.h" 21 20 #include "futex2test.h" 21 + #include "../../kselftest_harness.h" 22 22 23 23 #define MAX_THREADS 64 24 24 ··· 77 77 } 78 78 } 79 79 80 - static void __test_futex(void *futex_ptr, int must_fail, unsigned int futex_flags) 80 + static void __test_futex(void *futex_ptr, int err_value, unsigned int futex_flags) 81 81 { 82 82 int to_wake, ret, i, need_exit = 0; 83 83 ··· 88 88 89 89 do { 90 90 ret = futex2_wake(futex_ptr, to_wake, futex_flags); 91 - if (must_fail) { 92 - if (ret < 0) 93 - break; 94 - ksft_exit_fail_msg("futex2_wake(%d, 0x%x) should fail, but didn't\n", 95 - to_wake, futex_flags); 91 + 92 + if (err_value) { 93 + if (ret >= 0) 94 + ksft_exit_fail_msg("futex2_wake(%d, 0x%x) should fail, but didn't\n", 95 + to_wake, futex_flags); 96 + 97 + if (errno != err_value) 98 + ksft_exit_fail_msg("futex2_wake(%d, 0x%x) expected error was %d, but returned %d (%s)\n", 99 + to_wake, futex_flags, err_value, errno, strerror(errno)); 100 + 101 + break; 96 102 } 97 103 if (ret < 0) { 98 104 ksft_exit_fail_msg("Failed futex2_wake(%d, 0x%x): %m\n", ··· 112 106 join_max_threads(); 113 107 114 108 for (i = 0; i < MAX_THREADS; i++) { 115 - if (must_fail && thread_args[i].result != -1) { 109 + if (err_value && thread_args[i].result != -1) { 116 110 ksft_print_msg("Thread %d should fail but succeeded (%d)\n", 117 111 i, thread_args[i].result); 118 112 need_exit = 1; 119 113 } 120 - if (!must_fail && thread_args[i].result != 0) { 114 + if (!err_value && thread_args[i].result != 0) { 121 115 ksft_print_msg("Thread %d failed (%d)\n", i, thread_args[i].result); 122 116 need_exit = 1; 123 117 } ··· 126 120 ksft_exit_fail_msg("Aborting due to earlier errors.\n"); 127 121 } 128 122 129 - static void test_futex(void *futex_ptr, int must_fail) 123 + static void test_futex(void *futex_ptr, int err_value) 130 124 { 131 - __test_futex(futex_ptr, must_fail, FUTEX2_SIZE_U32 | FUTEX_PRIVATE_FLAG | FUTEX2_NUMA); 125 + __test_futex(futex_ptr, err_value, FUTEX2_SIZE_U32 | FUTEX_PRIVATE_FLAG | FUTEX2_NUMA); 132 126 } 133 127 134 - static void test_futex_mpol(void *futex_ptr, int must_fail) 128 + static void test_futex_mpol(void *futex_ptr, int err_value) 135 129 { 136 - __test_futex(futex_ptr, must_fail, FUTEX2_SIZE_U32 | FUTEX_PRIVATE_FLAG | FUTEX2_NUMA | FUTEX2_MPOL); 130 + __test_futex(futex_ptr, err_value, FUTEX2_SIZE_U32 | FUTEX_PRIVATE_FLAG | FUTEX2_NUMA | FUTEX2_MPOL); 137 131 } 138 132 139 - static void usage(char *prog) 140 - { 141 - printf("Usage: %s\n", prog); 142 - printf(" -c Use color\n"); 143 - printf(" -h Display this help message\n"); 144 - printf(" -v L Verbosity level: %d=QUIET %d=CRITICAL %d=INFO\n", 145 - VQUIET, VCRITICAL, VINFO); 146 - } 147 - 148 - int main(int argc, char *argv[]) 133 + TEST(futex_numa_mpol) 149 134 { 150 135 struct futex32_numa *futex_numa; 151 - int mem_size, i; 152 136 void *futex_ptr; 153 - int c; 154 - 155 - while ((c = getopt(argc, argv, "chv:")) != -1) { 156 - switch (c) { 157 - case 'c': 158 - log_color(1); 159 - break; 160 - case 'h': 161 - usage(basename(argv[0])); 162 - exit(0); 163 - break; 164 - case 'v': 165 - log_verbosity(atoi(optarg)); 166 - break; 167 - default: 168 - usage(basename(argv[0])); 169 - exit(1); 170 - } 171 - } 172 - 173 - ksft_print_header(); 174 - ksft_set_plan(1); 137 + int mem_size; 175 138 176 139 mem_size = sysconf(_SC_PAGE_SIZE); 177 - futex_ptr = mmap(NULL, mem_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0); 140 + futex_ptr = mmap(NULL, mem_size * 2, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0); 178 141 if (futex_ptr == MAP_FAILED) 179 142 ksft_exit_fail_msg("mmap() for %d bytes failed\n", mem_size); 143 + 144 + /* Create an invalid memory region for the "Memory out of range" test */ 145 + mprotect(futex_ptr + mem_size, mem_size, PROT_NONE); 180 146 181 147 futex_numa = futex_ptr; 182 148 ··· 160 182 if (futex_numa->numa == FUTEX_NO_NODE) 161 183 ksft_exit_fail_msg("NUMA node is left uninitialized\n"); 162 184 163 - ksft_print_msg("Memory too small\n"); 164 - test_futex(futex_ptr + mem_size - 4, 1); 185 + /* FUTEX2_NUMA futex must be 8-byte aligned */ 186 + ksft_print_msg("Mis-aligned futex\n"); 187 + test_futex(futex_ptr + mem_size - 4, EINVAL); 165 188 166 189 ksft_print_msg("Memory out of range\n"); 167 - test_futex(futex_ptr + mem_size, 1); 190 + test_futex(futex_ptr + mem_size, EFAULT); 168 191 169 192 futex_numa->numa = FUTEX_NO_NODE; 170 193 mprotect(futex_ptr, mem_size, PROT_READ); 171 194 ksft_print_msg("Memory, RO\n"); 172 - test_futex(futex_ptr, 1); 195 + test_futex(futex_ptr, EFAULT); 173 196 174 197 mprotect(futex_ptr, mem_size, PROT_NONE); 175 198 ksft_print_msg("Memory, no access\n"); 176 - test_futex(futex_ptr, 1); 199 + test_futex(futex_ptr, EFAULT); 177 200 178 201 mprotect(futex_ptr, mem_size, PROT_READ | PROT_WRITE); 179 202 ksft_print_msg("Memory back to RW\n"); 180 203 test_futex(futex_ptr, 0); 181 204 205 + ksft_test_result_pass("futex2 memory boundary tests passed\n"); 206 + 182 207 /* MPOL test. Does not work as expected */ 183 - for (i = 0; i < 4; i++) { 208 + #ifdef LIBNUMA_VER_SUFFICIENT 209 + for (int i = 0; i < 4; i++) { 184 210 unsigned long nodemask; 185 211 int ret; 186 212 ··· 203 221 ret = futex2_wake(futex_ptr, 0, FUTEX2_SIZE_U32 | FUTEX_PRIVATE_FLAG | FUTEX2_NUMA | FUTEX2_MPOL); 204 222 if (ret < 0) 205 223 ksft_test_result_fail("Failed to wake 0 with MPOL: %m\n"); 206 - if (0) 207 - test_futex_mpol(futex_numa, 0); 208 224 if (futex_numa->numa != i) { 209 225 ksft_exit_fail_msg("Returned NUMA node is %d expected %d\n", 210 226 futex_numa->numa, i); 211 227 } 212 228 } 213 229 } 214 - ksft_test_result_pass("NUMA MPOL tests passed\n"); 215 - ksft_finished(); 216 - return 0; 230 + ksft_test_result_pass("futex2 MPOL hints test passed\n"); 231 + #else 232 + ksft_test_result_skip("futex2 MPOL hints test requires libnuma 2.0.16+\n"); 233 + #endif 234 + munmap(futex_ptr, mem_size * 2); 217 235 } 236 + 237 + TEST_HARNESS_MAIN
+16 -51
tools/testing/selftests/futex/functional/futex_priv_hash.c
··· 14 14 #include <linux/prctl.h> 15 15 #include <sys/prctl.h> 16 16 17 - #include "logging.h" 17 + #include "../../kselftest_harness.h" 18 18 19 19 #define MAX_THREADS 64 20 20 ··· 128 128 ksft_exit_fail_msg("pthread_mutex_timedlock() did not timeout: %d.\n", ret); 129 129 } 130 130 131 - static void usage(char *prog) 132 - { 133 - printf("Usage: %s\n", prog); 134 - printf(" -c Use color\n"); 135 - printf(" -g Test global hash instead intead local immutable \n"); 136 - printf(" -h Display this help message\n"); 137 - printf(" -v L Verbosity level: %d=QUIET %d=CRITICAL %d=INFO\n", 138 - VQUIET, VCRITICAL, VINFO); 139 - } 140 - 141 131 static const char *test_msg_auto_create = "Automatic hash bucket init on thread creation.\n"; 142 132 static const char *test_msg_auto_inc = "Automatic increase with more than 16 CPUs\n"; 143 133 144 - int main(int argc, char *argv[]) 134 + TEST(priv_hash) 145 135 { 146 136 int futex_slots1, futex_slotsn, online_cpus; 147 137 pthread_mutexattr_t mutex_attr_pi; 148 138 int ret, retry = 20; 149 - int c; 150 - 151 - while ((c = getopt(argc, argv, "chv:")) != -1) { 152 - switch (c) { 153 - case 'c': 154 - log_color(1); 155 - break; 156 - case 'h': 157 - usage(basename(argv[0])); 158 - exit(0); 159 - break; 160 - case 'v': 161 - log_verbosity(atoi(optarg)); 162 - break; 163 - default: 164 - usage(basename(argv[0])); 165 - exit(1); 166 - } 167 - } 168 - 169 - ksft_print_header(); 170 - ksft_set_plan(21); 171 139 172 140 ret = pthread_mutexattr_init(&mutex_attr_pi); 173 141 ret |= pthread_mutexattr_setprotocol(&mutex_attr_pi, PTHREAD_PRIO_INHERIT); ··· 157 189 if (ret != 0) 158 190 ksft_exit_fail_msg("pthread_join() failed: %d, %m\n", ret); 159 191 160 - /* First thread, has to initialiaze private hash */ 192 + /* First thread, has to initialize private hash */ 161 193 futex_slots1 = futex_hash_slots_get(); 162 194 if (futex_slots1 <= 0) { 163 195 ksft_print_msg("Current hash buckets: %d\n", futex_slots1); 164 - ksft_exit_fail_msg(test_msg_auto_create); 196 + ksft_exit_fail_msg("%s", test_msg_auto_create); 165 197 } 166 198 167 - ksft_test_result_pass(test_msg_auto_create); 199 + ksft_test_result_pass("%s", test_msg_auto_create); 168 200 169 201 online_cpus = sysconf(_SC_NPROCESSORS_ONLN); 170 202 ret = pthread_barrier_init(&barrier_main, NULL, MAX_THREADS + 1); ··· 205 237 } 206 238 ksft_print_msg("Expected increase of hash buckets but got: %d -> %d\n", 207 239 futex_slots1, futex_slotsn); 208 - ksft_exit_fail_msg(test_msg_auto_inc); 240 + ksft_exit_fail_msg("%s", test_msg_auto_inc); 209 241 } 210 - ksft_test_result_pass(test_msg_auto_inc); 242 + ksft_test_result_pass("%s", test_msg_auto_inc); 211 243 } else { 212 - ksft_test_result_skip(test_msg_auto_inc); 244 + ksft_test_result_skip("%s", test_msg_auto_inc); 213 245 } 214 246 ret = pthread_mutex_unlock(&global_lock); 215 247 ··· 225 257 226 258 futex_hash_slots_set_verify(2); 227 259 join_max_threads(); 228 - ksft_test_result(counter == MAX_THREADS, "Created of waited for %d of %d threads\n", 260 + ksft_test_result(counter == MAX_THREADS, "Created and waited for %d of %d threads\n", 229 261 counter, MAX_THREADS); 230 262 counter = 0; 231 - /* Once the user set something, auto reisze must be disabled */ 263 + /* Once the user set something, auto resize must be disabled */ 232 264 ret = pthread_barrier_init(&barrier_main, NULL, MAX_THREADS); 233 265 234 266 create_max_threads(thread_lock_fn); 235 267 join_max_threads(); 236 268 237 269 ret = futex_hash_slots_get(); 238 - ksft_test_result(ret == 2, "No more auto-resize after manaul setting, got %d\n", 270 + ksft_test_result(ret == 2, "No more auto-resize after manual setting, got %d\n", 239 271 ret); 240 272 241 273 futex_hash_slots_set_must_fail(1 << 29); ··· 248 280 ret = futex_hash_slots_set(0); 249 281 ksft_test_result(ret == 0, "Global hash request\n"); 250 282 if (ret != 0) 251 - goto out; 283 + return; 252 284 253 285 futex_hash_slots_set_must_fail(4); 254 286 futex_hash_slots_set_must_fail(8); ··· 257 289 futex_hash_slots_set_must_fail(6); 258 290 259 291 ret = pthread_barrier_init(&barrier_main, NULL, MAX_THREADS); 260 - if (ret != 0) { 292 + if (ret != 0) 261 293 ksft_exit_fail_msg("pthread_barrier_init failed: %m\n"); 262 - return 1; 263 - } 294 + 264 295 create_max_threads(thread_lock_fn); 265 296 join_max_threads(); 266 297 267 298 ret = futex_hash_slots_get(); 268 299 ksft_test_result(ret == 0, "Continue to use global hash\n"); 269 - 270 - out: 271 - ksft_finished(); 272 - return 0; 273 300 } 301 + 302 + TEST_HARNESS_MAIN
+24 -54
tools/testing/selftests/futex/functional/futex_requeue.c
··· 7 7 8 8 #include <pthread.h> 9 9 #include <limits.h> 10 - #include "logging.h" 11 - #include "futextest.h" 12 10 13 - #define TEST_NAME "futex-requeue" 11 + #include "futextest.h" 12 + #include "../../kselftest_harness.h" 13 + 14 14 #define timeout_ns 30000000 15 15 #define WAKE_WAIT_US 10000 16 16 17 17 volatile futex_t *f1; 18 - 19 - void usage(char *prog) 20 - { 21 - printf("Usage: %s\n", prog); 22 - printf(" -c Use color\n"); 23 - printf(" -h Display this help message\n"); 24 - printf(" -v L Verbosity level: %d=QUIET %d=CRITICAL %d=INFO\n", 25 - VQUIET, VCRITICAL, VINFO); 26 - } 27 18 28 19 void *waiterfn(void *arg) 29 20 { ··· 29 38 return NULL; 30 39 } 31 40 32 - int main(int argc, char *argv[]) 41 + TEST(requeue_single) 33 42 { 34 - pthread_t waiter[10]; 35 - int res, ret = RET_PASS; 36 - int c, i; 37 43 volatile futex_t _f1 = 0; 38 44 volatile futex_t f2 = 0; 45 + pthread_t waiter[10]; 46 + int res; 39 47 40 48 f1 = &_f1; 41 - 42 - while ((c = getopt(argc, argv, "cht:v:")) != -1) { 43 - switch (c) { 44 - case 'c': 45 - log_color(1); 46 - break; 47 - case 'h': 48 - usage(basename(argv[0])); 49 - exit(0); 50 - case 'v': 51 - log_verbosity(atoi(optarg)); 52 - break; 53 - default: 54 - usage(basename(argv[0])); 55 - exit(1); 56 - } 57 - } 58 - 59 - ksft_print_header(); 60 - ksft_set_plan(2); 61 - ksft_print_msg("%s: Test futex_requeue\n", 62 - basename(argv[0])); 63 49 64 50 /* 65 51 * Requeue a waiter from f1 to f2, and wake f2. 66 52 */ 67 53 if (pthread_create(&waiter[0], NULL, waiterfn, NULL)) 68 - error("pthread_create failed\n", errno); 54 + ksft_exit_fail_msg("pthread_create failed\n"); 69 55 70 56 usleep(WAKE_WAIT_US); 71 57 72 - info("Requeuing 1 futex from f1 to f2\n"); 58 + ksft_print_dbg_msg("Requeuing 1 futex from f1 to f2\n"); 73 59 res = futex_cmp_requeue(f1, 0, &f2, 0, 1, 0); 74 - if (res != 1) { 60 + if (res != 1) 75 61 ksft_test_result_fail("futex_requeue simple returned: %d %s\n", 76 62 res ? errno : res, 77 63 res ? strerror(errno) : ""); 78 - ret = RET_FAIL; 79 - } 80 64 81 - 82 - info("Waking 1 futex at f2\n"); 65 + ksft_print_dbg_msg("Waking 1 futex at f2\n"); 83 66 res = futex_wake(&f2, 1, 0); 84 67 if (res != 1) { 85 68 ksft_test_result_fail("futex_requeue simple returned: %d %s\n", 86 69 res ? errno : res, 87 70 res ? strerror(errno) : ""); 88 - ret = RET_FAIL; 89 71 } else { 90 72 ksft_test_result_pass("futex_requeue simple succeeds\n"); 91 73 } 74 + } 92 75 76 + TEST(requeue_multiple) 77 + { 78 + volatile futex_t _f1 = 0; 79 + volatile futex_t f2 = 0; 80 + pthread_t waiter[10]; 81 + int res, i; 82 + 83 + f1 = &_f1; 93 84 94 85 /* 95 86 * Create 10 waiters at f1. At futex_requeue, wake 3 and requeue 7. ··· 79 106 */ 80 107 for (i = 0; i < 10; i++) { 81 108 if (pthread_create(&waiter[i], NULL, waiterfn, NULL)) 82 - error("pthread_create failed\n", errno); 109 + ksft_exit_fail_msg("pthread_create failed\n"); 83 110 } 84 111 85 112 usleep(WAKE_WAIT_US); 86 113 87 - info("Waking 3 futexes at f1 and requeuing 7 futexes from f1 to f2\n"); 114 + ksft_print_dbg_msg("Waking 3 futexes at f1 and requeuing 7 futexes from f1 to f2\n"); 88 115 res = futex_cmp_requeue(f1, 0, &f2, 3, 7, 0); 89 116 if (res != 10) { 90 117 ksft_test_result_fail("futex_requeue many returned: %d %s\n", 91 118 res ? errno : res, 92 119 res ? strerror(errno) : ""); 93 - ret = RET_FAIL; 94 120 } 95 121 96 - info("Waking INT_MAX futexes at f2\n"); 122 + ksft_print_dbg_msg("Waking INT_MAX futexes at f2\n"); 97 123 res = futex_wake(&f2, INT_MAX, 0); 98 124 if (res != 7) { 99 125 ksft_test_result_fail("futex_requeue many returned: %d %s\n", 100 126 res ? errno : res, 101 127 res ? strerror(errno) : ""); 102 - ret = RET_FAIL; 103 128 } else { 104 129 ksft_test_result_pass("futex_requeue many succeeds\n"); 105 130 } 106 - 107 - ksft_print_cnts(); 108 - return ret; 109 131 } 132 + 133 + TEST_HARNESS_MAIN
+123 -143
tools/testing/selftests/futex/functional/futex_requeue_pi.c
··· 26 26 #include <stdlib.h> 27 27 #include <signal.h> 28 28 #include <string.h> 29 + 29 30 #include "atomic.h" 30 31 #include "futextest.h" 31 - #include "logging.h" 32 + #include "../../kselftest_harness.h" 32 33 33 - #define TEST_NAME "futex-requeue-pi" 34 34 #define MAX_WAKE_ITERS 1000 35 35 #define THREAD_MAX 10 36 36 #define SIGNAL_PERIOD_US 100 ··· 42 42 futex_t f2 = FUTEX_INITIALIZER; 43 43 futex_t wake_complete = FUTEX_INITIALIZER; 44 44 45 - /* Test option defaults */ 46 - static long timeout_ns; 47 - static int broadcast; 48 - static int owner; 49 - static int locked; 50 - 51 45 struct thread_arg { 52 46 long id; 53 47 struct timespec *timeout; ··· 50 56 }; 51 57 #define THREAD_ARG_INITIALIZER { 0, NULL, 0, 0 } 52 58 53 - void usage(char *prog) 59 + FIXTURE(args) 54 60 { 55 - printf("Usage: %s\n", prog); 56 - printf(" -b Broadcast wakeup (all waiters)\n"); 57 - printf(" -c Use color\n"); 58 - printf(" -h Display this help message\n"); 59 - printf(" -l Lock the pi futex across requeue\n"); 60 - printf(" -o Use a third party pi futex owner during requeue (cancels -l)\n"); 61 - printf(" -t N Timeout in nanoseconds (default: 0)\n"); 62 - printf(" -v L Verbosity level: %d=QUIET %d=CRITICAL %d=INFO\n", 63 - VQUIET, VCRITICAL, VINFO); 64 - } 61 + }; 62 + 63 + FIXTURE_SETUP(args) 64 + { 65 + }; 66 + 67 + FIXTURE_TEARDOWN(args) 68 + { 69 + }; 70 + 71 + FIXTURE_VARIANT(args) 72 + { 73 + long timeout_ns; 74 + bool broadcast; 75 + bool owner; 76 + bool locked; 77 + }; 78 + 79 + /* 80 + * For a given timeout value, this macro creates a test input with all the 81 + * possible combinations of valid arguments 82 + */ 83 + #define FIXTURE_VARIANT_ADD_TIMEOUT(timeout) \ 84 + \ 85 + FIXTURE_VARIANT_ADD(args, t_##timeout) \ 86 + { \ 87 + .timeout_ns = timeout, \ 88 + }; \ 89 + \ 90 + FIXTURE_VARIANT_ADD(args, t_##timeout##_broadcast) \ 91 + { \ 92 + .timeout_ns = timeout, \ 93 + .broadcast = true, \ 94 + }; \ 95 + \ 96 + FIXTURE_VARIANT_ADD(args, t_##timeout##_broadcast_locked) \ 97 + { \ 98 + .timeout_ns = timeout, \ 99 + .broadcast = true, \ 100 + .locked = true, \ 101 + }; \ 102 + \ 103 + FIXTURE_VARIANT_ADD(args, t_##timeout##_broadcast_owner) \ 104 + { \ 105 + .timeout_ns = timeout, \ 106 + .broadcast = true, \ 107 + .owner = true, \ 108 + }; \ 109 + \ 110 + FIXTURE_VARIANT_ADD(args, t_##timeout##_locked) \ 111 + { \ 112 + .timeout_ns = timeout, \ 113 + .locked = true, \ 114 + }; \ 115 + \ 116 + FIXTURE_VARIANT_ADD(args, t_##timeout##_owner) \ 117 + { \ 118 + .timeout_ns = timeout, \ 119 + .owner = true, \ 120 + }; \ 121 + 122 + FIXTURE_VARIANT_ADD_TIMEOUT(0); 123 + FIXTURE_VARIANT_ADD_TIMEOUT(5000); 124 + FIXTURE_VARIANT_ADD_TIMEOUT(500000); 125 + FIXTURE_VARIANT_ADD_TIMEOUT(2000000000); 65 126 66 127 int create_rt_thread(pthread_t *pth, void*(*func)(void *), void *arg, 67 128 int policy, int prio) ··· 130 81 131 82 ret = pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED); 132 83 if (ret) { 133 - error("pthread_attr_setinheritsched\n", ret); 84 + ksft_exit_fail_msg("pthread_attr_setinheritsched\n"); 134 85 return -1; 135 86 } 136 87 137 88 ret = pthread_attr_setschedpolicy(&attr, policy); 138 89 if (ret) { 139 - error("pthread_attr_setschedpolicy\n", ret); 90 + ksft_exit_fail_msg("pthread_attr_setschedpolicy\n"); 140 91 return -1; 141 92 } 142 93 143 94 schedp.sched_priority = prio; 144 95 ret = pthread_attr_setschedparam(&attr, &schedp); 145 96 if (ret) { 146 - error("pthread_attr_setschedparam\n", ret); 97 + ksft_exit_fail_msg("pthread_attr_setschedparam\n"); 147 98 return -1; 148 99 } 149 100 150 101 ret = pthread_create(pth, &attr, func, arg); 151 102 if (ret) { 152 - error("pthread_create\n", ret); 103 + ksft_exit_fail_msg("pthread_create\n"); 153 104 return -1; 154 105 } 155 106 return 0; ··· 161 112 struct thread_arg *args = (struct thread_arg *)arg; 162 113 futex_t old_val; 163 114 164 - info("Waiter %ld: running\n", args->id); 115 + ksft_print_dbg_msg("Waiter %ld: running\n", args->id); 165 116 /* Each thread sleeps for a different amount of time 166 117 * This is to avoid races, because we don't lock the 167 118 * external mutex here */ ··· 169 120 170 121 old_val = f1; 171 122 atomic_inc(&waiters_blocked); 172 - info("Calling futex_wait_requeue_pi: %p (%u) -> %p\n", 123 + ksft_print_dbg_msg("Calling futex_wait_requeue_pi: %p (%u) -> %p\n", 173 124 &f1, f1, &f2); 174 125 args->ret = futex_wait_requeue_pi(&f1, old_val, &f2, args->timeout, 175 126 FUTEX_PRIVATE_FLAG); 176 127 177 - info("waiter %ld woke with %d %s\n", args->id, args->ret, 128 + ksft_print_dbg_msg("waiter %ld woke with %d %s\n", args->id, args->ret, 178 129 args->ret < 0 ? strerror(errno) : ""); 179 130 atomic_inc(&waiters_woken); 180 131 if (args->ret < 0) { 181 132 if (args->timeout && errno == ETIMEDOUT) 182 133 args->ret = 0; 183 134 else { 184 - args->ret = RET_ERROR; 185 - error("futex_wait_requeue_pi\n", errno); 135 + ksft_exit_fail_msg("futex_wait_requeue_pi\n"); 186 136 } 187 137 futex_lock_pi(&f2, NULL, 0, FUTEX_PRIVATE_FLAG); 188 138 } 189 139 futex_unlock_pi(&f2, FUTEX_PRIVATE_FLAG); 190 140 191 - info("Waiter %ld: exiting with %d\n", args->id, args->ret); 141 + ksft_print_dbg_msg("Waiter %ld: exiting with %d\n", args->id, args->ret); 192 142 pthread_exit((void *)&args->ret); 193 143 } 194 144 ··· 200 152 int nr_wake = 1; 201 153 int i = 0; 202 154 203 - info("Waker: waiting for waiters to block\n"); 155 + ksft_print_dbg_msg("Waker: waiting for waiters to block\n"); 204 156 while (waiters_blocked.val < THREAD_MAX) 205 157 usleep(1000); 206 158 usleep(1000); 207 159 208 - info("Waker: Calling broadcast\n"); 160 + ksft_print_dbg_msg("Waker: Calling broadcast\n"); 209 161 if (args->lock) { 210 - info("Calling FUTEX_LOCK_PI on mutex=%x @ %p\n", f2, &f2); 162 + ksft_print_dbg_msg("Calling FUTEX_LOCK_PI on mutex=%x @ %p\n", f2, &f2); 211 163 futex_lock_pi(&f2, NULL, 0, FUTEX_PRIVATE_FLAG); 212 164 } 213 165 continue_requeue: ··· 215 167 args->ret = futex_cmp_requeue_pi(&f1, old_val, &f2, nr_wake, nr_requeue, 216 168 FUTEX_PRIVATE_FLAG); 217 169 if (args->ret < 0) { 218 - args->ret = RET_ERROR; 219 - error("FUTEX_CMP_REQUEUE_PI failed\n", errno); 170 + ksft_exit_fail_msg("FUTEX_CMP_REQUEUE_PI failed\n"); 220 171 } else if (++i < MAX_WAKE_ITERS) { 221 172 task_count += args->ret; 222 173 if (task_count < THREAD_MAX - waiters_woken.val) 223 174 goto continue_requeue; 224 175 } else { 225 - error("max broadcast iterations (%d) reached with %d/%d tasks woken or requeued\n", 226 - 0, MAX_WAKE_ITERS, task_count, THREAD_MAX); 227 - args->ret = RET_ERROR; 176 + ksft_exit_fail_msg("max broadcast iterations (%d) reached with %d/%d tasks woken or requeued\n", 177 + MAX_WAKE_ITERS, task_count, THREAD_MAX); 228 178 } 229 179 230 180 futex_wake(&wake_complete, 1, FUTEX_PRIVATE_FLAG); ··· 233 187 if (args->ret > 0) 234 188 args->ret = task_count; 235 189 236 - info("Waker: exiting with %d\n", args->ret); 190 + ksft_print_dbg_msg("Waker: exiting with %d\n", args->ret); 237 191 pthread_exit((void *)&args->ret); 238 192 } 239 193 ··· 246 200 int nr_wake = 1; 247 201 int i = 0; 248 202 249 - info("Waker: waiting for waiters to block\n"); 203 + ksft_print_dbg_msg("Waker: waiting for waiters to block\n"); 250 204 while (waiters_blocked.val < THREAD_MAX) 251 205 usleep(1000); 252 206 usleep(1000); 253 207 254 208 while (task_count < THREAD_MAX && waiters_woken.val < THREAD_MAX) { 255 - info("task_count: %d, waiters_woken: %d\n", 209 + ksft_print_dbg_msg("task_count: %d, waiters_woken: %d\n", 256 210 task_count, waiters_woken.val); 257 211 if (args->lock) { 258 - info("Calling FUTEX_LOCK_PI on mutex=%x @ %p\n", 259 - f2, &f2); 212 + ksft_print_dbg_msg("Calling FUTEX_LOCK_PI on mutex=%x @ %p\n", 213 + f2, &f2); 260 214 futex_lock_pi(&f2, NULL, 0, FUTEX_PRIVATE_FLAG); 261 215 } 262 - info("Waker: Calling signal\n"); 216 + ksft_print_dbg_msg("Waker: Calling signal\n"); 263 217 /* cond_signal */ 264 218 old_val = f1; 265 219 args->ret = futex_cmp_requeue_pi(&f1, old_val, &f2, ··· 267 221 FUTEX_PRIVATE_FLAG); 268 222 if (args->ret < 0) 269 223 args->ret = -errno; 270 - info("futex: %x\n", f2); 224 + ksft_print_dbg_msg("futex: %x\n", f2); 271 225 if (args->lock) { 272 - info("Calling FUTEX_UNLOCK_PI on mutex=%x @ %p\n", 273 - f2, &f2); 226 + ksft_print_dbg_msg("Calling FUTEX_UNLOCK_PI on mutex=%x @ %p\n", 227 + f2, &f2); 274 228 futex_unlock_pi(&f2, FUTEX_PRIVATE_FLAG); 275 229 } 276 - info("futex: %x\n", f2); 277 - if (args->ret < 0) { 278 - error("FUTEX_CMP_REQUEUE_PI failed\n", errno); 279 - args->ret = RET_ERROR; 280 - break; 281 - } 230 + ksft_print_dbg_msg("futex: %x\n", f2); 231 + if (args->ret < 0) 232 + ksft_exit_fail_msg("FUTEX_CMP_REQUEUE_PI failed\n"); 282 233 283 234 task_count += args->ret; 284 235 usleep(SIGNAL_PERIOD_US); 285 236 i++; 286 237 /* we have to loop at least THREAD_MAX times */ 287 238 if (i > MAX_WAKE_ITERS + THREAD_MAX) { 288 - error("max signaling iterations (%d) reached, giving up on pending waiters.\n", 289 - 0, MAX_WAKE_ITERS + THREAD_MAX); 290 - args->ret = RET_ERROR; 291 - break; 239 + ksft_exit_fail_msg("max signaling iterations (%d) reached, giving up on pending waiters.\n", 240 + MAX_WAKE_ITERS + THREAD_MAX); 292 241 } 293 242 } 294 243 ··· 292 251 if (args->ret >= 0) 293 252 args->ret = task_count; 294 253 295 - info("Waker: exiting with %d\n", args->ret); 296 - info("Waker: waiters_woken: %d\n", waiters_woken.val); 254 + ksft_print_dbg_msg("Waker: exiting with %d\n", args->ret); 255 + ksft_print_dbg_msg("Waker: waiters_woken: %d\n", waiters_woken.val); 297 256 pthread_exit((void *)&args->ret); 298 257 } 299 258 ··· 310 269 ret2 = futex_unlock_pi(&f2, FUTEX_PRIVATE_FLAG); 311 270 312 271 out: 313 - if (args->ret || ret2) { 314 - error("third_party_blocker() futex error", 0); 315 - args->ret = RET_ERROR; 316 - } 272 + if (args->ret || ret2) 273 + ksft_exit_fail_msg("third_party_blocker() futex error"); 317 274 318 275 pthread_exit((void *)&args->ret); 319 276 } 320 277 321 - int unit_test(int broadcast, long lock, int third_party_owner, long timeout_ns) 278 + TEST_F(args, futex_requeue_pi) 322 279 { 323 - void *(*wakerfn)(void *) = signal_wakerfn; 324 280 struct thread_arg blocker_arg = THREAD_ARG_INITIALIZER; 325 281 struct thread_arg waker_arg = THREAD_ARG_INITIALIZER; 326 282 pthread_t waiter[THREAD_MAX], waker, blocker; 327 - struct timespec ts, *tsp = NULL; 283 + void *(*wakerfn)(void *) = signal_wakerfn; 284 + bool third_party_owner = variant->owner; 285 + long timeout_ns = variant->timeout_ns; 286 + bool broadcast = variant->broadcast; 328 287 struct thread_arg args[THREAD_MAX]; 329 - int *waiter_ret; 330 - int i, ret = RET_PASS; 288 + struct timespec ts, *tsp = NULL; 289 + bool lock = variant->locked; 290 + int *waiter_ret, i, ret = 0; 291 + 292 + ksft_print_msg( 293 + "\tArguments: broadcast=%d locked=%d owner=%d timeout=%ldns\n", 294 + broadcast, lock, third_party_owner, timeout_ns); 331 295 332 296 if (timeout_ns) { 333 297 time_t secs; 334 298 335 - info("timeout_ns = %ld\n", timeout_ns); 299 + ksft_print_dbg_msg("timeout_ns = %ld\n", timeout_ns); 336 300 ret = clock_gettime(CLOCK_MONOTONIC, &ts); 337 301 secs = (ts.tv_nsec + timeout_ns) / 1000000000; 338 302 ts.tv_nsec = ((int64_t)ts.tv_nsec + timeout_ns) % 1000000000; 339 303 ts.tv_sec += secs; 340 - info("ts.tv_sec = %ld\n", ts.tv_sec); 341 - info("ts.tv_nsec = %ld\n", ts.tv_nsec); 304 + ksft_print_dbg_msg("ts.tv_sec = %ld\n", ts.tv_sec); 305 + ksft_print_dbg_msg("ts.tv_nsec = %ld\n", ts.tv_nsec); 342 306 tsp = &ts; 343 307 } 344 308 ··· 353 307 if (third_party_owner) { 354 308 if (create_rt_thread(&blocker, third_party_blocker, 355 309 (void *)&blocker_arg, SCHED_FIFO, 1)) { 356 - error("Creating third party blocker thread failed\n", 357 - errno); 358 - ret = RET_ERROR; 359 - goto out; 310 + ksft_exit_fail_msg("Creating third party blocker thread failed\n"); 360 311 } 361 312 } 362 313 ··· 361 318 for (i = 0; i < THREAD_MAX; i++) { 362 319 args[i].id = i; 363 320 args[i].timeout = tsp; 364 - info("Starting thread %d\n", i); 321 + ksft_print_dbg_msg("Starting thread %d\n", i); 365 322 if (create_rt_thread(&waiter[i], waiterfn, (void *)&args[i], 366 323 SCHED_FIFO, 1)) { 367 - error("Creating waiting thread failed\n", errno); 368 - ret = RET_ERROR; 369 - goto out; 324 + ksft_exit_fail_msg("Creating waiting thread failed\n"); 370 325 } 371 326 } 372 327 waker_arg.lock = lock; 373 328 if (create_rt_thread(&waker, wakerfn, (void *)&waker_arg, 374 329 SCHED_FIFO, 1)) { 375 - error("Creating waker thread failed\n", errno); 376 - ret = RET_ERROR; 377 - goto out; 330 + ksft_exit_fail_msg("Creating waker thread failed\n"); 378 331 } 379 332 380 333 /* Wait for threads to finish */ ··· 384 345 pthread_join(blocker, NULL); 385 346 pthread_join(waker, NULL); 386 347 387 - out: 388 348 if (!ret) { 389 349 if (*waiter_ret) 390 350 ret = *waiter_ret; ··· 393 355 ret = blocker_arg.ret; 394 356 } 395 357 396 - return ret; 358 + if (ret) 359 + ksft_test_result_fail("fail"); 397 360 } 398 361 399 - int main(int argc, char *argv[]) 400 - { 401 - char *test_name; 402 - int c, ret; 403 - 404 - while ((c = getopt(argc, argv, "bchlot:v:")) != -1) { 405 - switch (c) { 406 - case 'b': 407 - broadcast = 1; 408 - break; 409 - case 'c': 410 - log_color(1); 411 - break; 412 - case 'h': 413 - usage(basename(argv[0])); 414 - exit(0); 415 - case 'l': 416 - locked = 1; 417 - break; 418 - case 'o': 419 - owner = 1; 420 - locked = 0; 421 - break; 422 - case 't': 423 - timeout_ns = atoi(optarg); 424 - break; 425 - case 'v': 426 - log_verbosity(atoi(optarg)); 427 - break; 428 - default: 429 - usage(basename(argv[0])); 430 - exit(1); 431 - } 432 - } 433 - 434 - ksft_print_header(); 435 - ksft_set_plan(1); 436 - ksft_print_msg("%s: Test requeue functionality\n", basename(argv[0])); 437 - ksft_print_msg( 438 - "\tArguments: broadcast=%d locked=%d owner=%d timeout=%ldns\n", 439 - broadcast, locked, owner, timeout_ns); 440 - 441 - ret = asprintf(&test_name, 442 - "%s broadcast=%d locked=%d owner=%d timeout=%ldns", 443 - TEST_NAME, broadcast, locked, owner, timeout_ns); 444 - if (ret < 0) { 445 - ksft_print_msg("Failed to generate test name\n"); 446 - test_name = TEST_NAME; 447 - } 448 - 449 - /* 450 - * FIXME: unit_test is obsolete now that we parse options and the 451 - * various style of runs are done by run.sh - simplify the code and move 452 - * unit_test into main() 453 - */ 454 - ret = unit_test(broadcast, locked, owner, timeout_ns); 455 - 456 - print_result(test_name, ret); 457 - return ret; 458 - } 362 + TEST_HARNESS_MAIN
+22 -64
tools/testing/selftests/futex/functional/futex_requeue_pi_mismatched_ops.c
··· 23 23 #include <stdlib.h> 24 24 #include <string.h> 25 25 #include <time.h> 26 - #include "futextest.h" 27 - #include "logging.h" 28 26 29 - #define TEST_NAME "futex-requeue-pi-mismatched-ops" 27 + #include "futextest.h" 28 + #include "../../kselftest_harness.h" 30 29 31 30 futex_t f1 = FUTEX_INITIALIZER; 32 31 futex_t f2 = FUTEX_INITIALIZER; 33 32 int child_ret = 0; 34 - 35 - void usage(char *prog) 36 - { 37 - printf("Usage: %s\n", prog); 38 - printf(" -c Use color\n"); 39 - printf(" -h Display this help message\n"); 40 - printf(" -v L Verbosity level: %d=QUIET %d=CRITICAL %d=INFO\n", 41 - VQUIET, VCRITICAL, VINFO); 42 - } 43 33 44 34 void *blocking_child(void *arg) 45 35 { 46 36 child_ret = futex_wait(&f1, f1, NULL, FUTEX_PRIVATE_FLAG); 47 37 if (child_ret < 0) { 48 38 child_ret = -errno; 49 - error("futex_wait\n", errno); 39 + ksft_exit_fail_msg("futex_wait\n"); 50 40 } 51 41 return (void *)&child_ret; 52 42 } 53 43 54 - int main(int argc, char *argv[]) 44 + TEST(requeue_pi_mismatched_ops) 55 45 { 56 - int ret = RET_PASS; 57 46 pthread_t child; 58 - int c; 47 + int ret; 59 48 60 - while ((c = getopt(argc, argv, "chv:")) != -1) { 61 - switch (c) { 62 - case 'c': 63 - log_color(1); 64 - break; 65 - case 'h': 66 - usage(basename(argv[0])); 67 - exit(0); 68 - case 'v': 69 - log_verbosity(atoi(optarg)); 70 - break; 71 - default: 72 - usage(basename(argv[0])); 73 - exit(1); 74 - } 75 - } 49 + if (pthread_create(&child, NULL, blocking_child, NULL)) 50 + ksft_exit_fail_msg("pthread_create\n"); 76 51 77 - ksft_print_header(); 78 - ksft_set_plan(1); 79 - ksft_print_msg("%s: Detect mismatched requeue_pi operations\n", 80 - basename(argv[0])); 81 - 82 - if (pthread_create(&child, NULL, blocking_child, NULL)) { 83 - error("pthread_create\n", errno); 84 - ret = RET_ERROR; 85 - goto out; 86 - } 87 52 /* Allow the child to block in the kernel. */ 88 53 sleep(1); 89 54 ··· 67 102 * FUTEX_WAKE. 68 103 */ 69 104 ret = futex_wake(&f1, 1, FUTEX_PRIVATE_FLAG); 70 - if (ret == 1) { 71 - ret = RET_PASS; 72 - } else if (ret < 0) { 73 - error("futex_wake\n", errno); 74 - ret = RET_ERROR; 75 - } else { 76 - error("futex_wake did not wake the child\n", 0); 77 - ret = RET_ERROR; 78 - } 105 + if (ret == 1) 106 + ret = 0; 107 + else if (ret < 0) 108 + ksft_exit_fail_msg("futex_wake\n"); 109 + else 110 + ksft_exit_fail_msg("futex_wake did not wake the child\n"); 79 111 } else { 80 - error("futex_cmp_requeue_pi\n", errno); 81 - ret = RET_ERROR; 112 + ksft_exit_fail_msg("futex_cmp_requeue_pi\n"); 82 113 } 83 114 } else if (ret > 0) { 84 - fail("futex_cmp_requeue_pi failed to detect the mismatch\n"); 85 - ret = RET_FAIL; 115 + ksft_test_result_fail("futex_cmp_requeue_pi failed to detect the mismatch\n"); 86 116 } else { 87 - error("futex_cmp_requeue_pi found no waiters\n", 0); 88 - ret = RET_ERROR; 117 + ksft_exit_fail_msg("futex_cmp_requeue_pi found no waiters\n"); 89 118 } 90 119 91 120 pthread_join(child, NULL); 92 121 93 - if (!ret) 94 - ret = child_ret; 95 - 96 - out: 97 - /* If the kernel crashes, we shouldn't return at all. */ 98 - print_result(TEST_NAME, ret); 99 - return ret; 122 + if (!ret && !child_ret) 123 + ksft_test_result_pass("futex_requeue_pi_mismatched_ops passed\n"); 124 + else 125 + ksft_test_result_pass("futex_requeue_pi_mismatched_ops failed\n"); 100 126 } 127 + 128 + TEST_HARNESS_MAIN
+37 -92
tools/testing/selftests/futex/functional/futex_requeue_pi_signal_restart.c
··· 24 24 #include <stdio.h> 25 25 #include <stdlib.h> 26 26 #include <string.h> 27 + 27 28 #include "atomic.h" 28 29 #include "futextest.h" 29 - #include "logging.h" 30 + #include "../../kselftest_harness.h" 30 31 31 - #define TEST_NAME "futex-requeue-pi-signal-restart" 32 32 #define DELAY_US 100 33 33 34 34 futex_t f1 = FUTEX_INITIALIZER; ··· 36 36 atomic_t requeued = ATOMIC_INITIALIZER; 37 37 38 38 int waiter_ret = 0; 39 - 40 - void usage(char *prog) 41 - { 42 - printf("Usage: %s\n", prog); 43 - printf(" -c Use color\n"); 44 - printf(" -h Display this help message\n"); 45 - printf(" -v L Verbosity level: %d=QUIET %d=CRITICAL %d=INFO\n", 46 - VQUIET, VCRITICAL, VINFO); 47 - } 48 39 49 40 int create_rt_thread(pthread_t *pth, void*(*func)(void *), void *arg, 50 41 int policy, int prio) ··· 48 57 memset(&schedp, 0, sizeof(schedp)); 49 58 50 59 ret = pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED); 51 - if (ret) { 52 - error("pthread_attr_setinheritsched\n", ret); 53 - return -1; 54 - } 60 + if (ret) 61 + ksft_exit_fail_msg("pthread_attr_setinheritsched\n"); 55 62 56 63 ret = pthread_attr_setschedpolicy(&attr, policy); 57 - if (ret) { 58 - error("pthread_attr_setschedpolicy\n", ret); 59 - return -1; 60 - } 64 + if (ret) 65 + ksft_exit_fail_msg("pthread_attr_setschedpolicy\n"); 61 66 62 67 schedp.sched_priority = prio; 63 68 ret = pthread_attr_setschedparam(&attr, &schedp); 64 - if (ret) { 65 - error("pthread_attr_setschedparam\n", ret); 66 - return -1; 67 - } 69 + if (ret) 70 + ksft_exit_fail_msg("pthread_attr_setschedparam\n"); 68 71 69 72 ret = pthread_create(pth, &attr, func, arg); 70 - if (ret) { 71 - error("pthread_create\n", ret); 72 - return -1; 73 - } 73 + if (ret) 74 + ksft_exit_fail_msg("pthread_create\n"); 75 + 74 76 return 0; 75 77 } 76 78 77 79 void handle_signal(int signo) 78 80 { 79 - info("signal received %s requeue\n", 81 + ksft_print_dbg_msg("signal received %s requeue\n", 80 82 requeued.val ? "after" : "prior to"); 81 83 } 82 84 ··· 78 94 unsigned int old_val; 79 95 int res; 80 96 81 - waiter_ret = RET_PASS; 82 - 83 - info("Waiter running\n"); 84 - info("Calling FUTEX_LOCK_PI on f2=%x @ %p\n", f2, &f2); 97 + ksft_print_dbg_msg("Waiter running\n"); 98 + ksft_print_dbg_msg("Calling FUTEX_LOCK_PI on f2=%x @ %p\n", f2, &f2); 85 99 old_val = f1; 86 100 res = futex_wait_requeue_pi(&f1, old_val, &(f2), NULL, 87 101 FUTEX_PRIVATE_FLAG); 88 102 if (!requeued.val || errno != EWOULDBLOCK) { 89 - fail("unexpected return from futex_wait_requeue_pi: %d (%s)\n", 103 + ksft_test_result_fail("unexpected return from futex_wait_requeue_pi: %d (%s)\n", 90 104 res, strerror(errno)); 91 - info("w2:futex: %x\n", f2); 105 + ksft_print_dbg_msg("w2:futex: %x\n", f2); 92 106 if (!res) 93 107 futex_unlock_pi(&f2, FUTEX_PRIVATE_FLAG); 94 - waiter_ret = RET_FAIL; 95 108 } 96 109 97 - info("Waiter exiting with %d\n", waiter_ret); 98 110 pthread_exit(NULL); 99 111 } 100 112 101 113 102 - int main(int argc, char *argv[]) 114 + TEST(futex_requeue_pi_signal_restart) 103 115 { 104 116 unsigned int old_val; 105 117 struct sigaction sa; 106 118 pthread_t waiter; 107 - int c, res, ret = RET_PASS; 108 - 109 - while ((c = getopt(argc, argv, "chv:")) != -1) { 110 - switch (c) { 111 - case 'c': 112 - log_color(1); 113 - break; 114 - case 'h': 115 - usage(basename(argv[0])); 116 - exit(0); 117 - case 'v': 118 - log_verbosity(atoi(optarg)); 119 - break; 120 - default: 121 - usage(basename(argv[0])); 122 - exit(1); 123 - } 124 - } 125 - 126 - ksft_print_header(); 127 - ksft_set_plan(1); 128 - ksft_print_msg("%s: Test signal handling during requeue_pi\n", 129 - basename(argv[0])); 130 - ksft_print_msg("\tArguments: <none>\n"); 119 + int res; 131 120 132 121 sa.sa_handler = handle_signal; 133 122 sigemptyset(&sa.sa_mask); 134 123 sa.sa_flags = 0; 135 - if (sigaction(SIGUSR1, &sa, NULL)) { 136 - error("sigaction\n", errno); 137 - exit(1); 138 - } 124 + if (sigaction(SIGUSR1, &sa, NULL)) 125 + ksft_exit_fail_msg("sigaction\n"); 139 126 140 - info("m1:f2: %x\n", f2); 141 - info("Creating waiter\n"); 127 + ksft_print_dbg_msg("m1:f2: %x\n", f2); 128 + ksft_print_dbg_msg("Creating waiter\n"); 142 129 res = create_rt_thread(&waiter, waiterfn, NULL, SCHED_FIFO, 1); 143 - if (res) { 144 - error("Creating waiting thread failed", res); 145 - ret = RET_ERROR; 146 - goto out; 147 - } 130 + if (res) 131 + ksft_exit_fail_msg("Creating waiting thread failed"); 148 132 149 - info("Calling FUTEX_LOCK_PI on f2=%x @ %p\n", f2, &f2); 150 - info("m2:f2: %x\n", f2); 133 + ksft_print_dbg_msg("Calling FUTEX_LOCK_PI on f2=%x @ %p\n", f2, &f2); 134 + ksft_print_dbg_msg("m2:f2: %x\n", f2); 151 135 futex_lock_pi(&f2, 0, 0, FUTEX_PRIVATE_FLAG); 152 - info("m3:f2: %x\n", f2); 136 + ksft_print_dbg_msg("m3:f2: %x\n", f2); 153 137 154 138 while (1) { 155 139 /* ··· 125 173 * restart futex_wait_requeue_pi() in the kernel. Wait for the 126 174 * waiter to block on f1 again. 127 175 */ 128 - info("Issuing SIGUSR1 to waiter\n"); 176 + ksft_print_dbg_msg("Issuing SIGUSR1 to waiter\n"); 129 177 pthread_kill(waiter, SIGUSR1); 130 178 usleep(DELAY_US); 131 179 132 - info("Requeueing waiter via FUTEX_CMP_REQUEUE_PI\n"); 180 + ksft_print_dbg_msg("Requeueing waiter via FUTEX_CMP_REQUEUE_PI\n"); 133 181 old_val = f1; 134 182 res = futex_cmp_requeue_pi(&f1, old_val, &(f2), 1, 0, 135 183 FUTEX_PRIVATE_FLAG); ··· 143 191 atomic_set(&requeued, 1); 144 192 break; 145 193 } else if (res < 0) { 146 - error("FUTEX_CMP_REQUEUE_PI failed\n", errno); 147 - ret = RET_ERROR; 148 - break; 194 + ksft_exit_fail_msg("FUTEX_CMP_REQUEUE_PI failed\n"); 149 195 } 150 196 } 151 - info("m4:f2: %x\n", f2); 197 + ksft_print_dbg_msg("m4:f2: %x\n", f2); 152 198 153 199 /* 154 200 * Signal the waiter after requeue, waiter should return from ··· 154 204 * futex_unlock_pi() can't happen before the signal wakeup is detected 155 205 * in the kernel. 156 206 */ 157 - info("Issuing SIGUSR1 to waiter\n"); 207 + ksft_print_dbg_msg("Issuing SIGUSR1 to waiter\n"); 158 208 pthread_kill(waiter, SIGUSR1); 159 - info("Waiting for waiter to return\n"); 209 + ksft_print_dbg_msg("Waiting for waiter to return\n"); 160 210 pthread_join(waiter, NULL); 161 211 162 - info("Calling FUTEX_UNLOCK_PI on mutex=%x @ %p\n", f2, &f2); 212 + ksft_print_dbg_msg("Calling FUTEX_UNLOCK_PI on mutex=%x @ %p\n", f2, &f2); 163 213 futex_unlock_pi(&f2, FUTEX_PRIVATE_FLAG); 164 - info("m5:f2: %x\n", f2); 165 - 166 - out: 167 - if (ret == RET_PASS && waiter_ret) 168 - ret = waiter_ret; 169 - 170 - print_result(TEST_NAME, ret); 171 - return ret; 214 + ksft_print_dbg_msg("m5:f2: %x\n", f2); 172 215 } 216 + 217 + TEST_HARNESS_MAIN
+39 -66
tools/testing/selftests/futex/functional/futex_wait.c
··· 9 9 #include <sys/shm.h> 10 10 #include <sys/mman.h> 11 11 #include <fcntl.h> 12 - #include "logging.h" 13 - #include "futextest.h" 14 12 15 - #define TEST_NAME "futex-wait" 13 + #include "futextest.h" 14 + #include "../../kselftest_harness.h" 15 + 16 16 #define timeout_ns 30000000 17 17 #define WAKE_WAIT_US 10000 18 18 #define SHM_PATH "futex_shm_file" 19 19 20 20 void *futex; 21 - 22 - void usage(char *prog) 23 - { 24 - printf("Usage: %s\n", prog); 25 - printf(" -c Use color\n"); 26 - printf(" -h Display this help message\n"); 27 - printf(" -v L Verbosity level: %d=QUIET %d=CRITICAL %d=INFO\n", 28 - VQUIET, VCRITICAL, VINFO); 29 - } 30 21 31 22 static void *waiterfn(void *arg) 32 23 { ··· 36 45 return NULL; 37 46 } 38 47 39 - int main(int argc, char *argv[]) 48 + TEST(private_futex) 40 49 { 41 - int res, ret = RET_PASS, fd, c, shm_id; 42 - u_int32_t f_private = 0, *shared_data; 43 50 unsigned int flags = FUTEX_PRIVATE_FLAG; 51 + u_int32_t f_private = 0; 44 52 pthread_t waiter; 45 - void *shm; 53 + int res; 46 54 47 55 futex = &f_private; 48 56 49 - while ((c = getopt(argc, argv, "cht:v:")) != -1) { 50 - switch (c) { 51 - case 'c': 52 - log_color(1); 53 - break; 54 - case 'h': 55 - usage(basename(argv[0])); 56 - exit(0); 57 - case 'v': 58 - log_verbosity(atoi(optarg)); 59 - break; 60 - default: 61 - usage(basename(argv[0])); 62 - exit(1); 63 - } 64 - } 65 - 66 - ksft_print_header(); 67 - ksft_set_plan(3); 68 - ksft_print_msg("%s: Test futex_wait\n", basename(argv[0])); 69 - 70 57 /* Testing a private futex */ 71 - info("Calling private futex_wait on futex: %p\n", futex); 58 + ksft_print_dbg_msg("Calling private futex_wait on futex: %p\n", futex); 72 59 if (pthread_create(&waiter, NULL, waiterfn, (void *) &flags)) 73 - error("pthread_create failed\n", errno); 60 + ksft_exit_fail_msg("pthread_create failed\n"); 74 61 75 62 usleep(WAKE_WAIT_US); 76 63 77 - info("Calling private futex_wake on futex: %p\n", futex); 64 + ksft_print_dbg_msg("Calling private futex_wake on futex: %p\n", futex); 78 65 res = futex_wake(futex, 1, FUTEX_PRIVATE_FLAG); 79 66 if (res != 1) { 80 67 ksft_test_result_fail("futex_wake private returned: %d %s\n", 81 68 errno, strerror(errno)); 82 - ret = RET_FAIL; 83 69 } else { 84 70 ksft_test_result_pass("futex_wake private succeeds\n"); 85 71 } 72 + } 73 + 74 + TEST(anon_page) 75 + { 76 + u_int32_t *shared_data; 77 + pthread_t waiter; 78 + int res, shm_id; 86 79 87 80 /* Testing an anon page shared memory */ 88 81 shm_id = shmget(IPC_PRIVATE, 4096, IPC_CREAT | 0666); ··· 80 105 *shared_data = 0; 81 106 futex = shared_data; 82 107 83 - info("Calling shared (page anon) futex_wait on futex: %p\n", futex); 108 + ksft_print_dbg_msg("Calling shared (page anon) futex_wait on futex: %p\n", futex); 84 109 if (pthread_create(&waiter, NULL, waiterfn, NULL)) 85 - error("pthread_create failed\n", errno); 110 + ksft_exit_fail_msg("pthread_create failed\n"); 86 111 87 112 usleep(WAKE_WAIT_US); 88 113 89 - info("Calling shared (page anon) futex_wake on futex: %p\n", futex); 114 + ksft_print_dbg_msg("Calling shared (page anon) futex_wake on futex: %p\n", futex); 90 115 res = futex_wake(futex, 1, 0); 91 116 if (res != 1) { 92 117 ksft_test_result_fail("futex_wake shared (page anon) returned: %d %s\n", 93 118 errno, strerror(errno)); 94 - ret = RET_FAIL; 95 119 } else { 96 120 ksft_test_result_pass("futex_wake shared (page anon) succeeds\n"); 97 121 } 98 122 123 + shmdt(shared_data); 124 + } 125 + 126 + TEST(file_backed) 127 + { 128 + u_int32_t f_private = 0; 129 + pthread_t waiter; 130 + int res, fd; 131 + void *shm; 99 132 100 133 /* Testing a file backed shared memory */ 101 134 fd = open(SHM_PATH, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); 102 - if (fd < 0) { 103 - perror("open"); 104 - exit(1); 105 - } 135 + if (fd < 0) 136 + ksft_exit_fail_msg("open"); 106 137 107 - if (ftruncate(fd, sizeof(f_private))) { 108 - perror("ftruncate"); 109 - exit(1); 110 - } 138 + if (ftruncate(fd, sizeof(f_private))) 139 + ksft_exit_fail_msg("ftruncate"); 111 140 112 141 shm = mmap(NULL, sizeof(f_private), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 113 - if (shm == MAP_FAILED) { 114 - perror("mmap"); 115 - exit(1); 116 - } 142 + if (shm == MAP_FAILED) 143 + ksft_exit_fail_msg("mmap"); 117 144 118 145 memcpy(shm, &f_private, sizeof(f_private)); 119 146 120 147 futex = shm; 121 148 122 - info("Calling shared (file backed) futex_wait on futex: %p\n", futex); 149 + ksft_print_dbg_msg("Calling shared (file backed) futex_wait on futex: %p\n", futex); 123 150 if (pthread_create(&waiter, NULL, waiterfn, NULL)) 124 - error("pthread_create failed\n", errno); 151 + ksft_exit_fail_msg("pthread_create failed\n"); 125 152 126 153 usleep(WAKE_WAIT_US); 127 154 128 - info("Calling shared (file backed) futex_wake on futex: %p\n", futex); 155 + ksft_print_dbg_msg("Calling shared (file backed) futex_wake on futex: %p\n", futex); 129 156 res = futex_wake(shm, 1, 0); 130 157 if (res != 1) { 131 158 ksft_test_result_fail("futex_wake shared (file backed) returned: %d %s\n", 132 159 errno, strerror(errno)); 133 - ret = RET_FAIL; 134 160 } else { 135 161 ksft_test_result_pass("futex_wake shared (file backed) succeeds\n"); 136 162 } 137 163 138 - /* Freeing resources */ 139 - shmdt(shared_data); 140 164 munmap(shm, sizeof(f_private)); 141 165 remove(SHM_PATH); 142 166 close(fd); 143 - 144 - ksft_print_cnts(); 145 - return ret; 146 167 } 168 + 169 + TEST_HARNESS_MAIN
+18 -61
tools/testing/selftests/futex/functional/futex_wait_private_mapped_file.c
··· 27 27 #include <libgen.h> 28 28 #include <signal.h> 29 29 30 - #include "logging.h" 31 30 #include "futextest.h" 31 + #include "../../kselftest_harness.h" 32 32 33 - #define TEST_NAME "futex-wait-private-mapped-file" 34 33 #define PAGE_SZ 4096 35 34 36 35 char pad[PAGE_SZ] = {1}; ··· 39 40 #define WAKE_WAIT_US 3000000 40 41 struct timespec wait_timeout = { .tv_sec = 5, .tv_nsec = 0}; 41 42 42 - void usage(char *prog) 43 - { 44 - printf("Usage: %s\n", prog); 45 - printf(" -c Use color\n"); 46 - printf(" -h Display this help message\n"); 47 - printf(" -v L Verbosity level: %d=QUIET %d=CRITICAL %d=INFO\n", 48 - VQUIET, VCRITICAL, VINFO); 49 - } 50 - 51 43 void *thr_futex_wait(void *arg) 52 44 { 53 45 int ret; 54 46 55 - info("futex wait\n"); 47 + ksft_print_dbg_msg("futex wait\n"); 56 48 ret = futex_wait(&val, 1, &wait_timeout, 0); 57 - if (ret && errno != EWOULDBLOCK && errno != ETIMEDOUT) { 58 - error("futex error.\n", errno); 59 - print_result(TEST_NAME, RET_ERROR); 60 - exit(RET_ERROR); 61 - } 49 + if (ret && errno != EWOULDBLOCK && errno != ETIMEDOUT) 50 + ksft_exit_fail_msg("futex error.\n"); 62 51 63 52 if (ret && errno == ETIMEDOUT) 64 - fail("waiter timedout\n"); 53 + ksft_exit_fail_msg("waiter timedout\n"); 65 54 66 - info("futex_wait: ret = %d, errno = %d\n", ret, errno); 55 + ksft_print_dbg_msg("futex_wait: ret = %d, errno = %d\n", ret, errno); 67 56 68 57 return NULL; 69 58 } 70 59 71 - int main(int argc, char **argv) 60 + TEST(wait_private_mapped_file) 72 61 { 73 62 pthread_t thr; 74 - int ret = RET_PASS; 75 63 int res; 76 - int c; 77 64 78 - while ((c = getopt(argc, argv, "chv:")) != -1) { 79 - switch (c) { 80 - case 'c': 81 - log_color(1); 82 - break; 83 - case 'h': 84 - usage(basename(argv[0])); 85 - exit(0); 86 - case 'v': 87 - log_verbosity(atoi(optarg)); 88 - break; 89 - default: 90 - usage(basename(argv[0])); 91 - exit(1); 92 - } 93 - } 65 + res = pthread_create(&thr, NULL, thr_futex_wait, NULL); 66 + if (res < 0) 67 + ksft_exit_fail_msg("pthread_create error\n"); 94 68 95 - ksft_print_header(); 96 - ksft_set_plan(1); 97 - ksft_print_msg( 98 - "%s: Test the futex value of private file mappings in FUTEX_WAIT\n", 99 - basename(argv[0])); 100 - 101 - ret = pthread_create(&thr, NULL, thr_futex_wait, NULL); 102 - if (ret < 0) { 103 - fprintf(stderr, "pthread_create error\n"); 104 - ret = RET_ERROR; 105 - goto out; 106 - } 107 - 108 - info("wait a while\n"); 69 + ksft_print_dbg_msg("wait a while\n"); 109 70 usleep(WAKE_WAIT_US); 110 71 val = 2; 111 72 res = futex_wake(&val, 1, 0); 112 - info("futex_wake %d\n", res); 113 - if (res != 1) { 114 - fail("FUTEX_WAKE didn't find the waiting thread.\n"); 115 - ret = RET_FAIL; 116 - } 73 + ksft_print_dbg_msg("futex_wake %d\n", res); 74 + if (res != 1) 75 + ksft_exit_fail_msg("FUTEX_WAKE didn't find the waiting thread.\n"); 117 76 118 - info("join\n"); 77 + ksft_print_dbg_msg("join\n"); 119 78 pthread_join(thr, NULL); 120 79 121 - out: 122 - print_result(TEST_NAME, ret); 123 - return ret; 80 + ksft_test_result_pass("wait_private_mapped_file"); 124 81 } 82 + 83 + TEST_HARNESS_MAIN
+60 -79
tools/testing/selftests/futex/functional/futex_wait_timeout.c
··· 16 16 *****************************************************************************/ 17 17 18 18 #include <pthread.h> 19 + 19 20 #include "futextest.h" 20 21 #include "futex2test.h" 21 - #include "logging.h" 22 - 23 - #define TEST_NAME "futex-wait-timeout" 22 + #include "../../kselftest_harness.h" 24 23 25 24 static long timeout_ns = 100000; /* 100us default timeout */ 26 25 static futex_t futex_pi; 27 26 static pthread_barrier_t barrier; 28 - 29 - void usage(char *prog) 30 - { 31 - printf("Usage: %s\n", prog); 32 - printf(" -c Use color\n"); 33 - printf(" -h Display this help message\n"); 34 - printf(" -t N Timeout in nanoseconds (default: 100,000)\n"); 35 - printf(" -v L Verbosity level: %d=QUIET %d=CRITICAL %d=INFO\n", 36 - VQUIET, VCRITICAL, VINFO); 37 - } 38 27 39 28 /* 40 29 * Get a PI lock and hold it forever, so the main thread lock_pi will block ··· 36 47 37 48 ret = futex_lock_pi(&futex_pi, NULL, 0, 0); 38 49 if (ret != 0) 39 - error("futex_lock_pi failed\n", ret); 50 + ksft_exit_fail_msg("futex_lock_pi failed\n"); 40 51 41 52 pthread_barrier_wait(&barrier); 42 53 43 54 /* Blocks forever */ 44 55 ret = futex_wait(&lock, 0, NULL, 0); 45 - error("futex_wait failed\n", ret); 56 + ksft_exit_fail_msg("futex_wait failed\n"); 46 57 47 58 return NULL; 48 59 } ··· 50 61 /* 51 62 * Check if the function returned the expected error 52 63 */ 53 - static void test_timeout(int res, int *ret, char *test_name, int err) 64 + static void test_timeout(int res, char *test_name, int err) 54 65 { 55 66 if (!res || errno != err) { 56 67 ksft_test_result_fail("%s returned %d\n", test_name, 57 68 res < 0 ? errno : res); 58 - *ret = RET_FAIL; 59 69 } else { 60 70 ksft_test_result_pass("%s succeeds\n", test_name); 61 71 } ··· 66 78 static int futex_get_abs_timeout(clockid_t clockid, struct timespec *to, 67 79 long timeout_ns) 68 80 { 69 - if (clock_gettime(clockid, to)) { 70 - error("clock_gettime failed\n", errno); 71 - return errno; 72 - } 81 + if (clock_gettime(clockid, to)) 82 + ksft_exit_fail_msg("clock_gettime failed\n"); 73 83 74 84 to->tv_nsec += timeout_ns; 75 85 ··· 79 93 return 0; 80 94 } 81 95 82 - int main(int argc, char *argv[]) 96 + TEST(wait_bitset) 83 97 { 84 98 futex_t f1 = FUTEX_INITIALIZER; 85 - int res, ret = RET_PASS; 86 99 struct timespec to; 87 - pthread_t thread; 88 - int c; 89 - struct futex_waitv waitv = { 90 - .uaddr = (uintptr_t)&f1, 91 - .val = f1, 92 - .flags = FUTEX_32, 93 - .__reserved = 0 94 - }; 95 - 96 - while ((c = getopt(argc, argv, "cht:v:")) != -1) { 97 - switch (c) { 98 - case 'c': 99 - log_color(1); 100 - break; 101 - case 'h': 102 - usage(basename(argv[0])); 103 - exit(0); 104 - case 't': 105 - timeout_ns = atoi(optarg); 106 - break; 107 - case 'v': 108 - log_verbosity(atoi(optarg)); 109 - break; 110 - default: 111 - usage(basename(argv[0])); 112 - exit(1); 113 - } 114 - } 115 - 116 - ksft_print_header(); 117 - ksft_set_plan(9); 118 - ksft_print_msg("%s: Block on a futex and wait for timeout\n", 119 - basename(argv[0])); 120 - ksft_print_msg("\tArguments: timeout=%ldns\n", timeout_ns); 121 - 122 - pthread_barrier_init(&barrier, NULL, 2); 123 - pthread_create(&thread, NULL, get_pi_lock, NULL); 100 + int res; 124 101 125 102 /* initialize relative timeout */ 126 103 to.tv_sec = 0; 127 104 to.tv_nsec = timeout_ns; 128 105 129 106 res = futex_wait(&f1, f1, &to, 0); 130 - test_timeout(res, &ret, "futex_wait relative", ETIMEDOUT); 107 + test_timeout(res, "futex_wait relative", ETIMEDOUT); 131 108 132 109 /* FUTEX_WAIT_BITSET with CLOCK_REALTIME */ 133 110 if (futex_get_abs_timeout(CLOCK_REALTIME, &to, timeout_ns)) 134 - return RET_FAIL; 111 + ksft_test_result_error("get_time error"); 135 112 res = futex_wait_bitset(&f1, f1, &to, 1, FUTEX_CLOCK_REALTIME); 136 - test_timeout(res, &ret, "futex_wait_bitset realtime", ETIMEDOUT); 113 + test_timeout(res, "futex_wait_bitset realtime", ETIMEDOUT); 137 114 138 115 /* FUTEX_WAIT_BITSET with CLOCK_MONOTONIC */ 139 116 if (futex_get_abs_timeout(CLOCK_MONOTONIC, &to, timeout_ns)) 140 - return RET_FAIL; 117 + ksft_test_result_error("get_time error"); 141 118 res = futex_wait_bitset(&f1, f1, &to, 1, 0); 142 - test_timeout(res, &ret, "futex_wait_bitset monotonic", ETIMEDOUT); 119 + test_timeout(res, "futex_wait_bitset monotonic", ETIMEDOUT); 120 + } 121 + 122 + TEST(requeue_pi) 123 + { 124 + futex_t f1 = FUTEX_INITIALIZER; 125 + struct timespec to; 126 + int res; 143 127 144 128 /* FUTEX_WAIT_REQUEUE_PI with CLOCK_REALTIME */ 145 129 if (futex_get_abs_timeout(CLOCK_REALTIME, &to, timeout_ns)) 146 - return RET_FAIL; 130 + ksft_test_result_error("get_time error"); 147 131 res = futex_wait_requeue_pi(&f1, f1, &futex_pi, &to, FUTEX_CLOCK_REALTIME); 148 - test_timeout(res, &ret, "futex_wait_requeue_pi realtime", ETIMEDOUT); 132 + test_timeout(res, "futex_wait_requeue_pi realtime", ETIMEDOUT); 149 133 150 134 /* FUTEX_WAIT_REQUEUE_PI with CLOCK_MONOTONIC */ 151 135 if (futex_get_abs_timeout(CLOCK_MONOTONIC, &to, timeout_ns)) 152 - return RET_FAIL; 136 + ksft_test_result_error("get_time error"); 153 137 res = futex_wait_requeue_pi(&f1, f1, &futex_pi, &to, 0); 154 - test_timeout(res, &ret, "futex_wait_requeue_pi monotonic", ETIMEDOUT); 138 + test_timeout(res, "futex_wait_requeue_pi monotonic", ETIMEDOUT); 139 + 140 + } 141 + 142 + TEST(lock_pi) 143 + { 144 + struct timespec to; 145 + pthread_t thread; 146 + int res; 147 + 148 + /* Create a thread that will lock forever so any waiter will timeout */ 149 + pthread_barrier_init(&barrier, NULL, 2); 150 + pthread_create(&thread, NULL, get_pi_lock, NULL); 155 151 156 152 /* Wait until the other thread calls futex_lock_pi() */ 157 153 pthread_barrier_wait(&barrier); 158 154 pthread_barrier_destroy(&barrier); 155 + 159 156 /* 160 157 * FUTEX_LOCK_PI with CLOCK_REALTIME 161 158 * Due to historical reasons, FUTEX_LOCK_PI supports only realtime ··· 150 181 * smaller than realtime and the syscall will timeout immediately. 151 182 */ 152 183 if (futex_get_abs_timeout(CLOCK_REALTIME, &to, timeout_ns)) 153 - return RET_FAIL; 184 + ksft_test_result_error("get_time error"); 154 185 res = futex_lock_pi(&futex_pi, &to, 0, 0); 155 - test_timeout(res, &ret, "futex_lock_pi realtime", ETIMEDOUT); 186 + test_timeout(res, "futex_lock_pi realtime", ETIMEDOUT); 156 187 157 188 /* Test operations that don't support FUTEX_CLOCK_REALTIME */ 158 189 res = futex_lock_pi(&futex_pi, NULL, 0, FUTEX_CLOCK_REALTIME); 159 - test_timeout(res, &ret, "futex_lock_pi invalid timeout flag", ENOSYS); 190 + test_timeout(res, "futex_lock_pi invalid timeout flag", ENOSYS); 191 + } 192 + 193 + TEST(waitv) 194 + { 195 + futex_t f1 = FUTEX_INITIALIZER; 196 + struct futex_waitv waitv = { 197 + .uaddr = (uintptr_t)&f1, 198 + .val = f1, 199 + .flags = FUTEX_32, 200 + .__reserved = 0, 201 + }; 202 + struct timespec to; 203 + int res; 160 204 161 205 /* futex_waitv with CLOCK_MONOTONIC */ 162 206 if (futex_get_abs_timeout(CLOCK_MONOTONIC, &to, timeout_ns)) 163 - return RET_FAIL; 207 + ksft_test_result_error("get_time error"); 164 208 res = futex_waitv(&waitv, 1, 0, &to, CLOCK_MONOTONIC); 165 - test_timeout(res, &ret, "futex_waitv monotonic", ETIMEDOUT); 209 + test_timeout(res, "futex_waitv monotonic", ETIMEDOUT); 166 210 167 211 /* futex_waitv with CLOCK_REALTIME */ 168 212 if (futex_get_abs_timeout(CLOCK_REALTIME, &to, timeout_ns)) 169 - return RET_FAIL; 213 + ksft_test_result_error("get_time error"); 170 214 res = futex_waitv(&waitv, 1, 0, &to, CLOCK_REALTIME); 171 - test_timeout(res, &ret, "futex_waitv realtime", ETIMEDOUT); 172 - 173 - ksft_print_cnts(); 174 - return ret; 215 + test_timeout(res, "futex_waitv realtime", ETIMEDOUT); 175 216 } 217 + 218 + TEST_HARNESS_MAIN
+18 -58
tools/testing/selftests/futex/functional/futex_wait_uninitialized_heap.c
··· 29 29 #include <linux/futex.h> 30 30 #include <libgen.h> 31 31 32 - #include "logging.h" 33 32 #include "futextest.h" 33 + #include "../../kselftest_harness.h" 34 34 35 - #define TEST_NAME "futex-wait-uninitialized-heap" 36 35 #define WAIT_US 5000000 37 36 38 37 static int child_blocked = 1; 39 - static int child_ret; 38 + static bool child_ret; 40 39 void *buf; 41 - 42 - void usage(char *prog) 43 - { 44 - printf("Usage: %s\n", prog); 45 - printf(" -c Use color\n"); 46 - printf(" -h Display this help message\n"); 47 - printf(" -v L Verbosity level: %d=QUIET %d=CRITICAL %d=INFO\n", 48 - VQUIET, VCRITICAL, VINFO); 49 - } 50 40 51 41 void *wait_thread(void *arg) 52 42 { 53 43 int res; 54 44 55 - child_ret = RET_PASS; 45 + child_ret = true; 56 46 res = futex_wait(buf, 1, NULL, 0); 57 47 child_blocked = 0; 58 48 59 49 if (res != 0 && errno != EWOULDBLOCK) { 60 - error("futex failure\n", errno); 61 - child_ret = RET_ERROR; 50 + ksft_exit_fail_msg("futex failure\n"); 51 + child_ret = false; 62 52 } 63 53 pthread_exit(NULL); 64 54 } 65 55 66 - int main(int argc, char **argv) 56 + TEST(futex_wait_uninitialized_heap) 67 57 { 68 - int c, ret = RET_PASS; 69 58 long page_size; 70 59 pthread_t thr; 71 - 72 - while ((c = getopt(argc, argv, "chv:")) != -1) { 73 - switch (c) { 74 - case 'c': 75 - log_color(1); 76 - break; 77 - case 'h': 78 - usage(basename(argv[0])); 79 - exit(0); 80 - case 'v': 81 - log_verbosity(atoi(optarg)); 82 - break; 83 - default: 84 - usage(basename(argv[0])); 85 - exit(1); 86 - } 87 - } 60 + int ret; 88 61 89 62 page_size = sysconf(_SC_PAGESIZE); 90 63 91 64 buf = mmap(NULL, page_size, PROT_READ|PROT_WRITE, 92 65 MAP_PRIVATE|MAP_ANONYMOUS, 0, 0); 93 - if (buf == (void *)-1) { 94 - error("mmap\n", errno); 95 - exit(1); 96 - } 97 - 98 - ksft_print_header(); 99 - ksft_set_plan(1); 100 - ksft_print_msg("%s: Test the uninitialized futex value in FUTEX_WAIT\n", 101 - basename(argv[0])); 102 - 66 + if (buf == (void *)-1) 67 + ksft_exit_fail_msg("mmap\n"); 103 68 104 69 ret = pthread_create(&thr, NULL, wait_thread, NULL); 105 - if (ret) { 106 - error("pthread_create\n", errno); 107 - ret = RET_ERROR; 108 - goto out; 109 - } 70 + if (ret) 71 + ksft_exit_fail_msg("pthread_create\n"); 110 72 111 - info("waiting %dus for child to return\n", WAIT_US); 73 + ksft_print_dbg_msg("waiting %dus for child to return\n", WAIT_US); 112 74 usleep(WAIT_US); 113 75 114 - ret = child_ret; 115 - if (child_blocked) { 116 - fail("child blocked in kernel\n"); 117 - ret = RET_FAIL; 118 - } 76 + if (child_blocked) 77 + ksft_test_result_fail("child blocked in kernel\n"); 119 78 120 - out: 121 - print_result(TEST_NAME, ret); 122 - return ret; 79 + if (!child_ret) 80 + ksft_test_result_fail("child error\n"); 123 81 } 82 + 83 + TEST_HARNESS_MAIN
+23 -53
tools/testing/selftests/futex/functional/futex_wait_wouldblock.c
··· 21 21 #include <stdlib.h> 22 22 #include <string.h> 23 23 #include <time.h> 24 + 24 25 #include "futextest.h" 25 26 #include "futex2test.h" 26 - #include "logging.h" 27 + #include "../../kselftest_harness.h" 27 28 28 - #define TEST_NAME "futex-wait-wouldblock" 29 29 #define timeout_ns 100000 30 30 31 - void usage(char *prog) 32 - { 33 - printf("Usage: %s\n", prog); 34 - printf(" -c Use color\n"); 35 - printf(" -h Display this help message\n"); 36 - printf(" -v L Verbosity level: %d=QUIET %d=CRITICAL %d=INFO\n", 37 - VQUIET, VCRITICAL, VINFO); 38 - } 39 - 40 - int main(int argc, char *argv[]) 31 + TEST(futex_wait_wouldblock) 41 32 { 42 33 struct timespec to = {.tv_sec = 0, .tv_nsec = timeout_ns}; 43 34 futex_t f1 = FUTEX_INITIALIZER; 44 - int res, ret = RET_PASS; 45 - int c; 46 - struct futex_waitv waitv = { 47 - .uaddr = (uintptr_t)&f1, 48 - .val = f1+1, 49 - .flags = FUTEX_32, 50 - .__reserved = 0 51 - }; 35 + int res; 52 36 53 - while ((c = getopt(argc, argv, "cht:v:")) != -1) { 54 - switch (c) { 55 - case 'c': 56 - log_color(1); 57 - break; 58 - case 'h': 59 - usage(basename(argv[0])); 60 - exit(0); 61 - case 'v': 62 - log_verbosity(atoi(optarg)); 63 - break; 64 - default: 65 - usage(basename(argv[0])); 66 - exit(1); 67 - } 68 - } 69 - 70 - ksft_print_header(); 71 - ksft_set_plan(2); 72 - ksft_print_msg("%s: Test the unexpected futex value in FUTEX_WAIT\n", 73 - basename(argv[0])); 74 - 75 - info("Calling futex_wait on f1: %u @ %p with val=%u\n", f1, &f1, f1+1); 37 + ksft_print_dbg_msg("Calling futex_wait on f1: %u @ %p with val=%u\n", f1, &f1, f1+1); 76 38 res = futex_wait(&f1, f1+1, &to, FUTEX_PRIVATE_FLAG); 77 39 if (!res || errno != EWOULDBLOCK) { 78 40 ksft_test_result_fail("futex_wait returned: %d %s\n", 79 41 res ? errno : res, 80 42 res ? strerror(errno) : ""); 81 - ret = RET_FAIL; 82 43 } else { 83 44 ksft_test_result_pass("futex_wait\n"); 84 45 } 46 + } 85 47 86 - if (clock_gettime(CLOCK_MONOTONIC, &to)) { 87 - error("clock_gettime failed\n", errno); 88 - return errno; 89 - } 48 + TEST(futex_waitv_wouldblock) 49 + { 50 + struct timespec to = {.tv_sec = 0, .tv_nsec = timeout_ns}; 51 + futex_t f1 = FUTEX_INITIALIZER; 52 + struct futex_waitv waitv = { 53 + .uaddr = (uintptr_t)&f1, 54 + .val = f1 + 1, 55 + .flags = FUTEX_32, 56 + .__reserved = 0, 57 + }; 58 + int res; 59 + 60 + if (clock_gettime(CLOCK_MONOTONIC, &to)) 61 + ksft_exit_fail_msg("clock_gettime failed %d\n", errno); 90 62 91 63 to.tv_nsec += timeout_ns; 92 64 ··· 67 95 to.tv_nsec -= 1000000000; 68 96 } 69 97 70 - info("Calling futex_waitv on f1: %u @ %p with val=%u\n", f1, &f1, f1+1); 98 + ksft_print_dbg_msg("Calling futex_waitv on f1: %u @ %p with val=%u\n", f1, &f1, f1+1); 71 99 res = futex_waitv(&waitv, 1, 0, &to, CLOCK_MONOTONIC); 72 100 if (!res || errno != EWOULDBLOCK) { 73 101 ksft_test_result_fail("futex_waitv returned: %d %s\n", 74 102 res ? errno : res, 75 103 res ? strerror(errno) : ""); 76 - ret = RET_FAIL; 77 104 } else { 78 105 ksft_test_result_pass("futex_waitv\n"); 79 106 } 80 - 81 - ksft_print_cnts(); 82 - return ret; 83 107 } 108 + 109 + TEST_HARNESS_MAIN
+44 -55
tools/testing/selftests/futex/functional/futex_waitv.c
··· 15 15 #include <pthread.h> 16 16 #include <stdint.h> 17 17 #include <sys/shm.h> 18 + 18 19 #include "futextest.h" 19 20 #include "futex2test.h" 20 - #include "logging.h" 21 + #include "../../kselftest_harness.h" 21 22 22 - #define TEST_NAME "futex-wait" 23 23 #define WAKE_WAIT_US 10000 24 24 #define NR_FUTEXES 30 25 25 static struct futex_waitv waitv[NR_FUTEXES]; 26 26 u_int32_t futexes[NR_FUTEXES] = {0}; 27 - 28 - void usage(char *prog) 29 - { 30 - printf("Usage: %s\n", prog); 31 - printf(" -c Use color\n"); 32 - printf(" -h Display this help message\n"); 33 - printf(" -v L Verbosity level: %d=QUIET %d=CRITICAL %d=INFO\n", 34 - VQUIET, VCRITICAL, VINFO); 35 - } 36 27 37 28 void *waiterfn(void *arg) 38 29 { ··· 32 41 33 42 /* setting absolute timeout for futex2 */ 34 43 if (clock_gettime(CLOCK_MONOTONIC, &to)) 35 - error("gettime64 failed\n", errno); 44 + ksft_exit_fail_msg("gettime64 failed\n"); 36 45 37 46 to.tv_sec++; 38 47 ··· 48 57 return NULL; 49 58 } 50 59 51 - int main(int argc, char *argv[]) 60 + TEST(private_waitv) 52 61 { 53 62 pthread_t waiter; 54 - int res, ret = RET_PASS; 55 - struct timespec to; 56 - int c, i; 57 - 58 - while ((c = getopt(argc, argv, "cht:v:")) != -1) { 59 - switch (c) { 60 - case 'c': 61 - log_color(1); 62 - break; 63 - case 'h': 64 - usage(basename(argv[0])); 65 - exit(0); 66 - case 'v': 67 - log_verbosity(atoi(optarg)); 68 - break; 69 - default: 70 - usage(basename(argv[0])); 71 - exit(1); 72 - } 73 - } 74 - 75 - ksft_print_header(); 76 - ksft_set_plan(7); 77 - ksft_print_msg("%s: Test FUTEX_WAITV\n", 78 - basename(argv[0])); 63 + int res, i; 79 64 80 65 for (i = 0; i < NR_FUTEXES; i++) { 81 66 waitv[i].uaddr = (uintptr_t)&futexes[i]; ··· 62 95 63 96 /* Private waitv */ 64 97 if (pthread_create(&waiter, NULL, waiterfn, NULL)) 65 - error("pthread_create failed\n", errno); 98 + ksft_exit_fail_msg("pthread_create failed\n"); 66 99 67 100 usleep(WAKE_WAIT_US); 68 101 ··· 71 104 ksft_test_result_fail("futex_wake private returned: %d %s\n", 72 105 res ? errno : res, 73 106 res ? strerror(errno) : ""); 74 - ret = RET_FAIL; 75 107 } else { 76 108 ksft_test_result_pass("futex_waitv private\n"); 77 109 } 110 + } 111 + 112 + TEST(shared_waitv) 113 + { 114 + pthread_t waiter; 115 + int res, i; 78 116 79 117 /* Shared waitv */ 80 118 for (i = 0; i < NR_FUTEXES; i++) { ··· 100 128 } 101 129 102 130 if (pthread_create(&waiter, NULL, waiterfn, NULL)) 103 - error("pthread_create failed\n", errno); 131 + ksft_exit_fail_msg("pthread_create failed\n"); 104 132 105 133 usleep(WAKE_WAIT_US); 106 134 ··· 109 137 ksft_test_result_fail("futex_wake shared returned: %d %s\n", 110 138 res ? errno : res, 111 139 res ? strerror(errno) : ""); 112 - ret = RET_FAIL; 113 140 } else { 114 141 ksft_test_result_pass("futex_waitv shared\n"); 115 142 } 116 143 117 144 for (i = 0; i < NR_FUTEXES; i++) 118 145 shmdt(u64_to_ptr(waitv[i].uaddr)); 146 + } 147 + 148 + TEST(invalid_flag) 149 + { 150 + struct timespec to; 151 + int res; 119 152 120 153 /* Testing a waiter without FUTEX_32 flag */ 121 154 waitv[0].flags = FUTEX_PRIVATE_FLAG; 122 155 123 156 if (clock_gettime(CLOCK_MONOTONIC, &to)) 124 - error("gettime64 failed\n", errno); 157 + ksft_exit_fail_msg("gettime64 failed\n"); 125 158 126 159 to.tv_sec++; 127 160 ··· 135 158 ksft_test_result_fail("futex_waitv private returned: %d %s\n", 136 159 res ? errno : res, 137 160 res ? strerror(errno) : ""); 138 - ret = RET_FAIL; 139 161 } else { 140 162 ksft_test_result_pass("futex_waitv without FUTEX_32\n"); 141 163 } 164 + } 165 + 166 + TEST(unaligned_address) 167 + { 168 + struct timespec to; 169 + int res; 142 170 143 171 /* Testing a waiter with an unaligned address */ 144 172 waitv[0].flags = FUTEX_PRIVATE_FLAG | FUTEX_32; 145 173 waitv[0].uaddr = 1; 146 174 147 175 if (clock_gettime(CLOCK_MONOTONIC, &to)) 148 - error("gettime64 failed\n", errno); 176 + ksft_exit_fail_msg("gettime64 failed\n"); 149 177 150 178 to.tv_sec++; 151 179 ··· 159 177 ksft_test_result_fail("futex_wake private returned: %d %s\n", 160 178 res ? errno : res, 161 179 res ? strerror(errno) : ""); 162 - ret = RET_FAIL; 163 180 } else { 164 181 ksft_test_result_pass("futex_waitv with an unaligned address\n"); 165 182 } 183 + } 184 + 185 + TEST(null_address) 186 + { 187 + struct timespec to; 188 + int res; 166 189 167 190 /* Testing a NULL address for waiters.uaddr */ 168 191 waitv[0].uaddr = 0x00000000; 169 192 170 193 if (clock_gettime(CLOCK_MONOTONIC, &to)) 171 - error("gettime64 failed\n", errno); 194 + ksft_exit_fail_msg("gettime64 failed\n"); 172 195 173 196 to.tv_sec++; 174 197 ··· 182 195 ksft_test_result_fail("futex_waitv private returned: %d %s\n", 183 196 res ? errno : res, 184 197 res ? strerror(errno) : ""); 185 - ret = RET_FAIL; 186 198 } else { 187 199 ksft_test_result_pass("futex_waitv NULL address in waitv.uaddr\n"); 188 200 } 189 201 190 202 /* Testing a NULL address for *waiters */ 191 203 if (clock_gettime(CLOCK_MONOTONIC, &to)) 192 - error("gettime64 failed\n", errno); 204 + ksft_exit_fail_msg("gettime64 failed\n"); 193 205 194 206 to.tv_sec++; 195 207 ··· 197 211 ksft_test_result_fail("futex_waitv private returned: %d %s\n", 198 212 res ? errno : res, 199 213 res ? strerror(errno) : ""); 200 - ret = RET_FAIL; 201 214 } else { 202 215 ksft_test_result_pass("futex_waitv NULL address in *waiters\n"); 203 216 } 217 + } 218 + 219 + TEST(invalid_clockid) 220 + { 221 + struct timespec to; 222 + int res; 204 223 205 224 /* Testing an invalid clockid */ 206 225 if (clock_gettime(CLOCK_MONOTONIC, &to)) 207 - error("gettime64 failed\n", errno); 226 + ksft_exit_fail_msg("gettime64 failed\n"); 208 227 209 228 to.tv_sec++; 210 229 ··· 218 227 ksft_test_result_fail("futex_waitv private returned: %d %s\n", 219 228 res ? errno : res, 220 229 res ? strerror(errno) : ""); 221 - ret = RET_FAIL; 222 230 } else { 223 231 ksft_test_result_pass("futex_waitv invalid clockid\n"); 224 232 } 225 - 226 - ksft_print_cnts(); 227 - return ret; 228 233 } 234 + 235 + TEST_HARNESS_MAIN
+13 -51
tools/testing/selftests/futex/functional/run.sh
··· 18 18 # 19 19 ############################################################################### 20 20 21 - # Test for a color capable console 22 - if [ -z "$USE_COLOR" ]; then 23 - tput setf 7 || tput setaf 7 24 - if [ $? -eq 0 ]; then 25 - USE_COLOR=1 26 - tput sgr0 27 - fi 28 - fi 29 - if [ "$USE_COLOR" -eq 1 ]; then 30 - COLOR="-c" 31 - fi 32 - 21 + echo 22 + ./futex_requeue_pi 33 23 34 24 echo 35 - # requeue pi testing 36 - # without timeouts 37 - ./futex_requeue_pi $COLOR 38 - ./futex_requeue_pi $COLOR -b 39 - ./futex_requeue_pi $COLOR -b -l 40 - ./futex_requeue_pi $COLOR -b -o 41 - ./futex_requeue_pi $COLOR -l 42 - ./futex_requeue_pi $COLOR -o 43 - # with timeouts 44 - ./futex_requeue_pi $COLOR -b -l -t 5000 45 - ./futex_requeue_pi $COLOR -l -t 5000 46 - ./futex_requeue_pi $COLOR -b -l -t 500000 47 - ./futex_requeue_pi $COLOR -l -t 500000 48 - ./futex_requeue_pi $COLOR -b -t 5000 49 - ./futex_requeue_pi $COLOR -t 5000 50 - ./futex_requeue_pi $COLOR -b -t 500000 51 - ./futex_requeue_pi $COLOR -t 500000 52 - ./futex_requeue_pi $COLOR -b -o -t 5000 53 - ./futex_requeue_pi $COLOR -l -t 5000 54 - ./futex_requeue_pi $COLOR -b -o -t 500000 55 - ./futex_requeue_pi $COLOR -l -t 500000 56 - # with long timeout 57 - ./futex_requeue_pi $COLOR -b -l -t 2000000000 58 - ./futex_requeue_pi $COLOR -l -t 2000000000 59 - 25 + ./futex_requeue_pi_mismatched_ops 60 26 61 27 echo 62 - ./futex_requeue_pi_mismatched_ops $COLOR 28 + ./futex_requeue_pi_signal_restart 63 29 64 30 echo 65 - ./futex_requeue_pi_signal_restart $COLOR 31 + ./futex_wait_timeout 66 32 67 33 echo 68 - ./futex_wait_timeout $COLOR 34 + ./futex_wait_wouldblock 69 35 70 36 echo 71 - ./futex_wait_wouldblock $COLOR 37 + ./futex_wait_uninitialized_heap 38 + ./futex_wait_private_mapped_file 72 39 73 40 echo 74 - ./futex_wait_uninitialized_heap $COLOR 75 - ./futex_wait_private_mapped_file $COLOR 41 + ./futex_wait 76 42 77 43 echo 78 - ./futex_wait $COLOR 44 + ./futex_requeue 79 45 80 46 echo 81 - ./futex_requeue $COLOR 47 + ./futex_waitv 82 48 83 49 echo 84 - ./futex_waitv $COLOR 50 + ./futex_priv_hash 85 51 86 52 echo 87 - ./futex_priv_hash $COLOR 88 - ./futex_priv_hash -g $COLOR 89 - 90 - echo 91 - ./futex_numa_mpol $COLOR 53 + ./futex_numa_mpol
+11
tools/testing/selftests/futex/include/futextest.h
··· 58 58 #define SYS_futex SYS_futex_time64 59 59 #endif 60 60 61 + /* 62 + * On 32bit systems if we use "-D_FILE_OFFSET_BITS=64 -D_TIME_BITS=64" or if 63 + * we are using a newer compiler then the size of the timestamps will be 64bit, 64 + * however, the SYS_futex will still point to the 32bit futex system call. 65 + */ 66 + #if __SIZEOF_POINTER__ == 4 && defined(SYS_futex_time64) && \ 67 + defined(_TIME_BITS) && _TIME_BITS == 64 68 + # undef SYS_futex 69 + # define SYS_futex SYS_futex_time64 70 + #endif 71 + 61 72 /** 62 73 * futex() - SYS_futex syscall wrapper 63 74 * @uaddr: address of first futex
-148
tools/testing/selftests/futex/include/logging.h
··· 1 - /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 - /****************************************************************************** 3 - * 4 - * Copyright © International Business Machines Corp., 2009 5 - * 6 - * DESCRIPTION 7 - * Glibc independent futex library for testing kernel functionality. 8 - * 9 - * AUTHOR 10 - * Darren Hart <dvhart@linux.intel.com> 11 - * 12 - * HISTORY 13 - * 2009-Nov-6: Initial version by Darren Hart <dvhart@linux.intel.com> 14 - * 15 - *****************************************************************************/ 16 - 17 - #ifndef _LOGGING_H 18 - #define _LOGGING_H 19 - 20 - #include <stdio.h> 21 - #include <string.h> 22 - #include <unistd.h> 23 - #include <linux/futex.h> 24 - #include "kselftest.h" 25 - 26 - /* 27 - * Define PASS, ERROR, and FAIL strings with and without color escape 28 - * sequences, default to no color. 29 - */ 30 - #define ESC 0x1B, '[' 31 - #define BRIGHT '1' 32 - #define GREEN '3', '2' 33 - #define YELLOW '3', '3' 34 - #define RED '3', '1' 35 - #define ESCEND 'm' 36 - #define BRIGHT_GREEN ESC, BRIGHT, ';', GREEN, ESCEND 37 - #define BRIGHT_YELLOW ESC, BRIGHT, ';', YELLOW, ESCEND 38 - #define BRIGHT_RED ESC, BRIGHT, ';', RED, ESCEND 39 - #define RESET_COLOR ESC, '0', 'm' 40 - static const char PASS_COLOR[] = {BRIGHT_GREEN, ' ', 'P', 'A', 'S', 'S', 41 - RESET_COLOR, 0}; 42 - static const char ERROR_COLOR[] = {BRIGHT_YELLOW, 'E', 'R', 'R', 'O', 'R', 43 - RESET_COLOR, 0}; 44 - static const char FAIL_COLOR[] = {BRIGHT_RED, ' ', 'F', 'A', 'I', 'L', 45 - RESET_COLOR, 0}; 46 - static const char INFO_NORMAL[] = " INFO"; 47 - static const char PASS_NORMAL[] = " PASS"; 48 - static const char ERROR_NORMAL[] = "ERROR"; 49 - static const char FAIL_NORMAL[] = " FAIL"; 50 - const char *INFO = INFO_NORMAL; 51 - const char *PASS = PASS_NORMAL; 52 - const char *ERROR = ERROR_NORMAL; 53 - const char *FAIL = FAIL_NORMAL; 54 - 55 - /* Verbosity setting for INFO messages */ 56 - #define VQUIET 0 57 - #define VCRITICAL 1 58 - #define VINFO 2 59 - #define VMAX VINFO 60 - int _verbose = VCRITICAL; 61 - 62 - /* Functional test return codes */ 63 - #define RET_PASS 0 64 - #define RET_ERROR -1 65 - #define RET_FAIL -2 66 - 67 - /** 68 - * log_color() - Use colored output for PASS, ERROR, and FAIL strings 69 - * @use_color: use color (1) or not (0) 70 - */ 71 - void log_color(int use_color) 72 - { 73 - if (use_color) { 74 - PASS = PASS_COLOR; 75 - ERROR = ERROR_COLOR; 76 - FAIL = FAIL_COLOR; 77 - } else { 78 - PASS = PASS_NORMAL; 79 - ERROR = ERROR_NORMAL; 80 - FAIL = FAIL_NORMAL; 81 - } 82 - } 83 - 84 - /** 85 - * log_verbosity() - Set verbosity of test output 86 - * @verbose: Enable (1) verbose output or not (0) 87 - * 88 - * Currently setting verbose=1 will enable INFO messages and 0 will disable 89 - * them. FAIL and ERROR messages are always displayed. 90 - */ 91 - void log_verbosity(int level) 92 - { 93 - if (level > VMAX) 94 - level = VMAX; 95 - else if (level < 0) 96 - level = 0; 97 - _verbose = level; 98 - } 99 - 100 - /** 101 - * print_result() - Print standard PASS | ERROR | FAIL results 102 - * @ret: the return value to be considered: 0 | RET_ERROR | RET_FAIL 103 - * 104 - * print_result() is primarily intended for functional tests. 105 - */ 106 - void print_result(const char *test_name, int ret) 107 - { 108 - switch (ret) { 109 - case RET_PASS: 110 - ksft_test_result_pass("%s\n", test_name); 111 - ksft_print_cnts(); 112 - return; 113 - case RET_ERROR: 114 - ksft_test_result_error("%s\n", test_name); 115 - ksft_print_cnts(); 116 - return; 117 - case RET_FAIL: 118 - ksft_test_result_fail("%s\n", test_name); 119 - ksft_print_cnts(); 120 - return; 121 - } 122 - } 123 - 124 - /* log level macros */ 125 - #define info(message, vargs...) \ 126 - do { \ 127 - if (_verbose >= VINFO) \ 128 - fprintf(stderr, "\t%s: "message, INFO, ##vargs); \ 129 - } while (0) 130 - 131 - #define error(message, err, args...) \ 132 - do { \ 133 - if (_verbose >= VCRITICAL) {\ 134 - if (err) \ 135 - fprintf(stderr, "\t%s: %s: "message, \ 136 - ERROR, strerror(err), ##args); \ 137 - else \ 138 - fprintf(stderr, "\t%s: "message, ERROR, ##args); \ 139 - } \ 140 - } while (0) 141 - 142 - #define fail(message, args...) \ 143 - do { \ 144 - if (_verbose >= VCRITICAL) \ 145 - fprintf(stderr, "\t%s: "message, FAIL, ##args); \ 146 - } while (0) 147 - 148 - #endif
+14
tools/testing/selftests/kselftest.h
··· 54 54 #include <stdlib.h> 55 55 #include <unistd.h> 56 56 #include <stdarg.h> 57 + #include <stdbool.h> 57 58 #include <string.h> 58 59 #include <stdio.h> 59 60 #include <sys/utsname.h> ··· 105 104 106 105 static struct ksft_count ksft_cnt; 107 106 static unsigned int ksft_plan; 107 + static bool ksft_debug_enabled; 108 108 109 109 static inline unsigned int ksft_test_num(void) 110 110 { ··· 174 172 printf("# "); 175 173 errno = saved_errno; 176 174 vprintf(msg, args); 175 + va_end(args); 176 + } 177 + 178 + static inline void ksft_print_dbg_msg(const char *msg, ...) 179 + { 180 + va_list args; 181 + 182 + if (!ksft_debug_enabled) 183 + return; 184 + 185 + va_start(args, msg); 186 + ksft_print_msg(msg, args); 177 187 va_end(args); 178 188 } 179 189
+9 -4
tools/testing/selftests/kselftest_harness.h
··· 1091 1091 { 1092 1092 int opt; 1093 1093 1094 - while ((opt = getopt(argc, argv, "hlF:f:V:v:t:T:r:")) != -1) { 1094 + while ((opt = getopt(argc, argv, "dhlF:f:V:v:t:T:r:")) != -1) { 1095 1095 switch (opt) { 1096 1096 case 'f': 1097 1097 case 'F': ··· 1104 1104 case 'l': 1105 1105 test_harness_list_tests(); 1106 1106 return KSFT_SKIP; 1107 + case 'd': 1108 + ksft_debug_enabled = true; 1109 + break; 1107 1110 case 'h': 1108 1111 default: 1109 1112 fprintf(stderr, 1110 - "Usage: %s [-h|-l] [-t|-T|-v|-V|-f|-F|-r name]\n" 1113 + "Usage: %s [-h|-l|-d] [-t|-T|-v|-V|-f|-F|-r name]\n" 1111 1114 "\t-h print help\n" 1112 1115 "\t-l list all tests\n" 1116 + "\t-d enable debug prints\n" 1113 1117 "\n" 1114 1118 "\t-t name include test\n" 1115 1119 "\t-T name exclude test\n" ··· 1146 1142 int opt; 1147 1143 1148 1144 optind = 1; 1149 - while ((opt = getopt(argc, argv, "F:f:V:v:t:T:r:")) != -1) { 1150 - has_positive |= islower(opt); 1145 + while ((opt = getopt(argc, argv, "dF:f:V:v:t:T:r:")) != -1) { 1146 + if (opt != 'd') 1147 + has_positive |= islower(opt); 1151 1148 1152 1149 switch (tolower(opt)) { 1153 1150 case 't':