]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - contrib/netbsd-tests/lib/libpthread/t_cond.c
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / contrib / netbsd-tests / lib / libpthread / t_cond.c
1 /* $NetBSD: t_cond.c,v 1.6 2014/09/03 16:23:24 gson Exp $ */
2
3 /*
4  * Copyright (c) 2008 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  * POSSIBILITY OF SUCH DAMAGE.
27  */
28
29 #include <sys/cdefs.h>
30 __COPYRIGHT("@(#) Copyright (c) 2008\
31  The NetBSD Foundation, inc. All rights reserved.");
32 __RCSID("$NetBSD: t_cond.c,v 1.6 2014/09/03 16:23:24 gson Exp $");
33
34 #include <sys/time.h>
35
36 #include <errno.h>
37 #include <pthread.h>
38 #include <stdio.h>
39 #include <unistd.h>
40
41 #include <atf-c.h>
42
43 #include "h_common.h"
44
45 static pthread_mutex_t mutex;
46 static pthread_cond_t cond;
47 static pthread_mutex_t static_mutex = PTHREAD_MUTEX_INITIALIZER;
48 static pthread_cond_t static_cond = PTHREAD_COND_INITIALIZER;
49 static int count, share, toggle, total;
50
51 static void *
52 signal_delay_wait_threadfunc(void *arg)
53 {
54         int *shared = (int *) arg;
55
56         printf("2: Second thread.\n");
57
58         printf("2: Locking mutex\n");
59         PTHREAD_REQUIRE(pthread_mutex_lock(&mutex));
60         printf("2: Got mutex.\n");
61         printf("Shared value: %d. Changing to 0.\n", *shared);
62         *shared = 0;
63
64         PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
65         PTHREAD_REQUIRE(pthread_cond_signal(&cond));
66
67         return NULL;
68 }
69
70 ATF_TC(signal_delay_wait);
71 ATF_TC_HEAD(signal_delay_wait, tc)
72 {
73         atf_tc_set_md_var(tc, "descr", "Checks condition variables");
74 }
75 ATF_TC_BODY(signal_delay_wait, tc)
76 {
77         pthread_t new;
78         void *joinval;
79         int sharedval;
80
81         printf("1: condition variable test 1\n");
82
83         PTHREAD_REQUIRE(pthread_mutex_init(&mutex, NULL));
84         PTHREAD_REQUIRE(pthread_cond_init(&cond, NULL));
85
86         PTHREAD_REQUIRE(pthread_mutex_lock(&mutex));
87
88         sharedval = 1;
89
90         PTHREAD_REQUIRE(pthread_create(&new, NULL, signal_delay_wait_threadfunc,
91             &sharedval));
92
93         printf("1: Before waiting.\n");
94         do {
95                 sleep(2);
96                 PTHREAD_REQUIRE(pthread_cond_wait(&cond, &mutex));
97                 printf("1: After waiting, in loop.\n");
98         } while (sharedval != 0);
99
100         printf("1: After the loop.\n");
101
102         PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
103
104         printf("1: After releasing the mutex.\n");
105         PTHREAD_REQUIRE(pthread_join(new, &joinval));
106
107         printf("1: Thread joined.\n");
108 }
109
110 static void *
111 signal_before_unlock_threadfunc(void *arg)
112 {
113         int *shared = (int *) arg;
114
115         printf("2: Second thread.\n");
116
117         printf("2: Locking mutex\n");
118         PTHREAD_REQUIRE(pthread_mutex_lock(&mutex));
119         printf("2: Got mutex.\n");
120         printf("Shared value: %d. Changing to 0.\n", *shared);
121         *shared = 0;
122
123         /* Signal first, then unlock, for a different test than #1. */
124         PTHREAD_REQUIRE(pthread_cond_signal(&cond));
125         PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
126
127         return NULL;
128 }
129
130 ATF_TC(signal_before_unlock);
131 ATF_TC_HEAD(signal_before_unlock, tc)
132 {
133         atf_tc_set_md_var(tc, "descr",
134                 "Checks condition variables: signal before unlocking mutex");
135 }
136 ATF_TC_BODY(signal_before_unlock, tc)
137 {
138         pthread_t new;
139         void *joinval;
140         int sharedval;
141
142         printf("1: condition variable test 2\n");
143
144         PTHREAD_REQUIRE(pthread_mutex_init(&mutex, NULL));
145         PTHREAD_REQUIRE(pthread_cond_init(&cond, NULL));
146
147         PTHREAD_REQUIRE(pthread_mutex_lock(&mutex));
148
149         sharedval = 1;
150
151         PTHREAD_REQUIRE(pthread_create(&new, NULL,
152             signal_before_unlock_threadfunc, &sharedval));
153
154         printf("1: Before waiting.\n");
155         do {
156                 sleep(2);
157                 PTHREAD_REQUIRE(pthread_cond_wait(&cond, &mutex));
158                 printf("1: After waiting, in loop.\n");
159         } while (sharedval != 0);
160
161         printf("1: After the loop.\n");
162
163         PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
164
165         printf("1: After releasing the mutex.\n");
166         PTHREAD_REQUIRE(pthread_join(new, &joinval));
167
168         printf("1: Thread joined.\n");
169 }
170
171 static void *
172 signal_before_unlock_static_init_threadfunc(void *arg)
173 {
174         int *shared = (int *) arg;
175
176         printf("2: Second thread.\n");
177
178         printf("2: Locking mutex\n");
179         PTHREAD_REQUIRE(pthread_mutex_lock(&static_mutex));
180         printf("2: Got mutex.\n");
181         printf("Shared value: %d. Changing to 0.\n", *shared);
182         *shared = 0;
183
184         /* Signal first, then unlock, for a different test than #1. */
185         PTHREAD_REQUIRE(pthread_cond_signal(&static_cond));
186         PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex));
187
188         return NULL;
189 }
190
191 ATF_TC(signal_before_unlock_static_init);
192 ATF_TC_HEAD(signal_before_unlock_static_init, tc)
193 {
194         atf_tc_set_md_var(tc, "descr",
195                 "Checks condition variables: signal before unlocking "
196                 "mutex, use static initializers");
197 }
198 ATF_TC_BODY(signal_before_unlock_static_init, tc)
199 {
200         pthread_t new;
201         void *joinval;
202         int sharedval;
203
204         printf("1: condition variable test 3\n");
205
206         PTHREAD_REQUIRE(pthread_mutex_lock(&static_mutex));
207
208         sharedval = 1;
209
210         PTHREAD_REQUIRE(pthread_create(&new, NULL,
211             signal_before_unlock_static_init_threadfunc, &sharedval));
212
213         printf("1: Before waiting.\n");
214         do {
215                 sleep(2);
216                 PTHREAD_REQUIRE(pthread_cond_wait(&static_cond, &static_mutex));
217                 printf("1: After waiting, in loop.\n");
218         } while (sharedval != 0);
219
220         printf("1: After the loop.\n");
221
222         PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex));
223
224         printf("1: After releasing the mutex.\n");
225         PTHREAD_REQUIRE(pthread_join(new, &joinval));
226
227         printf("1: Thread joined.\n");
228 }
229
230 static void *
231 signal_wait_race_threadfunc(void *arg)
232 {
233         printf("2: Second thread.\n");
234         PTHREAD_REQUIRE(pthread_mutex_lock(&static_mutex));
235         printf("2: Before the loop.\n");
236         while (count>0) {
237                 count--;
238                 total++;
239                 toggle = 0;
240                 /* printf("2: Before signal %d.\n", count); */
241                 PTHREAD_REQUIRE(pthread_cond_signal(&static_cond));
242                 do {
243                         PTHREAD_REQUIRE(pthread_cond_wait(&static_cond,
244                             &static_mutex));
245                 } while (toggle != 1);
246         }
247         printf("2: After the loop.\n");
248         PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex));
249
250         return NULL;
251 }
252
253 ATF_TC(signal_wait_race);
254 ATF_TC_HEAD(signal_wait_race, tc)
255 {
256         atf_tc_set_md_var(tc, "descr", "Checks condition variables");
257 }
258 ATF_TC_BODY(signal_wait_race, tc)
259 {
260         pthread_t new;
261         void *joinval;
262         int sharedval;
263
264         printf("1: condition variable test 4\n");
265
266         PTHREAD_REQUIRE(pthread_mutex_lock(&static_mutex));
267
268         count = 50000;
269         toggle = 0;
270
271         PTHREAD_REQUIRE(pthread_create(&new, NULL, signal_wait_race_threadfunc,
272             &sharedval));
273
274         printf("1: Before waiting.\n");
275         while (count>0) {
276                 count--;
277                 total++;
278                 toggle = 1;
279                 /* printf("1: Before signal %d.\n", count); */
280                 PTHREAD_REQUIRE(pthread_cond_signal(&static_cond));
281                 do {
282                         PTHREAD_REQUIRE(pthread_cond_wait(&static_cond,
283                             &static_mutex));
284                 } while (toggle != 0);
285         }
286         printf("1: After the loop.\n");
287
288         toggle = 1;
289         PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex));
290         PTHREAD_REQUIRE(pthread_cond_signal(&static_cond));
291
292         printf("1: After releasing the mutex.\n");
293         PTHREAD_REQUIRE(pthread_join(new, &joinval));
294
295         printf("1: Thread joined. Final count = %d, total = %d\n",
296                 count, total);
297
298         ATF_REQUIRE_EQ(count, 0);
299         ATF_REQUIRE_EQ(total, 50000);
300 }
301
302 static void *
303 pthread_cond_timedwait_func(void *arg)
304 {
305         struct timespec ts;
306         size_t i = 0;
307         int rv;
308
309         for (;;) {
310
311                 if (i++ >= 10000)
312                         pthread_exit(NULL);
313
314                 (void)memset(&ts, 0, sizeof(struct timespec));
315
316                 ATF_REQUIRE(clock_gettime(CLOCK_REALTIME, &ts) == 0);
317
318                 /*
319                  * Set to one second in the past:
320                  * pthread_cond_timedwait(3) should
321                  * return ETIMEDOUT immediately.
322                  */
323                 ts.tv_sec = ts.tv_sec - 1;
324
325                 PTHREAD_REQUIRE(pthread_mutex_lock(&static_mutex));
326                 rv = pthread_cond_timedwait(&static_cond, &static_mutex, &ts);
327
328                 /*
329                  * Sometimes we catch ESRCH.
330                  * This should never happen.
331                  */
332                 ATF_REQUIRE(rv == ETIMEDOUT);
333                 PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex));
334         }
335 }
336
337 ATF_TC(cond_timedwait_race);
338 ATF_TC_HEAD(cond_timedwait_race, tc)
339 {
340         atf_tc_set_md_var(tc, "descr", "Test pthread_cond_timedwait(3)");
341
342 }
343 ATF_TC_BODY(cond_timedwait_race, tc)
344 {
345         pthread_t tid[64];
346         size_t i;
347
348         for (i = 0; i < __arraycount(tid); i++) {
349
350                 PTHREAD_REQUIRE(pthread_create(&tid[i], NULL,
351                     pthread_cond_timedwait_func, NULL));
352         }
353
354         for (i = 0; i < __arraycount(tid); i++) {
355
356                 PTHREAD_REQUIRE(pthread_join(tid[i], NULL));
357         }
358 }
359
360 static void *
361 broadcast_threadfunc(void *arg)
362 {
363         printf("2: Second thread.\n");
364
365         PTHREAD_REQUIRE(pthread_mutex_lock(&static_mutex));
366         while (count>0) {
367                 count--;
368                 total++;
369                 toggle = 0;
370                 PTHREAD_REQUIRE(pthread_cond_signal(&static_cond));
371                 do {
372                         PTHREAD_REQUIRE(pthread_cond_wait(&static_cond,
373                             &static_mutex));
374                 } while (toggle != 1);
375         }
376         printf("2: After the loop.\n");
377         PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex));
378
379         return NULL;
380 }
381
382
383 ATF_TC(broadcast);
384 ATF_TC_HEAD(broadcast, tc)
385 {
386         atf_tc_set_md_var(tc, "descr",
387                 "Checks condition variables: use pthread_cond_broadcast()");
388 }
389 ATF_TC_BODY(broadcast, tc)
390 {
391         pthread_t new;
392         void *joinval;
393         int sharedval;
394
395         printf("1: condition variable test 5\n");
396
397         PTHREAD_REQUIRE(pthread_mutex_lock(&static_mutex));
398
399         count = 50000;
400         toggle = 0;
401
402         PTHREAD_REQUIRE(pthread_create(&new, NULL, broadcast_threadfunc,
403             &sharedval));
404
405         printf("1: Before waiting.\n");
406         while (count>0) {
407                 count--;
408                 total++;
409                 toggle = 1;
410                 PTHREAD_REQUIRE(pthread_cond_broadcast(&static_cond));
411                 do {
412                         PTHREAD_REQUIRE(pthread_cond_wait(&static_cond,
413                             &static_mutex));
414                 } while (toggle != 0);
415         }
416         printf("1: After the loop.\n");
417
418         toggle = 1;
419         PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex));
420         PTHREAD_REQUIRE(pthread_cond_signal(&static_cond));
421
422         printf("1: After releasing the mutex.\n");
423         PTHREAD_REQUIRE(pthread_join(new, &joinval));
424
425         printf("1: Thread joined. Final count = %d, total = %d\n", count,
426             total);
427
428         ATF_REQUIRE_EQ(count, 0);
429         ATF_REQUIRE_EQ(total, 50000);
430 }
431
432 static void *
433 bogus_timedwaits_threadfunc(void *arg)
434 {
435         return NULL;
436 }
437
438 ATF_TC(bogus_timedwaits);
439 ATF_TC_HEAD(bogus_timedwaits, tc)
440 {
441         atf_tc_set_md_var(tc, "descr",
442                 "Checks condition variables: bogus timedwaits");
443 }
444 ATF_TC_BODY(bogus_timedwaits, tc)
445 {
446         pthread_t new;
447         struct timespec ts;
448         struct timeval tv;
449
450         printf("condition variable test 6: bogus timedwaits\n");
451
452         PTHREAD_REQUIRE(pthread_mutex_lock(&static_mutex));
453
454         printf("unthreaded test (past)\n");
455         gettimeofday(&tv, NULL);
456         tv.tv_sec -= 2; /* Place the time in the past */
457         TIMEVAL_TO_TIMESPEC(&tv, &ts);
458
459         ATF_REQUIRE_EQ_MSG(pthread_cond_timedwait(&static_cond, &static_mutex,
460             &ts), ETIMEDOUT, "pthread_cond_timedwait() (unthreaded) in the "
461             "past");
462
463         printf("unthreaded test (zero time)\n");
464         tv.tv_sec = 0;
465         tv.tv_usec = 0;
466         TIMEVAL_TO_TIMESPEC(&tv, &ts);
467
468         ATF_REQUIRE_EQ_MSG(pthread_cond_timedwait(&static_cond, &static_mutex,
469             &ts), ETIMEDOUT, "pthread_cond_timedwait() (unthreaded) with zero "
470             "time");
471
472         PTHREAD_REQUIRE(pthread_create(&new, NULL, bogus_timedwaits_threadfunc,
473             NULL));
474         PTHREAD_REQUIRE(pthread_join(new, NULL));
475
476         printf("threaded test\n");
477         gettimeofday(&tv, NULL);
478         tv.tv_sec -= 2; /* Place the time in the past */
479         TIMEVAL_TO_TIMESPEC(&tv, &ts);
480
481         ATF_REQUIRE_EQ_MSG(pthread_cond_timedwait(&static_cond, &static_mutex,
482             &ts), ETIMEDOUT, "pthread_cond_timedwait() (threaded) in the past");
483
484         printf("threaded test (zero time)\n");
485         tv.tv_sec = 0;
486         tv.tv_usec = 0;
487         TIMEVAL_TO_TIMESPEC(&tv, &ts);
488
489         ATF_REQUIRE_EQ_MSG(pthread_cond_timedwait(&static_cond, &static_mutex,
490             &ts), ETIMEDOUT, "pthread_cond_timedwait() (threaded) with zero "
491             "time");
492
493         PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex));
494 }
495
496 static void
497 unlock(void *arg)
498 {
499         pthread_mutex_unlock((pthread_mutex_t *)arg);
500 }
501
502 static void *
503 destroy_after_cancel_threadfunc(void *arg)
504 {
505         PTHREAD_REQUIRE(pthread_mutex_lock(&mutex));
506
507         pthread_cleanup_push(unlock, &mutex);
508
509         while (1) {
510                 share = 1;
511                 PTHREAD_REQUIRE(pthread_cond_broadcast(&cond));
512                 PTHREAD_REQUIRE(pthread_cond_wait(&cond, &mutex));
513         }
514
515         pthread_cleanup_pop(0);
516         PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
517
518         return NULL;
519 }
520
521 ATF_TC(destroy_after_cancel);
522 ATF_TC_HEAD(destroy_after_cancel, tc)
523 {
524         atf_tc_set_md_var(tc, "descr", "Checks destroying a condition variable "
525             "after cancelling a wait");
526 }
527 ATF_TC_BODY(destroy_after_cancel, tc)
528 {
529         pthread_t thread;
530
531         PTHREAD_REQUIRE(pthread_mutex_init(&mutex, NULL));
532         PTHREAD_REQUIRE(pthread_cond_init(&cond, NULL));
533         PTHREAD_REQUIRE(pthread_mutex_lock(&mutex));
534         PTHREAD_REQUIRE(pthread_create(&thread, NULL,
535             destroy_after_cancel_threadfunc, NULL));
536
537         while (share == 0) {
538                 PTHREAD_REQUIRE(pthread_cond_wait(&cond, &mutex));
539         }
540
541         PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
542         PTHREAD_REQUIRE(pthread_cancel(thread));
543
544         PTHREAD_REQUIRE(pthread_join(thread, NULL));
545         PTHREAD_REQUIRE(pthread_cond_destroy(&cond));
546
547         PTHREAD_REQUIRE(pthread_mutex_destroy(&mutex));
548 }
549
550 ATF_TP_ADD_TCS(tp)
551 {
552
553         ATF_TP_ADD_TC(tp, signal_delay_wait);
554         ATF_TP_ADD_TC(tp, signal_before_unlock);
555         ATF_TP_ADD_TC(tp, signal_before_unlock_static_init);
556         ATF_TP_ADD_TC(tp, signal_wait_race);
557         ATF_TP_ADD_TC(tp, cond_timedwait_race);
558         ATF_TP_ADD_TC(tp, broadcast);
559         ATF_TP_ADD_TC(tp, bogus_timedwaits);
560         ATF_TP_ADD_TC(tp, destroy_after_cancel);
561
562         return atf_no_error();
563 }