]> git.ipfire.org Git - thirdparty/glibc.git/blame - nptl/tst-cond25.c
Update copyright notices with scripts/update-copyrights
[thirdparty/glibc.git] / nptl / tst-cond25.c
CommitLineData
0e3b5d6a
SP
1/* Verify that condition variables synchronized by PI mutexes don't hang on
2 on cancellation.
d4697bc9 3 Copyright (C) 2012-2014 Free Software Foundation, Inc.
0e3b5d6a
SP
4 This file is part of the GNU C Library.
5
6 The GNU C Library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
10
11 The GNU C Library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public
17 License along with the GNU C Library; if not, see
18 <http://www.gnu.org/licenses/>. */
19
20#include <pthread.h>
21#include <stdio.h>
22#include <stdlib.h>
c0a1472e 23#include <stdint.h>
0e3b5d6a
SP
24#include <string.h>
25#include <errno.h>
26#include <sys/types.h>
27#include <sys/syscall.h>
28#include <unistd.h>
29#include <sys/time.h>
30#include <time.h>
31
32#define NUM 5
33#define ITERS 10000
34#define COUNT 100
35
36typedef void *(*thr_func) (void *);
37
38pthread_mutex_t mutex;
39pthread_cond_t cond;
40
41void cleanup (void *u)
42{
43 /* pthread_cond_wait should always return with the mutex locked. */
44 if (pthread_mutex_unlock (&mutex))
45 abort ();
46}
47
48void *
49signaller (void *u)
50{
51 int i, ret = 0;
52 void *tret = NULL;
53
54 for (i = 0; i < ITERS; i++)
55 {
56 if ((ret = pthread_mutex_lock (&mutex)) != 0)
57 {
58 tret = (void *)1;
59 printf ("signaller:mutex_lock failed: %s\n", strerror (ret));
60 goto out;
61 }
62 if ((ret = pthread_cond_signal (&cond)) != 0)
63 {
64 tret = (void *)1;
65 printf ("signaller:signal failed: %s\n", strerror (ret));
66 goto unlock_out;
67 }
68 if ((ret = pthread_mutex_unlock (&mutex)) != 0)
69 {
70 tret = (void *)1;
71 printf ("signaller:mutex_unlock failed: %s\n", strerror (ret));
72 goto out;
73 }
74 pthread_testcancel ();
75 }
76
77out:
78 return tret;
79
80unlock_out:
81 if ((ret = pthread_mutex_unlock (&mutex)) != 0)
82 printf ("signaller:mutex_unlock[2] failed: %s\n", strerror (ret));
83 goto out;
84}
85
86void *
87waiter (void *u)
88{
89 int i, ret = 0;
90 void *tret = NULL;
c0a1472e 91 int seq = (uintptr_t) u;
0e3b5d6a
SP
92
93 for (i = 0; i < ITERS / NUM; i++)
94 {
95 if ((ret = pthread_mutex_lock (&mutex)) != 0)
96 {
c0a1472e 97 tret = (void *) (uintptr_t) 1;
0e3b5d6a
SP
98 printf ("waiter[%u]:mutex_lock failed: %s\n", seq, strerror (ret));
99 goto out;
100 }
101 pthread_cleanup_push (cleanup, NULL);
102
103 if ((ret = pthread_cond_wait (&cond, &mutex)) != 0)
104 {
c0a1472e 105 tret = (void *) (uintptr_t) 1;
0e3b5d6a
SP
106 printf ("waiter[%u]:wait failed: %s\n", seq, strerror (ret));
107 goto unlock_out;
108 }
109
110 if ((ret = pthread_mutex_unlock (&mutex)) != 0)
111 {
c0a1472e 112 tret = (void *) (uintptr_t) 1;
0e3b5d6a
SP
113 printf ("waiter[%u]:mutex_unlock failed: %s\n", seq, strerror (ret));
114 goto out;
115 }
116 pthread_cleanup_pop (0);
117 }
118
119out:
120 puts ("waiter tests done");
121 return tret;
122
123unlock_out:
124 if ((ret = pthread_mutex_unlock (&mutex)) != 0)
125 printf ("waiter:mutex_unlock[2] failed: %s\n", strerror (ret));
126 goto out;
127}
128
129void *
130timed_waiter (void *u)
131{
132 int i, ret;
133 void *tret = NULL;
c0a1472e 134 int seq = (uintptr_t) u;
0e3b5d6a
SP
135
136 for (i = 0; i < ITERS / NUM; i++)
137 {
138 struct timespec ts;
139
140 if ((ret = clock_gettime(CLOCK_REALTIME, &ts)) != 0)
141 {
c0a1472e 142 tret = (void *) (uintptr_t) 1;
0e3b5d6a
SP
143 printf ("%u:clock_gettime failed: %s\n", seq, strerror (errno));
144 goto out;
145 }
146 ts.tv_sec += 20;
147
148 if ((ret = pthread_mutex_lock (&mutex)) != 0)
149 {
c0a1472e 150 tret = (void *) (uintptr_t) 1;
0e3b5d6a
SP
151 printf ("waiter[%u]:mutex_lock failed: %s\n", seq, strerror (ret));
152 goto out;
153 }
154 pthread_cleanup_push (cleanup, NULL);
155
156 /* We should not time out either. */
157 if ((ret = pthread_cond_timedwait (&cond, &mutex, &ts)) != 0)
158 {
c0a1472e 159 tret = (void *) (uintptr_t) 1;
0e3b5d6a
SP
160 printf ("waiter[%u]:timedwait failed: %s\n", seq, strerror (ret));
161 goto unlock_out;
162 }
163 if ((ret = pthread_mutex_unlock (&mutex)) != 0)
164 {
c0a1472e 165 tret = (void *) (uintptr_t) 1;
0e3b5d6a
SP
166 printf ("waiter[%u]:mutex_unlock failed: %s\n", seq, strerror (ret));
167 goto out;
168 }
169 pthread_cleanup_pop (0);
170 }
171
172out:
173 puts ("timed_waiter tests done");
174 return tret;
175
176unlock_out:
177 if ((ret = pthread_mutex_unlock (&mutex)) != 0)
178 printf ("waiter[%u]:mutex_unlock[2] failed: %s\n", seq, strerror (ret));
179 goto out;
180}
181
182int
183do_test_wait (thr_func f)
184{
185 pthread_t w[NUM];
186 pthread_t s;
187 pthread_mutexattr_t attr;
188 int i, j, ret = 0;
189 void *thr_ret;
190
191 for (i = 0; i < COUNT; i++)
192 {
193 if ((ret = pthread_mutexattr_init (&attr)) != 0)
194 {
195 printf ("mutexattr_init failed: %s\n", strerror (ret));
196 goto out;
197 }
198
c0a1472e
RM
199 if ((ret = pthread_mutexattr_setprotocol (&attr,
200 PTHREAD_PRIO_INHERIT)) != 0)
0e3b5d6a
SP
201 {
202 printf ("mutexattr_setprotocol failed: %s\n", strerror (ret));
203 goto out;
204 }
205
206 if ((ret = pthread_cond_init (&cond, NULL)) != 0)
207 {
208 printf ("cond_init failed: %s\n", strerror (ret));
209 goto out;
210 }
211
212 if ((ret = pthread_mutex_init (&mutex, &attr)) != 0)
213 {
214 printf ("mutex_init failed: %s\n", strerror (ret));
215 goto out;
216 }
217
218 for (j = 0; j < NUM; j++)
c0a1472e
RM
219 if ((ret = pthread_create (&w[j], NULL,
220 f, (void *) (uintptr_t) j)) != 0)
0e3b5d6a
SP
221 {
222 printf ("waiter[%d]: create failed: %s\n", j, strerror (ret));
223 goto out;
224 }
225
226 if ((ret = pthread_create (&s, NULL, signaller, NULL)) != 0)
227 {
228 printf ("signaller: create failed: %s\n", strerror (ret));
229 goto out;
230 }
231
232 for (j = 0; j < NUM; j++)
233 {
37785907 234 pthread_cancel (w[j]);
0e3b5d6a
SP
235
236 if ((ret = pthread_join (w[j], &thr_ret)) != 0)
237 {
238 printf ("waiter[%d]: join failed: %s\n", j, strerror (ret));
239 goto out;
240 }
241
242 if (thr_ret != NULL && thr_ret != PTHREAD_CANCELED)
243 {
244 ret = 1;
245 goto out;
246 }
247 }
248
249 /* The signalling thread could have ended before it was cancelled. */
250 pthread_cancel (s);
251
252 if ((ret = pthread_join (s, &thr_ret)) != 0)
253 {
254 printf ("signaller: join failed: %s\n", strerror (ret));
255 goto out;
256 }
257
258 if (thr_ret != NULL && thr_ret != PTHREAD_CANCELED)
259 {
260 ret = 1;
261 goto out;
262 }
263 }
264
265out:
266 return ret;
267}
268
269int
270do_test (int argc, char **argv)
271{
272 int ret = do_test_wait (waiter);
273
274 if (ret)
275 return ret;
276
277 return do_test_wait (timed_waiter);
278}
279
280#define TIMEOUT 5
281#include "../test-skeleton.c"