xref: /netbsd-src/tests/lib/libpthread/t_cond.c (revision a1d54d8ee294c6d001ccb41a768311915365fecf)
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