Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/tools/testing/selftests/futex/functional/futex_waitv.c
29271 views
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/*
3
* futex_waitv() test by AndrĂ© Almeida <[email protected]>
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
25
static struct futex_waitv waitv[NR_FUTEXES];
26
u_int32_t futexes[NR_FUTEXES] = {0};
27
28
void *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
51
TEST(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
79
TEST(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
perror("shmget");
90
exit(1);
91
}
92
93
unsigned int *shared_data = shmat(shm_id, NULL, 0);
94
95
*shared_data = 0;
96
waitv[i].uaddr = (uintptr_t)shared_data;
97
waitv[i].flags = FUTEX_32;
98
waitv[i].val = 0;
99
waitv[i].__reserved = 0;
100
}
101
102
if (pthread_create(&waiter, NULL, waiterfn, NULL))
103
ksft_exit_fail_msg("pthread_create failed\n");
104
105
usleep(WAKE_WAIT_US);
106
107
res = futex_wake(u64_to_ptr(waitv[NR_FUTEXES - 1].uaddr), 1, 0);
108
if (res != 1) {
109
ksft_test_result_fail("futex_wake shared returned: %d %s\n",
110
res ? errno : res,
111
res ? strerror(errno) : "");
112
} else {
113
ksft_test_result_pass("futex_waitv shared\n");
114
}
115
116
for (i = 0; i < NR_FUTEXES; i++)
117
shmdt(u64_to_ptr(waitv[i].uaddr));
118
}
119
120
TEST(invalid_flag)
121
{
122
struct timespec to;
123
int res;
124
125
/* Testing a waiter without FUTEX_32 flag */
126
waitv[0].flags = FUTEX_PRIVATE_FLAG;
127
128
if (clock_gettime(CLOCK_MONOTONIC, &to))
129
ksft_exit_fail_msg("gettime64 failed\n");
130
131
to.tv_sec++;
132
133
res = futex_waitv(waitv, NR_FUTEXES, 0, &to, CLOCK_MONOTONIC);
134
if (res == EINVAL) {
135
ksft_test_result_fail("futex_waitv private returned: %d %s\n",
136
res ? errno : res,
137
res ? strerror(errno) : "");
138
} else {
139
ksft_test_result_pass("futex_waitv without FUTEX_32\n");
140
}
141
}
142
143
TEST(unaligned_address)
144
{
145
struct timespec to;
146
int res;
147
148
/* Testing a waiter with an unaligned address */
149
waitv[0].flags = FUTEX_PRIVATE_FLAG | FUTEX_32;
150
waitv[0].uaddr = 1;
151
152
if (clock_gettime(CLOCK_MONOTONIC, &to))
153
ksft_exit_fail_msg("gettime64 failed\n");
154
155
to.tv_sec++;
156
157
res = futex_waitv(waitv, NR_FUTEXES, 0, &to, CLOCK_MONOTONIC);
158
if (res == EINVAL) {
159
ksft_test_result_fail("futex_wake private returned: %d %s\n",
160
res ? errno : res,
161
res ? strerror(errno) : "");
162
} else {
163
ksft_test_result_pass("futex_waitv with an unaligned address\n");
164
}
165
}
166
167
TEST(null_address)
168
{
169
struct timespec to;
170
int res;
171
172
/* Testing a NULL address for waiters.uaddr */
173
waitv[0].uaddr = 0x00000000;
174
175
if (clock_gettime(CLOCK_MONOTONIC, &to))
176
ksft_exit_fail_msg("gettime64 failed\n");
177
178
to.tv_sec++;
179
180
res = futex_waitv(waitv, NR_FUTEXES, 0, &to, CLOCK_MONOTONIC);
181
if (res == EINVAL) {
182
ksft_test_result_fail("futex_waitv private returned: %d %s\n",
183
res ? errno : res,
184
res ? strerror(errno) : "");
185
} else {
186
ksft_test_result_pass("futex_waitv NULL address in waitv.uaddr\n");
187
}
188
189
/* Testing a NULL address for *waiters */
190
if (clock_gettime(CLOCK_MONOTONIC, &to))
191
ksft_exit_fail_msg("gettime64 failed\n");
192
193
to.tv_sec++;
194
195
res = futex_waitv(NULL, NR_FUTEXES, 0, &to, CLOCK_MONOTONIC);
196
if (res == EINVAL) {
197
ksft_test_result_fail("futex_waitv private returned: %d %s\n",
198
res ? errno : res,
199
res ? strerror(errno) : "");
200
} else {
201
ksft_test_result_pass("futex_waitv NULL address in *waiters\n");
202
}
203
}
204
205
TEST(invalid_clockid)
206
{
207
struct timespec to;
208
int res;
209
210
/* Testing an invalid clockid */
211
if (clock_gettime(CLOCK_MONOTONIC, &to))
212
ksft_exit_fail_msg("gettime64 failed\n");
213
214
to.tv_sec++;
215
216
res = futex_waitv(NULL, NR_FUTEXES, 0, &to, CLOCK_TAI);
217
if (res == EINVAL) {
218
ksft_test_result_fail("futex_waitv private returned: %d %s\n",
219
res ? errno : res,
220
res ? strerror(errno) : "");
221
} else {
222
ksft_test_result_pass("futex_waitv invalid clockid\n");
223
}
224
}
225
226
TEST_HARNESS_MAIN
227
228