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 * 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 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 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 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 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 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 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 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 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 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 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 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 * 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 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 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