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