File Index
Files and directories
Sign in
FILE

futex_waitv.c

File preview with syntax highlighting.

linux-6.19.14/tools/testing/selftests/futex/functional/futex_waitv.c C
  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
~/ Read-only file preview.