1*a1d54d8eSad /* $NetBSD: t_cond.c,v 1.8 2020/06/10 21:46:50 ad Exp $ */
2ac555471Sjmmv
3ac555471Sjmmv /*
4ac555471Sjmmv * Copyright (c) 2008 The NetBSD Foundation, Inc.
5ac555471Sjmmv * All rights reserved.
6ac555471Sjmmv *
7ac555471Sjmmv * Redistribution and use in source and binary forms, with or without
8ac555471Sjmmv * modification, are permitted provided that the following conditions
9ac555471Sjmmv * are met:
10ac555471Sjmmv * 1. Redistributions of source code must retain the above copyright
11ac555471Sjmmv * notice, this list of conditions and the following disclaimer.
12ac555471Sjmmv * 2. Redistributions in binary form must reproduce the above copyright
13ac555471Sjmmv * notice, this list of conditions and the following disclaimer in the
14ac555471Sjmmv * documentation and/or other materials provided with the distribution.
15ac555471Sjmmv *
16ac555471Sjmmv * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17ac555471Sjmmv * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18ac555471Sjmmv * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19ac555471Sjmmv * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20ac555471Sjmmv * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21ac555471Sjmmv * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22ac555471Sjmmv * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23ac555471Sjmmv * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24ac555471Sjmmv * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25ac555471Sjmmv * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26ac555471Sjmmv * POSSIBILITY OF SUCH DAMAGE.
27ac555471Sjmmv */
28ac555471Sjmmv
29ac555471Sjmmv #include <sys/cdefs.h>
30ac555471Sjmmv __COPYRIGHT("@(#) Copyright (c) 2008\
31ac555471Sjmmv The NetBSD Foundation, inc. All rights reserved.");
32*a1d54d8eSad __RCSID("$NetBSD: t_cond.c,v 1.8 2020/06/10 21:46:50 ad Exp $");
33ac555471Sjmmv
34ac555471Sjmmv #include <sys/time.h>
35ac555471Sjmmv
36ac555471Sjmmv #include <errno.h>
37ac555471Sjmmv #include <pthread.h>
38ac555471Sjmmv #include <stdio.h>
39ac555471Sjmmv #include <unistd.h>
40ac555471Sjmmv
41ac555471Sjmmv #include <atf-c.h>
42ac555471Sjmmv
43ac555471Sjmmv #include "h_common.h"
44ac555471Sjmmv
45ac555471Sjmmv static pthread_mutex_t mutex;
46ac555471Sjmmv static pthread_cond_t cond;
47ac555471Sjmmv static pthread_mutex_t static_mutex = PTHREAD_MUTEX_INITIALIZER;
48ac555471Sjmmv static pthread_cond_t static_cond = PTHREAD_COND_INITIALIZER;
49ac555471Sjmmv static int count, share, toggle, total;
50ac555471Sjmmv
51ac555471Sjmmv static void *
signal_delay_wait_threadfunc(void * arg)52ac555471Sjmmv signal_delay_wait_threadfunc(void *arg)
53ac555471Sjmmv {
540f10aa9dSchristos int *shared = (int *) arg;
55ac555471Sjmmv
56ac555471Sjmmv printf("2: Second thread.\n");
57ac555471Sjmmv
58ac555471Sjmmv printf("2: Locking mutex\n");
59ac555471Sjmmv PTHREAD_REQUIRE(pthread_mutex_lock(&mutex));
60ac555471Sjmmv printf("2: Got mutex.\n");
610f10aa9dSchristos printf("Shared value: %d. Changing to 0.\n", *shared);
620f10aa9dSchristos *shared = 0;
63ac555471Sjmmv
64ac555471Sjmmv PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
65ac555471Sjmmv PTHREAD_REQUIRE(pthread_cond_signal(&cond));
66ac555471Sjmmv
67ac555471Sjmmv return NULL;
68ac555471Sjmmv }
69ac555471Sjmmv
70ac555471Sjmmv ATF_TC(signal_delay_wait);
ATF_TC_HEAD(signal_delay_wait,tc)71ac555471Sjmmv ATF_TC_HEAD(signal_delay_wait, tc)
72ac555471Sjmmv {
73ac555471Sjmmv atf_tc_set_md_var(tc, "descr", "Checks condition variables");
74ac555471Sjmmv }
ATF_TC_BODY(signal_delay_wait,tc)75ac555471Sjmmv ATF_TC_BODY(signal_delay_wait, tc)
76ac555471Sjmmv {
77ac555471Sjmmv pthread_t new;
78ac555471Sjmmv void *joinval;
79ac555471Sjmmv int sharedval;
80ac555471Sjmmv
81ac555471Sjmmv printf("1: condition variable test 1\n");
82ac555471Sjmmv
83ac555471Sjmmv PTHREAD_REQUIRE(pthread_mutex_init(&mutex, NULL));
84ac555471Sjmmv PTHREAD_REQUIRE(pthread_cond_init(&cond, NULL));
85ac555471Sjmmv
86ac555471Sjmmv PTHREAD_REQUIRE(pthread_mutex_lock(&mutex));
87ac555471Sjmmv
88ac555471Sjmmv sharedval = 1;
89ac555471Sjmmv
90ac555471Sjmmv PTHREAD_REQUIRE(pthread_create(&new, NULL, signal_delay_wait_threadfunc,
91ac555471Sjmmv &sharedval));
92ac555471Sjmmv
93ac555471Sjmmv printf("1: Before waiting.\n");
94ac555471Sjmmv do {
95ac555471Sjmmv sleep(2);
96ac555471Sjmmv PTHREAD_REQUIRE(pthread_cond_wait(&cond, &mutex));
97ac555471Sjmmv printf("1: After waiting, in loop.\n");
98ac555471Sjmmv } while (sharedval != 0);
99ac555471Sjmmv
100ac555471Sjmmv printf("1: After the loop.\n");
101ac555471Sjmmv
102ac555471Sjmmv PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
103ac555471Sjmmv
104ac555471Sjmmv printf("1: After releasing the mutex.\n");
105ac555471Sjmmv PTHREAD_REQUIRE(pthread_join(new, &joinval));
106ac555471Sjmmv
107ac555471Sjmmv printf("1: Thread joined.\n");
108ac555471Sjmmv }
109ac555471Sjmmv
110ac555471Sjmmv static void *
signal_before_unlock_threadfunc(void * arg)111ac555471Sjmmv signal_before_unlock_threadfunc(void *arg)
112ac555471Sjmmv {
1130f10aa9dSchristos int *shared = (int *) arg;
114ac555471Sjmmv
115ac555471Sjmmv printf("2: Second thread.\n");
116ac555471Sjmmv
117ac555471Sjmmv printf("2: Locking mutex\n");
118ac555471Sjmmv PTHREAD_REQUIRE(pthread_mutex_lock(&mutex));
119ac555471Sjmmv printf("2: Got mutex.\n");
1200f10aa9dSchristos printf("Shared value: %d. Changing to 0.\n", *shared);
1210f10aa9dSchristos *shared = 0;
122ac555471Sjmmv
123ac555471Sjmmv /* Signal first, then unlock, for a different test than #1. */
124ac555471Sjmmv PTHREAD_REQUIRE(pthread_cond_signal(&cond));
125ac555471Sjmmv PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
126ac555471Sjmmv
127ac555471Sjmmv return NULL;
128ac555471Sjmmv }
129ac555471Sjmmv
130ac555471Sjmmv ATF_TC(signal_before_unlock);
ATF_TC_HEAD(signal_before_unlock,tc)131ac555471Sjmmv ATF_TC_HEAD(signal_before_unlock, tc)
132ac555471Sjmmv {
133ac555471Sjmmv atf_tc_set_md_var(tc, "descr",
134ac555471Sjmmv "Checks condition variables: signal before unlocking mutex");
135ac555471Sjmmv }
ATF_TC_BODY(signal_before_unlock,tc)136ac555471Sjmmv ATF_TC_BODY(signal_before_unlock, tc)
137ac555471Sjmmv {
138ac555471Sjmmv pthread_t new;
139ac555471Sjmmv void *joinval;
140ac555471Sjmmv int sharedval;
141ac555471Sjmmv
142ac555471Sjmmv printf("1: condition variable test 2\n");
143ac555471Sjmmv
144ac555471Sjmmv PTHREAD_REQUIRE(pthread_mutex_init(&mutex, NULL));
145ac555471Sjmmv PTHREAD_REQUIRE(pthread_cond_init(&cond, NULL));
146ac555471Sjmmv
147ac555471Sjmmv PTHREAD_REQUIRE(pthread_mutex_lock(&mutex));
148ac555471Sjmmv
149ac555471Sjmmv sharedval = 1;
150ac555471Sjmmv
151ac555471Sjmmv PTHREAD_REQUIRE(pthread_create(&new, NULL,
152ac555471Sjmmv signal_before_unlock_threadfunc, &sharedval));
153ac555471Sjmmv
154ac555471Sjmmv printf("1: Before waiting.\n");
155ac555471Sjmmv do {
156ac555471Sjmmv sleep(2);
157ac555471Sjmmv PTHREAD_REQUIRE(pthread_cond_wait(&cond, &mutex));
158ac555471Sjmmv printf("1: After waiting, in loop.\n");
159ac555471Sjmmv } while (sharedval != 0);
160ac555471Sjmmv
161ac555471Sjmmv printf("1: After the loop.\n");
162ac555471Sjmmv
163ac555471Sjmmv PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
164ac555471Sjmmv
165ac555471Sjmmv printf("1: After releasing the mutex.\n");
166ac555471Sjmmv PTHREAD_REQUIRE(pthread_join(new, &joinval));
167ac555471Sjmmv
168ac555471Sjmmv printf("1: Thread joined.\n");
169ac555471Sjmmv }
170ac555471Sjmmv
171ac555471Sjmmv static void *
signal_before_unlock_static_init_threadfunc(void * arg)172ac555471Sjmmv signal_before_unlock_static_init_threadfunc(void *arg)
173ac555471Sjmmv {
1740f10aa9dSchristos int *shared = (int *) arg;
175ac555471Sjmmv
176ac555471Sjmmv printf("2: Second thread.\n");
177ac555471Sjmmv
178ac555471Sjmmv printf("2: Locking mutex\n");
179ac555471Sjmmv PTHREAD_REQUIRE(pthread_mutex_lock(&static_mutex));
180ac555471Sjmmv printf("2: Got mutex.\n");
1810f10aa9dSchristos printf("Shared value: %d. Changing to 0.\n", *shared);
1820f10aa9dSchristos *shared = 0;
183ac555471Sjmmv
184ac555471Sjmmv /* Signal first, then unlock, for a different test than #1. */
185ac555471Sjmmv PTHREAD_REQUIRE(pthread_cond_signal(&static_cond));
186ac555471Sjmmv PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex));
187ac555471Sjmmv
188ac555471Sjmmv return NULL;
189ac555471Sjmmv }
190ac555471Sjmmv
191ac555471Sjmmv ATF_TC(signal_before_unlock_static_init);
ATF_TC_HEAD(signal_before_unlock_static_init,tc)192ac555471Sjmmv ATF_TC_HEAD(signal_before_unlock_static_init, tc)
193ac555471Sjmmv {
194ac555471Sjmmv atf_tc_set_md_var(tc, "descr",
195ac555471Sjmmv "Checks condition variables: signal before unlocking "
196ac555471Sjmmv "mutex, use static initializers");
197ac555471Sjmmv }
ATF_TC_BODY(signal_before_unlock_static_init,tc)198ac555471Sjmmv ATF_TC_BODY(signal_before_unlock_static_init, tc)
199ac555471Sjmmv {
200ac555471Sjmmv pthread_t new;
201ac555471Sjmmv void *joinval;
202ac555471Sjmmv int sharedval;
203ac555471Sjmmv
204ac555471Sjmmv printf("1: condition variable test 3\n");
205ac555471Sjmmv
206ac555471Sjmmv PTHREAD_REQUIRE(pthread_mutex_lock(&static_mutex));
207ac555471Sjmmv
208ac555471Sjmmv sharedval = 1;
209ac555471Sjmmv
210ac555471Sjmmv PTHREAD_REQUIRE(pthread_create(&new, NULL,
211ac555471Sjmmv signal_before_unlock_static_init_threadfunc, &sharedval));
212ac555471Sjmmv
213ac555471Sjmmv printf("1: Before waiting.\n");
214ac555471Sjmmv do {
215ac555471Sjmmv sleep(2);
216ac555471Sjmmv PTHREAD_REQUIRE(pthread_cond_wait(&static_cond, &static_mutex));
217ac555471Sjmmv printf("1: After waiting, in loop.\n");
218ac555471Sjmmv } while (sharedval != 0);
219ac555471Sjmmv
220ac555471Sjmmv printf("1: After the loop.\n");
221ac555471Sjmmv
222ac555471Sjmmv PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex));
223ac555471Sjmmv
224ac555471Sjmmv printf("1: After releasing the mutex.\n");
225ac555471Sjmmv PTHREAD_REQUIRE(pthread_join(new, &joinval));
226ac555471Sjmmv
227ac555471Sjmmv printf("1: Thread joined.\n");
228ac555471Sjmmv }
229ac555471Sjmmv
230ac555471Sjmmv static void *
signal_wait_race_threadfunc(void * arg)231ac555471Sjmmv signal_wait_race_threadfunc(void *arg)
232ac555471Sjmmv {
233ac555471Sjmmv printf("2: Second thread.\n");
234ac555471Sjmmv PTHREAD_REQUIRE(pthread_mutex_lock(&static_mutex));
235ac555471Sjmmv printf("2: Before the loop.\n");
236ac555471Sjmmv while (count>0) {
237ac555471Sjmmv count--;
238ac555471Sjmmv total++;
239ac555471Sjmmv toggle = 0;
240ac555471Sjmmv /* printf("2: Before signal %d.\n", count); */
241ac555471Sjmmv PTHREAD_REQUIRE(pthread_cond_signal(&static_cond));
242ac555471Sjmmv do {
243ac555471Sjmmv PTHREAD_REQUIRE(pthread_cond_wait(&static_cond,
244ac555471Sjmmv &static_mutex));
245ac555471Sjmmv } while (toggle != 1);
246ac555471Sjmmv }
247ac555471Sjmmv printf("2: After the loop.\n");
248ac555471Sjmmv PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex));
249ac555471Sjmmv
250ac555471Sjmmv return NULL;
251ac555471Sjmmv }
252ac555471Sjmmv
253ac555471Sjmmv ATF_TC(signal_wait_race);
ATF_TC_HEAD(signal_wait_race,tc)254ac555471Sjmmv ATF_TC_HEAD(signal_wait_race, tc)
255ac555471Sjmmv {
256ac555471Sjmmv atf_tc_set_md_var(tc, "descr", "Checks condition variables");
257ac555471Sjmmv }
ATF_TC_BODY(signal_wait_race,tc)258ac555471Sjmmv ATF_TC_BODY(signal_wait_race, tc)
259ac555471Sjmmv {
260ac555471Sjmmv pthread_t new;
261ac555471Sjmmv void *joinval;
262ac555471Sjmmv int sharedval;
263ac555471Sjmmv
264ac555471Sjmmv printf("1: condition variable test 4\n");
265ac555471Sjmmv
266ac555471Sjmmv PTHREAD_REQUIRE(pthread_mutex_lock(&static_mutex));
267ac555471Sjmmv
268ac555471Sjmmv count = 50000;
269ac555471Sjmmv toggle = 0;
270ac555471Sjmmv
271ac555471Sjmmv PTHREAD_REQUIRE(pthread_create(&new, NULL, signal_wait_race_threadfunc,
272ac555471Sjmmv &sharedval));
273ac555471Sjmmv
274ac555471Sjmmv printf("1: Before waiting.\n");
275ac555471Sjmmv while (count>0) {
276ac555471Sjmmv count--;
277ac555471Sjmmv total++;
278ac555471Sjmmv toggle = 1;
279ac555471Sjmmv /* printf("1: Before signal %d.\n", count); */
280ac555471Sjmmv PTHREAD_REQUIRE(pthread_cond_signal(&static_cond));
281ac555471Sjmmv do {
282ac555471Sjmmv PTHREAD_REQUIRE(pthread_cond_wait(&static_cond,
283ac555471Sjmmv &static_mutex));
284ac555471Sjmmv } while (toggle != 0);
285ac555471Sjmmv }
286ac555471Sjmmv printf("1: After the loop.\n");
287ac555471Sjmmv
288ac555471Sjmmv toggle = 1;
289ac555471Sjmmv PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex));
290ac555471Sjmmv PTHREAD_REQUIRE(pthread_cond_signal(&static_cond));
291ac555471Sjmmv
292ac555471Sjmmv printf("1: After releasing the mutex.\n");
293ac555471Sjmmv PTHREAD_REQUIRE(pthread_join(new, &joinval));
294ac555471Sjmmv
295ac555471Sjmmv printf("1: Thread joined. Final count = %d, total = %d\n",
296ac555471Sjmmv count, total);
297ac555471Sjmmv
298ac555471Sjmmv ATF_REQUIRE_EQ(count, 0);
299ac555471Sjmmv ATF_REQUIRE_EQ(total, 50000);
300ac555471Sjmmv }
301ac555471Sjmmv
302ac555471Sjmmv static void *
pthread_cond_timedwait_func(void * arg)3031b871e25Sjruoho pthread_cond_timedwait_func(void *arg)
3041b871e25Sjruoho {
3051b871e25Sjruoho struct timespec ts;
3061b871e25Sjruoho size_t i = 0;
3071b871e25Sjruoho int rv;
3081b871e25Sjruoho
3091b871e25Sjruoho for (;;) {
3101b871e25Sjruoho
3111b871e25Sjruoho if (i++ >= 10000)
3121b871e25Sjruoho pthread_exit(NULL);
3131b871e25Sjruoho
3141b871e25Sjruoho (void)memset(&ts, 0, sizeof(struct timespec));
3151b871e25Sjruoho
3161b871e25Sjruoho ATF_REQUIRE(clock_gettime(CLOCK_REALTIME, &ts) == 0);
3171b871e25Sjruoho
3181b871e25Sjruoho /*
3191b871e25Sjruoho * Set to one second in the past:
3201b871e25Sjruoho * pthread_cond_timedwait(3) should
3211b871e25Sjruoho * return ETIMEDOUT immediately.
3221b871e25Sjruoho */
3231b871e25Sjruoho ts.tv_sec = ts.tv_sec - 1;
3241b871e25Sjruoho
3251b871e25Sjruoho PTHREAD_REQUIRE(pthread_mutex_lock(&static_mutex));
3261b871e25Sjruoho rv = pthread_cond_timedwait(&static_cond, &static_mutex, &ts);
3271b871e25Sjruoho
3281b871e25Sjruoho /*
3291b871e25Sjruoho * Sometimes we catch ESRCH.
3301b871e25Sjruoho * This should never happen.
3311b871e25Sjruoho */
332*a1d54d8eSad ATF_REQUIRE(rv == ETIMEDOUT || rv == 0);
3331b871e25Sjruoho PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex));
3341b871e25Sjruoho }
3351b871e25Sjruoho }
3361b871e25Sjruoho
3371b871e25Sjruoho ATF_TC(cond_timedwait_race);
ATF_TC_HEAD(cond_timedwait_race,tc)3381b871e25Sjruoho ATF_TC_HEAD(cond_timedwait_race, tc)
3391b871e25Sjruoho {
3401b871e25Sjruoho atf_tc_set_md_var(tc, "descr", "Test pthread_cond_timedwait(3)");
3411b871e25Sjruoho
3421b871e25Sjruoho }
ATF_TC_BODY(cond_timedwait_race,tc)3431b871e25Sjruoho ATF_TC_BODY(cond_timedwait_race, tc)
3441b871e25Sjruoho {
3451b871e25Sjruoho pthread_t tid[64];
34635cbd4f0Sgson size_t i;
3471b871e25Sjruoho
3481b871e25Sjruoho for (i = 0; i < __arraycount(tid); i++) {
3491b871e25Sjruoho
3501b871e25Sjruoho PTHREAD_REQUIRE(pthread_create(&tid[i], NULL,
3511b871e25Sjruoho pthread_cond_timedwait_func, NULL));
3521b871e25Sjruoho }
3531b871e25Sjruoho
3541b871e25Sjruoho for (i = 0; i < __arraycount(tid); i++) {
3551b871e25Sjruoho
3561b871e25Sjruoho PTHREAD_REQUIRE(pthread_join(tid[i], NULL));
3571b871e25Sjruoho }
3581b871e25Sjruoho }
3591b871e25Sjruoho
3601b871e25Sjruoho static void *
broadcast_threadfunc(void * arg)361ac555471Sjmmv broadcast_threadfunc(void *arg)
362ac555471Sjmmv {
363ac555471Sjmmv printf("2: Second thread.\n");
364ac555471Sjmmv
365ac555471Sjmmv PTHREAD_REQUIRE(pthread_mutex_lock(&static_mutex));
366ac555471Sjmmv while (count>0) {
367ac555471Sjmmv count--;
368ac555471Sjmmv total++;
369ac555471Sjmmv toggle = 0;
370ac555471Sjmmv PTHREAD_REQUIRE(pthread_cond_signal(&static_cond));
371ac555471Sjmmv do {
372ac555471Sjmmv PTHREAD_REQUIRE(pthread_cond_wait(&static_cond,
373ac555471Sjmmv &static_mutex));
374ac555471Sjmmv } while (toggle != 1);
375ac555471Sjmmv }
376ac555471Sjmmv printf("2: After the loop.\n");
377ac555471Sjmmv PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex));
378ac555471Sjmmv
379ac555471Sjmmv return NULL;
380ac555471Sjmmv }
381ac555471Sjmmv
382ac555471Sjmmv
383ac555471Sjmmv ATF_TC(broadcast);
ATF_TC_HEAD(broadcast,tc)384ac555471Sjmmv ATF_TC_HEAD(broadcast, tc)
385ac555471Sjmmv {
386ac555471Sjmmv atf_tc_set_md_var(tc, "descr",
387ac555471Sjmmv "Checks condition variables: use pthread_cond_broadcast()");
388ac555471Sjmmv }
ATF_TC_BODY(broadcast,tc)389ac555471Sjmmv ATF_TC_BODY(broadcast, tc)
390ac555471Sjmmv {
391ac555471Sjmmv pthread_t new;
392ac555471Sjmmv void *joinval;
393ac555471Sjmmv int sharedval;
394ac555471Sjmmv
395ac555471Sjmmv printf("1: condition variable test 5\n");
396ac555471Sjmmv
397ac555471Sjmmv PTHREAD_REQUIRE(pthread_mutex_lock(&static_mutex));
398ac555471Sjmmv
399ac555471Sjmmv count = 50000;
400ac555471Sjmmv toggle = 0;
401ac555471Sjmmv
402ac555471Sjmmv PTHREAD_REQUIRE(pthread_create(&new, NULL, broadcast_threadfunc,
403ac555471Sjmmv &sharedval));
404ac555471Sjmmv
405ac555471Sjmmv printf("1: Before waiting.\n");
406ac555471Sjmmv while (count>0) {
407ac555471Sjmmv count--;
408ac555471Sjmmv total++;
409ac555471Sjmmv toggle = 1;
410ac555471Sjmmv PTHREAD_REQUIRE(pthread_cond_broadcast(&static_cond));
411ac555471Sjmmv do {
412ac555471Sjmmv PTHREAD_REQUIRE(pthread_cond_wait(&static_cond,
413ac555471Sjmmv &static_mutex));
414ac555471Sjmmv } while (toggle != 0);
415ac555471Sjmmv }
416ac555471Sjmmv printf("1: After the loop.\n");
417ac555471Sjmmv
418ac555471Sjmmv toggle = 1;
419ac555471Sjmmv PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex));
420ac555471Sjmmv PTHREAD_REQUIRE(pthread_cond_signal(&static_cond));
421ac555471Sjmmv
422ac555471Sjmmv printf("1: After releasing the mutex.\n");
423ac555471Sjmmv PTHREAD_REQUIRE(pthread_join(new, &joinval));
424ac555471Sjmmv
425ac555471Sjmmv printf("1: Thread joined. Final count = %d, total = %d\n", count,
426ac555471Sjmmv total);
427ac555471Sjmmv
428ac555471Sjmmv ATF_REQUIRE_EQ(count, 0);
429ac555471Sjmmv ATF_REQUIRE_EQ(total, 50000);
430ac555471Sjmmv }
431ac555471Sjmmv
432ac555471Sjmmv static void *
bogus_timedwaits_threadfunc(void * arg)433ac555471Sjmmv bogus_timedwaits_threadfunc(void *arg)
434ac555471Sjmmv {
435ac555471Sjmmv return NULL;
436ac555471Sjmmv }
437ac555471Sjmmv
438ac555471Sjmmv ATF_TC(bogus_timedwaits);
ATF_TC_HEAD(bogus_timedwaits,tc)439ac555471Sjmmv ATF_TC_HEAD(bogus_timedwaits, tc)
440ac555471Sjmmv {
441ac555471Sjmmv atf_tc_set_md_var(tc, "descr",
442ac555471Sjmmv "Checks condition variables: bogus timedwaits");
443ac555471Sjmmv }
ATF_TC_BODY(bogus_timedwaits,tc)444ac555471Sjmmv ATF_TC_BODY(bogus_timedwaits, tc)
445ac555471Sjmmv {
446ac555471Sjmmv pthread_t new;
447ac555471Sjmmv struct timespec ts;
448ac555471Sjmmv struct timeval tv;
449ac555471Sjmmv
450ac555471Sjmmv printf("condition variable test 6: bogus timedwaits\n");
451ac555471Sjmmv
452ac555471Sjmmv PTHREAD_REQUIRE(pthread_mutex_lock(&static_mutex));
453ac555471Sjmmv
454ac555471Sjmmv printf("unthreaded test (past)\n");
455ac555471Sjmmv gettimeofday(&tv, NULL);
456ac555471Sjmmv tv.tv_sec -= 2; /* Place the time in the past */
457ac555471Sjmmv TIMEVAL_TO_TIMESPEC(&tv, &ts);
458ac555471Sjmmv
459ac555471Sjmmv ATF_REQUIRE_EQ_MSG(pthread_cond_timedwait(&static_cond, &static_mutex,
460ac555471Sjmmv &ts), ETIMEDOUT, "pthread_cond_timedwait() (unthreaded) in the "
461ac555471Sjmmv "past");
462ac555471Sjmmv
463ac555471Sjmmv printf("unthreaded test (zero time)\n");
464ac555471Sjmmv tv.tv_sec = 0;
465ac555471Sjmmv tv.tv_usec = 0;
466ac555471Sjmmv TIMEVAL_TO_TIMESPEC(&tv, &ts);
467ac555471Sjmmv
468ac555471Sjmmv ATF_REQUIRE_EQ_MSG(pthread_cond_timedwait(&static_cond, &static_mutex,
469ac555471Sjmmv &ts), ETIMEDOUT, "pthread_cond_timedwait() (unthreaded) with zero "
470ac555471Sjmmv "time");
471ac555471Sjmmv
472ac555471Sjmmv PTHREAD_REQUIRE(pthread_create(&new, NULL, bogus_timedwaits_threadfunc,
473ac555471Sjmmv NULL));
474ac555471Sjmmv PTHREAD_REQUIRE(pthread_join(new, NULL));
475ac555471Sjmmv
476ac555471Sjmmv printf("threaded test\n");
477ac555471Sjmmv gettimeofday(&tv, NULL);
478ac555471Sjmmv tv.tv_sec -= 2; /* Place the time in the past */
479ac555471Sjmmv TIMEVAL_TO_TIMESPEC(&tv, &ts);
480ac555471Sjmmv
481ac555471Sjmmv ATF_REQUIRE_EQ_MSG(pthread_cond_timedwait(&static_cond, &static_mutex,
482ac555471Sjmmv &ts), ETIMEDOUT, "pthread_cond_timedwait() (threaded) in the past");
483ac555471Sjmmv
484ac555471Sjmmv printf("threaded test (zero time)\n");
485ac555471Sjmmv tv.tv_sec = 0;
486ac555471Sjmmv tv.tv_usec = 0;
487ac555471Sjmmv TIMEVAL_TO_TIMESPEC(&tv, &ts);
488ac555471Sjmmv
489ac555471Sjmmv ATF_REQUIRE_EQ_MSG(pthread_cond_timedwait(&static_cond, &static_mutex,
490ac555471Sjmmv &ts), ETIMEDOUT, "pthread_cond_timedwait() (threaded) with zero "
491ac555471Sjmmv "time");
492ac555471Sjmmv
493ac555471Sjmmv PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex));
494ac555471Sjmmv }
495ac555471Sjmmv
496ac555471Sjmmv static void
unlock(void * arg)497ac555471Sjmmv unlock(void *arg)
498ac555471Sjmmv {
499ac555471Sjmmv pthread_mutex_unlock((pthread_mutex_t *)arg);
500ac555471Sjmmv }
501ac555471Sjmmv
502ac555471Sjmmv static void *
destroy_after_cancel_threadfunc(void * arg)503ac555471Sjmmv destroy_after_cancel_threadfunc(void *arg)
504ac555471Sjmmv {
505ac555471Sjmmv PTHREAD_REQUIRE(pthread_mutex_lock(&mutex));
506ac555471Sjmmv
507ac555471Sjmmv pthread_cleanup_push(unlock, &mutex);
508ac555471Sjmmv
509ac555471Sjmmv while (1) {
510ac555471Sjmmv share = 1;
511ac555471Sjmmv PTHREAD_REQUIRE(pthread_cond_broadcast(&cond));
512ac555471Sjmmv PTHREAD_REQUIRE(pthread_cond_wait(&cond, &mutex));
513ac555471Sjmmv }
514ac555471Sjmmv
515ac555471Sjmmv pthread_cleanup_pop(0);
516ac555471Sjmmv PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
517ac555471Sjmmv
518ac555471Sjmmv return NULL;
519ac555471Sjmmv }
520ac555471Sjmmv
521ac555471Sjmmv ATF_TC(destroy_after_cancel);
ATF_TC_HEAD(destroy_after_cancel,tc)522ac555471Sjmmv ATF_TC_HEAD(destroy_after_cancel, tc)
523ac555471Sjmmv {
524ac555471Sjmmv atf_tc_set_md_var(tc, "descr", "Checks destroying a condition variable "
525ac555471Sjmmv "after cancelling a wait");
526ac555471Sjmmv }
ATF_TC_BODY(destroy_after_cancel,tc)527ac555471Sjmmv ATF_TC_BODY(destroy_after_cancel, tc)
528ac555471Sjmmv {
529ac555471Sjmmv pthread_t thread;
530ac555471Sjmmv
531ac555471Sjmmv PTHREAD_REQUIRE(pthread_mutex_init(&mutex, NULL));
532ac555471Sjmmv PTHREAD_REQUIRE(pthread_cond_init(&cond, NULL));
533ac555471Sjmmv PTHREAD_REQUIRE(pthread_mutex_lock(&mutex));
534ac555471Sjmmv PTHREAD_REQUIRE(pthread_create(&thread, NULL,
535ac555471Sjmmv destroy_after_cancel_threadfunc, NULL));
536ac555471Sjmmv
537ac555471Sjmmv while (share == 0) {
538ac555471Sjmmv PTHREAD_REQUIRE(pthread_cond_wait(&cond, &mutex));
539ac555471Sjmmv }
540ac555471Sjmmv
541ac555471Sjmmv PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
542ac555471Sjmmv PTHREAD_REQUIRE(pthread_cancel(thread));
543ac555471Sjmmv
544ac555471Sjmmv PTHREAD_REQUIRE(pthread_join(thread, NULL));
545ac555471Sjmmv PTHREAD_REQUIRE(pthread_cond_destroy(&cond));
546ac555471Sjmmv
547ac555471Sjmmv PTHREAD_REQUIRE(pthread_mutex_destroy(&mutex));
548ac555471Sjmmv }
549ac555471Sjmmv
5507cf7644fSchristos ATF_TC(condattr);
ATF_TC_HEAD(condattr,tc)5517cf7644fSchristos ATF_TC_HEAD(condattr, tc)
5527cf7644fSchristos {
5537cf7644fSchristos atf_tc_set_md_var(tc, "descr", "Checks Condattr");
5547cf7644fSchristos }
ATF_TC_BODY(condattr,tc)5557cf7644fSchristos ATF_TC_BODY(condattr, tc)
5567cf7644fSchristos {
5577cf7644fSchristos pthread_condattr_t condattr;
5587cf7644fSchristos clockid_t clockid;
5597cf7644fSchristos
5607cf7644fSchristos PTHREAD_REQUIRE(pthread_condattr_init(&condattr));
5617cf7644fSchristos PTHREAD_REQUIRE(pthread_condattr_setclock(&condattr, CLOCK_REALTIME));
5627cf7644fSchristos PTHREAD_REQUIRE(pthread_condattr_getclock(&condattr, &clockid));
5637cf7644fSchristos ATF_REQUIRE_EQ(clockid, CLOCK_REALTIME);
5647cf7644fSchristos
5657cf7644fSchristos PTHREAD_REQUIRE(pthread_condattr_setclock(&condattr, CLOCK_MONOTONIC));
5667cf7644fSchristos PTHREAD_REQUIRE(pthread_condattr_getclock(&condattr, &clockid));
5677cf7644fSchristos ATF_REQUIRE_EQ(clockid, CLOCK_MONOTONIC);
5687cf7644fSchristos }
5697cf7644fSchristos
ATF_TP_ADD_TCS(tp)570ac555471Sjmmv ATF_TP_ADD_TCS(tp)
571ac555471Sjmmv {
572ac555471Sjmmv
573ac555471Sjmmv ATF_TP_ADD_TC(tp, signal_delay_wait);
574ac555471Sjmmv ATF_TP_ADD_TC(tp, signal_before_unlock);
575ac555471Sjmmv ATF_TP_ADD_TC(tp, signal_before_unlock_static_init);
576ac555471Sjmmv ATF_TP_ADD_TC(tp, signal_wait_race);
5771b871e25Sjruoho ATF_TP_ADD_TC(tp, cond_timedwait_race);
578ac555471Sjmmv ATF_TP_ADD_TC(tp, broadcast);
579ac555471Sjmmv ATF_TP_ADD_TC(tp, bogus_timedwaits);
580ac555471Sjmmv ATF_TP_ADD_TC(tp, destroy_after_cancel);
5817cf7644fSchristos ATF_TP_ADD_TC(tp, condattr);
582ac555471Sjmmv
583ac555471Sjmmv return atf_no_error();
584ac555471Sjmmv }
585