t_mutex.c revision 276478
1/* $NetBSD: t_mutex.c,v 1.7 2014/11/04 00:20:19 justin 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.7 2014/11/04 00:20:19 justin Exp $");
33
34#include <pthread.h>
35#include <stdio.h>
36#include <string.h>
37#include <unistd.h>
38
39#include <atf-c.h>
40
41#include "h_common.h"
42
43static pthread_mutex_t mutex;
44static pthread_mutex_t static_mutex = PTHREAD_MUTEX_INITIALIZER;
45static int global_x;
46
47static void *
48mutex1_threadfunc(void *arg)
49{
50	int *param;
51
52	printf("2: Second thread.\n");
53
54	param = arg;
55	printf("2: Locking mutex\n");
56	pthread_mutex_lock(&mutex);
57	printf("2: Got mutex. *param = %d\n", *param);
58	ATF_REQUIRE_EQ(*param, 20);
59	(*param)++;
60
61	pthread_mutex_unlock(&mutex);
62
63	return param;
64}
65
66ATF_TC(mutex1);
67ATF_TC_HEAD(mutex1, tc)
68{
69	atf_tc_set_md_var(tc, "descr", "Checks mutexes");
70}
71ATF_TC_BODY(mutex1, tc)
72{
73	int x;
74	pthread_t new;
75	void *joinval;
76
77	printf("1: Mutex-test 1\n");
78
79	PTHREAD_REQUIRE(pthread_mutex_init(&mutex, NULL));
80	x = 1;
81	PTHREAD_REQUIRE(pthread_mutex_lock(&mutex));
82	PTHREAD_REQUIRE(pthread_create(&new, NULL, mutex1_threadfunc, &x));
83	printf("1: Before changing the value.\n");
84	sleep(2);
85	x = 20;
86	printf("1: Before releasing the mutex.\n");
87	sleep(2);
88	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
89	printf("1: After releasing the mutex.\n");
90	PTHREAD_REQUIRE(pthread_join(new, &joinval));
91
92	PTHREAD_REQUIRE(pthread_mutex_lock(&mutex));
93	printf("1: Thread joined. X was %d. Return value (int) was %d\n",
94		x, *(int *)joinval);
95	ATF_REQUIRE_EQ(x, 21);
96	ATF_REQUIRE_EQ(*(int *)joinval, 21);
97	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
98}
99
100static void *
101mutex2_threadfunc(void *arg)
102{
103	long count = *(int *)arg;
104
105	printf("2: Second thread (%p). Count is %ld\n", pthread_self(), count);
106
107	while (count--) {
108		PTHREAD_REQUIRE(pthread_mutex_lock(&mutex));
109		global_x++;
110		PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
111	}
112
113	return (void *)count;
114}
115
116ATF_TC(mutex2);
117ATF_TC_HEAD(mutex2, tc)
118{
119	atf_tc_set_md_var(tc, "descr", "Checks mutexes");
120#ifdef __NetBSD__
121#if defined(__powerpc__)
122	atf_tc_set_md_var(tc, "timeout", "40");
123#endif
124#endif
125}
126ATF_TC_BODY(mutex2, tc)
127{
128	int count, count2;
129	pthread_t new;
130	void *joinval;
131
132	printf("1: Mutex-test 2\n");
133
134#ifdef __NetBSD__
135#if defined(__powerpc__)
136	atf_tc_expect_timeout("PR port-powerpc/44387");
137#endif
138#endif
139
140	PTHREAD_REQUIRE(pthread_mutex_init(&mutex, NULL));
141
142	global_x = 0;
143	count = count2 = 10000000;
144
145	PTHREAD_REQUIRE(pthread_mutex_lock(&mutex));
146	PTHREAD_REQUIRE(pthread_create(&new, NULL, mutex2_threadfunc, &count2));
147
148	printf("1: Thread %p\n", pthread_self());
149
150	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
151
152	while (count--) {
153		PTHREAD_REQUIRE(pthread_mutex_lock(&mutex));
154		global_x++;
155		PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
156	}
157
158	PTHREAD_REQUIRE(pthread_join(new, &joinval));
159
160	PTHREAD_REQUIRE(pthread_mutex_lock(&mutex));
161	printf("1: Thread joined. X was %d. Return value (long) was %ld\n",
162		global_x, (long)joinval);
163	ATF_REQUIRE_EQ(global_x, 20000000);
164
165#ifdef __NetBSD__
166#if defined(__powerpc__)
167	/* XXX force a timeout in ppc case since an un-triggered race
168	   otherwise looks like a "failure" */
169	/* We sleep for longer than the timeout to make ATF not
170	   complain about unexpected success */
171	sleep(41);
172#endif
173#endif
174}
175
176static void *
177mutex3_threadfunc(void *arg)
178{
179	long count = *(int *)arg;
180
181	printf("2: Second thread (%p). Count is %ld\n", pthread_self(), count);
182
183	while (count--) {
184		PTHREAD_REQUIRE(pthread_mutex_lock(&static_mutex));
185		global_x++;
186		PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex));
187	}
188
189	return (void *)count;
190}
191
192ATF_TC(mutex3);
193ATF_TC_HEAD(mutex3, tc)
194{
195	atf_tc_set_md_var(tc, "descr", "Checks mutexes using a static "
196	    "initializer");
197#ifdef __NetBSD__
198#if defined(__powerpc__)
199	atf_tc_set_md_var(tc, "timeout", "40");
200#endif
201#endif
202}
203ATF_TC_BODY(mutex3, tc)
204{
205	int count, count2;
206	pthread_t new;
207	void *joinval;
208
209	printf("1: Mutex-test 3\n");
210
211#ifdef __NetBSD__
212#if defined(__powerpc__)
213	atf_tc_expect_timeout("PR port-powerpc/44387");
214#endif
215#endif
216
217	global_x = 0;
218	count = count2 = 10000000;
219
220	PTHREAD_REQUIRE(pthread_mutex_lock(&static_mutex));
221	PTHREAD_REQUIRE(pthread_create(&new, NULL, mutex3_threadfunc, &count2));
222
223	printf("1: Thread %p\n", pthread_self());
224
225	PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex));
226
227	while (count--) {
228		PTHREAD_REQUIRE(pthread_mutex_lock(&static_mutex));
229		global_x++;
230		PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex));
231	}
232
233	PTHREAD_REQUIRE(pthread_join(new, &joinval));
234
235	PTHREAD_REQUIRE(pthread_mutex_lock(&static_mutex));
236	printf("1: Thread joined. X was %d. Return value (long) was %ld\n",
237		global_x, (long)joinval);
238	ATF_REQUIRE_EQ(global_x, 20000000);
239
240#ifdef __NetBSD__
241#if defined(__powerpc__)
242	/* XXX force a timeout in ppc case since an un-triggered race
243	   otherwise looks like a "failure" */
244	/* We sleep for longer than the timeout to make ATF not
245	   complain about unexpected success */
246	sleep(41);
247#endif
248#endif
249}
250
251static void *
252mutex4_threadfunc(void *arg)
253{
254	int *param;
255
256	printf("2: Second thread.\n");
257
258	param = arg;
259	printf("2: Locking mutex\n");
260	PTHREAD_REQUIRE(pthread_mutex_lock(&mutex));
261	printf("2: Got mutex. *param = %d\n", *param);
262	(*param)++;
263
264	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
265
266	return param;
267}
268
269ATF_TC(mutex4);
270ATF_TC_HEAD(mutex4, tc)
271{
272	atf_tc_set_md_var(tc, "descr", "Checks mutexes");
273}
274ATF_TC_BODY(mutex4, tc)
275{
276	int x;
277	pthread_t new;
278	pthread_mutexattr_t mattr;
279	void *joinval;
280
281	printf("1: Mutex-test 4\n");
282
283	PTHREAD_REQUIRE(pthread_mutexattr_init(&mattr));
284	PTHREAD_REQUIRE(pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_RECURSIVE));
285
286	PTHREAD_REQUIRE(pthread_mutex_init(&mutex, &mattr));
287
288	PTHREAD_REQUIRE(pthread_mutexattr_destroy(&mattr));
289
290	x = 1;
291	PTHREAD_REQUIRE(pthread_mutex_lock(&mutex));
292	PTHREAD_REQUIRE(pthread_create(&new, NULL, mutex4_threadfunc, &x));
293
294	printf("1: Before recursively acquiring the mutex.\n");
295	PTHREAD_REQUIRE(pthread_mutex_lock(&mutex));
296
297	printf("1: Before releasing the mutex once.\n");
298	sleep(2);
299	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
300	printf("1: After releasing the mutex once.\n");
301
302	x = 20;
303
304	printf("1: Before releasing the mutex twice.\n");
305	sleep(2);
306	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
307	printf("1: After releasing the mutex twice.\n");
308
309	PTHREAD_REQUIRE(pthread_join(new, &joinval));
310
311	PTHREAD_REQUIRE(pthread_mutex_lock(&mutex));
312	printf("1: Thread joined. X was %d. Return value (int) was %d\n",
313		x, *(int *)joinval);
314	ATF_REQUIRE_EQ(x, 21);
315	ATF_REQUIRE_EQ(*(int *)joinval, 21);
316	PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
317}
318
319ATF_TP_ADD_TCS(tp)
320{
321	ATF_TP_ADD_TC(tp, mutex1);
322	ATF_TP_ADD_TC(tp, mutex2);
323	ATF_TP_ADD_TC(tp, mutex3);
324	ATF_TP_ADD_TC(tp, mutex4);
325
326	return atf_no_error();
327}
328