]>
Commit | Line | Data |
---|---|---|
6d7e8eda | 1 | /* Copyright (C) 2003-2023 Free Software Foundation, Inc. |
61623643 | 2 | This file is part of the GNU C Library. |
61623643 UD |
3 | |
4 | The GNU C Library is free software; you can redistribute it and/or | |
5 | modify it under the terms of the GNU Lesser General Public | |
6 | License as published by the Free Software Foundation; either | |
7 | version 2.1 of the License, or (at your option) any later version. | |
8 | ||
9 | The GNU C Library is distributed in the hope that it will be useful, | |
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
12 | Lesser General Public License for more details. | |
13 | ||
14 | You should have received a copy of the GNU Lesser General Public | |
59ba27a6 | 15 | License along with the GNU C Library; if not, see |
5a82c748 | 16 | <https://www.gnu.org/licenses/>. */ |
61623643 UD |
17 | |
18 | /* This test checks behavior not required by POSIX. */ | |
19 | #include <errno.h> | |
20 | #include <pthread.h> | |
21 | #include <stdbool.h> | |
22 | #include <stdio.h> | |
23 | #include <stdlib.h> | |
87245073 SL |
24 | #include <unistd.h> |
25 | #include <elf/dl-tunables.h> | |
61623643 UD |
26 | |
27 | static pthread_mutex_t *m; | |
28 | static pthread_barrier_t b; | |
29 | static pthread_cond_t c; | |
30 | static bool done; | |
31 | ||
32 | ||
33 | static void | |
34 | cl (void *arg) | |
35 | { | |
36 | if (pthread_mutex_unlock (m) != 0) | |
37 | { | |
38 | puts ("cl: mutex_unlocked failed"); | |
39 | exit (1); | |
40 | } | |
41 | } | |
42 | ||
43 | ||
44 | static void * | |
45 | tf (void *arg) | |
46 | { | |
47 | if (pthread_mutex_lock (m) != 0) | |
48 | { | |
49 | puts ("tf: mutex_lock failed"); | |
50 | return (void *) 1l; | |
51 | } | |
52 | ||
53 | int e = pthread_barrier_wait (&b); | |
54 | if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD) | |
55 | { | |
56 | puts ("barrier_wait failed"); | |
57 | return (void *) 1l; | |
58 | } | |
59 | ||
60 | if (arg == NULL) | |
61 | do | |
62 | if (pthread_cond_wait (&c, m) != 0) | |
63 | { | |
64 | puts ("tf: cond_wait failed"); | |
65 | return (void *) 1l; | |
66 | } | |
67 | while (! done); | |
68 | else | |
69 | do | |
70 | { | |
71 | pthread_cleanup_push (cl, NULL); | |
72 | ||
73 | if (pthread_cond_wait (&c, m) != 0) | |
74 | { | |
75 | puts ("tf: cond_wait failed"); | |
76 | return (void *) 1l; | |
77 | } | |
78 | ||
79 | pthread_cleanup_pop (0); | |
80 | } | |
81 | while (! done); | |
82 | ||
83 | if (pthread_mutex_unlock (m) != 0) | |
84 | { | |
85 | puts ("tf: mutex_unlock failed"); | |
86 | return (void *) 1l; | |
87 | } | |
88 | ||
89 | return NULL; | |
90 | } | |
91 | ||
92 | ||
93 | static int | |
94 | check_type (const char *mas, pthread_mutexattr_t *ma) | |
95 | { | |
53247a0b | 96 | int e; |
68cc2935 | 97 | |
87245073 SL |
98 | /* Check if a mutex will be elided. Lock elision can only be activated via |
99 | the tunables framework. By default, lock elision is disabled. */ | |
100 | bool assume_elided_mutex = false; | |
87245073 SL |
101 | int ma_type = PTHREAD_MUTEX_TIMED_NP; |
102 | if (ma != NULL) | |
103 | { | |
104 | e = pthread_mutexattr_gettype (ma, &ma_type); | |
105 | if (e != 0) | |
106 | { | |
107 | printf ("pthread_mutexattr_gettype failed with %d (%m)\n", e); | |
108 | return 1; | |
109 | } | |
110 | } | |
111 | if (ma_type == PTHREAD_MUTEX_TIMED_NP) | |
112 | { | |
113 | /* This type of mutex can be elided if elision is enabled via the tunables | |
114 | framework. Some tests below are failing if the mutex is elided. | |
115 | Thus we only run those if we assume that the mutex won't be elided. */ | |
116 | if (TUNABLE_GET_FULL (glibc, elision, enable, int32_t, NULL) == 1) | |
117 | assume_elided_mutex = true; | |
118 | } | |
87245073 | 119 | |
53247a0b MR |
120 | e = pthread_mutex_init (m, ma); |
121 | if (e != 0) | |
61623643 | 122 | { |
53247a0b MR |
123 | #ifdef ENABLE_PI |
124 | if (e == ENOTSUP) | |
125 | { | |
126 | puts ("PI mutexes unsupported"); | |
127 | return 0; | |
128 | } | |
129 | #endif | |
61623643 UD |
130 | printf ("1st mutex_init failed for %s\n", mas); |
131 | return 1; | |
132 | } | |
133 | ||
134 | if (pthread_mutex_destroy (m) != 0) | |
135 | { | |
136 | printf ("immediate mutex_destroy failed for %s\n", mas); | |
137 | return 1; | |
138 | } | |
139 | ||
140 | if (pthread_mutex_init (m, ma) != 0) | |
141 | { | |
142 | printf ("2nd mutex_init failed for %s\n", mas); | |
143 | return 1; | |
144 | } | |
145 | ||
146 | if (pthread_mutex_lock (m) != 0) | |
147 | { | |
148 | printf ("1st mutex_lock failed for %s\n", mas); | |
149 | return 1; | |
150 | } | |
151 | ||
87245073 SL |
152 | /* Elided mutexes don't fail destroy, thus only test this if we don't assume |
153 | elision. */ | |
154 | if (assume_elided_mutex == false) | |
61623643 | 155 | { |
87245073 SL |
156 | e = pthread_mutex_destroy (m); |
157 | if (e == 0) | |
158 | { | |
159 | printf ("mutex_destroy of self-locked mutex succeeded for %s\n", mas); | |
160 | return 1; | |
161 | } | |
162 | if (e != EBUSY) | |
163 | { | |
164 | printf ("\ | |
165 | mutex_destroy of self-locked mutex did not return EBUSY %s\n", | |
166 | mas); | |
167 | return 1; | |
168 | } | |
61623643 UD |
169 | } |
170 | ||
171 | if (pthread_mutex_unlock (m) != 0) | |
172 | { | |
173 | printf ("1st mutex_unlock failed for %s\n", mas); | |
174 | return 1; | |
175 | } | |
176 | ||
177 | if (pthread_mutex_trylock (m) != 0) | |
178 | { | |
179 | printf ("mutex_trylock failed for %s\n", mas); | |
180 | return 1; | |
181 | } | |
182 | ||
68cc2935 | 183 | /* Elided mutexes don't fail destroy. */ |
87245073 | 184 | if (assume_elided_mutex == false) |
61623643 | 185 | { |
87245073 SL |
186 | e = pthread_mutex_destroy (m); |
187 | if (e == 0) | |
188 | { | |
189 | printf ("mutex_destroy of self-trylocked mutex succeeded for %s\n", | |
190 | mas); | |
191 | return 1; | |
192 | } | |
193 | if (e != EBUSY) | |
194 | { | |
195 | printf ("\ | |
61623643 | 196 | mutex_destroy of self-trylocked mutex did not return EBUSY %s\n", |
87245073 SL |
197 | mas); |
198 | return 1; | |
199 | } | |
61623643 UD |
200 | } |
201 | ||
202 | if (pthread_mutex_unlock (m) != 0) | |
203 | { | |
204 | printf ("2nd mutex_unlock failed for %s\n", mas); | |
205 | return 1; | |
206 | } | |
207 | ||
208 | pthread_t th; | |
209 | if (pthread_create (&th, NULL, tf, NULL) != 0) | |
210 | { | |
211 | puts ("1st create failed"); | |
212 | return 1; | |
213 | } | |
214 | done = false; | |
215 | ||
216 | e = pthread_barrier_wait (&b); | |
217 | if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD) | |
218 | { | |
219 | puts ("1st barrier_wait failed"); | |
220 | return 1; | |
221 | } | |
222 | ||
223 | if (pthread_mutex_lock (m) != 0) | |
224 | { | |
225 | printf ("2nd mutex_lock failed for %s\n", mas); | |
226 | return 1; | |
227 | } | |
228 | ||
229 | if (pthread_mutex_unlock (m) != 0) | |
230 | { | |
231 | printf ("3rd mutex_unlock failed for %s\n", mas); | |
232 | return 1; | |
233 | } | |
234 | ||
68cc2935 | 235 | /* Elided mutexes don't fail destroy. */ |
87245073 | 236 | if (assume_elided_mutex == false) |
61623643 | 237 | { |
87245073 SL |
238 | e = pthread_mutex_destroy (m); |
239 | if (e == 0) | |
240 | { | |
241 | printf ("mutex_destroy of condvar-used mutex succeeded for %s\n", | |
242 | mas); | |
243 | return 1; | |
244 | } | |
245 | if (e != EBUSY) | |
246 | { | |
247 | printf ("\ | |
61623643 | 248 | mutex_destroy of condvar-used mutex did not return EBUSY for %s\n", mas); |
87245073 SL |
249 | return 1; |
250 | } | |
61623643 UD |
251 | } |
252 | ||
253 | done = true; | |
254 | if (pthread_cond_signal (&c) != 0) | |
255 | { | |
256 | puts ("cond_signal failed"); | |
257 | return 1; | |
258 | } | |
259 | ||
260 | void *r; | |
261 | if (pthread_join (th, &r) != 0) | |
262 | { | |
263 | puts ("join failed"); | |
264 | return 1; | |
265 | } | |
266 | if (r != NULL) | |
267 | { | |
268 | puts ("thread didn't return NULL"); | |
269 | return 1; | |
270 | } | |
271 | ||
272 | if (pthread_mutex_destroy (m) != 0) | |
273 | { | |
274 | printf ("mutex_destroy after condvar-use failed for %s\n", mas); | |
275 | return 1; | |
276 | } | |
277 | ||
278 | if (pthread_mutex_init (m, ma) != 0) | |
279 | { | |
280 | printf ("3rd mutex_init failed for %s\n", mas); | |
281 | return 1; | |
282 | } | |
283 | ||
284 | if (pthread_create (&th, NULL, tf, (void *) 1) != 0) | |
285 | { | |
286 | puts ("2nd create failed"); | |
287 | return 1; | |
288 | } | |
289 | done = false; | |
290 | ||
291 | e = pthread_barrier_wait (&b); | |
292 | if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD) | |
293 | { | |
294 | puts ("2nd barrier_wait failed"); | |
295 | return 1; | |
296 | } | |
297 | ||
298 | if (pthread_mutex_lock (m) != 0) | |
299 | { | |
300 | printf ("3rd mutex_lock failed for %s\n", mas); | |
301 | return 1; | |
302 | } | |
303 | ||
304 | if (pthread_mutex_unlock (m) != 0) | |
305 | { | |
306 | printf ("4th mutex_unlock failed for %s\n", mas); | |
307 | return 1; | |
308 | } | |
309 | ||
68cc2935 | 310 | /* Elided mutexes don't fail destroy. */ |
87245073 | 311 | if (assume_elided_mutex == false) |
61623643 | 312 | { |
87245073 SL |
313 | e = pthread_mutex_destroy (m); |
314 | if (e == 0) | |
315 | { | |
316 | printf ("2nd mutex_destroy of condvar-used mutex succeeded for %s\n", | |
317 | mas); | |
318 | return 1; | |
319 | } | |
320 | if (e != EBUSY) | |
321 | { | |
322 | printf ("\ | |
61623643 | 323 | 2nd mutex_destroy of condvar-used mutex did not return EBUSY for %s\n", |
87245073 SL |
324 | mas); |
325 | return 1; | |
326 | } | |
61623643 UD |
327 | } |
328 | ||
329 | if (pthread_cancel (th) != 0) | |
330 | { | |
331 | puts ("cond_cancel failed"); | |
332 | return 1; | |
333 | } | |
334 | ||
335 | if (pthread_join (th, &r) != 0) | |
336 | { | |
337 | puts ("join failed"); | |
338 | return 1; | |
339 | } | |
340 | if (r != PTHREAD_CANCELED) | |
341 | { | |
342 | puts ("thread not canceled"); | |
343 | return 1; | |
344 | } | |
345 | ||
346 | if (pthread_mutex_destroy (m) != 0) | |
347 | { | |
348 | printf ("mutex_destroy after condvar-canceled failed for %s\n", mas); | |
349 | return 1; | |
350 | } | |
351 | ||
352 | return 0; | |
353 | } | |
354 | ||
355 | ||
356 | static int | |
357 | do_test (void) | |
358 | { | |
359 | pthread_mutex_t mm; | |
360 | m = &mm; | |
361 | ||
362 | if (pthread_barrier_init (&b, NULL, 2) != 0) | |
363 | { | |
364 | puts ("barrier_init failed"); | |
365 | return 1; | |
366 | } | |
367 | ||
368 | if (pthread_cond_init (&c, NULL) != 0) | |
369 | { | |
370 | puts ("cond_init failed"); | |
371 | return 1; | |
372 | } | |
373 | ||
374 | puts ("check normal mutex"); | |
375 | int res = check_type ("normal", NULL); | |
376 | ||
377 | pthread_mutexattr_t ma; | |
378 | if (pthread_mutexattr_init (&ma) != 0) | |
379 | { | |
380 | puts ("1st mutexattr_init failed"); | |
381 | return 1; | |
382 | } | |
383 | if (pthread_mutexattr_settype (&ma, PTHREAD_MUTEX_RECURSIVE) != 0) | |
384 | { | |
385 | puts ("1st mutexattr_settype failed"); | |
386 | return 1; | |
387 | } | |
66c13581 AK |
388 | #ifdef ENABLE_PI |
389 | if (pthread_mutexattr_setprotocol (&ma, PTHREAD_PRIO_INHERIT)) | |
390 | { | |
391 | puts ("1st pthread_mutexattr_setprotocol failed"); | |
392 | return 1; | |
393 | } | |
394 | #endif | |
61623643 UD |
395 | puts ("check recursive mutex"); |
396 | res |= check_type ("recursive", &ma); | |
397 | if (pthread_mutexattr_destroy (&ma) != 0) | |
398 | { | |
399 | puts ("1st mutexattr_destroy failed"); | |
400 | return 1; | |
401 | } | |
402 | ||
403 | if (pthread_mutexattr_init (&ma) != 0) | |
404 | { | |
405 | puts ("2nd mutexattr_init failed"); | |
406 | return 1; | |
407 | } | |
408 | if (pthread_mutexattr_settype (&ma, PTHREAD_MUTEX_ERRORCHECK) != 0) | |
409 | { | |
410 | puts ("2nd mutexattr_settype failed"); | |
411 | return 1; | |
412 | } | |
66c13581 AK |
413 | #ifdef ENABLE_PI |
414 | if (pthread_mutexattr_setprotocol (&ma, PTHREAD_PRIO_INHERIT)) | |
415 | { | |
416 | puts ("2nd pthread_mutexattr_setprotocol failed"); | |
417 | return 1; | |
418 | } | |
419 | #endif | |
61623643 UD |
420 | puts ("check error-checking mutex"); |
421 | res |= check_type ("error-checking", &ma); | |
422 | if (pthread_mutexattr_destroy (&ma) != 0) | |
423 | { | |
424 | puts ("2nd mutexattr_destroy failed"); | |
425 | return 1; | |
426 | } | |
427 | ||
428 | return res; | |
429 | } | |
430 | ||
431 | #define TEST_FUNCTION do_test () | |
432 | #include "../test-skeleton.c" |