xref: /netbsd-src/tests/lib/libpthread/t_mutex.c (revision b1c86f5f087524e68db12794ee9c3e3da1ab17a0)
1 /* $NetBSD: t_mutex.c,v 1.2 2010/07/16 18:16:43 njoly 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.2 2010/07/16 18:16:43 njoly 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 int global_x;
44 
45 static void *
46 mutex1_threadfunc(void *arg)
47 {
48 	int *param;
49 
50 	printf("2: Second thread.\n");
51 
52 	param = arg;
53 	printf("2: Locking mutex\n");
54 	pthread_mutex_lock(&mutex);
55 	printf("2: Got mutex. *param = %d\n", *param);
56 	ATF_REQUIRE_EQ(*param, 20);
57 	(*param)++;
58 
59 	pthread_mutex_unlock(&mutex);
60 
61 	return param;
62 }
63 
64 ATF_TC(mutex1);
65 ATF_TC_HEAD(mutex1, tc)
66 {
67 	atf_tc_set_md_var(tc, "descr", "Checks mutexes");
68 }
69 ATF_TC_BODY(mutex1, tc)
70 {
71 	int x;
72 	pthread_t new;
73 	void *joinval;
74 
75 	printf("1: Mutex-test 1\n");
76 
77 	PTHREAD_REQUIRE(pthread_mutex_init(&mutex, NULL));
78 	x = 1;
79 	PTHREAD_REQUIRE(pthread_mutex_lock(&mutex));
80 	PTHREAD_REQUIRE(pthread_create(&new, NULL, mutex1_threadfunc, &x));
81 	printf("1: Before changing the value.\n");
82 	sleep(2);
83 	x = 20;
84 	printf("1: Before releasing the mutex.\n");
85 	sleep(2);
86 	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
87 	printf("1: After releasing the mutex.\n");
88 	PTHREAD_REQUIRE(pthread_join(new, &joinval));
89 
90 	PTHREAD_REQUIRE(pthread_mutex_lock(&mutex));
91 	printf("1: Thread joined. X was %d. Return value (int) was %d\n",
92 		x, *(int *)joinval);
93 	ATF_REQUIRE_EQ(x, 21);
94 	ATF_REQUIRE_EQ(*(int *)joinval, 21);
95 	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
96 }
97 
98 static void *
99 mutex2_threadfunc(void *arg)
100 {
101 	long count = *(int *)arg;
102 
103 	printf("2: Second thread (%p). Count is %ld\n", pthread_self(), count);
104 
105 	while (count--) {
106 		PTHREAD_REQUIRE(pthread_mutex_lock(&mutex));
107 		global_x++;
108 		PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
109 	}
110 
111 	return (void *)count;
112 }
113 
114 ATF_TC(mutex2);
115 ATF_TC_HEAD(mutex2, tc)
116 {
117 	atf_tc_set_md_var(tc, "descr", "Checks mutexes");
118 }
119 ATF_TC_BODY(mutex2, tc)
120 {
121 	int count, count2;
122 	pthread_t new;
123 	void *joinval;
124 
125 	printf("1: Mutex-test 2\n");
126 
127 	PTHREAD_REQUIRE(pthread_mutex_init(&mutex, NULL));
128 
129 	global_x = 0;
130 	count = count2 = 10000000;
131 
132 	PTHREAD_REQUIRE(pthread_mutex_lock(&mutex));
133 	PTHREAD_REQUIRE(pthread_create(&new, NULL, mutex2_threadfunc, &count2));
134 
135 	printf("1: Thread %p\n", pthread_self());
136 
137 	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
138 
139 	while (count--) {
140 		PTHREAD_REQUIRE(pthread_mutex_lock(&mutex));
141 		global_x++;
142 		PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
143 	}
144 
145 	PTHREAD_REQUIRE(pthread_join(new, &joinval));
146 
147 	PTHREAD_REQUIRE(pthread_mutex_lock(&mutex));
148 	printf("1: Thread joined. X was %d. Return value (long) was %ld\n",
149 		global_x, (long)joinval);
150 	ATF_REQUIRE_EQ(global_x, 20000000);
151 }
152 
153 static void *
154 mutex3_threadfunc(void *arg)
155 {
156 	long count = *(int *)arg;
157 
158 	printf("2: Second thread (%p). Count is %ld\n", pthread_self(), count);
159 
160 	while (count--) {
161 		PTHREAD_REQUIRE(pthread_mutex_lock(&mutex));
162 		global_x++;
163 		PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
164 	}
165 
166 	return (void *)count;
167 }
168 
169 ATF_TC(mutex3);
170 ATF_TC_HEAD(mutex3, tc)
171 {
172 	atf_tc_set_md_var(tc, "descr", "Checks mutexes");
173 }
174 ATF_TC_BODY(mutex3, tc)
175 {
176 	int count, count2;
177 	pthread_t new;
178 	void *joinval;
179 
180 	printf("1: Mutex-test 3\n");
181 
182 	PTHREAD_REQUIRE(pthread_mutex_init(&mutex, NULL));
183 
184 	global_x = 0;
185 	count = count2 = 10000000;
186 
187 	PTHREAD_REQUIRE(pthread_mutex_lock(&mutex));
188 	PTHREAD_REQUIRE(pthread_create(&new, NULL, mutex3_threadfunc, &count2));
189 
190 	printf("1: Thread %p\n", pthread_self());
191 	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
192 
193 	while (count--) {
194 		PTHREAD_REQUIRE(pthread_mutex_lock(&mutex));
195 		global_x++;
196 		PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
197 	}
198 
199 	PTHREAD_REQUIRE(pthread_join(new, &joinval));
200 
201 	PTHREAD_REQUIRE(pthread_mutex_lock(&mutex));
202 	printf("1: Thread joined. X was %d. Return value (long) was %ld\n",
203 		global_x, (long)joinval);
204 	ATF_REQUIRE_EQ(global_x, 20000000);
205 }
206 
207 static void *
208 mutex4_threadfunc(void *arg)
209 {
210 	int *param;
211 
212 	printf("2: Second thread.\n");
213 
214 	param = arg;
215 	printf("2: Locking mutex\n");
216 	PTHREAD_REQUIRE(pthread_mutex_lock(&mutex));
217 	printf("2: Got mutex. *param = %d\n", *param);
218 	(*param)++;
219 
220 	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
221 
222 	return param;
223 }
224 
225 ATF_TC(mutex4);
226 ATF_TC_HEAD(mutex4, tc)
227 {
228 	atf_tc_set_md_var(tc, "descr", "Checks mutexes");
229 }
230 ATF_TC_BODY(mutex4, tc)
231 {
232 	int x;
233 	pthread_t new;
234 	pthread_mutexattr_t mattr;
235 	void *joinval;
236 
237 	printf("1: Mutex-test 4\n");
238 
239 	PTHREAD_REQUIRE(pthread_mutexattr_init(&mattr));
240 	PTHREAD_REQUIRE(pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_RECURSIVE));
241 
242 	PTHREAD_REQUIRE(pthread_mutex_init(&mutex, &mattr));
243 
244 	PTHREAD_REQUIRE(pthread_mutexattr_destroy(&mattr));
245 
246 	x = 1;
247 	PTHREAD_REQUIRE(pthread_mutex_lock(&mutex));
248 	PTHREAD_REQUIRE(pthread_create(&new, NULL, mutex4_threadfunc, &x));
249 
250 	printf("1: Before recursively acquiring the mutex.\n");
251 	PTHREAD_REQUIRE(pthread_mutex_lock(&mutex));
252 
253 	printf("1: Before releasing the mutex once.\n");
254 	sleep(2);
255 	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
256 	printf("1: After releasing the mutex once.\n");
257 
258 	x = 20;
259 
260 	printf("1: Before releasing the mutex twice.\n");
261 	sleep(2);
262 	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
263 	printf("1: After releasing the mutex twice.\n");
264 
265 	PTHREAD_REQUIRE(pthread_join(new, &joinval));
266 
267 	PTHREAD_REQUIRE(pthread_mutex_lock(&mutex));
268 	printf("1: Thread joined. X was %d. Return value (int) was %d\n",
269 		x, *(int *)joinval);
270 	ATF_REQUIRE_EQ(x, 21);
271 	ATF_REQUIRE_EQ(*(int *)joinval, 21);
272 	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
273 }
274 
275 ATF_TP_ADD_TCS(tp)
276 {
277 	ATF_TP_ADD_TC(tp, mutex1);
278 	ATF_TP_ADD_TC(tp, mutex2);
279 	ATF_TP_ADD_TC(tp, mutex3);
280 	ATF_TP_ADD_TC(tp, mutex4);
281 
282 	return atf_no_error();
283 }
284