]>
Commit | Line | Data |
---|---|---|
b168057a | 1 | /* Copyright (C) 2003-2015 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> | |
25 | ||
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 | |
53247a0b MR |
98 | e = pthread_mutex_init (m, ma); |
99 | if (e != 0) | |
61623643 | 100 | { |
53247a0b MR |
101 | #ifdef ENABLE_PI |
102 | if (e == ENOTSUP) | |
103 | { | |
104 | puts ("PI mutexes unsupported"); | |
105 | return 0; | |
106 | } | |
107 | #endif | |
61623643 UD |
108 | printf ("1st mutex_init failed for %s\n", mas); |
109 | return 1; | |
110 | } | |
111 | ||
112 | if (pthread_mutex_destroy (m) != 0) | |
113 | { | |
114 | printf ("immediate mutex_destroy failed for %s\n", mas); | |
115 | return 1; | |
116 | } | |
117 | ||
118 | if (pthread_mutex_init (m, ma) != 0) | |
119 | { | |
120 | printf ("2nd mutex_init failed for %s\n", mas); | |
121 | return 1; | |
122 | } | |
123 | ||
124 | if (pthread_mutex_lock (m) != 0) | |
125 | { | |
126 | printf ("1st mutex_lock failed for %s\n", mas); | |
127 | return 1; | |
128 | } | |
129 | ||
68cc2935 AK |
130 | /* Elided mutexes don't fail destroy. If elision is not explicitly disabled |
131 | we don't know, so can also not check this. */ | |
132 | #ifndef ENABLE_LOCK_ELISION | |
133 | e = pthread_mutex_destroy (m); | |
61623643 UD |
134 | if (e == 0) |
135 | { | |
136 | printf ("mutex_destroy of self-locked mutex succeeded for %s\n", mas); | |
137 | return 1; | |
138 | } | |
139 | if (e != EBUSY) | |
140 | { | |
141 | printf ("mutex_destroy of self-locked mutex did not return EBUSY %s\n", | |
142 | mas); | |
143 | return 1; | |
144 | } | |
68cc2935 | 145 | #endif |
61623643 UD |
146 | |
147 | if (pthread_mutex_unlock (m) != 0) | |
148 | { | |
149 | printf ("1st mutex_unlock failed for %s\n", mas); | |
150 | return 1; | |
151 | } | |
152 | ||
153 | if (pthread_mutex_trylock (m) != 0) | |
154 | { | |
155 | printf ("mutex_trylock failed for %s\n", mas); | |
156 | return 1; | |
157 | } | |
158 | ||
68cc2935 AK |
159 | /* Elided mutexes don't fail destroy. */ |
160 | #ifndef ENABLE_LOCK_ELISION | |
61623643 UD |
161 | e = pthread_mutex_destroy (m); |
162 | if (e == 0) | |
163 | { | |
164 | printf ("mutex_destroy of self-trylocked mutex succeeded for %s\n", mas); | |
165 | return 1; | |
166 | } | |
167 | if (e != EBUSY) | |
168 | { | |
169 | printf ("\ | |
170 | mutex_destroy of self-trylocked mutex did not return EBUSY %s\n", | |
171 | mas); | |
172 | return 1; | |
173 | } | |
68cc2935 | 174 | #endif |
61623643 UD |
175 | |
176 | if (pthread_mutex_unlock (m) != 0) | |
177 | { | |
178 | printf ("2nd mutex_unlock failed for %s\n", mas); | |
179 | return 1; | |
180 | } | |
181 | ||
182 | pthread_t th; | |
183 | if (pthread_create (&th, NULL, tf, NULL) != 0) | |
184 | { | |
185 | puts ("1st create failed"); | |
186 | return 1; | |
187 | } | |
188 | done = false; | |
189 | ||
190 | e = pthread_barrier_wait (&b); | |
191 | if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD) | |
192 | { | |
193 | puts ("1st barrier_wait failed"); | |
194 | return 1; | |
195 | } | |
196 | ||
197 | if (pthread_mutex_lock (m) != 0) | |
198 | { | |
199 | printf ("2nd mutex_lock failed for %s\n", mas); | |
200 | return 1; | |
201 | } | |
202 | ||
203 | if (pthread_mutex_unlock (m) != 0) | |
204 | { | |
205 | printf ("3rd mutex_unlock failed for %s\n", mas); | |
206 | return 1; | |
207 | } | |
208 | ||
68cc2935 AK |
209 | /* Elided mutexes don't fail destroy. */ |
210 | #ifndef ENABLE_LOCK_ELISION | |
61623643 UD |
211 | e = pthread_mutex_destroy (m); |
212 | if (e == 0) | |
213 | { | |
214 | printf ("mutex_destroy of condvar-used mutex succeeded for %s\n", mas); | |
215 | return 1; | |
216 | } | |
217 | if (e != EBUSY) | |
218 | { | |
219 | printf ("\ | |
220 | mutex_destroy of condvar-used mutex did not return EBUSY for %s\n", mas); | |
221 | return 1; | |
222 | } | |
68cc2935 | 223 | #endif |
61623643 UD |
224 | |
225 | done = true; | |
226 | if (pthread_cond_signal (&c) != 0) | |
227 | { | |
228 | puts ("cond_signal failed"); | |
229 | return 1; | |
230 | } | |
231 | ||
232 | void *r; | |
233 | if (pthread_join (th, &r) != 0) | |
234 | { | |
235 | puts ("join failed"); | |
236 | return 1; | |
237 | } | |
238 | if (r != NULL) | |
239 | { | |
240 | puts ("thread didn't return NULL"); | |
241 | return 1; | |
242 | } | |
243 | ||
244 | if (pthread_mutex_destroy (m) != 0) | |
245 | { | |
246 | printf ("mutex_destroy after condvar-use failed for %s\n", mas); | |
247 | return 1; | |
248 | } | |
249 | ||
250 | if (pthread_mutex_init (m, ma) != 0) | |
251 | { | |
252 | printf ("3rd mutex_init failed for %s\n", mas); | |
253 | return 1; | |
254 | } | |
255 | ||
256 | if (pthread_create (&th, NULL, tf, (void *) 1) != 0) | |
257 | { | |
258 | puts ("2nd create failed"); | |
259 | return 1; | |
260 | } | |
261 | done = false; | |
262 | ||
263 | e = pthread_barrier_wait (&b); | |
264 | if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD) | |
265 | { | |
266 | puts ("2nd barrier_wait failed"); | |
267 | return 1; | |
268 | } | |
269 | ||
270 | if (pthread_mutex_lock (m) != 0) | |
271 | { | |
272 | printf ("3rd mutex_lock failed for %s\n", mas); | |
273 | return 1; | |
274 | } | |
275 | ||
276 | if (pthread_mutex_unlock (m) != 0) | |
277 | { | |
278 | printf ("4th mutex_unlock failed for %s\n", mas); | |
279 | return 1; | |
280 | } | |
281 | ||
68cc2935 AK |
282 | /* Elided mutexes don't fail destroy. */ |
283 | #ifndef ENABLE_LOCK_ELISION | |
61623643 UD |
284 | e = pthread_mutex_destroy (m); |
285 | if (e == 0) | |
286 | { | |
287 | printf ("2nd mutex_destroy of condvar-used mutex succeeded for %s\n", | |
288 | mas); | |
289 | return 1; | |
290 | } | |
291 | if (e != EBUSY) | |
292 | { | |
293 | printf ("\ | |
294 | 2nd mutex_destroy of condvar-used mutex did not return EBUSY for %s\n", | |
295 | mas); | |
296 | return 1; | |
297 | } | |
68cc2935 | 298 | #endif |
61623643 UD |
299 | |
300 | if (pthread_cancel (th) != 0) | |
301 | { | |
302 | puts ("cond_cancel failed"); | |
303 | return 1; | |
304 | } | |
305 | ||
306 | if (pthread_join (th, &r) != 0) | |
307 | { | |
308 | puts ("join failed"); | |
309 | return 1; | |
310 | } | |
311 | if (r != PTHREAD_CANCELED) | |
312 | { | |
313 | puts ("thread not canceled"); | |
314 | return 1; | |
315 | } | |
316 | ||
317 | if (pthread_mutex_destroy (m) != 0) | |
318 | { | |
319 | printf ("mutex_destroy after condvar-canceled failed for %s\n", mas); | |
320 | return 1; | |
321 | } | |
322 | ||
323 | return 0; | |
324 | } | |
325 | ||
326 | ||
327 | static int | |
328 | do_test (void) | |
329 | { | |
330 | pthread_mutex_t mm; | |
331 | m = &mm; | |
332 | ||
333 | if (pthread_barrier_init (&b, NULL, 2) != 0) | |
334 | { | |
335 | puts ("barrier_init failed"); | |
336 | return 1; | |
337 | } | |
338 | ||
339 | if (pthread_cond_init (&c, NULL) != 0) | |
340 | { | |
341 | puts ("cond_init failed"); | |
342 | return 1; | |
343 | } | |
344 | ||
345 | puts ("check normal mutex"); | |
346 | int res = check_type ("normal", NULL); | |
347 | ||
348 | pthread_mutexattr_t ma; | |
349 | if (pthread_mutexattr_init (&ma) != 0) | |
350 | { | |
351 | puts ("1st mutexattr_init failed"); | |
352 | return 1; | |
353 | } | |
354 | if (pthread_mutexattr_settype (&ma, PTHREAD_MUTEX_RECURSIVE) != 0) | |
355 | { | |
356 | puts ("1st mutexattr_settype failed"); | |
357 | return 1; | |
358 | } | |
66c13581 AK |
359 | #ifdef ENABLE_PI |
360 | if (pthread_mutexattr_setprotocol (&ma, PTHREAD_PRIO_INHERIT)) | |
361 | { | |
362 | puts ("1st pthread_mutexattr_setprotocol failed"); | |
363 | return 1; | |
364 | } | |
365 | #endif | |
61623643 UD |
366 | puts ("check recursive mutex"); |
367 | res |= check_type ("recursive", &ma); | |
368 | if (pthread_mutexattr_destroy (&ma) != 0) | |
369 | { | |
370 | puts ("1st mutexattr_destroy failed"); | |
371 | return 1; | |
372 | } | |
373 | ||
374 | if (pthread_mutexattr_init (&ma) != 0) | |
375 | { | |
376 | puts ("2nd mutexattr_init failed"); | |
377 | return 1; | |
378 | } | |
379 | if (pthread_mutexattr_settype (&ma, PTHREAD_MUTEX_ERRORCHECK) != 0) | |
380 | { | |
381 | puts ("2nd mutexattr_settype failed"); | |
382 | return 1; | |
383 | } | |
66c13581 AK |
384 | #ifdef ENABLE_PI |
385 | if (pthread_mutexattr_setprotocol (&ma, PTHREAD_PRIO_INHERIT)) | |
386 | { | |
387 | puts ("2nd pthread_mutexattr_setprotocol failed"); | |
388 | return 1; | |
389 | } | |
390 | #endif | |
61623643 UD |
391 | puts ("check error-checking mutex"); |
392 | res |= check_type ("error-checking", &ma); | |
393 | if (pthread_mutexattr_destroy (&ma) != 0) | |
394 | { | |
395 | puts ("2nd mutexattr_destroy failed"); | |
396 | return 1; | |
397 | } | |
398 | ||
399 | return res; | |
400 | } | |
401 | ||
402 | #define TEST_FUNCTION do_test () | |
403 | #include "../test-skeleton.c" |