1 /* $NetBSD: t_cond.c,v 1.6 2014/09/03 16:23:24 gson Exp $ */
4 * Copyright (c) 2008 The NetBSD Foundation, Inc.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
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.
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 $");
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
;
52 signal_delay_wait_threadfunc(void *arg
)
54 int *shared
= (int *) arg
;
56 printf("2: Second thread.\n");
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
);
64 PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex
));
65 PTHREAD_REQUIRE(pthread_cond_signal(&cond
));
70 ATF_TC(signal_delay_wait
);
71 ATF_TC_HEAD(signal_delay_wait
, tc
)
73 atf_tc_set_md_var(tc
, "descr", "Checks condition variables");
75 ATF_TC_BODY(signal_delay_wait
, tc
)
81 printf("1: condition variable test 1\n");
83 PTHREAD_REQUIRE(pthread_mutex_init(&mutex
, NULL
));
84 PTHREAD_REQUIRE(pthread_cond_init(&cond
, NULL
));
86 PTHREAD_REQUIRE(pthread_mutex_lock(&mutex
));
90 PTHREAD_REQUIRE(pthread_create(&new, NULL
, signal_delay_wait_threadfunc
,
93 printf("1: Before waiting.\n");
96 PTHREAD_REQUIRE(pthread_cond_wait(&cond
, &mutex
));
97 printf("1: After waiting, in loop.\n");
98 } while (sharedval
!= 0);
100 printf("1: After the loop.\n");
102 PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex
));
104 printf("1: After releasing the mutex.\n");
105 PTHREAD_REQUIRE(pthread_join(new, &joinval
));
107 printf("1: Thread joined.\n");
111 signal_before_unlock_threadfunc(void *arg
)
113 int *shared
= (int *) arg
;
115 printf("2: Second thread.\n");
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
);
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
));
130 ATF_TC(signal_before_unlock
);
131 ATF_TC_HEAD(signal_before_unlock
, tc
)
133 atf_tc_set_md_var(tc
, "descr",
134 "Checks condition variables: signal before unlocking mutex");
136 ATF_TC_BODY(signal_before_unlock
, tc
)
142 printf("1: condition variable test 2\n");
144 PTHREAD_REQUIRE(pthread_mutex_init(&mutex
, NULL
));
145 PTHREAD_REQUIRE(pthread_cond_init(&cond
, NULL
));
147 PTHREAD_REQUIRE(pthread_mutex_lock(&mutex
));
151 PTHREAD_REQUIRE(pthread_create(&new, NULL
,
152 signal_before_unlock_threadfunc
, &sharedval
));
154 printf("1: Before waiting.\n");
157 PTHREAD_REQUIRE(pthread_cond_wait(&cond
, &mutex
));
158 printf("1: After waiting, in loop.\n");
159 } while (sharedval
!= 0);
161 printf("1: After the loop.\n");
163 PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex
));
165 printf("1: After releasing the mutex.\n");
166 PTHREAD_REQUIRE(pthread_join(new, &joinval
));
168 printf("1: Thread joined.\n");
172 signal_before_unlock_static_init_threadfunc(void *arg
)
174 int *shared
= (int *) arg
;
176 printf("2: Second thread.\n");
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
);
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
));
191 ATF_TC(signal_before_unlock_static_init
);
192 ATF_TC_HEAD(signal_before_unlock_static_init
, tc
)
194 atf_tc_set_md_var(tc
, "descr",
195 "Checks condition variables: signal before unlocking "
196 "mutex, use static initializers");
198 ATF_TC_BODY(signal_before_unlock_static_init
, tc
)
204 printf("1: condition variable test 3\n");
206 PTHREAD_REQUIRE(pthread_mutex_lock(&static_mutex
));
210 PTHREAD_REQUIRE(pthread_create(&new, NULL
,
211 signal_before_unlock_static_init_threadfunc
, &sharedval
));
213 printf("1: Before waiting.\n");
216 PTHREAD_REQUIRE(pthread_cond_wait(&static_cond
, &static_mutex
));
217 printf("1: After waiting, in loop.\n");
218 } while (sharedval
!= 0);
220 printf("1: After the loop.\n");
222 PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex
));
224 printf("1: After releasing the mutex.\n");
225 PTHREAD_REQUIRE(pthread_join(new, &joinval
));
227 printf("1: Thread joined.\n");
231 signal_wait_race_threadfunc(void *arg
)
233 printf("2: Second thread.\n");
234 PTHREAD_REQUIRE(pthread_mutex_lock(&static_mutex
));
235 printf("2: Before the loop.\n");
240 /* printf("2: Before signal %d.\n", count); */
241 PTHREAD_REQUIRE(pthread_cond_signal(&static_cond
));
243 PTHREAD_REQUIRE(pthread_cond_wait(&static_cond
,
245 } while (toggle
!= 1);
247 printf("2: After the loop.\n");
248 PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex
));
253 ATF_TC(signal_wait_race
);
254 ATF_TC_HEAD(signal_wait_race
, tc
)
256 atf_tc_set_md_var(tc
, "descr", "Checks condition variables");
258 ATF_TC_BODY(signal_wait_race
, tc
)
264 printf("1: condition variable test 4\n");
266 PTHREAD_REQUIRE(pthread_mutex_lock(&static_mutex
));
271 PTHREAD_REQUIRE(pthread_create(&new, NULL
, signal_wait_race_threadfunc
,
274 printf("1: Before waiting.\n");
279 /* printf("1: Before signal %d.\n", count); */
280 PTHREAD_REQUIRE(pthread_cond_signal(&static_cond
));
282 PTHREAD_REQUIRE(pthread_cond_wait(&static_cond
,
284 } while (toggle
!= 0);
286 printf("1: After the loop.\n");
289 PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex
));
290 PTHREAD_REQUIRE(pthread_cond_signal(&static_cond
));
292 printf("1: After releasing the mutex.\n");
293 PTHREAD_REQUIRE(pthread_join(new, &joinval
));
295 printf("1: Thread joined. Final count = %d, total = %d\n",
298 ATF_REQUIRE_EQ(count
, 0);
299 ATF_REQUIRE_EQ(total
, 50000);
303 pthread_cond_timedwait_func(void *arg
)
314 (void)memset(&ts
, 0, sizeof(struct timespec
));
316 ATF_REQUIRE(clock_gettime(CLOCK_REALTIME
, &ts
) == 0);
319 * Set to one second in the past:
320 * pthread_cond_timedwait(3) should
321 * return ETIMEDOUT immediately.
323 ts
.tv_sec
= ts
.tv_sec
- 1;
325 PTHREAD_REQUIRE(pthread_mutex_lock(&static_mutex
));
326 rv
= pthread_cond_timedwait(&static_cond
, &static_mutex
, &ts
);
329 * Sometimes we catch ESRCH.
330 * This should never happen.
332 ATF_REQUIRE(rv
== ETIMEDOUT
);
333 PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex
));
337 ATF_TC(cond_timedwait_race
);
338 ATF_TC_HEAD(cond_timedwait_race
, tc
)
340 atf_tc_set_md_var(tc
, "descr", "Test pthread_cond_timedwait(3)");
343 ATF_TC_BODY(cond_timedwait_race
, tc
)
348 for (i
= 0; i
< __arraycount(tid
); i
++) {
350 PTHREAD_REQUIRE(pthread_create(&tid
[i
], NULL
,
351 pthread_cond_timedwait_func
, NULL
));
354 for (i
= 0; i
< __arraycount(tid
); i
++) {
356 PTHREAD_REQUIRE(pthread_join(tid
[i
], NULL
));
361 broadcast_threadfunc(void *arg
)
363 printf("2: Second thread.\n");
365 PTHREAD_REQUIRE(pthread_mutex_lock(&static_mutex
));
370 PTHREAD_REQUIRE(pthread_cond_signal(&static_cond
));
372 PTHREAD_REQUIRE(pthread_cond_wait(&static_cond
,
374 } while (toggle
!= 1);
376 printf("2: After the loop.\n");
377 PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex
));
384 ATF_TC_HEAD(broadcast
, tc
)
386 atf_tc_set_md_var(tc
, "descr",
387 "Checks condition variables: use pthread_cond_broadcast()");
389 ATF_TC_BODY(broadcast
, tc
)
395 printf("1: condition variable test 5\n");
397 PTHREAD_REQUIRE(pthread_mutex_lock(&static_mutex
));
402 PTHREAD_REQUIRE(pthread_create(&new, NULL
, broadcast_threadfunc
,
405 printf("1: Before waiting.\n");
410 PTHREAD_REQUIRE(pthread_cond_broadcast(&static_cond
));
412 PTHREAD_REQUIRE(pthread_cond_wait(&static_cond
,
414 } while (toggle
!= 0);
416 printf("1: After the loop.\n");
419 PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex
));
420 PTHREAD_REQUIRE(pthread_cond_signal(&static_cond
));
422 printf("1: After releasing the mutex.\n");
423 PTHREAD_REQUIRE(pthread_join(new, &joinval
));
425 printf("1: Thread joined. Final count = %d, total = %d\n", count
,
428 ATF_REQUIRE_EQ(count
, 0);
429 ATF_REQUIRE_EQ(total
, 50000);
433 bogus_timedwaits_threadfunc(void *arg
)
438 ATF_TC(bogus_timedwaits
);
439 ATF_TC_HEAD(bogus_timedwaits
, tc
)
441 atf_tc_set_md_var(tc
, "descr",
442 "Checks condition variables: bogus timedwaits");
444 ATF_TC_BODY(bogus_timedwaits
, tc
)
450 printf("condition variable test 6: bogus timedwaits\n");
452 PTHREAD_REQUIRE(pthread_mutex_lock(&static_mutex
));
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
);
459 ATF_REQUIRE_EQ_MSG(pthread_cond_timedwait(&static_cond
, &static_mutex
,
460 &ts
), ETIMEDOUT
, "pthread_cond_timedwait() (unthreaded) in the "
463 printf("unthreaded test (zero time)\n");
466 TIMEVAL_TO_TIMESPEC(&tv
, &ts
);
468 ATF_REQUIRE_EQ_MSG(pthread_cond_timedwait(&static_cond
, &static_mutex
,
469 &ts
), ETIMEDOUT
, "pthread_cond_timedwait() (unthreaded) with zero "
472 PTHREAD_REQUIRE(pthread_create(&new, NULL
, bogus_timedwaits_threadfunc
,
474 PTHREAD_REQUIRE(pthread_join(new, NULL
));
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
);
481 ATF_REQUIRE_EQ_MSG(pthread_cond_timedwait(&static_cond
, &static_mutex
,
482 &ts
), ETIMEDOUT
, "pthread_cond_timedwait() (threaded) in the past");
484 printf("threaded test (zero time)\n");
487 TIMEVAL_TO_TIMESPEC(&tv
, &ts
);
489 ATF_REQUIRE_EQ_MSG(pthread_cond_timedwait(&static_cond
, &static_mutex
,
490 &ts
), ETIMEDOUT
, "pthread_cond_timedwait() (threaded) with zero "
493 PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex
));
499 pthread_mutex_unlock((pthread_mutex_t
*)arg
);
503 destroy_after_cancel_threadfunc(void *arg
)
505 PTHREAD_REQUIRE(pthread_mutex_lock(&mutex
));
507 pthread_cleanup_push(unlock
, &mutex
);
511 PTHREAD_REQUIRE(pthread_cond_broadcast(&cond
));
512 PTHREAD_REQUIRE(pthread_cond_wait(&cond
, &mutex
));
515 pthread_cleanup_pop(0);
516 PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex
));
521 ATF_TC(destroy_after_cancel
);
522 ATF_TC_HEAD(destroy_after_cancel
, tc
)
524 atf_tc_set_md_var(tc
, "descr", "Checks destroying a condition variable "
525 "after cancelling a wait");
527 ATF_TC_BODY(destroy_after_cancel
, tc
)
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
));
538 PTHREAD_REQUIRE(pthread_cond_wait(&cond
, &mutex
));
541 PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex
));
542 PTHREAD_REQUIRE(pthread_cancel(thread
));
544 PTHREAD_REQUIRE(pthread_join(thread
, NULL
));
545 PTHREAD_REQUIRE(pthread_cond_destroy(&cond
));
547 PTHREAD_REQUIRE(pthread_mutex_destroy(&mutex
));
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
);
562 return atf_no_error();