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.

at master 228 lines 5.4 kB view raw
1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * futex_waitv() test by André Almeida <andrealmeid@collabora.com> 4 * 5 * Copyright 2021 Collabora Ltd. 6 */ 7 8#include <errno.h> 9#include <error.h> 10#include <getopt.h> 11#include <stdio.h> 12#include <stdlib.h> 13#include <string.h> 14#include <time.h> 15#include <pthread.h> 16#include <stdint.h> 17#include <sys/shm.h> 18 19#include "futextest.h" 20#include "futex2test.h" 21#include "kselftest_harness.h" 22 23#define WAKE_WAIT_US 10000 24#define NR_FUTEXES 30 25static struct futex_waitv waitv[NR_FUTEXES]; 26u_int32_t futexes[NR_FUTEXES] = {0}; 27 28void *waiterfn(void *arg) 29{ 30 struct timespec to; 31 int res; 32 33 /* setting absolute timeout for futex2 */ 34 if (clock_gettime(CLOCK_MONOTONIC, &to)) 35 ksft_exit_fail_msg("gettime64 failed\n"); 36 37 to.tv_sec++; 38 39 res = futex_waitv(waitv, NR_FUTEXES, 0, &to, CLOCK_MONOTONIC); 40 if (res < 0) { 41 ksft_test_result_fail("futex_waitv returned: %d %s\n", 42 errno, strerror(errno)); 43 } else if (res != NR_FUTEXES - 1) { 44 ksft_test_result_fail("futex_waitv returned: %d, expecting %d\n", 45 res, NR_FUTEXES - 1); 46 } 47 48 return NULL; 49} 50 51TEST(private_waitv) 52{ 53 pthread_t waiter; 54 int res, i; 55 56 for (i = 0; i < NR_FUTEXES; i++) { 57 waitv[i].uaddr = (uintptr_t)&futexes[i]; 58 waitv[i].flags = FUTEX_32 | FUTEX_PRIVATE_FLAG; 59 waitv[i].val = 0; 60 waitv[i].__reserved = 0; 61 } 62 63 /* Private waitv */ 64 if (pthread_create(&waiter, NULL, waiterfn, NULL)) 65 ksft_exit_fail_msg("pthread_create failed\n"); 66 67 usleep(WAKE_WAIT_US); 68 69 res = futex_wake(u64_to_ptr(waitv[NR_FUTEXES - 1].uaddr), 1, FUTEX_PRIVATE_FLAG); 70 if (res != 1) { 71 ksft_test_result_fail("futex_wake private returned: %d %s\n", 72 res ? errno : res, 73 res ? strerror(errno) : ""); 74 } else { 75 ksft_test_result_pass("futex_waitv private\n"); 76 } 77} 78 79TEST(shared_waitv) 80{ 81 pthread_t waiter; 82 int res, i; 83 84 /* Shared waitv */ 85 for (i = 0; i < NR_FUTEXES; i++) { 86 int shm_id = shmget(IPC_PRIVATE, 4096, IPC_CREAT | 0666); 87 88 if (shm_id < 0) { 89 if (errno == ENOSYS) 90 ksft_exit_skip("shmget syscall not supported\n"); 91 perror("shmget"); 92 exit(1); 93 } 94 95 unsigned int *shared_data = shmat(shm_id, NULL, 0); 96 97 *shared_data = 0; 98 waitv[i].uaddr = (uintptr_t)shared_data; 99 waitv[i].flags = FUTEX_32; 100 waitv[i].val = 0; 101 waitv[i].__reserved = 0; 102 } 103 104 if (pthread_create(&waiter, NULL, waiterfn, NULL)) 105 ksft_exit_fail_msg("pthread_create failed\n"); 106 107 usleep(WAKE_WAIT_US); 108 109 res = futex_wake(u64_to_ptr(waitv[NR_FUTEXES - 1].uaddr), 1, 0); 110 if (res != 1) { 111 ksft_test_result_fail("futex_wake shared returned: %d %s\n", 112 res ? errno : res, 113 res ? strerror(errno) : ""); 114 } else { 115 ksft_test_result_pass("futex_waitv shared\n"); 116 } 117 118 for (i = 0; i < NR_FUTEXES; i++) 119 shmdt(u64_to_ptr(waitv[i].uaddr)); 120} 121 122TEST(invalid_flag) 123{ 124 struct timespec to; 125 int res; 126 127 /* Testing a waiter without FUTEX_32 flag */ 128 waitv[0].flags = FUTEX_PRIVATE_FLAG; 129 130 if (clock_gettime(CLOCK_MONOTONIC, &to)) 131 ksft_exit_fail_msg("gettime64 failed\n"); 132 133 to.tv_sec++; 134 135 res = futex_waitv(waitv, NR_FUTEXES, 0, &to, CLOCK_MONOTONIC); 136 if (res == EINVAL) { 137 ksft_test_result_fail("futex_waitv private returned: %d %s\n", 138 res ? errno : res, 139 res ? strerror(errno) : ""); 140 } else { 141 ksft_test_result_pass("futex_waitv without FUTEX_32\n"); 142 } 143} 144 145TEST(unaligned_address) 146{ 147 struct timespec to; 148 int res; 149 150 /* Testing a waiter with an unaligned address */ 151 waitv[0].flags = FUTEX_PRIVATE_FLAG | FUTEX_32; 152 waitv[0].uaddr = 1; 153 154 if (clock_gettime(CLOCK_MONOTONIC, &to)) 155 ksft_exit_fail_msg("gettime64 failed\n"); 156 157 to.tv_sec++; 158 159 res = futex_waitv(waitv, NR_FUTEXES, 0, &to, CLOCK_MONOTONIC); 160 if (res == EINVAL) { 161 ksft_test_result_fail("futex_wake private returned: %d %s\n", 162 res ? errno : res, 163 res ? strerror(errno) : ""); 164 } else { 165 ksft_test_result_pass("futex_waitv with an unaligned address\n"); 166 } 167} 168 169TEST(null_address) 170{ 171 struct timespec to; 172 int res; 173 174 /* Testing a NULL address for waiters.uaddr */ 175 waitv[0].uaddr = 0x00000000; 176 177 if (clock_gettime(CLOCK_MONOTONIC, &to)) 178 ksft_exit_fail_msg("gettime64 failed\n"); 179 180 to.tv_sec++; 181 182 res = futex_waitv(waitv, NR_FUTEXES, 0, &to, CLOCK_MONOTONIC); 183 if (res == EINVAL) { 184 ksft_test_result_fail("futex_waitv private returned: %d %s\n", 185 res ? errno : res, 186 res ? strerror(errno) : ""); 187 } else { 188 ksft_test_result_pass("futex_waitv NULL address in waitv.uaddr\n"); 189 } 190 191 /* Testing a NULL address for *waiters */ 192 if (clock_gettime(CLOCK_MONOTONIC, &to)) 193 ksft_exit_fail_msg("gettime64 failed\n"); 194 195 to.tv_sec++; 196 197 res = futex_waitv(NULL, NR_FUTEXES, 0, &to, CLOCK_MONOTONIC); 198 if (res == EINVAL) { 199 ksft_test_result_fail("futex_waitv private returned: %d %s\n", 200 res ? errno : res, 201 res ? strerror(errno) : ""); 202 } else { 203 ksft_test_result_pass("futex_waitv NULL address in *waiters\n"); 204 } 205} 206 207TEST(invalid_clockid) 208{ 209 struct timespec to; 210 int res; 211 212 /* Testing an invalid clockid */ 213 if (clock_gettime(CLOCK_MONOTONIC, &to)) 214 ksft_exit_fail_msg("gettime64 failed\n"); 215 216 to.tv_sec++; 217 218 res = futex_waitv(NULL, NR_FUTEXES, 0, &to, CLOCK_TAI); 219 if (res == EINVAL) { 220 ksft_test_result_fail("futex_waitv private returned: %d %s\n", 221 res ? errno : res, 222 res ? strerror(errno) : ""); 223 } else { 224 ksft_test_result_pass("futex_waitv invalid clockid\n"); 225 } 226} 227 228TEST_HARNESS_MAIN