1*0a6a1f1dSLionel Sambuc /* $NetBSD: t_cond.c,v 1.6 2014/09/03 16:23:24 gson Exp $ */
211be35a1SLionel Sambuc
311be35a1SLionel Sambuc /*
411be35a1SLionel Sambuc * Copyright (c) 2008 The NetBSD Foundation, Inc.
511be35a1SLionel Sambuc * All rights reserved.
611be35a1SLionel Sambuc *
711be35a1SLionel Sambuc * Redistribution and use in source and binary forms, with or without
811be35a1SLionel Sambuc * modification, are permitted provided that the following conditions
911be35a1SLionel Sambuc * are met:
1011be35a1SLionel Sambuc * 1. Redistributions of source code must retain the above copyright
1111be35a1SLionel Sambuc * notice, this list of conditions and the following disclaimer.
1211be35a1SLionel Sambuc * 2. Redistributions in binary form must reproduce the above copyright
1311be35a1SLionel Sambuc * notice, this list of conditions and the following disclaimer in the
1411be35a1SLionel Sambuc * documentation and/or other materials provided with the distribution.
1511be35a1SLionel Sambuc *
1611be35a1SLionel Sambuc * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
1711be35a1SLionel Sambuc * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
1811be35a1SLionel Sambuc * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
1911be35a1SLionel Sambuc * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
2011be35a1SLionel Sambuc * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2111be35a1SLionel Sambuc * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2211be35a1SLionel Sambuc * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2311be35a1SLionel Sambuc * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2411be35a1SLionel Sambuc * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2511be35a1SLionel Sambuc * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2611be35a1SLionel Sambuc * POSSIBILITY OF SUCH DAMAGE.
2711be35a1SLionel Sambuc */
2811be35a1SLionel Sambuc
2911be35a1SLionel Sambuc #include <sys/cdefs.h>
3011be35a1SLionel Sambuc __COPYRIGHT("@(#) Copyright (c) 2008\
3111be35a1SLionel Sambuc The NetBSD Foundation, inc. All rights reserved.");
32*0a6a1f1dSLionel Sambuc __RCSID("$NetBSD: t_cond.c,v 1.6 2014/09/03 16:23:24 gson Exp $");
3311be35a1SLionel Sambuc
3411be35a1SLionel Sambuc #include <sys/time.h>
3511be35a1SLionel Sambuc
3611be35a1SLionel Sambuc #include <errno.h>
3711be35a1SLionel Sambuc #include <pthread.h>
3811be35a1SLionel Sambuc #include <stdio.h>
3911be35a1SLionel Sambuc #include <unistd.h>
4011be35a1SLionel Sambuc
4111be35a1SLionel Sambuc #include <atf-c.h>
4211be35a1SLionel Sambuc
4311be35a1SLionel Sambuc #include "h_common.h"
4411be35a1SLionel Sambuc
4511be35a1SLionel Sambuc static pthread_mutex_t mutex;
4611be35a1SLionel Sambuc static pthread_cond_t cond;
4711be35a1SLionel Sambuc static pthread_mutex_t static_mutex = PTHREAD_MUTEX_INITIALIZER;
4811be35a1SLionel Sambuc static pthread_cond_t static_cond = PTHREAD_COND_INITIALIZER;
4911be35a1SLionel Sambuc static int count, share, toggle, total;
5011be35a1SLionel Sambuc
5111be35a1SLionel Sambuc static void *
signal_delay_wait_threadfunc(void * arg)5211be35a1SLionel Sambuc signal_delay_wait_threadfunc(void *arg)
5311be35a1SLionel Sambuc {
5411be35a1SLionel Sambuc int *shared = (int *) arg;
5511be35a1SLionel Sambuc
5611be35a1SLionel Sambuc printf("2: Second thread.\n");
5711be35a1SLionel Sambuc
5811be35a1SLionel Sambuc printf("2: Locking mutex\n");
5911be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_mutex_lock(&mutex));
6011be35a1SLionel Sambuc printf("2: Got mutex.\n");
6111be35a1SLionel Sambuc printf("Shared value: %d. Changing to 0.\n", *shared);
6211be35a1SLionel Sambuc *shared = 0;
6311be35a1SLionel Sambuc
6411be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
6511be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_cond_signal(&cond));
6611be35a1SLionel Sambuc
6711be35a1SLionel Sambuc return NULL;
6811be35a1SLionel Sambuc }
6911be35a1SLionel Sambuc
7011be35a1SLionel Sambuc ATF_TC(signal_delay_wait);
ATF_TC_HEAD(signal_delay_wait,tc)7111be35a1SLionel Sambuc ATF_TC_HEAD(signal_delay_wait, tc)
7211be35a1SLionel Sambuc {
7311be35a1SLionel Sambuc atf_tc_set_md_var(tc, "descr", "Checks condition variables");
7411be35a1SLionel Sambuc }
ATF_TC_BODY(signal_delay_wait,tc)7511be35a1SLionel Sambuc ATF_TC_BODY(signal_delay_wait, tc)
7611be35a1SLionel Sambuc {
7711be35a1SLionel Sambuc pthread_t new;
7811be35a1SLionel Sambuc void *joinval;
7911be35a1SLionel Sambuc int sharedval;
8011be35a1SLionel Sambuc
8111be35a1SLionel Sambuc printf("1: condition variable test 1\n");
8211be35a1SLionel Sambuc
8311be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_mutex_init(&mutex, NULL));
8411be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_cond_init(&cond, NULL));
8511be35a1SLionel Sambuc
8611be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_mutex_lock(&mutex));
8711be35a1SLionel Sambuc
8811be35a1SLionel Sambuc sharedval = 1;
8911be35a1SLionel Sambuc
9011be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_create(&new, NULL, signal_delay_wait_threadfunc,
9111be35a1SLionel Sambuc &sharedval));
9211be35a1SLionel Sambuc
9311be35a1SLionel Sambuc printf("1: Before waiting.\n");
9411be35a1SLionel Sambuc do {
9511be35a1SLionel Sambuc sleep(2);
9611be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_cond_wait(&cond, &mutex));
9711be35a1SLionel Sambuc printf("1: After waiting, in loop.\n");
9811be35a1SLionel Sambuc } while (sharedval != 0);
9911be35a1SLionel Sambuc
10011be35a1SLionel Sambuc printf("1: After the loop.\n");
10111be35a1SLionel Sambuc
10211be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
10311be35a1SLionel Sambuc
10411be35a1SLionel Sambuc printf("1: After releasing the mutex.\n");
10511be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_join(new, &joinval));
10611be35a1SLionel Sambuc
10711be35a1SLionel Sambuc printf("1: Thread joined.\n");
10811be35a1SLionel Sambuc }
10911be35a1SLionel Sambuc
11011be35a1SLionel Sambuc static void *
signal_before_unlock_threadfunc(void * arg)11111be35a1SLionel Sambuc signal_before_unlock_threadfunc(void *arg)
11211be35a1SLionel Sambuc {
11311be35a1SLionel Sambuc int *shared = (int *) arg;
11411be35a1SLionel Sambuc
11511be35a1SLionel Sambuc printf("2: Second thread.\n");
11611be35a1SLionel Sambuc
11711be35a1SLionel Sambuc printf("2: Locking mutex\n");
11811be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_mutex_lock(&mutex));
11911be35a1SLionel Sambuc printf("2: Got mutex.\n");
12011be35a1SLionel Sambuc printf("Shared value: %d. Changing to 0.\n", *shared);
12111be35a1SLionel Sambuc *shared = 0;
12211be35a1SLionel Sambuc
12311be35a1SLionel Sambuc /* Signal first, then unlock, for a different test than #1. */
12411be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_cond_signal(&cond));
12511be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
12611be35a1SLionel Sambuc
12711be35a1SLionel Sambuc return NULL;
12811be35a1SLionel Sambuc }
12911be35a1SLionel Sambuc
13011be35a1SLionel Sambuc ATF_TC(signal_before_unlock);
ATF_TC_HEAD(signal_before_unlock,tc)13111be35a1SLionel Sambuc ATF_TC_HEAD(signal_before_unlock, tc)
13211be35a1SLionel Sambuc {
13311be35a1SLionel Sambuc atf_tc_set_md_var(tc, "descr",
13411be35a1SLionel Sambuc "Checks condition variables: signal before unlocking mutex");
13511be35a1SLionel Sambuc }
ATF_TC_BODY(signal_before_unlock,tc)13611be35a1SLionel Sambuc ATF_TC_BODY(signal_before_unlock, tc)
13711be35a1SLionel Sambuc {
13811be35a1SLionel Sambuc pthread_t new;
13911be35a1SLionel Sambuc void *joinval;
14011be35a1SLionel Sambuc int sharedval;
14111be35a1SLionel Sambuc
14211be35a1SLionel Sambuc printf("1: condition variable test 2\n");
14311be35a1SLionel Sambuc
14411be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_mutex_init(&mutex, NULL));
14511be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_cond_init(&cond, NULL));
14611be35a1SLionel Sambuc
14711be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_mutex_lock(&mutex));
14811be35a1SLionel Sambuc
14911be35a1SLionel Sambuc sharedval = 1;
15011be35a1SLionel Sambuc
15111be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_create(&new, NULL,
15211be35a1SLionel Sambuc signal_before_unlock_threadfunc, &sharedval));
15311be35a1SLionel Sambuc
15411be35a1SLionel Sambuc printf("1: Before waiting.\n");
15511be35a1SLionel Sambuc do {
15611be35a1SLionel Sambuc sleep(2);
15711be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_cond_wait(&cond, &mutex));
15811be35a1SLionel Sambuc printf("1: After waiting, in loop.\n");
15911be35a1SLionel Sambuc } while (sharedval != 0);
16011be35a1SLionel Sambuc
16111be35a1SLionel Sambuc printf("1: After the loop.\n");
16211be35a1SLionel Sambuc
16311be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
16411be35a1SLionel Sambuc
16511be35a1SLionel Sambuc printf("1: After releasing the mutex.\n");
16611be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_join(new, &joinval));
16711be35a1SLionel Sambuc
16811be35a1SLionel Sambuc printf("1: Thread joined.\n");
16911be35a1SLionel Sambuc }
17011be35a1SLionel Sambuc
17111be35a1SLionel Sambuc static void *
signal_before_unlock_static_init_threadfunc(void * arg)17211be35a1SLionel Sambuc signal_before_unlock_static_init_threadfunc(void *arg)
17311be35a1SLionel Sambuc {
17411be35a1SLionel Sambuc int *shared = (int *) arg;
17511be35a1SLionel Sambuc
17611be35a1SLionel Sambuc printf("2: Second thread.\n");
17711be35a1SLionel Sambuc
17811be35a1SLionel Sambuc printf("2: Locking mutex\n");
17911be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_mutex_lock(&static_mutex));
18011be35a1SLionel Sambuc printf("2: Got mutex.\n");
18111be35a1SLionel Sambuc printf("Shared value: %d. Changing to 0.\n", *shared);
18211be35a1SLionel Sambuc *shared = 0;
18311be35a1SLionel Sambuc
18411be35a1SLionel Sambuc /* Signal first, then unlock, for a different test than #1. */
18511be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_cond_signal(&static_cond));
18611be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex));
18711be35a1SLionel Sambuc
18811be35a1SLionel Sambuc return NULL;
18911be35a1SLionel Sambuc }
19011be35a1SLionel Sambuc
19111be35a1SLionel Sambuc ATF_TC(signal_before_unlock_static_init);
ATF_TC_HEAD(signal_before_unlock_static_init,tc)19211be35a1SLionel Sambuc ATF_TC_HEAD(signal_before_unlock_static_init, tc)
19311be35a1SLionel Sambuc {
19411be35a1SLionel Sambuc atf_tc_set_md_var(tc, "descr",
19511be35a1SLionel Sambuc "Checks condition variables: signal before unlocking "
19611be35a1SLionel Sambuc "mutex, use static initializers");
19711be35a1SLionel Sambuc }
ATF_TC_BODY(signal_before_unlock_static_init,tc)19811be35a1SLionel Sambuc ATF_TC_BODY(signal_before_unlock_static_init, tc)
19911be35a1SLionel Sambuc {
20011be35a1SLionel Sambuc pthread_t new;
20111be35a1SLionel Sambuc void *joinval;
20211be35a1SLionel Sambuc int sharedval;
20311be35a1SLionel Sambuc
20411be35a1SLionel Sambuc printf("1: condition variable test 3\n");
20511be35a1SLionel Sambuc
20611be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_mutex_lock(&static_mutex));
20711be35a1SLionel Sambuc
20811be35a1SLionel Sambuc sharedval = 1;
20911be35a1SLionel Sambuc
21011be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_create(&new, NULL,
21111be35a1SLionel Sambuc signal_before_unlock_static_init_threadfunc, &sharedval));
21211be35a1SLionel Sambuc
21311be35a1SLionel Sambuc printf("1: Before waiting.\n");
21411be35a1SLionel Sambuc do {
21511be35a1SLionel Sambuc sleep(2);
21611be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_cond_wait(&static_cond, &static_mutex));
21711be35a1SLionel Sambuc printf("1: After waiting, in loop.\n");
21811be35a1SLionel Sambuc } while (sharedval != 0);
21911be35a1SLionel Sambuc
22011be35a1SLionel Sambuc printf("1: After the loop.\n");
22111be35a1SLionel Sambuc
22211be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex));
22311be35a1SLionel Sambuc
22411be35a1SLionel Sambuc printf("1: After releasing the mutex.\n");
22511be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_join(new, &joinval));
22611be35a1SLionel Sambuc
22711be35a1SLionel Sambuc printf("1: Thread joined.\n");
22811be35a1SLionel Sambuc }
22911be35a1SLionel Sambuc
23011be35a1SLionel Sambuc static void *
signal_wait_race_threadfunc(void * arg)23111be35a1SLionel Sambuc signal_wait_race_threadfunc(void *arg)
23211be35a1SLionel Sambuc {
23311be35a1SLionel Sambuc printf("2: Second thread.\n");
23411be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_mutex_lock(&static_mutex));
23511be35a1SLionel Sambuc printf("2: Before the loop.\n");
23611be35a1SLionel Sambuc while (count>0) {
23711be35a1SLionel Sambuc count--;
23811be35a1SLionel Sambuc total++;
23911be35a1SLionel Sambuc toggle = 0;
24011be35a1SLionel Sambuc /* printf("2: Before signal %d.\n", count); */
24111be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_cond_signal(&static_cond));
24211be35a1SLionel Sambuc do {
24311be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_cond_wait(&static_cond,
24411be35a1SLionel Sambuc &static_mutex));
24511be35a1SLionel Sambuc } while (toggle != 1);
24611be35a1SLionel Sambuc }
24711be35a1SLionel Sambuc printf("2: After the loop.\n");
24811be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex));
24911be35a1SLionel Sambuc
25011be35a1SLionel Sambuc return NULL;
25111be35a1SLionel Sambuc }
25211be35a1SLionel Sambuc
25311be35a1SLionel Sambuc ATF_TC(signal_wait_race);
ATF_TC_HEAD(signal_wait_race,tc)25411be35a1SLionel Sambuc ATF_TC_HEAD(signal_wait_race, tc)
25511be35a1SLionel Sambuc {
25611be35a1SLionel Sambuc atf_tc_set_md_var(tc, "descr", "Checks condition variables");
25711be35a1SLionel Sambuc }
ATF_TC_BODY(signal_wait_race,tc)25811be35a1SLionel Sambuc ATF_TC_BODY(signal_wait_race, tc)
25911be35a1SLionel Sambuc {
26011be35a1SLionel Sambuc pthread_t new;
26111be35a1SLionel Sambuc void *joinval;
26211be35a1SLionel Sambuc int sharedval;
26311be35a1SLionel Sambuc
26411be35a1SLionel Sambuc printf("1: condition variable test 4\n");
26511be35a1SLionel Sambuc
26611be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_mutex_lock(&static_mutex));
26711be35a1SLionel Sambuc
26811be35a1SLionel Sambuc count = 50000;
26911be35a1SLionel Sambuc toggle = 0;
27011be35a1SLionel Sambuc
27111be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_create(&new, NULL, signal_wait_race_threadfunc,
27211be35a1SLionel Sambuc &sharedval));
27311be35a1SLionel Sambuc
27411be35a1SLionel Sambuc printf("1: Before waiting.\n");
27511be35a1SLionel Sambuc while (count>0) {
27611be35a1SLionel Sambuc count--;
27711be35a1SLionel Sambuc total++;
27811be35a1SLionel Sambuc toggle = 1;
27911be35a1SLionel Sambuc /* printf("1: Before signal %d.\n", count); */
28011be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_cond_signal(&static_cond));
28111be35a1SLionel Sambuc do {
28211be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_cond_wait(&static_cond,
28311be35a1SLionel Sambuc &static_mutex));
28411be35a1SLionel Sambuc } while (toggle != 0);
28511be35a1SLionel Sambuc }
28611be35a1SLionel Sambuc printf("1: After the loop.\n");
28711be35a1SLionel Sambuc
28811be35a1SLionel Sambuc toggle = 1;
28911be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex));
29011be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_cond_signal(&static_cond));
29111be35a1SLionel Sambuc
29211be35a1SLionel Sambuc printf("1: After releasing the mutex.\n");
29311be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_join(new, &joinval));
29411be35a1SLionel Sambuc
29511be35a1SLionel Sambuc printf("1: Thread joined. Final count = %d, total = %d\n",
29611be35a1SLionel Sambuc count, total);
29711be35a1SLionel Sambuc
29811be35a1SLionel Sambuc ATF_REQUIRE_EQ(count, 0);
29911be35a1SLionel Sambuc ATF_REQUIRE_EQ(total, 50000);
30011be35a1SLionel Sambuc }
30111be35a1SLionel Sambuc
30211be35a1SLionel Sambuc static void *
pthread_cond_timedwait_func(void * arg)30311be35a1SLionel Sambuc pthread_cond_timedwait_func(void *arg)
30411be35a1SLionel Sambuc {
30511be35a1SLionel Sambuc struct timespec ts;
30611be35a1SLionel Sambuc size_t i = 0;
30711be35a1SLionel Sambuc int rv;
30811be35a1SLionel Sambuc
30911be35a1SLionel Sambuc for (;;) {
31011be35a1SLionel Sambuc
31111be35a1SLionel Sambuc if (i++ >= 10000)
31211be35a1SLionel Sambuc pthread_exit(NULL);
31311be35a1SLionel Sambuc
31411be35a1SLionel Sambuc (void)memset(&ts, 0, sizeof(struct timespec));
31511be35a1SLionel Sambuc
31611be35a1SLionel Sambuc ATF_REQUIRE(clock_gettime(CLOCK_REALTIME, &ts) == 0);
31711be35a1SLionel Sambuc
31811be35a1SLionel Sambuc /*
31911be35a1SLionel Sambuc * Set to one second in the past:
32011be35a1SLionel Sambuc * pthread_cond_timedwait(3) should
32111be35a1SLionel Sambuc * return ETIMEDOUT immediately.
32211be35a1SLionel Sambuc */
32311be35a1SLionel Sambuc ts.tv_sec = ts.tv_sec - 1;
32411be35a1SLionel Sambuc
32511be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_mutex_lock(&static_mutex));
32611be35a1SLionel Sambuc rv = pthread_cond_timedwait(&static_cond, &static_mutex, &ts);
32711be35a1SLionel Sambuc
32811be35a1SLionel Sambuc /*
32911be35a1SLionel Sambuc * Sometimes we catch ESRCH.
33011be35a1SLionel Sambuc * This should never happen.
33111be35a1SLionel Sambuc */
33211be35a1SLionel Sambuc ATF_REQUIRE(rv == ETIMEDOUT);
33311be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex));
33411be35a1SLionel Sambuc }
33511be35a1SLionel Sambuc }
33611be35a1SLionel Sambuc
33711be35a1SLionel Sambuc ATF_TC(cond_timedwait_race);
ATF_TC_HEAD(cond_timedwait_race,tc)33811be35a1SLionel Sambuc ATF_TC_HEAD(cond_timedwait_race, tc)
33911be35a1SLionel Sambuc {
34011be35a1SLionel Sambuc atf_tc_set_md_var(tc, "descr", "Test pthread_cond_timedwait(3)");
34111be35a1SLionel Sambuc
34211be35a1SLionel Sambuc }
ATF_TC_BODY(cond_timedwait_race,tc)34311be35a1SLionel Sambuc ATF_TC_BODY(cond_timedwait_race, tc)
34411be35a1SLionel Sambuc {
34511be35a1SLionel Sambuc pthread_t tid[64];
346*0a6a1f1dSLionel Sambuc size_t i;
34711be35a1SLionel Sambuc
34811be35a1SLionel Sambuc for (i = 0; i < __arraycount(tid); i++) {
34911be35a1SLionel Sambuc
35011be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_create(&tid[i], NULL,
35111be35a1SLionel Sambuc pthread_cond_timedwait_func, NULL));
35211be35a1SLionel Sambuc }
35311be35a1SLionel Sambuc
35411be35a1SLionel Sambuc for (i = 0; i < __arraycount(tid); i++) {
35511be35a1SLionel Sambuc
35611be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_join(tid[i], NULL));
35711be35a1SLionel Sambuc }
35811be35a1SLionel Sambuc }
35911be35a1SLionel Sambuc
36011be35a1SLionel Sambuc static void *
broadcast_threadfunc(void * arg)36111be35a1SLionel Sambuc broadcast_threadfunc(void *arg)
36211be35a1SLionel Sambuc {
36311be35a1SLionel Sambuc printf("2: Second thread.\n");
36411be35a1SLionel Sambuc
36511be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_mutex_lock(&static_mutex));
36611be35a1SLionel Sambuc while (count>0) {
36711be35a1SLionel Sambuc count--;
36811be35a1SLionel Sambuc total++;
36911be35a1SLionel Sambuc toggle = 0;
37011be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_cond_signal(&static_cond));
37111be35a1SLionel Sambuc do {
37211be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_cond_wait(&static_cond,
37311be35a1SLionel Sambuc &static_mutex));
37411be35a1SLionel Sambuc } while (toggle != 1);
37511be35a1SLionel Sambuc }
37611be35a1SLionel Sambuc printf("2: After the loop.\n");
37711be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex));
37811be35a1SLionel Sambuc
37911be35a1SLionel Sambuc return NULL;
38011be35a1SLionel Sambuc }
38111be35a1SLionel Sambuc
38211be35a1SLionel Sambuc
38311be35a1SLionel Sambuc ATF_TC(broadcast);
ATF_TC_HEAD(broadcast,tc)38411be35a1SLionel Sambuc ATF_TC_HEAD(broadcast, tc)
38511be35a1SLionel Sambuc {
38611be35a1SLionel Sambuc atf_tc_set_md_var(tc, "descr",
38711be35a1SLionel Sambuc "Checks condition variables: use pthread_cond_broadcast()");
38811be35a1SLionel Sambuc }
ATF_TC_BODY(broadcast,tc)38911be35a1SLionel Sambuc ATF_TC_BODY(broadcast, tc)
39011be35a1SLionel Sambuc {
39111be35a1SLionel Sambuc pthread_t new;
39211be35a1SLionel Sambuc void *joinval;
39311be35a1SLionel Sambuc int sharedval;
39411be35a1SLionel Sambuc
39511be35a1SLionel Sambuc printf("1: condition variable test 5\n");
39611be35a1SLionel Sambuc
39711be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_mutex_lock(&static_mutex));
39811be35a1SLionel Sambuc
39911be35a1SLionel Sambuc count = 50000;
40011be35a1SLionel Sambuc toggle = 0;
40111be35a1SLionel Sambuc
40211be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_create(&new, NULL, broadcast_threadfunc,
40311be35a1SLionel Sambuc &sharedval));
40411be35a1SLionel Sambuc
40511be35a1SLionel Sambuc printf("1: Before waiting.\n");
40611be35a1SLionel Sambuc while (count>0) {
40711be35a1SLionel Sambuc count--;
40811be35a1SLionel Sambuc total++;
40911be35a1SLionel Sambuc toggle = 1;
41011be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_cond_broadcast(&static_cond));
41111be35a1SLionel Sambuc do {
41211be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_cond_wait(&static_cond,
41311be35a1SLionel Sambuc &static_mutex));
41411be35a1SLionel Sambuc } while (toggle != 0);
41511be35a1SLionel Sambuc }
41611be35a1SLionel Sambuc printf("1: After the loop.\n");
41711be35a1SLionel Sambuc
41811be35a1SLionel Sambuc toggle = 1;
41911be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex));
42011be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_cond_signal(&static_cond));
42111be35a1SLionel Sambuc
42211be35a1SLionel Sambuc printf("1: After releasing the mutex.\n");
42311be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_join(new, &joinval));
42411be35a1SLionel Sambuc
42511be35a1SLionel Sambuc printf("1: Thread joined. Final count = %d, total = %d\n", count,
42611be35a1SLionel Sambuc total);
42711be35a1SLionel Sambuc
42811be35a1SLionel Sambuc ATF_REQUIRE_EQ(count, 0);
42911be35a1SLionel Sambuc ATF_REQUIRE_EQ(total, 50000);
43011be35a1SLionel Sambuc }
43111be35a1SLionel Sambuc
43211be35a1SLionel Sambuc static void *
bogus_timedwaits_threadfunc(void * arg)43311be35a1SLionel Sambuc bogus_timedwaits_threadfunc(void *arg)
43411be35a1SLionel Sambuc {
43511be35a1SLionel Sambuc return NULL;
43611be35a1SLionel Sambuc }
43711be35a1SLionel Sambuc
43811be35a1SLionel Sambuc ATF_TC(bogus_timedwaits);
ATF_TC_HEAD(bogus_timedwaits,tc)43911be35a1SLionel Sambuc ATF_TC_HEAD(bogus_timedwaits, tc)
44011be35a1SLionel Sambuc {
44111be35a1SLionel Sambuc atf_tc_set_md_var(tc, "descr",
44211be35a1SLionel Sambuc "Checks condition variables: bogus timedwaits");
44311be35a1SLionel Sambuc }
ATF_TC_BODY(bogus_timedwaits,tc)44411be35a1SLionel Sambuc ATF_TC_BODY(bogus_timedwaits, tc)
44511be35a1SLionel Sambuc {
44611be35a1SLionel Sambuc pthread_t new;
44711be35a1SLionel Sambuc struct timespec ts;
44811be35a1SLionel Sambuc struct timeval tv;
44911be35a1SLionel Sambuc
45011be35a1SLionel Sambuc printf("condition variable test 6: bogus timedwaits\n");
45111be35a1SLionel Sambuc
45211be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_mutex_lock(&static_mutex));
45311be35a1SLionel Sambuc
45411be35a1SLionel Sambuc printf("unthreaded test (past)\n");
45511be35a1SLionel Sambuc gettimeofday(&tv, NULL);
45611be35a1SLionel Sambuc tv.tv_sec -= 2; /* Place the time in the past */
45711be35a1SLionel Sambuc TIMEVAL_TO_TIMESPEC(&tv, &ts);
45811be35a1SLionel Sambuc
45911be35a1SLionel Sambuc ATF_REQUIRE_EQ_MSG(pthread_cond_timedwait(&static_cond, &static_mutex,
46011be35a1SLionel Sambuc &ts), ETIMEDOUT, "pthread_cond_timedwait() (unthreaded) in the "
46111be35a1SLionel Sambuc "past");
46211be35a1SLionel Sambuc
46311be35a1SLionel Sambuc printf("unthreaded test (zero time)\n");
46411be35a1SLionel Sambuc tv.tv_sec = 0;
46511be35a1SLionel Sambuc tv.tv_usec = 0;
46611be35a1SLionel Sambuc TIMEVAL_TO_TIMESPEC(&tv, &ts);
46711be35a1SLionel Sambuc
46811be35a1SLionel Sambuc ATF_REQUIRE_EQ_MSG(pthread_cond_timedwait(&static_cond, &static_mutex,
46911be35a1SLionel Sambuc &ts), ETIMEDOUT, "pthread_cond_timedwait() (unthreaded) with zero "
47011be35a1SLionel Sambuc "time");
47111be35a1SLionel Sambuc
47211be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_create(&new, NULL, bogus_timedwaits_threadfunc,
47311be35a1SLionel Sambuc NULL));
47411be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_join(new, NULL));
47511be35a1SLionel Sambuc
47611be35a1SLionel Sambuc printf("threaded test\n");
47711be35a1SLionel Sambuc gettimeofday(&tv, NULL);
47811be35a1SLionel Sambuc tv.tv_sec -= 2; /* Place the time in the past */
47911be35a1SLionel Sambuc TIMEVAL_TO_TIMESPEC(&tv, &ts);
48011be35a1SLionel Sambuc
48111be35a1SLionel Sambuc ATF_REQUIRE_EQ_MSG(pthread_cond_timedwait(&static_cond, &static_mutex,
48211be35a1SLionel Sambuc &ts), ETIMEDOUT, "pthread_cond_timedwait() (threaded) in the past");
48311be35a1SLionel Sambuc
48411be35a1SLionel Sambuc printf("threaded test (zero time)\n");
48511be35a1SLionel Sambuc tv.tv_sec = 0;
48611be35a1SLionel Sambuc tv.tv_usec = 0;
48711be35a1SLionel Sambuc TIMEVAL_TO_TIMESPEC(&tv, &ts);
48811be35a1SLionel Sambuc
48911be35a1SLionel Sambuc ATF_REQUIRE_EQ_MSG(pthread_cond_timedwait(&static_cond, &static_mutex,
49011be35a1SLionel Sambuc &ts), ETIMEDOUT, "pthread_cond_timedwait() (threaded) with zero "
49111be35a1SLionel Sambuc "time");
49211be35a1SLionel Sambuc
49311be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex));
49411be35a1SLionel Sambuc }
49511be35a1SLionel Sambuc
49611be35a1SLionel Sambuc static void
unlock(void * arg)49711be35a1SLionel Sambuc unlock(void *arg)
49811be35a1SLionel Sambuc {
49911be35a1SLionel Sambuc pthread_mutex_unlock((pthread_mutex_t *)arg);
50011be35a1SLionel Sambuc }
50111be35a1SLionel Sambuc
50211be35a1SLionel Sambuc static void *
destroy_after_cancel_threadfunc(void * arg)50311be35a1SLionel Sambuc destroy_after_cancel_threadfunc(void *arg)
50411be35a1SLionel Sambuc {
50511be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_mutex_lock(&mutex));
50611be35a1SLionel Sambuc
50711be35a1SLionel Sambuc pthread_cleanup_push(unlock, &mutex);
50811be35a1SLionel Sambuc
50911be35a1SLionel Sambuc while (1) {
51011be35a1SLionel Sambuc share = 1;
51111be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_cond_broadcast(&cond));
51211be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_cond_wait(&cond, &mutex));
51311be35a1SLionel Sambuc }
51411be35a1SLionel Sambuc
51511be35a1SLionel Sambuc pthread_cleanup_pop(0);
51611be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
51711be35a1SLionel Sambuc
51811be35a1SLionel Sambuc return NULL;
51911be35a1SLionel Sambuc }
52011be35a1SLionel Sambuc
52111be35a1SLionel Sambuc ATF_TC(destroy_after_cancel);
ATF_TC_HEAD(destroy_after_cancel,tc)52211be35a1SLionel Sambuc ATF_TC_HEAD(destroy_after_cancel, tc)
52311be35a1SLionel Sambuc {
52411be35a1SLionel Sambuc atf_tc_set_md_var(tc, "descr", "Checks destroying a condition variable "
52511be35a1SLionel Sambuc "after cancelling a wait");
52611be35a1SLionel Sambuc }
ATF_TC_BODY(destroy_after_cancel,tc)52711be35a1SLionel Sambuc ATF_TC_BODY(destroy_after_cancel, tc)
52811be35a1SLionel Sambuc {
52911be35a1SLionel Sambuc pthread_t thread;
53011be35a1SLionel Sambuc
53111be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_mutex_init(&mutex, NULL));
53211be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_cond_init(&cond, NULL));
53311be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_mutex_lock(&mutex));
53411be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_create(&thread, NULL,
53511be35a1SLionel Sambuc destroy_after_cancel_threadfunc, NULL));
53611be35a1SLionel Sambuc
53711be35a1SLionel Sambuc while (share == 0) {
53811be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_cond_wait(&cond, &mutex));
53911be35a1SLionel Sambuc }
54011be35a1SLionel Sambuc
54111be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
54211be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_cancel(thread));
54311be35a1SLionel Sambuc
54411be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_join(thread, NULL));
54511be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_cond_destroy(&cond));
54611be35a1SLionel Sambuc
54711be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_mutex_destroy(&mutex));
54811be35a1SLionel Sambuc }
54911be35a1SLionel Sambuc
ATF_TP_ADD_TCS(tp)55011be35a1SLionel Sambuc ATF_TP_ADD_TCS(tp)
55111be35a1SLionel Sambuc {
55211be35a1SLionel Sambuc
55311be35a1SLionel Sambuc ATF_TP_ADD_TC(tp, signal_delay_wait);
55411be35a1SLionel Sambuc ATF_TP_ADD_TC(tp, signal_before_unlock);
55511be35a1SLionel Sambuc ATF_TP_ADD_TC(tp, signal_before_unlock_static_init);
55611be35a1SLionel Sambuc ATF_TP_ADD_TC(tp, signal_wait_race);
55711be35a1SLionel Sambuc ATF_TP_ADD_TC(tp, cond_timedwait_race);
55811be35a1SLionel Sambuc ATF_TP_ADD_TC(tp, broadcast);
55911be35a1SLionel Sambuc ATF_TP_ADD_TC(tp, bogus_timedwaits);
56011be35a1SLionel Sambuc ATF_TP_ADD_TC(tp, destroy_after_cancel);
56111be35a1SLionel Sambuc
56211be35a1SLionel Sambuc return atf_no_error();
56311be35a1SLionel Sambuc }
564