1309466Sngie/* $NetBSD: t_cond.c,v 1.7 2016/07/03 14:24:59 christos Exp $ */
2272343Sngie
3272343Sngie/*
4272343Sngie * Copyright (c) 2008 The NetBSD Foundation, Inc.
5272343Sngie * All rights reserved.
6272343Sngie *
7272343Sngie * Redistribution and use in source and binary forms, with or without
8272343Sngie * modification, are permitted provided that the following conditions
9272343Sngie * are met:
10272343Sngie * 1. Redistributions of source code must retain the above copyright
11272343Sngie *    notice, this list of conditions and the following disclaimer.
12272343Sngie * 2. Redistributions in binary form must reproduce the above copyright
13272343Sngie *    notice, this list of conditions and the following disclaimer in the
14272343Sngie *    documentation and/or other materials provided with the distribution.
15272343Sngie *
16272343Sngie * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17272343Sngie * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18272343Sngie * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19272343Sngie * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20272343Sngie * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21272343Sngie * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22272343Sngie * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23272343Sngie * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24272343Sngie * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25272343Sngie * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26272343Sngie * POSSIBILITY OF SUCH DAMAGE.
27272343Sngie */
28272343Sngie
29272343Sngie#include <sys/cdefs.h>
30272343Sngie__COPYRIGHT("@(#) Copyright (c) 2008\
31272343Sngie The NetBSD Foundation, inc. All rights reserved.");
32309466Sngie__RCSID("$NetBSD: t_cond.c,v 1.7 2016/07/03 14:24:59 christos Exp $");
33272343Sngie
34272343Sngie#include <sys/time.h>
35272343Sngie
36272343Sngie#include <errno.h>
37272343Sngie#include <pthread.h>
38272343Sngie#include <stdio.h>
39272343Sngie#include <unistd.h>
40272343Sngie
41272343Sngie#include <atf-c.h>
42272343Sngie
43272343Sngie#include "h_common.h"
44272343Sngie
45272343Sngiestatic pthread_mutex_t mutex;
46272343Sngiestatic pthread_cond_t cond;
47272343Sngiestatic pthread_mutex_t static_mutex = PTHREAD_MUTEX_INITIALIZER;
48272343Sngiestatic pthread_cond_t static_cond = PTHREAD_COND_INITIALIZER;
49272343Sngiestatic int count, share, toggle, total;
50272343Sngie
51272343Sngiestatic void *
52272343Sngiesignal_delay_wait_threadfunc(void *arg)
53272343Sngie{
54272343Sngie	int *shared = (int *) arg;
55272343Sngie
56272343Sngie	printf("2: Second thread.\n");
57272343Sngie
58272343Sngie	printf("2: Locking mutex\n");
59272343Sngie	PTHREAD_REQUIRE(pthread_mutex_lock(&mutex));
60272343Sngie	printf("2: Got mutex.\n");
61272343Sngie	printf("Shared value: %d. Changing to 0.\n", *shared);
62272343Sngie	*shared = 0;
63272343Sngie
64272343Sngie	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
65272343Sngie	PTHREAD_REQUIRE(pthread_cond_signal(&cond));
66272343Sngie
67272343Sngie	return NULL;
68272343Sngie}
69272343Sngie
70272343SngieATF_TC(signal_delay_wait);
71272343SngieATF_TC_HEAD(signal_delay_wait, tc)
72272343Sngie{
73272343Sngie	atf_tc_set_md_var(tc, "descr", "Checks condition variables");
74272343Sngie}
75272343SngieATF_TC_BODY(signal_delay_wait, tc)
76272343Sngie{
77272343Sngie	pthread_t new;
78272343Sngie	void *joinval;
79272343Sngie	int sharedval;
80272343Sngie
81272343Sngie	printf("1: condition variable test 1\n");
82272343Sngie
83272343Sngie	PTHREAD_REQUIRE(pthread_mutex_init(&mutex, NULL));
84272343Sngie	PTHREAD_REQUIRE(pthread_cond_init(&cond, NULL));
85272343Sngie
86272343Sngie	PTHREAD_REQUIRE(pthread_mutex_lock(&mutex));
87272343Sngie
88272343Sngie	sharedval = 1;
89272343Sngie
90272343Sngie	PTHREAD_REQUIRE(pthread_create(&new, NULL, signal_delay_wait_threadfunc,
91272343Sngie	    &sharedval));
92272343Sngie
93272343Sngie	printf("1: Before waiting.\n");
94272343Sngie	do {
95272343Sngie		sleep(2);
96272343Sngie		PTHREAD_REQUIRE(pthread_cond_wait(&cond, &mutex));
97272343Sngie		printf("1: After waiting, in loop.\n");
98272343Sngie	} while (sharedval != 0);
99272343Sngie
100272343Sngie	printf("1: After the loop.\n");
101272343Sngie
102272343Sngie	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
103272343Sngie
104272343Sngie	printf("1: After releasing the mutex.\n");
105272343Sngie	PTHREAD_REQUIRE(pthread_join(new, &joinval));
106272343Sngie
107272343Sngie	printf("1: Thread joined.\n");
108272343Sngie}
109272343Sngie
110272343Sngiestatic void *
111272343Sngiesignal_before_unlock_threadfunc(void *arg)
112272343Sngie{
113272343Sngie	int *shared = (int *) arg;
114272343Sngie
115272343Sngie	printf("2: Second thread.\n");
116272343Sngie
117272343Sngie	printf("2: Locking mutex\n");
118272343Sngie	PTHREAD_REQUIRE(pthread_mutex_lock(&mutex));
119272343Sngie	printf("2: Got mutex.\n");
120272343Sngie	printf("Shared value: %d. Changing to 0.\n", *shared);
121272343Sngie	*shared = 0;
122272343Sngie
123272343Sngie	/* Signal first, then unlock, for a different test than #1. */
124272343Sngie	PTHREAD_REQUIRE(pthread_cond_signal(&cond));
125272343Sngie	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
126272343Sngie
127272343Sngie	return NULL;
128272343Sngie}
129272343Sngie
130272343SngieATF_TC(signal_before_unlock);
131272343SngieATF_TC_HEAD(signal_before_unlock, tc)
132272343Sngie{
133272343Sngie	atf_tc_set_md_var(tc, "descr",
134272343Sngie		"Checks condition variables: signal before unlocking mutex");
135272343Sngie}
136272343SngieATF_TC_BODY(signal_before_unlock, tc)
137272343Sngie{
138272343Sngie	pthread_t new;
139272343Sngie	void *joinval;
140272343Sngie	int sharedval;
141272343Sngie
142272343Sngie	printf("1: condition variable test 2\n");
143272343Sngie
144272343Sngie	PTHREAD_REQUIRE(pthread_mutex_init(&mutex, NULL));
145272343Sngie	PTHREAD_REQUIRE(pthread_cond_init(&cond, NULL));
146272343Sngie
147272343Sngie	PTHREAD_REQUIRE(pthread_mutex_lock(&mutex));
148272343Sngie
149272343Sngie	sharedval = 1;
150272343Sngie
151272343Sngie	PTHREAD_REQUIRE(pthread_create(&new, NULL,
152272343Sngie	    signal_before_unlock_threadfunc, &sharedval));
153272343Sngie
154272343Sngie	printf("1: Before waiting.\n");
155272343Sngie	do {
156272343Sngie		sleep(2);
157272343Sngie		PTHREAD_REQUIRE(pthread_cond_wait(&cond, &mutex));
158272343Sngie		printf("1: After waiting, in loop.\n");
159272343Sngie	} while (sharedval != 0);
160272343Sngie
161272343Sngie	printf("1: After the loop.\n");
162272343Sngie
163272343Sngie	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
164272343Sngie
165272343Sngie	printf("1: After releasing the mutex.\n");
166272343Sngie	PTHREAD_REQUIRE(pthread_join(new, &joinval));
167272343Sngie
168272343Sngie	printf("1: Thread joined.\n");
169272343Sngie}
170272343Sngie
171272343Sngiestatic void *
172272343Sngiesignal_before_unlock_static_init_threadfunc(void *arg)
173272343Sngie{
174272343Sngie	int *shared = (int *) arg;
175272343Sngie
176272343Sngie	printf("2: Second thread.\n");
177272343Sngie
178272343Sngie	printf("2: Locking mutex\n");
179272343Sngie	PTHREAD_REQUIRE(pthread_mutex_lock(&static_mutex));
180272343Sngie	printf("2: Got mutex.\n");
181272343Sngie	printf("Shared value: %d. Changing to 0.\n", *shared);
182272343Sngie	*shared = 0;
183272343Sngie
184272343Sngie	/* Signal first, then unlock, for a different test than #1. */
185272343Sngie	PTHREAD_REQUIRE(pthread_cond_signal(&static_cond));
186272343Sngie	PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex));
187272343Sngie
188272343Sngie	return NULL;
189272343Sngie}
190272343Sngie
191272343SngieATF_TC(signal_before_unlock_static_init);
192272343SngieATF_TC_HEAD(signal_before_unlock_static_init, tc)
193272343Sngie{
194272343Sngie	atf_tc_set_md_var(tc, "descr",
195272343Sngie		"Checks condition variables: signal before unlocking "
196272343Sngie		"mutex, use static initializers");
197272343Sngie}
198272343SngieATF_TC_BODY(signal_before_unlock_static_init, tc)
199272343Sngie{
200272343Sngie	pthread_t new;
201272343Sngie	void *joinval;
202272343Sngie	int sharedval;
203272343Sngie
204272343Sngie	printf("1: condition variable test 3\n");
205272343Sngie
206272343Sngie	PTHREAD_REQUIRE(pthread_mutex_lock(&static_mutex));
207272343Sngie
208272343Sngie	sharedval = 1;
209272343Sngie
210272343Sngie	PTHREAD_REQUIRE(pthread_create(&new, NULL,
211272343Sngie	    signal_before_unlock_static_init_threadfunc, &sharedval));
212272343Sngie
213272343Sngie	printf("1: Before waiting.\n");
214272343Sngie	do {
215272343Sngie		sleep(2);
216272343Sngie		PTHREAD_REQUIRE(pthread_cond_wait(&static_cond, &static_mutex));
217272343Sngie		printf("1: After waiting, in loop.\n");
218272343Sngie	} while (sharedval != 0);
219272343Sngie
220272343Sngie	printf("1: After the loop.\n");
221272343Sngie
222272343Sngie	PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex));
223272343Sngie
224272343Sngie	printf("1: After releasing the mutex.\n");
225272343Sngie	PTHREAD_REQUIRE(pthread_join(new, &joinval));
226272343Sngie
227272343Sngie	printf("1: Thread joined.\n");
228272343Sngie}
229272343Sngie
230272343Sngiestatic void *
231272343Sngiesignal_wait_race_threadfunc(void *arg)
232272343Sngie{
233272343Sngie	printf("2: Second thread.\n");
234272343Sngie	PTHREAD_REQUIRE(pthread_mutex_lock(&static_mutex));
235272343Sngie	printf("2: Before the loop.\n");
236272343Sngie	while (count>0) {
237272343Sngie		count--;
238272343Sngie		total++;
239272343Sngie		toggle = 0;
240272343Sngie		/* printf("2: Before signal %d.\n", count); */
241272343Sngie		PTHREAD_REQUIRE(pthread_cond_signal(&static_cond));
242272343Sngie		do {
243272343Sngie			PTHREAD_REQUIRE(pthread_cond_wait(&static_cond,
244272343Sngie			    &static_mutex));
245272343Sngie		} while (toggle != 1);
246272343Sngie	}
247272343Sngie	printf("2: After the loop.\n");
248272343Sngie	PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex));
249272343Sngie
250272343Sngie	return NULL;
251272343Sngie}
252272343Sngie
253272343SngieATF_TC(signal_wait_race);
254272343SngieATF_TC_HEAD(signal_wait_race, tc)
255272343Sngie{
256272343Sngie	atf_tc_set_md_var(tc, "descr", "Checks condition variables");
257272343Sngie}
258272343SngieATF_TC_BODY(signal_wait_race, tc)
259272343Sngie{
260272343Sngie	pthread_t new;
261272343Sngie	void *joinval;
262272343Sngie	int sharedval;
263272343Sngie
264272343Sngie	printf("1: condition variable test 4\n");
265272343Sngie
266272343Sngie	PTHREAD_REQUIRE(pthread_mutex_lock(&static_mutex));
267272343Sngie
268272343Sngie	count = 50000;
269272343Sngie	toggle = 0;
270272343Sngie
271272343Sngie	PTHREAD_REQUIRE(pthread_create(&new, NULL, signal_wait_race_threadfunc,
272272343Sngie	    &sharedval));
273272343Sngie
274272343Sngie	printf("1: Before waiting.\n");
275272343Sngie	while (count>0) {
276272343Sngie		count--;
277272343Sngie		total++;
278272343Sngie		toggle = 1;
279272343Sngie		/* printf("1: Before signal %d.\n", count); */
280272343Sngie		PTHREAD_REQUIRE(pthread_cond_signal(&static_cond));
281272343Sngie		do {
282272343Sngie			PTHREAD_REQUIRE(pthread_cond_wait(&static_cond,
283272343Sngie			    &static_mutex));
284272343Sngie		} while (toggle != 0);
285272343Sngie	}
286272343Sngie	printf("1: After the loop.\n");
287272343Sngie
288272343Sngie	toggle = 1;
289272343Sngie	PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex));
290272343Sngie	PTHREAD_REQUIRE(pthread_cond_signal(&static_cond));
291272343Sngie
292272343Sngie	printf("1: After releasing the mutex.\n");
293272343Sngie	PTHREAD_REQUIRE(pthread_join(new, &joinval));
294272343Sngie
295272343Sngie	printf("1: Thread joined. Final count = %d, total = %d\n",
296272343Sngie		count, total);
297272343Sngie
298272343Sngie	ATF_REQUIRE_EQ(count, 0);
299272343Sngie	ATF_REQUIRE_EQ(total, 50000);
300272343Sngie}
301272343Sngie
302272343Sngiestatic void *
303272343Sngiepthread_cond_timedwait_func(void *arg)
304272343Sngie{
305272343Sngie	struct timespec ts;
306272343Sngie	size_t i = 0;
307272343Sngie	int rv;
308272343Sngie
309272343Sngie	for (;;) {
310272343Sngie
311272343Sngie		if (i++ >= 10000)
312272343Sngie			pthread_exit(NULL);
313272343Sngie
314272343Sngie		(void)memset(&ts, 0, sizeof(struct timespec));
315272343Sngie
316272343Sngie		ATF_REQUIRE(clock_gettime(CLOCK_REALTIME, &ts) == 0);
317272343Sngie
318272343Sngie		/*
319272343Sngie		 * Set to one second in the past:
320272343Sngie		 * pthread_cond_timedwait(3) should
321272343Sngie		 * return ETIMEDOUT immediately.
322272343Sngie		 */
323272343Sngie		ts.tv_sec = ts.tv_sec - 1;
324272343Sngie
325272343Sngie		PTHREAD_REQUIRE(pthread_mutex_lock(&static_mutex));
326272343Sngie		rv = pthread_cond_timedwait(&static_cond, &static_mutex, &ts);
327272343Sngie
328272343Sngie		/*
329272343Sngie		 * Sometimes we catch ESRCH.
330272343Sngie		 * This should never happen.
331272343Sngie		 */
332272343Sngie		ATF_REQUIRE(rv == ETIMEDOUT);
333272343Sngie		PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex));
334272343Sngie	}
335272343Sngie}
336272343Sngie
337272343SngieATF_TC(cond_timedwait_race);
338272343SngieATF_TC_HEAD(cond_timedwait_race, tc)
339272343Sngie{
340272343Sngie	atf_tc_set_md_var(tc, "descr", "Test pthread_cond_timedwait(3)");
341272343Sngie
342272343Sngie}
343272343SngieATF_TC_BODY(cond_timedwait_race, tc)
344272343Sngie{
345272343Sngie	pthread_t tid[64];
346272343Sngie	size_t i;
347272343Sngie
348272343Sngie	for (i = 0; i < __arraycount(tid); i++) {
349272343Sngie
350272343Sngie		PTHREAD_REQUIRE(pthread_create(&tid[i], NULL,
351272343Sngie		    pthread_cond_timedwait_func, NULL));
352272343Sngie	}
353272343Sngie
354272343Sngie	for (i = 0; i < __arraycount(tid); i++) {
355272343Sngie
356272343Sngie		PTHREAD_REQUIRE(pthread_join(tid[i], NULL));
357272343Sngie	}
358272343Sngie}
359272343Sngie
360272343Sngiestatic void *
361272343Sngiebroadcast_threadfunc(void *arg)
362272343Sngie{
363272343Sngie	printf("2: Second thread.\n");
364272343Sngie
365272343Sngie	PTHREAD_REQUIRE(pthread_mutex_lock(&static_mutex));
366272343Sngie	while (count>0) {
367272343Sngie		count--;
368272343Sngie		total++;
369272343Sngie		toggle = 0;
370272343Sngie		PTHREAD_REQUIRE(pthread_cond_signal(&static_cond));
371272343Sngie		do {
372272343Sngie			PTHREAD_REQUIRE(pthread_cond_wait(&static_cond,
373272343Sngie			    &static_mutex));
374272343Sngie		} while (toggle != 1);
375272343Sngie	}
376272343Sngie	printf("2: After the loop.\n");
377272343Sngie	PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex));
378272343Sngie
379272343Sngie	return NULL;
380272343Sngie}
381272343Sngie
382272343Sngie
383272343SngieATF_TC(broadcast);
384272343SngieATF_TC_HEAD(broadcast, tc)
385272343Sngie{
386272343Sngie	atf_tc_set_md_var(tc, "descr",
387272343Sngie		"Checks condition variables: use pthread_cond_broadcast()");
388272343Sngie}
389272343SngieATF_TC_BODY(broadcast, tc)
390272343Sngie{
391272343Sngie	pthread_t new;
392272343Sngie	void *joinval;
393272343Sngie	int sharedval;
394272343Sngie
395272343Sngie	printf("1: condition variable test 5\n");
396272343Sngie
397272343Sngie	PTHREAD_REQUIRE(pthread_mutex_lock(&static_mutex));
398272343Sngie
399272343Sngie	count = 50000;
400272343Sngie	toggle = 0;
401272343Sngie
402272343Sngie	PTHREAD_REQUIRE(pthread_create(&new, NULL, broadcast_threadfunc,
403272343Sngie	    &sharedval));
404272343Sngie
405272343Sngie	printf("1: Before waiting.\n");
406272343Sngie	while (count>0) {
407272343Sngie		count--;
408272343Sngie		total++;
409272343Sngie		toggle = 1;
410272343Sngie		PTHREAD_REQUIRE(pthread_cond_broadcast(&static_cond));
411272343Sngie		do {
412272343Sngie			PTHREAD_REQUIRE(pthread_cond_wait(&static_cond,
413272343Sngie			    &static_mutex));
414272343Sngie		} while (toggle != 0);
415272343Sngie	}
416272343Sngie	printf("1: After the loop.\n");
417272343Sngie
418272343Sngie	toggle = 1;
419272343Sngie	PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex));
420272343Sngie	PTHREAD_REQUIRE(pthread_cond_signal(&static_cond));
421272343Sngie
422272343Sngie	printf("1: After releasing the mutex.\n");
423272343Sngie	PTHREAD_REQUIRE(pthread_join(new, &joinval));
424272343Sngie
425272343Sngie	printf("1: Thread joined. Final count = %d, total = %d\n", count,
426272343Sngie	    total);
427272343Sngie
428272343Sngie	ATF_REQUIRE_EQ(count, 0);
429272343Sngie	ATF_REQUIRE_EQ(total, 50000);
430272343Sngie}
431272343Sngie
432272343Sngiestatic void *
433272343Sngiebogus_timedwaits_threadfunc(void *arg)
434272343Sngie{
435272343Sngie	return NULL;
436272343Sngie}
437272343Sngie
438272343SngieATF_TC(bogus_timedwaits);
439272343SngieATF_TC_HEAD(bogus_timedwaits, tc)
440272343Sngie{
441272343Sngie	atf_tc_set_md_var(tc, "descr",
442272343Sngie		"Checks condition variables: bogus timedwaits");
443272343Sngie}
444272343SngieATF_TC_BODY(bogus_timedwaits, tc)
445272343Sngie{
446272343Sngie	pthread_t new;
447272343Sngie	struct timespec ts;
448272343Sngie	struct timeval tv;
449272343Sngie
450272343Sngie	printf("condition variable test 6: bogus timedwaits\n");
451272343Sngie
452272343Sngie	PTHREAD_REQUIRE(pthread_mutex_lock(&static_mutex));
453272343Sngie
454272343Sngie	printf("unthreaded test (past)\n");
455272343Sngie	gettimeofday(&tv, NULL);
456272343Sngie	tv.tv_sec -= 2; /* Place the time in the past */
457272343Sngie	TIMEVAL_TO_TIMESPEC(&tv, &ts);
458272343Sngie
459272343Sngie	ATF_REQUIRE_EQ_MSG(pthread_cond_timedwait(&static_cond, &static_mutex,
460272343Sngie	    &ts), ETIMEDOUT, "pthread_cond_timedwait() (unthreaded) in the "
461272343Sngie	    "past");
462272343Sngie
463272343Sngie	printf("unthreaded test (zero time)\n");
464272343Sngie	tv.tv_sec = 0;
465272343Sngie	tv.tv_usec = 0;
466272343Sngie	TIMEVAL_TO_TIMESPEC(&tv, &ts);
467272343Sngie
468272343Sngie	ATF_REQUIRE_EQ_MSG(pthread_cond_timedwait(&static_cond, &static_mutex,
469272343Sngie	    &ts), ETIMEDOUT, "pthread_cond_timedwait() (unthreaded) with zero "
470272343Sngie	    "time");
471272343Sngie
472272343Sngie	PTHREAD_REQUIRE(pthread_create(&new, NULL, bogus_timedwaits_threadfunc,
473272343Sngie	    NULL));
474272343Sngie	PTHREAD_REQUIRE(pthread_join(new, NULL));
475272343Sngie
476272343Sngie	printf("threaded test\n");
477272343Sngie	gettimeofday(&tv, NULL);
478272343Sngie	tv.tv_sec -= 2; /* Place the time in the past */
479272343Sngie	TIMEVAL_TO_TIMESPEC(&tv, &ts);
480272343Sngie
481272343Sngie	ATF_REQUIRE_EQ_MSG(pthread_cond_timedwait(&static_cond, &static_mutex,
482272343Sngie	    &ts), ETIMEDOUT, "pthread_cond_timedwait() (threaded) in the past");
483272343Sngie
484272343Sngie	printf("threaded test (zero time)\n");
485272343Sngie	tv.tv_sec = 0;
486272343Sngie	tv.tv_usec = 0;
487272343Sngie	TIMEVAL_TO_TIMESPEC(&tv, &ts);
488272343Sngie
489272343Sngie	ATF_REQUIRE_EQ_MSG(pthread_cond_timedwait(&static_cond, &static_mutex,
490272343Sngie	    &ts), ETIMEDOUT, "pthread_cond_timedwait() (threaded) with zero "
491272343Sngie	    "time");
492272343Sngie
493272343Sngie	PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex));
494272343Sngie}
495272343Sngie
496272343Sngiestatic void
497272343Sngieunlock(void *arg)
498272343Sngie{
499272343Sngie	pthread_mutex_unlock((pthread_mutex_t *)arg);
500272343Sngie}
501272343Sngie
502272343Sngiestatic void *
503272343Sngiedestroy_after_cancel_threadfunc(void *arg)
504272343Sngie{
505272343Sngie	PTHREAD_REQUIRE(pthread_mutex_lock(&mutex));
506272343Sngie
507272343Sngie	pthread_cleanup_push(unlock, &mutex);
508272343Sngie
509272343Sngie	while (1) {
510272343Sngie		share = 1;
511272343Sngie		PTHREAD_REQUIRE(pthread_cond_broadcast(&cond));
512272343Sngie		PTHREAD_REQUIRE(pthread_cond_wait(&cond, &mutex));
513272343Sngie	}
514272343Sngie
515272343Sngie	pthread_cleanup_pop(0);
516272343Sngie	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
517272343Sngie
518272343Sngie	return NULL;
519272343Sngie}
520272343Sngie
521272343SngieATF_TC(destroy_after_cancel);
522272343SngieATF_TC_HEAD(destroy_after_cancel, tc)
523272343Sngie{
524272343Sngie	atf_tc_set_md_var(tc, "descr", "Checks destroying a condition variable "
525272343Sngie	    "after cancelling a wait");
526272343Sngie}
527272343SngieATF_TC_BODY(destroy_after_cancel, tc)
528272343Sngie{
529272343Sngie	pthread_t thread;
530272343Sngie
531272343Sngie	PTHREAD_REQUIRE(pthread_mutex_init(&mutex, NULL));
532272343Sngie	PTHREAD_REQUIRE(pthread_cond_init(&cond, NULL));
533272343Sngie	PTHREAD_REQUIRE(pthread_mutex_lock(&mutex));
534272343Sngie	PTHREAD_REQUIRE(pthread_create(&thread, NULL,
535272343Sngie	    destroy_after_cancel_threadfunc, NULL));
536272343Sngie
537272343Sngie	while (share == 0) {
538272343Sngie		PTHREAD_REQUIRE(pthread_cond_wait(&cond, &mutex));
539272343Sngie	}
540272343Sngie
541272343Sngie	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
542272343Sngie	PTHREAD_REQUIRE(pthread_cancel(thread));
543272343Sngie
544272343Sngie	PTHREAD_REQUIRE(pthread_join(thread, NULL));
545272343Sngie	PTHREAD_REQUIRE(pthread_cond_destroy(&cond));
546272343Sngie
547272343Sngie	PTHREAD_REQUIRE(pthread_mutex_destroy(&mutex));
548272343Sngie}
549272343Sngie
550309466SngieATF_TC(condattr);
551309466SngieATF_TC_HEAD(condattr, tc)
552309466Sngie{
553309466Sngie	atf_tc_set_md_var(tc, "descr", "Checks Condattr");
554309466Sngie}
555309466SngieATF_TC_BODY(condattr, tc)
556309466Sngie{
557309466Sngie	pthread_condattr_t condattr;
558309466Sngie	clockid_t clockid;
559309466Sngie
560309466Sngie	PTHREAD_REQUIRE(pthread_condattr_init(&condattr));
561309466Sngie	PTHREAD_REQUIRE(pthread_condattr_setclock(&condattr, CLOCK_REALTIME));
562309466Sngie	PTHREAD_REQUIRE(pthread_condattr_getclock(&condattr, &clockid));
563309466Sngie	ATF_REQUIRE_EQ(clockid, CLOCK_REALTIME);
564309466Sngie
565309466Sngie	PTHREAD_REQUIRE(pthread_condattr_setclock(&condattr, CLOCK_MONOTONIC));
566309466Sngie	PTHREAD_REQUIRE(pthread_condattr_getclock(&condattr, &clockid));
567309466Sngie 	ATF_REQUIRE_EQ(clockid, CLOCK_MONOTONIC);
568309466Sngie}
569309466Sngie
570272343SngieATF_TP_ADD_TCS(tp)
571272343Sngie{
572272343Sngie
573272343Sngie	ATF_TP_ADD_TC(tp, signal_delay_wait);
574272343Sngie	ATF_TP_ADD_TC(tp, signal_before_unlock);
575272343Sngie	ATF_TP_ADD_TC(tp, signal_before_unlock_static_init);
576272343Sngie	ATF_TP_ADD_TC(tp, signal_wait_race);
577272343Sngie	ATF_TP_ADD_TC(tp, cond_timedwait_race);
578272343Sngie	ATF_TP_ADD_TC(tp, broadcast);
579272343Sngie	ATF_TP_ADD_TC(tp, bogus_timedwaits);
580272343Sngie	ATF_TP_ADD_TC(tp, destroy_after_cancel);
581309466Sngie	ATF_TP_ADD_TC(tp, condattr);
582272343Sngie
583272343Sngie	return atf_no_error();
584272343Sngie}
585