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