stdlib: Improve fortify with clang
[glibc.git] / nptl / tst-mutex8.c
blobbe38e11068037aec49724602c691992e938d1f99
1 /* Copyright (C) 2003-2024 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
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.
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.
14 You should have received a copy of the GNU Lesser General Public
15 License along with the GNU C Library; if not, see
16 <https://www.gnu.org/licenses/>. */
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>
24 #include <unistd.h>
25 #include <elf/dl-tunables.h>
27 static pthread_mutex_t *m;
28 static pthread_barrier_t b;
29 static pthread_cond_t c;
30 static bool done;
33 static void
34 cl (void *arg)
36 if (pthread_mutex_unlock (m) != 0)
38 puts ("cl: mutex_unlocked failed");
39 exit (1);
44 static void *
45 tf (void *arg)
47 if (pthread_mutex_lock (m) != 0)
49 puts ("tf: mutex_lock failed");
50 return (void *) 1l;
53 int e = pthread_barrier_wait (&b);
54 if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
56 puts ("barrier_wait failed");
57 return (void *) 1l;
60 if (arg == NULL)
62 if (pthread_cond_wait (&c, m) != 0)
64 puts ("tf: cond_wait failed");
65 return (void *) 1l;
67 while (! done);
68 else
71 pthread_cleanup_push (cl, NULL);
73 if (pthread_cond_wait (&c, m) != 0)
75 puts ("tf: cond_wait failed");
76 return (void *) 1l;
79 pthread_cleanup_pop (0);
81 while (! done);
83 if (pthread_mutex_unlock (m) != 0)
85 puts ("tf: mutex_unlock failed");
86 return (void *) 1l;
89 return NULL;
93 static int
94 check_type (const char *mas, pthread_mutexattr_t *ma)
96 int e;
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;
101 int ma_type = PTHREAD_MUTEX_TIMED_NP;
102 if (ma != NULL)
104 e = pthread_mutexattr_gettype (ma, &ma_type);
105 if (e != 0)
107 printf ("pthread_mutexattr_gettype failed with %d (%m)\n", e);
108 return 1;
111 if (ma_type == PTHREAD_MUTEX_TIMED_NP)
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;
120 e = pthread_mutex_init (m, ma);
121 if (e != 0)
123 #ifdef ENABLE_PI
124 if (e == ENOTSUP)
126 puts ("PI mutexes unsupported");
127 return 0;
129 #endif
130 printf ("1st mutex_init failed for %s\n", mas);
131 return 1;
134 if (pthread_mutex_destroy (m) != 0)
136 printf ("immediate mutex_destroy failed for %s\n", mas);
137 return 1;
140 if (pthread_mutex_init (m, ma) != 0)
142 printf ("2nd mutex_init failed for %s\n", mas);
143 return 1;
146 if (pthread_mutex_lock (m) != 0)
148 printf ("1st mutex_lock failed for %s\n", mas);
149 return 1;
152 /* Elided mutexes don't fail destroy, thus only test this if we don't assume
153 elision. */
154 if (assume_elided_mutex == false)
156 e = pthread_mutex_destroy (m);
157 if (e == 0)
159 printf ("mutex_destroy of self-locked mutex succeeded for %s\n", mas);
160 return 1;
162 if (e != EBUSY)
164 printf ("\
165 mutex_destroy of self-locked mutex did not return EBUSY %s\n",
166 mas);
167 return 1;
171 if (pthread_mutex_unlock (m) != 0)
173 printf ("1st mutex_unlock failed for %s\n", mas);
174 return 1;
177 if (pthread_mutex_trylock (m) != 0)
179 printf ("mutex_trylock failed for %s\n", mas);
180 return 1;
183 /* Elided mutexes don't fail destroy. */
184 if (assume_elided_mutex == false)
186 e = pthread_mutex_destroy (m);
187 if (e == 0)
189 printf ("mutex_destroy of self-trylocked mutex succeeded for %s\n",
190 mas);
191 return 1;
193 if (e != EBUSY)
195 printf ("\
196 mutex_destroy of self-trylocked mutex did not return EBUSY %s\n",
197 mas);
198 return 1;
202 if (pthread_mutex_unlock (m) != 0)
204 printf ("2nd mutex_unlock failed for %s\n", mas);
205 return 1;
208 pthread_t th;
209 if (pthread_create (&th, NULL, tf, NULL) != 0)
211 puts ("1st create failed");
212 return 1;
214 done = false;
216 e = pthread_barrier_wait (&b);
217 if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
219 puts ("1st barrier_wait failed");
220 return 1;
223 if (pthread_mutex_lock (m) != 0)
225 printf ("2nd mutex_lock failed for %s\n", mas);
226 return 1;
229 if (pthread_mutex_unlock (m) != 0)
231 printf ("3rd mutex_unlock failed for %s\n", mas);
232 return 1;
235 /* Elided mutexes don't fail destroy. */
236 if (assume_elided_mutex == false)
238 e = pthread_mutex_destroy (m);
239 if (e == 0)
241 printf ("mutex_destroy of condvar-used mutex succeeded for %s\n",
242 mas);
243 return 1;
245 if (e != EBUSY)
247 printf ("\
248 mutex_destroy of condvar-used mutex did not return EBUSY for %s\n", mas);
249 return 1;
253 done = true;
254 if (pthread_cond_signal (&c) != 0)
256 puts ("cond_signal failed");
257 return 1;
260 void *r;
261 if (pthread_join (th, &r) != 0)
263 puts ("join failed");
264 return 1;
266 if (r != NULL)
268 puts ("thread didn't return NULL");
269 return 1;
272 if (pthread_mutex_destroy (m) != 0)
274 printf ("mutex_destroy after condvar-use failed for %s\n", mas);
275 return 1;
278 if (pthread_mutex_init (m, ma) != 0)
280 printf ("3rd mutex_init failed for %s\n", mas);
281 return 1;
284 if (pthread_create (&th, NULL, tf, (void *) 1) != 0)
286 puts ("2nd create failed");
287 return 1;
289 done = false;
291 e = pthread_barrier_wait (&b);
292 if (e != 0 && e != PTHREAD_BARRIER_SERIAL_THREAD)
294 puts ("2nd barrier_wait failed");
295 return 1;
298 if (pthread_mutex_lock (m) != 0)
300 printf ("3rd mutex_lock failed for %s\n", mas);
301 return 1;
304 if (pthread_mutex_unlock (m) != 0)
306 printf ("4th mutex_unlock failed for %s\n", mas);
307 return 1;
310 /* Elided mutexes don't fail destroy. */
311 if (assume_elided_mutex == false)
313 e = pthread_mutex_destroy (m);
314 if (e == 0)
316 printf ("2nd mutex_destroy of condvar-used mutex succeeded for %s\n",
317 mas);
318 return 1;
320 if (e != EBUSY)
322 printf ("\
323 2nd mutex_destroy of condvar-used mutex did not return EBUSY for %s\n",
324 mas);
325 return 1;
329 if (pthread_cancel (th) != 0)
331 puts ("cond_cancel failed");
332 return 1;
335 if (pthread_join (th, &r) != 0)
337 puts ("join failed");
338 return 1;
340 if (r != PTHREAD_CANCELED)
342 puts ("thread not canceled");
343 return 1;
346 if (pthread_mutex_destroy (m) != 0)
348 printf ("mutex_destroy after condvar-canceled failed for %s\n", mas);
349 return 1;
352 return 0;
356 static int
357 do_test (void)
359 pthread_mutex_t mm;
360 m = &mm;
362 if (pthread_barrier_init (&b, NULL, 2) != 0)
364 puts ("barrier_init failed");
365 return 1;
368 if (pthread_cond_init (&c, NULL) != 0)
370 puts ("cond_init failed");
371 return 1;
374 puts ("check normal mutex");
375 int res = check_type ("normal", NULL);
377 pthread_mutexattr_t ma;
378 if (pthread_mutexattr_init (&ma) != 0)
380 puts ("1st mutexattr_init failed");
381 return 1;
383 if (pthread_mutexattr_settype (&ma, PTHREAD_MUTEX_RECURSIVE) != 0)
385 puts ("1st mutexattr_settype failed");
386 return 1;
388 #ifdef ENABLE_PI
389 if (pthread_mutexattr_setprotocol (&ma, PTHREAD_PRIO_INHERIT))
391 puts ("1st pthread_mutexattr_setprotocol failed");
392 return 1;
394 #endif
395 puts ("check recursive mutex");
396 res |= check_type ("recursive", &ma);
397 if (pthread_mutexattr_destroy (&ma) != 0)
399 puts ("1st mutexattr_destroy failed");
400 return 1;
403 if (pthread_mutexattr_init (&ma) != 0)
405 puts ("2nd mutexattr_init failed");
406 return 1;
408 if (pthread_mutexattr_settype (&ma, PTHREAD_MUTEX_ERRORCHECK) != 0)
410 puts ("2nd mutexattr_settype failed");
411 return 1;
413 #ifdef ENABLE_PI
414 if (pthread_mutexattr_setprotocol (&ma, PTHREAD_PRIO_INHERIT))
416 puts ("2nd pthread_mutexattr_setprotocol failed");
417 return 1;
419 #endif
420 puts ("check error-checking mutex");
421 res |= check_type ("error-checking", &ma);
422 if (pthread_mutexattr_destroy (&ma) != 0)
424 puts ("2nd mutexattr_destroy failed");
425 return 1;
428 return res;
431 #define TEST_FUNCTION do_test ()
432 #include "../test-skeleton.c"