1 /* $NetBSD: t_mutex.c,v 1.2 2010/07/16 18:16:43 njoly 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.2 2010/07/16 18:16:43 njoly Exp $"); 33 34 #include <pthread.h> 35 #include <stdio.h> 36 #include <unistd.h> 37 38 #include <atf-c.h> 39 40 #include "h_common.h" 41 42 static pthread_mutex_t mutex; 43 static int global_x; 44 45 static void * 46 mutex1_threadfunc(void *arg) 47 { 48 int *param; 49 50 printf("2: Second thread.\n"); 51 52 param = arg; 53 printf("2: Locking mutex\n"); 54 pthread_mutex_lock(&mutex); 55 printf("2: Got mutex. *param = %d\n", *param); 56 ATF_REQUIRE_EQ(*param, 20); 57 (*param)++; 58 59 pthread_mutex_unlock(&mutex); 60 61 return param; 62 } 63 64 ATF_TC(mutex1); 65 ATF_TC_HEAD(mutex1, tc) 66 { 67 atf_tc_set_md_var(tc, "descr", "Checks mutexes"); 68 } 69 ATF_TC_BODY(mutex1, tc) 70 { 71 int x; 72 pthread_t new; 73 void *joinval; 74 75 printf("1: Mutex-test 1\n"); 76 77 PTHREAD_REQUIRE(pthread_mutex_init(&mutex, NULL)); 78 x = 1; 79 PTHREAD_REQUIRE(pthread_mutex_lock(&mutex)); 80 PTHREAD_REQUIRE(pthread_create(&new, NULL, mutex1_threadfunc, &x)); 81 printf("1: Before changing the value.\n"); 82 sleep(2); 83 x = 20; 84 printf("1: Before releasing the mutex.\n"); 85 sleep(2); 86 PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex)); 87 printf("1: After releasing the mutex.\n"); 88 PTHREAD_REQUIRE(pthread_join(new, &joinval)); 89 90 PTHREAD_REQUIRE(pthread_mutex_lock(&mutex)); 91 printf("1: Thread joined. X was %d. Return value (int) was %d\n", 92 x, *(int *)joinval); 93 ATF_REQUIRE_EQ(x, 21); 94 ATF_REQUIRE_EQ(*(int *)joinval, 21); 95 PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex)); 96 } 97 98 static void * 99 mutex2_threadfunc(void *arg) 100 { 101 long count = *(int *)arg; 102 103 printf("2: Second thread (%p). Count is %ld\n", pthread_self(), count); 104 105 while (count--) { 106 PTHREAD_REQUIRE(pthread_mutex_lock(&mutex)); 107 global_x++; 108 PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex)); 109 } 110 111 return (void *)count; 112 } 113 114 ATF_TC(mutex2); 115 ATF_TC_HEAD(mutex2, tc) 116 { 117 atf_tc_set_md_var(tc, "descr", "Checks mutexes"); 118 } 119 ATF_TC_BODY(mutex2, tc) 120 { 121 int count, count2; 122 pthread_t new; 123 void *joinval; 124 125 printf("1: Mutex-test 2\n"); 126 127 PTHREAD_REQUIRE(pthread_mutex_init(&mutex, NULL)); 128 129 global_x = 0; 130 count = count2 = 10000000; 131 132 PTHREAD_REQUIRE(pthread_mutex_lock(&mutex)); 133 PTHREAD_REQUIRE(pthread_create(&new, NULL, mutex2_threadfunc, &count2)); 134 135 printf("1: Thread %p\n", pthread_self()); 136 137 PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex)); 138 139 while (count--) { 140 PTHREAD_REQUIRE(pthread_mutex_lock(&mutex)); 141 global_x++; 142 PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex)); 143 } 144 145 PTHREAD_REQUIRE(pthread_join(new, &joinval)); 146 147 PTHREAD_REQUIRE(pthread_mutex_lock(&mutex)); 148 printf("1: Thread joined. X was %d. Return value (long) was %ld\n", 149 global_x, (long)joinval); 150 ATF_REQUIRE_EQ(global_x, 20000000); 151 } 152 153 static void * 154 mutex3_threadfunc(void *arg) 155 { 156 long count = *(int *)arg; 157 158 printf("2: Second thread (%p). Count is %ld\n", pthread_self(), count); 159 160 while (count--) { 161 PTHREAD_REQUIRE(pthread_mutex_lock(&mutex)); 162 global_x++; 163 PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex)); 164 } 165 166 return (void *)count; 167 } 168 169 ATF_TC(mutex3); 170 ATF_TC_HEAD(mutex3, tc) 171 { 172 atf_tc_set_md_var(tc, "descr", "Checks mutexes"); 173 } 174 ATF_TC_BODY(mutex3, tc) 175 { 176 int count, count2; 177 pthread_t new; 178 void *joinval; 179 180 printf("1: Mutex-test 3\n"); 181 182 PTHREAD_REQUIRE(pthread_mutex_init(&mutex, NULL)); 183 184 global_x = 0; 185 count = count2 = 10000000; 186 187 PTHREAD_REQUIRE(pthread_mutex_lock(&mutex)); 188 PTHREAD_REQUIRE(pthread_create(&new, NULL, mutex3_threadfunc, &count2)); 189 190 printf("1: Thread %p\n", pthread_self()); 191 PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex)); 192 193 while (count--) { 194 PTHREAD_REQUIRE(pthread_mutex_lock(&mutex)); 195 global_x++; 196 PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex)); 197 } 198 199 PTHREAD_REQUIRE(pthread_join(new, &joinval)); 200 201 PTHREAD_REQUIRE(pthread_mutex_lock(&mutex)); 202 printf("1: Thread joined. X was %d. Return value (long) was %ld\n", 203 global_x, (long)joinval); 204 ATF_REQUIRE_EQ(global_x, 20000000); 205 } 206 207 static void * 208 mutex4_threadfunc(void *arg) 209 { 210 int *param; 211 212 printf("2: Second thread.\n"); 213 214 param = arg; 215 printf("2: Locking mutex\n"); 216 PTHREAD_REQUIRE(pthread_mutex_lock(&mutex)); 217 printf("2: Got mutex. *param = %d\n", *param); 218 (*param)++; 219 220 PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex)); 221 222 return param; 223 } 224 225 ATF_TC(mutex4); 226 ATF_TC_HEAD(mutex4, tc) 227 { 228 atf_tc_set_md_var(tc, "descr", "Checks mutexes"); 229 } 230 ATF_TC_BODY(mutex4, tc) 231 { 232 int x; 233 pthread_t new; 234 pthread_mutexattr_t mattr; 235 void *joinval; 236 237 printf("1: Mutex-test 4\n"); 238 239 PTHREAD_REQUIRE(pthread_mutexattr_init(&mattr)); 240 PTHREAD_REQUIRE(pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_RECURSIVE)); 241 242 PTHREAD_REQUIRE(pthread_mutex_init(&mutex, &mattr)); 243 244 PTHREAD_REQUIRE(pthread_mutexattr_destroy(&mattr)); 245 246 x = 1; 247 PTHREAD_REQUIRE(pthread_mutex_lock(&mutex)); 248 PTHREAD_REQUIRE(pthread_create(&new, NULL, mutex4_threadfunc, &x)); 249 250 printf("1: Before recursively acquiring the mutex.\n"); 251 PTHREAD_REQUIRE(pthread_mutex_lock(&mutex)); 252 253 printf("1: Before releasing the mutex once.\n"); 254 sleep(2); 255 PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex)); 256 printf("1: After releasing the mutex once.\n"); 257 258 x = 20; 259 260 printf("1: Before releasing the mutex twice.\n"); 261 sleep(2); 262 PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex)); 263 printf("1: After releasing the mutex twice.\n"); 264 265 PTHREAD_REQUIRE(pthread_join(new, &joinval)); 266 267 PTHREAD_REQUIRE(pthread_mutex_lock(&mutex)); 268 printf("1: Thread joined. X was %d. Return value (int) was %d\n", 269 x, *(int *)joinval); 270 ATF_REQUIRE_EQ(x, 21); 271 ATF_REQUIRE_EQ(*(int *)joinval, 21); 272 PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex)); 273 } 274 275 ATF_TP_ADD_TCS(tp) 276 { 277 ATF_TP_ADD_TC(tp, mutex1); 278 ATF_TP_ADD_TC(tp, mutex2); 279 ATF_TP_ADD_TC(tp, mutex3); 280 ATF_TP_ADD_TC(tp, mutex4); 281 282 return atf_no_error(); 283 } 284