1 /*	$OpenBSD: pthread_mutex.c,v 1.10 2012/03/24 21:39:10 guenther Exp $	*/
2 /*
3  * Copyright (c) 1993, 1994, 1995, 1996 by Chris Provenzano and contributors,
4  * proven@mit.edu All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. All advertising materials mentioning features or use of this software
15  *    must display the following acknowledgement:
16  *	This product includes software developed by Chris Provenzano,
17  *	the University of California, Berkeley, and contributors.
18  * 4. Neither the name of Chris Provenzano, the University, nor the names of
19  *   contributors may be used to endorse or promote products derived
20  *   from this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY CHRIS PROVENZANO AND CONTRIBUTORS ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED.  IN NO EVENT SHALL CHRIS PROVENZANO, THE REGENTS OR
26  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
27  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
29  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
30  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
31  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
32  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  */
34 
35 /* ==== test_pthread_cond.c =========================================
36  * Copyright (c) 1993 by Chris Provenzano, proven@athena.mit.edu
37  *
38  * Description : Test pthread_mutex(). Run this after test_create()
39  *
40  *  1.23 94/05/04 proven
41  *      -Started coding this file.
42  */
43 
44 #include <sys/time.h>
45 #include <errno.h>
46 #include <pthread.h>
47 #include <pthread_np.h>
48 #include <stdio.h>
49 #include <stdlib.h>
50 #include <unistd.h>
51 #include "test.h"
52 
53 int contention_variable;
54 
55 static void *
thread_contention(void * arg)56 thread_contention(void *arg)
57 {
58 	pthread_mutex_t *mutex = arg;
59 
60 	SET_NAME("cntntn");
61 
62 	CHECKr(pthread_mutex_lock(mutex));
63 	ASSERT(contention_variable == 1);
64 	contention_variable = 2;
65 	CHECKr(pthread_mutex_unlock(mutex));
66 	pthread_exit(NULL);
67 }
68 
69 static void
test_contention_lock(pthread_mutex_t * mutex)70 test_contention_lock(pthread_mutex_t *mutex)
71 {
72 	pthread_t thread;
73 
74 	printf("  test_contention_lock()\n");
75 	CHECKr(pthread_mutex_lock(mutex));
76 	contention_variable = 0;
77 	CHECKr(pthread_create(&thread, NULL, thread_contention, mutex));
78 	pthread_yield();
79 	contention_variable = 1;
80 	CHECKr(pthread_mutex_unlock(mutex));
81 	sleep(1);
82 	CHECKr(pthread_mutex_lock(mutex));
83 	ASSERT(contention_variable == 2);
84 	CHECKr(pthread_mutex_unlock(mutex));
85 	CHECKr(pthread_join(thread, NULL));
86 }
87 
88 static void
test_nocontention_lock(pthread_mutex_t * mutex)89 test_nocontention_lock(pthread_mutex_t *mutex)
90 {
91 	printf("  test_nocontention_lock()\n");
92 	CHECKr(pthread_mutex_lock(mutex));
93 	CHECKr(pthread_mutex_unlock(mutex));
94 }
95 
96 static void
test_debug_double_lock(pthread_mutex_t * mutex)97 test_debug_double_lock(pthread_mutex_t *mutex)
98 {
99 	printf("  test_debug_double_lock()\n");
100 	CHECKr(pthread_mutex_lock(mutex));
101 	ASSERTe(pthread_mutex_lock(mutex), == EDEADLK);
102 	CHECKr(pthread_mutex_unlock(mutex));
103 }
104 
105 static void
test_debug_double_unlock(pthread_mutex_t * mutex)106 test_debug_double_unlock(pthread_mutex_t *mutex)
107 {
108 	printf("  test_debug_double_unlock()\n");
109 	CHECKr(pthread_mutex_lock(mutex));
110 	CHECKr(pthread_mutex_unlock(mutex));
111 	/* Posix D10 says undefined behaviour? */
112 	ASSERTe(pthread_mutex_unlock(mutex), != 0);
113 }
114 
115 static void
test_nocontention_trylock(pthread_mutex_t * mutex)116 test_nocontention_trylock(pthread_mutex_t *mutex)
117 {
118 	printf("  test_nocontention_trylock()\n");
119 	CHECKr(pthread_mutex_trylock(mutex));
120 	CHECKr(pthread_mutex_unlock(mutex));
121 }
122 
123 static void
test_mutex_static(void)124 test_mutex_static(void)
125 {
126 	pthread_mutex_t mutex_static = PTHREAD_MUTEX_INITIALIZER;
127 
128 	printf("test_mutex_static()\n");
129 	test_nocontention_lock(&mutex_static);
130 	test_nocontention_trylock(&mutex_static);
131 	test_contention_lock(&mutex_static);
132 }
133 
134 static void
test_mutex_fast(void)135 test_mutex_fast(void)
136 {
137 	pthread_mutex_t mutex_fast;
138 
139 	printf("test_mutex_fast()\n");
140 	CHECKr(pthread_mutex_init(&mutex_fast, NULL));
141 	test_nocontention_lock(&mutex_fast);
142 	test_nocontention_trylock(&mutex_fast);
143 	test_contention_lock(&mutex_fast);
144 	CHECKr(pthread_mutex_destroy(&mutex_fast));
145 }
146 
147 static void
test_mutex_debug(void)148 test_mutex_debug(void)
149 {
150 	pthread_mutexattr_t mutex_debug_attr;
151 	pthread_mutex_t mutex_debug;
152 
153 	printf("test_mutex_debug()\n");
154 	CHECKr(pthread_mutexattr_init(&mutex_debug_attr));
155 	CHECKr(pthread_mutexattr_settype(&mutex_debug_attr,
156 	    PTHREAD_MUTEX_ERRORCHECK));
157 	CHECKr(pthread_mutex_init(&mutex_debug, &mutex_debug_attr));
158 	CHECKr(pthread_mutexattr_destroy(&mutex_debug_attr));
159 	test_nocontention_lock(&mutex_debug);
160 	test_nocontention_trylock(&mutex_debug);
161 	test_contention_lock(&mutex_debug);
162 	test_debug_double_lock(&mutex_debug);
163 	test_debug_double_unlock(&mutex_debug);
164 	CHECKr(pthread_mutex_destroy(&mutex_debug));
165 }
166 
167 static void
test_mutex_recursive_lock(pthread_mutex_t * mutex)168 test_mutex_recursive_lock(pthread_mutex_t *mutex)
169 {
170 	int i;
171 	int j = 9;
172 
173 	printf("  %s()\n", __func__);
174 	CHECKr(pthread_mutex_lock(mutex));
175 	for (i = 0; i < j; i++)
176 		CHECKr(pthread_mutex_lock(mutex));
177 	for (i = 0; i < j; i++)
178 		CHECKr(pthread_mutex_unlock(mutex));
179 	CHECKr(pthread_mutex_unlock(mutex));
180 }
181 
182 static void
test_mutex_recursive_trylock(pthread_mutex_t * mutex)183 test_mutex_recursive_trylock(pthread_mutex_t *mutex)
184 {
185 	int i;
186 	int j = 9;
187 
188 	printf("  %s()\n", __func__);
189 	CHECKr(pthread_mutex_trylock(mutex));
190 	for (i = 0; i < j; i++)
191 		CHECKr(pthread_mutex_trylock(mutex));
192 	for (i = 0; i < j; i++)
193 		CHECKr(pthread_mutex_unlock(mutex));
194 	CHECKr(pthread_mutex_unlock(mutex));
195 }
196 
197 static void
test_mutex_recursive(void)198 test_mutex_recursive(void)
199 {
200 	pthread_mutexattr_t mutex_recursive_attr;
201 	pthread_mutex_t mutex_recursive;
202 
203 	printf("test_mutex_recursive()\n");
204 	CHECKr(pthread_mutexattr_init(&mutex_recursive_attr));
205 	CHECKr(pthread_mutexattr_settype(&mutex_recursive_attr,
206 	    PTHREAD_MUTEX_RECURSIVE));
207 	CHECKr(pthread_mutex_init(&mutex_recursive, &mutex_recursive_attr));
208 	CHECKr(pthread_mutexattr_destroy(&mutex_recursive_attr));
209 	test_mutex_recursive_lock(&mutex_recursive);
210 	test_mutex_recursive_trylock(&mutex_recursive);
211 	/* Posix D10 says undefined behaviour? */
212 	ASSERTe(pthread_mutex_unlock(&mutex_recursive), != 0);
213 	CHECKr(pthread_mutex_destroy(&mutex_recursive));
214 }
215 
216 static void *
thread_deadlock(void * arg)217 thread_deadlock(void *arg)
218 {
219 	pthread_mutex_t *mutex = arg;;
220 
221 	/* intentionally deadlock this thread */
222 	CHECKr(pthread_mutex_lock(mutex));
223 	CHECKr(pthread_mutex_lock(mutex));
224 
225 	/* never reached */
226 	abort();
227 }
228 
229 static void
test_mutex_normal(void)230 test_mutex_normal(void)
231 {
232 	pthread_mutexattr_t mutex_normal_attr;
233 	pthread_mutex_t mutex_normal;
234 	pthread_t thread;
235 	struct timespec ts;
236 
237 	printf("test_mutex_normal()\n");
238 	CHECKr(pthread_mutexattr_init(&mutex_normal_attr));
239 	CHECKr(pthread_mutexattr_settype(&mutex_normal_attr,
240 	    PTHREAD_MUTEX_NORMAL));
241 	CHECKr(pthread_mutex_init(&mutex_normal, &mutex_normal_attr));
242 	CHECKr(pthread_mutexattr_destroy(&mutex_normal_attr));
243 	test_nocontention_lock(&mutex_normal);
244 	test_nocontention_trylock(&mutex_normal);
245 	test_contention_lock(&mutex_normal);
246 
247 	/* test self-deadlock with timeout */
248 	CHECKr(pthread_mutex_lock(&mutex_normal));
249 	CHECKe(clock_gettime(CLOCK_REALTIME, &ts));
250 	ts.tv_sec += 2;
251 	ASSERTe(pthread_mutex_timedlock(&mutex_normal, &ts), == ETIMEDOUT);
252 	CHECKr(pthread_mutex_unlock(&mutex_normal));
253 	/* verify that it can still be locked and unlocked */
254 	CHECKr(pthread_mutex_lock(&mutex_normal));
255 	CHECKr(pthread_mutex_unlock(&mutex_normal));
256 	CHECKr(pthread_create(&thread, NULL, thread_deadlock, &mutex_normal));
257 	sleep(1);
258 }
259 
260 int
main(int argc,char * argv[])261 main(int argc, char *argv[])
262 {
263 	test_mutex_static();
264 	test_mutex_fast();
265 	test_mutex_debug();
266 	test_mutex_recursive();
267 	test_mutex_normal();
268 	SUCCEED;
269 }
270