Home | History | Annotate | Line # | Download | only in libpthread
t_mutex.c revision 1.3
      1 /* $NetBSD: t_mutex.c,v 1.3 2011/02/20 14:37:44 jmmv Exp $ */
      2 
      3 /*
      4  * Copyright (c) 2008 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  *
     16  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     17  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     18  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     19  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     20  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     26  * POSSIBILITY OF SUCH DAMAGE.
     27  */
     28 
     29 #include <sys/cdefs.h>
     30 __COPYRIGHT("@(#) Copyright (c) 2008\
     31  The NetBSD Foundation, inc. All rights reserved.");
     32 __RCSID("$NetBSD: t_mutex.c,v 1.3 2011/02/20 14:37:44 jmmv Exp $");
     33 
     34 #include <pthread.h>
     35 #include <stdio.h>
     36 #include <unistd.h>
     37 
     38 #include <atf-c.h>
     39 
     40 #include "h_common.h"
     41 
     42 static pthread_mutex_t mutex;
     43 static pthread_mutex_t static_mutex = PTHREAD_MUTEX_INITIALIZER;
     44 static int global_x;
     45 
     46 static void *
     47 mutex1_threadfunc(void *arg)
     48 {
     49 	int *param;
     50 
     51 	printf("2: Second thread.\n");
     52 
     53 	param = arg;
     54 	printf("2: Locking mutex\n");
     55 	pthread_mutex_lock(&mutex);
     56 	printf("2: Got mutex. *param = %d\n", *param);
     57 	ATF_REQUIRE_EQ(*param, 20);
     58 	(*param)++;
     59 
     60 	pthread_mutex_unlock(&mutex);
     61 
     62 	return param;
     63 }
     64 
     65 ATF_TC(mutex1);
     66 ATF_TC_HEAD(mutex1, tc)
     67 {
     68 	atf_tc_set_md_var(tc, "descr", "Checks mutexes");
     69 }
     70 ATF_TC_BODY(mutex1, tc)
     71 {
     72 	int x;
     73 	pthread_t new;
     74 	void *joinval;
     75 
     76 	printf("1: Mutex-test 1\n");
     77 
     78 	PTHREAD_REQUIRE(pthread_mutex_init(&mutex, NULL));
     79 	x = 1;
     80 	PTHREAD_REQUIRE(pthread_mutex_lock(&mutex));
     81 	PTHREAD_REQUIRE(pthread_create(&new, NULL, mutex1_threadfunc, &x));
     82 	printf("1: Before changing the value.\n");
     83 	sleep(2);
     84 	x = 20;
     85 	printf("1: Before releasing the mutex.\n");
     86 	sleep(2);
     87 	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
     88 	printf("1: After releasing the mutex.\n");
     89 	PTHREAD_REQUIRE(pthread_join(new, &joinval));
     90 
     91 	PTHREAD_REQUIRE(pthread_mutex_lock(&mutex));
     92 	printf("1: Thread joined. X was %d. Return value (int) was %d\n",
     93 		x, *(int *)joinval);
     94 	ATF_REQUIRE_EQ(x, 21);
     95 	ATF_REQUIRE_EQ(*(int *)joinval, 21);
     96 	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
     97 }
     98 
     99 static void *
    100 mutex2_threadfunc(void *arg)
    101 {
    102 	long count = *(int *)arg;
    103 
    104 	printf("2: Second thread (%p). Count is %ld\n", pthread_self(), count);
    105 
    106 	while (count--) {
    107 		PTHREAD_REQUIRE(pthread_mutex_lock(&mutex));
    108 		global_x++;
    109 		PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
    110 	}
    111 
    112 	return (void *)count;
    113 }
    114 
    115 ATF_TC(mutex2);
    116 ATF_TC_HEAD(mutex2, tc)
    117 {
    118 	atf_tc_set_md_var(tc, "descr", "Checks mutexes");
    119 }
    120 ATF_TC_BODY(mutex2, tc)
    121 {
    122 	int count, count2;
    123 	pthread_t new;
    124 	void *joinval;
    125 
    126 	printf("1: Mutex-test 2\n");
    127 
    128 	PTHREAD_REQUIRE(pthread_mutex_init(&mutex, NULL));
    129 
    130 	global_x = 0;
    131 	count = count2 = 10000000;
    132 
    133 	PTHREAD_REQUIRE(pthread_mutex_lock(&mutex));
    134 	PTHREAD_REQUIRE(pthread_create(&new, NULL, mutex2_threadfunc, &count2));
    135 
    136 	printf("1: Thread %p\n", pthread_self());
    137 
    138 	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
    139 
    140 	while (count--) {
    141 		PTHREAD_REQUIRE(pthread_mutex_lock(&mutex));
    142 		global_x++;
    143 		PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
    144 	}
    145 
    146 	PTHREAD_REQUIRE(pthread_join(new, &joinval));
    147 
    148 	PTHREAD_REQUIRE(pthread_mutex_lock(&mutex));
    149 	printf("1: Thread joined. X was %d. Return value (long) was %ld\n",
    150 		global_x, (long)joinval);
    151 	ATF_REQUIRE_EQ(global_x, 20000000);
    152 }
    153 
    154 static void *
    155 mutex3_threadfunc(void *arg)
    156 {
    157 	long count = *(int *)arg;
    158 
    159 	printf("2: Second thread (%p). Count is %ld\n", pthread_self(), count);
    160 
    161 	while (count--) {
    162 		PTHREAD_REQUIRE(pthread_mutex_lock(&static_mutex));
    163 		global_x++;
    164 		PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex));
    165 	}
    166 
    167 	return (void *)count;
    168 }
    169 
    170 ATF_TC(mutex3);
    171 ATF_TC_HEAD(mutex3, tc)
    172 {
    173 	atf_tc_set_md_var(tc, "descr", "Checks mutexes using a static "
    174 	    "initializer");
    175 }
    176 ATF_TC_BODY(mutex3, tc)
    177 {
    178 	int count, count2;
    179 	pthread_t new;
    180 	void *joinval;
    181 
    182 	printf("1: Mutex-test 3\n");
    183 
    184 	global_x = 0;
    185 	count = count2 = 10000000;
    186 
    187 	PTHREAD_REQUIRE(pthread_mutex_lock(&static_mutex));
    188 	PTHREAD_REQUIRE(pthread_create(&new, NULL, mutex3_threadfunc, &count2));
    189 
    190 	printf("1: Thread %p\n", pthread_self());
    191 
    192 	PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex));
    193 
    194 	while (count--) {
    195 		PTHREAD_REQUIRE(pthread_mutex_lock(&static_mutex));
    196 		global_x++;
    197 		PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex));
    198 	}
    199 
    200 	PTHREAD_REQUIRE(pthread_join(new, &joinval));
    201 
    202 	PTHREAD_REQUIRE(pthread_mutex_lock(&static_mutex));
    203 	printf("1: Thread joined. X was %d. Return value (long) was %ld\n",
    204 		global_x, (long)joinval);
    205 	ATF_REQUIRE_EQ(global_x, 20000000);
    206 }
    207 
    208 static void *
    209 mutex4_threadfunc(void *arg)
    210 {
    211 	int *param;
    212 
    213 	printf("2: Second thread.\n");
    214 
    215 	param = arg;
    216 	printf("2: Locking mutex\n");
    217 	PTHREAD_REQUIRE(pthread_mutex_lock(&mutex));
    218 	printf("2: Got mutex. *param = %d\n", *param);
    219 	(*param)++;
    220 
    221 	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
    222 
    223 	return param;
    224 }
    225 
    226 ATF_TC(mutex4);
    227 ATF_TC_HEAD(mutex4, tc)
    228 {
    229 	atf_tc_set_md_var(tc, "descr", "Checks mutexes");
    230 }
    231 ATF_TC_BODY(mutex4, tc)
    232 {
    233 	int x;
    234 	pthread_t new;
    235 	pthread_mutexattr_t mattr;
    236 	void *joinval;
    237 
    238 	printf("1: Mutex-test 4\n");
    239 
    240 	PTHREAD_REQUIRE(pthread_mutexattr_init(&mattr));
    241 	PTHREAD_REQUIRE(pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_RECURSIVE));
    242 
    243 	PTHREAD_REQUIRE(pthread_mutex_init(&mutex, &mattr));
    244 
    245 	PTHREAD_REQUIRE(pthread_mutexattr_destroy(&mattr));
    246 
    247 	x = 1;
    248 	PTHREAD_REQUIRE(pthread_mutex_lock(&mutex));
    249 	PTHREAD_REQUIRE(pthread_create(&new, NULL, mutex4_threadfunc, &x));
    250 
    251 	printf("1: Before recursively acquiring the mutex.\n");
    252 	PTHREAD_REQUIRE(pthread_mutex_lock(&mutex));
    253 
    254 	printf("1: Before releasing the mutex once.\n");
    255 	sleep(2);
    256 	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
    257 	printf("1: After releasing the mutex once.\n");
    258 
    259 	x = 20;
    260 
    261 	printf("1: Before releasing the mutex twice.\n");
    262 	sleep(2);
    263 	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
    264 	printf("1: After releasing the mutex twice.\n");
    265 
    266 	PTHREAD_REQUIRE(pthread_join(new, &joinval));
    267 
    268 	PTHREAD_REQUIRE(pthread_mutex_lock(&mutex));
    269 	printf("1: Thread joined. X was %d. Return value (int) was %d\n",
    270 		x, *(int *)joinval);
    271 	ATF_REQUIRE_EQ(x, 21);
    272 	ATF_REQUIRE_EQ(*(int *)joinval, 21);
    273 	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
    274 }
    275 
    276 ATF_TP_ADD_TCS(tp)
    277 {
    278 	ATF_TP_ADD_TC(tp, mutex1);
    279 	ATF_TP_ADD_TC(tp, mutex2);
    280 	ATF_TP_ADD_TC(tp, mutex3);
    281 	ATF_TP_ADD_TC(tp, mutex4);
    282 
    283 	return atf_no_error();
    284 }
    285