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