1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Copyright Collabora Ltd., 2021 4 * 5 * futex cmp requeue test by André Almeida <andrealmeid@collabora.com> 6 */ 7 8 #include <pthread.h> 9 #include <sys/shm.h> 10 #include <sys/mman.h> 11 #include <fcntl.h> 12 13 #include "futextest.h" 14 #include "../../kselftest_harness.h" 15 16 #define timeout_ns 30000000 17 #define WAKE_WAIT_US 10000 18 #define SHM_PATH "futex_shm_file" 19 20 void *futex; 21 22 static void *waiterfn(void *arg) 23 { 24 struct timespec to; 25 unsigned int flags = 0; 26 27 if (arg) 28 flags = *((unsigned int *) arg); 29 30 to.tv_sec = 0; 31 to.tv_nsec = timeout_ns; 32 33 if (futex_wait(futex, 0, &to, flags)) 34 printf("waiter failed errno %d\n", errno); 35 36 return NULL; 37 } 38 39 TEST(private_futex) 40 { 41 unsigned int flags = FUTEX_PRIVATE_FLAG; 42 u_int32_t f_private = 0; 43 pthread_t waiter; 44 int res; 45 46 futex = &f_private; 47 48 /* Testing a private futex */ 49 ksft_print_dbg_msg("Calling private futex_wait on futex: %p\n", futex); 50 if (pthread_create(&waiter, NULL, waiterfn, (void *) &flags)) 51 ksft_exit_fail_msg("pthread_create failed\n"); 52 53 usleep(WAKE_WAIT_US); 54 55 ksft_print_dbg_msg("Calling private futex_wake on futex: %p\n", futex); 56 res = futex_wake(futex, 1, FUTEX_PRIVATE_FLAG); 57 if (res != 1) { 58 ksft_test_result_fail("futex_wake private returned: %d %s\n", 59 errno, strerror(errno)); 60 } else { 61 ksft_test_result_pass("futex_wake private succeeds\n"); 62 } 63 } 64 65 TEST(anon_page) 66 { 67 u_int32_t *shared_data; 68 pthread_t waiter; 69 int res, shm_id; 70 71 /* Testing an anon page shared memory */ 72 shm_id = shmget(IPC_PRIVATE, 4096, IPC_CREAT | 0666); 73 if (shm_id < 0) { 74 perror("shmget"); 75 exit(1); 76 } 77 78 shared_data = shmat(shm_id, NULL, 0); 79 80 *shared_data = 0; 81 futex = shared_data; 82 83 ksft_print_dbg_msg("Calling shared (page anon) futex_wait on futex: %p\n", futex); 84 if (pthread_create(&waiter, NULL, waiterfn, NULL)) 85 ksft_exit_fail_msg("pthread_create failed\n"); 86 87 usleep(WAKE_WAIT_US); 88 89 ksft_print_dbg_msg("Calling shared (page anon) futex_wake on futex: %p\n", futex); 90 res = futex_wake(futex, 1, 0); 91 if (res != 1) { 92 ksft_test_result_fail("futex_wake shared (page anon) returned: %d %s\n", 93 errno, strerror(errno)); 94 } else { 95 ksft_test_result_pass("futex_wake shared (page anon) succeeds\n"); 96 } 97 98 shmdt(shared_data); 99 } 100 101 TEST(file_backed) 102 { 103 u_int32_t f_private = 0; 104 pthread_t waiter; 105 int res, fd; 106 void *shm; 107 108 /* Testing a file backed shared memory */ 109 fd = open(SHM_PATH, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); 110 if (fd < 0) 111 ksft_exit_fail_msg("open"); 112 113 if (ftruncate(fd, sizeof(f_private))) 114 ksft_exit_fail_msg("ftruncate"); 115 116 shm = mmap(NULL, sizeof(f_private), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 117 if (shm == MAP_FAILED) 118 ksft_exit_fail_msg("mmap"); 119 120 memcpy(shm, &f_private, sizeof(f_private)); 121 122 futex = shm; 123 124 ksft_print_dbg_msg("Calling shared (file backed) futex_wait on futex: %p\n", futex); 125 if (pthread_create(&waiter, NULL, waiterfn, NULL)) 126 ksft_exit_fail_msg("pthread_create failed\n"); 127 128 usleep(WAKE_WAIT_US); 129 130 ksft_print_dbg_msg("Calling shared (file backed) futex_wake on futex: %p\n", futex); 131 res = futex_wake(shm, 1, 0); 132 if (res != 1) { 133 ksft_test_result_fail("futex_wake shared (file backed) returned: %d %s\n", 134 errno, strerror(errno)); 135 } else { 136 ksft_test_result_pass("futex_wake shared (file backed) succeeds\n"); 137 } 138 139 munmap(shm, sizeof(f_private)); 140 remove(SHM_PATH); 141 close(fd); 142 } 143 144 TEST_HARNESS_MAIN 145