1*0a6a1f1dSLionel Sambuc /* $NetBSD: t_mutex.c,v 1.7 2014/11/04 00:20:19 justin 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_mutex.c,v 1.7 2014/11/04 00:20:19 justin Exp $");
3311be35a1SLionel Sambuc
3411be35a1SLionel Sambuc #include <pthread.h>
3511be35a1SLionel Sambuc #include <stdio.h>
3611be35a1SLionel Sambuc #include <string.h>
3711be35a1SLionel Sambuc #include <unistd.h>
3811be35a1SLionel Sambuc
3911be35a1SLionel Sambuc #include <atf-c.h>
4011be35a1SLionel Sambuc
4111be35a1SLionel Sambuc #include "h_common.h"
4211be35a1SLionel Sambuc
4311be35a1SLionel Sambuc static pthread_mutex_t mutex;
4411be35a1SLionel Sambuc static pthread_mutex_t static_mutex = PTHREAD_MUTEX_INITIALIZER;
4511be35a1SLionel Sambuc static int global_x;
4611be35a1SLionel Sambuc
4711be35a1SLionel Sambuc static void *
mutex1_threadfunc(void * arg)4811be35a1SLionel Sambuc mutex1_threadfunc(void *arg)
4911be35a1SLionel Sambuc {
5011be35a1SLionel Sambuc int *param;
5111be35a1SLionel Sambuc
5211be35a1SLionel Sambuc printf("2: Second thread.\n");
5311be35a1SLionel Sambuc
5411be35a1SLionel Sambuc param = arg;
5511be35a1SLionel Sambuc printf("2: Locking mutex\n");
5611be35a1SLionel Sambuc pthread_mutex_lock(&mutex);
5711be35a1SLionel Sambuc printf("2: Got mutex. *param = %d\n", *param);
5811be35a1SLionel Sambuc ATF_REQUIRE_EQ(*param, 20);
5911be35a1SLionel Sambuc (*param)++;
6011be35a1SLionel Sambuc
6111be35a1SLionel Sambuc pthread_mutex_unlock(&mutex);
6211be35a1SLionel Sambuc
6311be35a1SLionel Sambuc return param;
6411be35a1SLionel Sambuc }
6511be35a1SLionel Sambuc
6611be35a1SLionel Sambuc ATF_TC(mutex1);
ATF_TC_HEAD(mutex1,tc)6711be35a1SLionel Sambuc ATF_TC_HEAD(mutex1, tc)
6811be35a1SLionel Sambuc {
6911be35a1SLionel Sambuc atf_tc_set_md_var(tc, "descr", "Checks mutexes");
7011be35a1SLionel Sambuc }
ATF_TC_BODY(mutex1,tc)7111be35a1SLionel Sambuc ATF_TC_BODY(mutex1, tc)
7211be35a1SLionel Sambuc {
7311be35a1SLionel Sambuc int x;
7411be35a1SLionel Sambuc pthread_t new;
7511be35a1SLionel Sambuc void *joinval;
7611be35a1SLionel Sambuc
7711be35a1SLionel Sambuc printf("1: Mutex-test 1\n");
7811be35a1SLionel Sambuc
7911be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_mutex_init(&mutex, NULL));
8011be35a1SLionel Sambuc x = 1;
8111be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_mutex_lock(&mutex));
8211be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_create(&new, NULL, mutex1_threadfunc, &x));
8311be35a1SLionel Sambuc printf("1: Before changing the value.\n");
8411be35a1SLionel Sambuc sleep(2);
8511be35a1SLionel Sambuc x = 20;
8611be35a1SLionel Sambuc printf("1: Before releasing the mutex.\n");
8711be35a1SLionel Sambuc sleep(2);
8811be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
8911be35a1SLionel Sambuc printf("1: After releasing the mutex.\n");
9011be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_join(new, &joinval));
9111be35a1SLionel Sambuc
9211be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_mutex_lock(&mutex));
9311be35a1SLionel Sambuc printf("1: Thread joined. X was %d. Return value (int) was %d\n",
9411be35a1SLionel Sambuc x, *(int *)joinval);
9511be35a1SLionel Sambuc ATF_REQUIRE_EQ(x, 21);
9611be35a1SLionel Sambuc ATF_REQUIRE_EQ(*(int *)joinval, 21);
9711be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
9811be35a1SLionel Sambuc }
9911be35a1SLionel Sambuc
10011be35a1SLionel Sambuc static void *
mutex2_threadfunc(void * arg)10111be35a1SLionel Sambuc mutex2_threadfunc(void *arg)
10211be35a1SLionel Sambuc {
10311be35a1SLionel Sambuc long count = *(int *)arg;
10411be35a1SLionel Sambuc
10511be35a1SLionel Sambuc printf("2: Second thread (%p). Count is %ld\n", pthread_self(), count);
10611be35a1SLionel Sambuc
10711be35a1SLionel Sambuc while (count--) {
10811be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_mutex_lock(&mutex));
10911be35a1SLionel Sambuc global_x++;
11011be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
11111be35a1SLionel Sambuc }
11211be35a1SLionel Sambuc
11311be35a1SLionel Sambuc return (void *)count;
11411be35a1SLionel Sambuc }
11511be35a1SLionel Sambuc
11611be35a1SLionel Sambuc ATF_TC(mutex2);
ATF_TC_HEAD(mutex2,tc)11711be35a1SLionel Sambuc ATF_TC_HEAD(mutex2, tc)
11811be35a1SLionel Sambuc {
11911be35a1SLionel Sambuc atf_tc_set_md_var(tc, "descr", "Checks mutexes");
120*0a6a1f1dSLionel Sambuc #if defined(__powerpc__)
12111be35a1SLionel Sambuc atf_tc_set_md_var(tc, "timeout", "40");
122*0a6a1f1dSLionel Sambuc #endif
12311be35a1SLionel Sambuc }
ATF_TC_BODY(mutex2,tc)12411be35a1SLionel Sambuc ATF_TC_BODY(mutex2, tc)
12511be35a1SLionel Sambuc {
12611be35a1SLionel Sambuc int count, count2;
12711be35a1SLionel Sambuc pthread_t new;
12811be35a1SLionel Sambuc void *joinval;
12911be35a1SLionel Sambuc
13011be35a1SLionel Sambuc printf("1: Mutex-test 2\n");
13111be35a1SLionel Sambuc
132*0a6a1f1dSLionel Sambuc #if defined(__powerpc__)
13311be35a1SLionel Sambuc atf_tc_expect_timeout("PR port-powerpc/44387");
134*0a6a1f1dSLionel Sambuc #endif
13511be35a1SLionel Sambuc
13611be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_mutex_init(&mutex, NULL));
13711be35a1SLionel Sambuc
13811be35a1SLionel Sambuc global_x = 0;
13911be35a1SLionel Sambuc count = count2 = 10000000;
14011be35a1SLionel Sambuc
14111be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_mutex_lock(&mutex));
14211be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_create(&new, NULL, mutex2_threadfunc, &count2));
14311be35a1SLionel Sambuc
14411be35a1SLionel Sambuc printf("1: Thread %p\n", pthread_self());
14511be35a1SLionel Sambuc
14611be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
14711be35a1SLionel Sambuc
14811be35a1SLionel Sambuc while (count--) {
14911be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_mutex_lock(&mutex));
15011be35a1SLionel Sambuc global_x++;
15111be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
15211be35a1SLionel Sambuc }
15311be35a1SLionel Sambuc
15411be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_join(new, &joinval));
15511be35a1SLionel Sambuc
15611be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_mutex_lock(&mutex));
15711be35a1SLionel Sambuc printf("1: Thread joined. X was %d. Return value (long) was %ld\n",
15811be35a1SLionel Sambuc global_x, (long)joinval);
15911be35a1SLionel Sambuc ATF_REQUIRE_EQ(global_x, 20000000);
16011be35a1SLionel Sambuc
161*0a6a1f1dSLionel Sambuc #if defined(__powerpc__)
16211be35a1SLionel Sambuc /* XXX force a timeout in ppc case since an un-triggered race
16311be35a1SLionel Sambuc otherwise looks like a "failure" */
16411be35a1SLionel Sambuc /* We sleep for longer than the timeout to make ATF not
16511be35a1SLionel Sambuc complain about unexpected success */
16611be35a1SLionel Sambuc sleep(41);
167*0a6a1f1dSLionel Sambuc #endif
16811be35a1SLionel Sambuc }
16911be35a1SLionel Sambuc
17011be35a1SLionel Sambuc static void *
mutex3_threadfunc(void * arg)17111be35a1SLionel Sambuc mutex3_threadfunc(void *arg)
17211be35a1SLionel Sambuc {
17311be35a1SLionel Sambuc long count = *(int *)arg;
17411be35a1SLionel Sambuc
17511be35a1SLionel Sambuc printf("2: Second thread (%p). Count is %ld\n", pthread_self(), count);
17611be35a1SLionel Sambuc
17711be35a1SLionel Sambuc while (count--) {
17811be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_mutex_lock(&static_mutex));
17911be35a1SLionel Sambuc global_x++;
18011be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex));
18111be35a1SLionel Sambuc }
18211be35a1SLionel Sambuc
18311be35a1SLionel Sambuc return (void *)count;
18411be35a1SLionel Sambuc }
18511be35a1SLionel Sambuc
18611be35a1SLionel Sambuc ATF_TC(mutex3);
ATF_TC_HEAD(mutex3,tc)18711be35a1SLionel Sambuc ATF_TC_HEAD(mutex3, tc)
18811be35a1SLionel Sambuc {
18911be35a1SLionel Sambuc atf_tc_set_md_var(tc, "descr", "Checks mutexes using a static "
19011be35a1SLionel Sambuc "initializer");
191*0a6a1f1dSLionel Sambuc #if defined(__powerpc__)
19211be35a1SLionel Sambuc atf_tc_set_md_var(tc, "timeout", "40");
193*0a6a1f1dSLionel Sambuc #endif
19411be35a1SLionel Sambuc }
ATF_TC_BODY(mutex3,tc)19511be35a1SLionel Sambuc ATF_TC_BODY(mutex3, tc)
19611be35a1SLionel Sambuc {
19711be35a1SLionel Sambuc int count, count2;
19811be35a1SLionel Sambuc pthread_t new;
19911be35a1SLionel Sambuc void *joinval;
20011be35a1SLionel Sambuc
20111be35a1SLionel Sambuc printf("1: Mutex-test 3\n");
20211be35a1SLionel Sambuc
203*0a6a1f1dSLionel Sambuc #if defined(__powerpc__)
20411be35a1SLionel Sambuc atf_tc_expect_timeout("PR port-powerpc/44387");
205*0a6a1f1dSLionel Sambuc #endif
20611be35a1SLionel Sambuc
20711be35a1SLionel Sambuc global_x = 0;
20811be35a1SLionel Sambuc count = count2 = 10000000;
20911be35a1SLionel Sambuc
21011be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_mutex_lock(&static_mutex));
21111be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_create(&new, NULL, mutex3_threadfunc, &count2));
21211be35a1SLionel Sambuc
21311be35a1SLionel Sambuc printf("1: Thread %p\n", pthread_self());
21411be35a1SLionel Sambuc
21511be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex));
21611be35a1SLionel Sambuc
21711be35a1SLionel Sambuc while (count--) {
21811be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_mutex_lock(&static_mutex));
21911be35a1SLionel Sambuc global_x++;
22011be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex));
22111be35a1SLionel Sambuc }
22211be35a1SLionel Sambuc
22311be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_join(new, &joinval));
22411be35a1SLionel Sambuc
22511be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_mutex_lock(&static_mutex));
22611be35a1SLionel Sambuc printf("1: Thread joined. X was %d. Return value (long) was %ld\n",
22711be35a1SLionel Sambuc global_x, (long)joinval);
22811be35a1SLionel Sambuc ATF_REQUIRE_EQ(global_x, 20000000);
22911be35a1SLionel Sambuc
230*0a6a1f1dSLionel Sambuc #if defined(__powerpc__)
23111be35a1SLionel Sambuc /* XXX force a timeout in ppc case since an un-triggered race
23211be35a1SLionel Sambuc otherwise looks like a "failure" */
23311be35a1SLionel Sambuc /* We sleep for longer than the timeout to make ATF not
23411be35a1SLionel Sambuc complain about unexpected success */
23511be35a1SLionel Sambuc sleep(41);
236*0a6a1f1dSLionel Sambuc #endif
23711be35a1SLionel Sambuc }
23811be35a1SLionel Sambuc
23911be35a1SLionel Sambuc static void *
mutex4_threadfunc(void * arg)24011be35a1SLionel Sambuc mutex4_threadfunc(void *arg)
24111be35a1SLionel Sambuc {
24211be35a1SLionel Sambuc int *param;
24311be35a1SLionel Sambuc
24411be35a1SLionel Sambuc printf("2: Second thread.\n");
24511be35a1SLionel Sambuc
24611be35a1SLionel Sambuc param = arg;
24711be35a1SLionel Sambuc printf("2: Locking mutex\n");
24811be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_mutex_lock(&mutex));
24911be35a1SLionel Sambuc printf("2: Got mutex. *param = %d\n", *param);
25011be35a1SLionel Sambuc (*param)++;
25111be35a1SLionel Sambuc
25211be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
25311be35a1SLionel Sambuc
25411be35a1SLionel Sambuc return param;
25511be35a1SLionel Sambuc }
25611be35a1SLionel Sambuc
25711be35a1SLionel Sambuc ATF_TC(mutex4);
ATF_TC_HEAD(mutex4,tc)25811be35a1SLionel Sambuc ATF_TC_HEAD(mutex4, tc)
25911be35a1SLionel Sambuc {
26011be35a1SLionel Sambuc atf_tc_set_md_var(tc, "descr", "Checks mutexes");
26111be35a1SLionel Sambuc }
ATF_TC_BODY(mutex4,tc)26211be35a1SLionel Sambuc ATF_TC_BODY(mutex4, tc)
26311be35a1SLionel Sambuc {
26411be35a1SLionel Sambuc int x;
26511be35a1SLionel Sambuc pthread_t new;
26611be35a1SLionel Sambuc pthread_mutexattr_t mattr;
26711be35a1SLionel Sambuc void *joinval;
26811be35a1SLionel Sambuc
26911be35a1SLionel Sambuc printf("1: Mutex-test 4\n");
27011be35a1SLionel Sambuc
27111be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_mutexattr_init(&mattr));
27211be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_RECURSIVE));
27311be35a1SLionel Sambuc
27411be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_mutex_init(&mutex, &mattr));
27511be35a1SLionel Sambuc
27611be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_mutexattr_destroy(&mattr));
27711be35a1SLionel Sambuc
27811be35a1SLionel Sambuc x = 1;
27911be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_mutex_lock(&mutex));
28011be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_create(&new, NULL, mutex4_threadfunc, &x));
28111be35a1SLionel Sambuc
28211be35a1SLionel Sambuc printf("1: Before recursively acquiring the mutex.\n");
28311be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_mutex_lock(&mutex));
28411be35a1SLionel Sambuc
28511be35a1SLionel Sambuc printf("1: Before releasing the mutex once.\n");
28611be35a1SLionel Sambuc sleep(2);
28711be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
28811be35a1SLionel Sambuc printf("1: After releasing the mutex once.\n");
28911be35a1SLionel Sambuc
29011be35a1SLionel Sambuc x = 20;
29111be35a1SLionel Sambuc
29211be35a1SLionel Sambuc printf("1: Before releasing the mutex twice.\n");
29311be35a1SLionel Sambuc sleep(2);
29411be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
29511be35a1SLionel Sambuc printf("1: After releasing the mutex twice.\n");
29611be35a1SLionel Sambuc
29711be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_join(new, &joinval));
29811be35a1SLionel Sambuc
29911be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_mutex_lock(&mutex));
30011be35a1SLionel Sambuc printf("1: Thread joined. X was %d. Return value (int) was %d\n",
30111be35a1SLionel Sambuc x, *(int *)joinval);
30211be35a1SLionel Sambuc ATF_REQUIRE_EQ(x, 21);
30311be35a1SLionel Sambuc ATF_REQUIRE_EQ(*(int *)joinval, 21);
30411be35a1SLionel Sambuc PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
30511be35a1SLionel Sambuc }
30611be35a1SLionel Sambuc
ATF_TP_ADD_TCS(tp)30711be35a1SLionel Sambuc ATF_TP_ADD_TCS(tp)
30811be35a1SLionel Sambuc {
30911be35a1SLionel Sambuc ATF_TP_ADD_TC(tp, mutex1);
31011be35a1SLionel Sambuc ATF_TP_ADD_TC(tp, mutex2);
31111be35a1SLionel Sambuc ATF_TP_ADD_TC(tp, mutex3);
31211be35a1SLionel Sambuc ATF_TP_ADD_TC(tp, mutex4);
31311be35a1SLionel Sambuc
31411be35a1SLionel Sambuc return atf_no_error();
31511be35a1SLionel Sambuc }
316