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
53int contention_variable;
54
55static void *
56thread_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
69static void
70test_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
88static void
89test_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
96static void
97test_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
105static void
106test_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
115static void
116test_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
123static void
124test_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
134static void
135test_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
147static void
148test_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
167static void
168test_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
182static void
183test_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
197static void
198test_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
216static void *
217thread_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
229static void
230test_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
260int
261main(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