1*57718be8SEnji Cooper /* $NetBSD: t_mutex.c,v 1.6 2014/02/09 21:26:07 jmmv Exp $ */ 2*57718be8SEnji Cooper 3*57718be8SEnji Cooper /* 4*57718be8SEnji Cooper * Copyright (c) 2008 The NetBSD Foundation, Inc. 5*57718be8SEnji Cooper * All rights reserved. 6*57718be8SEnji Cooper * 7*57718be8SEnji Cooper * Redistribution and use in source and binary forms, with or without 8*57718be8SEnji Cooper * modification, are permitted provided that the following conditions 9*57718be8SEnji Cooper * are met: 10*57718be8SEnji Cooper * 1. Redistributions of source code must retain the above copyright 11*57718be8SEnji Cooper * notice, this list of conditions and the following disclaimer. 12*57718be8SEnji Cooper * 2. Redistributions in binary form must reproduce the above copyright 13*57718be8SEnji Cooper * notice, this list of conditions and the following disclaimer in the 14*57718be8SEnji Cooper * documentation and/or other materials provided with the distribution. 15*57718be8SEnji Cooper * 16*57718be8SEnji Cooper * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 17*57718be8SEnji Cooper * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18*57718be8SEnji Cooper * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19*57718be8SEnji Cooper * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 20*57718be8SEnji Cooper * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21*57718be8SEnji Cooper * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22*57718be8SEnji Cooper * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23*57718be8SEnji Cooper * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24*57718be8SEnji Cooper * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25*57718be8SEnji Cooper * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26*57718be8SEnji Cooper * POSSIBILITY OF SUCH DAMAGE. 27*57718be8SEnji Cooper */ 28*57718be8SEnji Cooper 29*57718be8SEnji Cooper #include <sys/cdefs.h> 30*57718be8SEnji Cooper __COPYRIGHT("@(#) Copyright (c) 2008\ 31*57718be8SEnji Cooper The NetBSD Foundation, inc. All rights reserved."); 32*57718be8SEnji Cooper __RCSID("$NetBSD: t_mutex.c,v 1.6 2014/02/09 21:26:07 jmmv Exp $"); 33*57718be8SEnji Cooper 34*57718be8SEnji Cooper #include <pthread.h> 35*57718be8SEnji Cooper #include <stdio.h> 36*57718be8SEnji Cooper #include <string.h> 37*57718be8SEnji Cooper #include <unistd.h> 38*57718be8SEnji Cooper 39*57718be8SEnji Cooper #include <atf-c.h> 40*57718be8SEnji Cooper #include <atf-c/config.h> 41*57718be8SEnji Cooper 42*57718be8SEnji Cooper #include "h_common.h" 43*57718be8SEnji Cooper 44*57718be8SEnji Cooper static pthread_mutex_t mutex; 45*57718be8SEnji Cooper static pthread_mutex_t static_mutex = PTHREAD_MUTEX_INITIALIZER; 46*57718be8SEnji Cooper static int global_x; 47*57718be8SEnji Cooper 48*57718be8SEnji Cooper static void * 49*57718be8SEnji Cooper mutex1_threadfunc(void *arg) 50*57718be8SEnji Cooper { 51*57718be8SEnji Cooper int *param; 52*57718be8SEnji Cooper 53*57718be8SEnji Cooper printf("2: Second thread.\n"); 54*57718be8SEnji Cooper 55*57718be8SEnji Cooper param = arg; 56*57718be8SEnji Cooper printf("2: Locking mutex\n"); 57*57718be8SEnji Cooper pthread_mutex_lock(&mutex); 58*57718be8SEnji Cooper printf("2: Got mutex. *param = %d\n", *param); 59*57718be8SEnji Cooper ATF_REQUIRE_EQ(*param, 20); 60*57718be8SEnji Cooper (*param)++; 61*57718be8SEnji Cooper 62*57718be8SEnji Cooper pthread_mutex_unlock(&mutex); 63*57718be8SEnji Cooper 64*57718be8SEnji Cooper return param; 65*57718be8SEnji Cooper } 66*57718be8SEnji Cooper 67*57718be8SEnji Cooper ATF_TC(mutex1); 68*57718be8SEnji Cooper ATF_TC_HEAD(mutex1, tc) 69*57718be8SEnji Cooper { 70*57718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Checks mutexes"); 71*57718be8SEnji Cooper } 72*57718be8SEnji Cooper ATF_TC_BODY(mutex1, tc) 73*57718be8SEnji Cooper { 74*57718be8SEnji Cooper int x; 75*57718be8SEnji Cooper pthread_t new; 76*57718be8SEnji Cooper void *joinval; 77*57718be8SEnji Cooper 78*57718be8SEnji Cooper printf("1: Mutex-test 1\n"); 79*57718be8SEnji Cooper 80*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_init(&mutex, NULL)); 81*57718be8SEnji Cooper x = 1; 82*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_lock(&mutex)); 83*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_create(&new, NULL, mutex1_threadfunc, &x)); 84*57718be8SEnji Cooper printf("1: Before changing the value.\n"); 85*57718be8SEnji Cooper sleep(2); 86*57718be8SEnji Cooper x = 20; 87*57718be8SEnji Cooper printf("1: Before releasing the mutex.\n"); 88*57718be8SEnji Cooper sleep(2); 89*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex)); 90*57718be8SEnji Cooper printf("1: After releasing the mutex.\n"); 91*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_join(new, &joinval)); 92*57718be8SEnji Cooper 93*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_lock(&mutex)); 94*57718be8SEnji Cooper printf("1: Thread joined. X was %d. Return value (int) was %d\n", 95*57718be8SEnji Cooper x, *(int *)joinval); 96*57718be8SEnji Cooper ATF_REQUIRE_EQ(x, 21); 97*57718be8SEnji Cooper ATF_REQUIRE_EQ(*(int *)joinval, 21); 98*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex)); 99*57718be8SEnji Cooper } 100*57718be8SEnji Cooper 101*57718be8SEnji Cooper static void * 102*57718be8SEnji Cooper mutex2_threadfunc(void *arg) 103*57718be8SEnji Cooper { 104*57718be8SEnji Cooper long count = *(int *)arg; 105*57718be8SEnji Cooper 106*57718be8SEnji Cooper printf("2: Second thread (%p). Count is %ld\n", pthread_self(), count); 107*57718be8SEnji Cooper 108*57718be8SEnji Cooper while (count--) { 109*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_lock(&mutex)); 110*57718be8SEnji Cooper global_x++; 111*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex)); 112*57718be8SEnji Cooper } 113*57718be8SEnji Cooper 114*57718be8SEnji Cooper return (void *)count; 115*57718be8SEnji Cooper } 116*57718be8SEnji Cooper 117*57718be8SEnji Cooper ATF_TC(mutex2); 118*57718be8SEnji Cooper ATF_TC_HEAD(mutex2, tc) 119*57718be8SEnji Cooper { 120*57718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Checks mutexes"); 121*57718be8SEnji Cooper #if defined(__powerpc__) 122*57718be8SEnji Cooper atf_tc_set_md_var(tc, "timeout", "40"); 123*57718be8SEnji Cooper #endif 124*57718be8SEnji Cooper } 125*57718be8SEnji Cooper ATF_TC_BODY(mutex2, tc) 126*57718be8SEnji Cooper { 127*57718be8SEnji Cooper int count, count2; 128*57718be8SEnji Cooper pthread_t new; 129*57718be8SEnji Cooper void *joinval; 130*57718be8SEnji Cooper 131*57718be8SEnji Cooper printf("1: Mutex-test 2\n"); 132*57718be8SEnji Cooper 133*57718be8SEnji Cooper #if defined(__powerpc__) 134*57718be8SEnji Cooper atf_tc_expect_timeout("PR port-powerpc/44387"); 135*57718be8SEnji Cooper #endif 136*57718be8SEnji Cooper 137*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_init(&mutex, NULL)); 138*57718be8SEnji Cooper 139*57718be8SEnji Cooper global_x = 0; 140*57718be8SEnji Cooper count = count2 = 10000000; 141*57718be8SEnji Cooper 142*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_lock(&mutex)); 143*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_create(&new, NULL, mutex2_threadfunc, &count2)); 144*57718be8SEnji Cooper 145*57718be8SEnji Cooper printf("1: Thread %p\n", pthread_self()); 146*57718be8SEnji Cooper 147*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex)); 148*57718be8SEnji Cooper 149*57718be8SEnji Cooper while (count--) { 150*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_lock(&mutex)); 151*57718be8SEnji Cooper global_x++; 152*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex)); 153*57718be8SEnji Cooper } 154*57718be8SEnji Cooper 155*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_join(new, &joinval)); 156*57718be8SEnji Cooper 157*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_lock(&mutex)); 158*57718be8SEnji Cooper printf("1: Thread joined. X was %d. Return value (long) was %ld\n", 159*57718be8SEnji Cooper global_x, (long)joinval); 160*57718be8SEnji Cooper ATF_REQUIRE_EQ(global_x, 20000000); 161*57718be8SEnji Cooper 162*57718be8SEnji Cooper #if defined(__powerpc__) 163*57718be8SEnji Cooper /* XXX force a timeout in ppc case since an un-triggered race 164*57718be8SEnji Cooper otherwise looks like a "failure" */ 165*57718be8SEnji Cooper /* We sleep for longer than the timeout to make ATF not 166*57718be8SEnji Cooper complain about unexpected success */ 167*57718be8SEnji Cooper sleep(41); 168*57718be8SEnji Cooper #endif 169*57718be8SEnji Cooper } 170*57718be8SEnji Cooper 171*57718be8SEnji Cooper static void * 172*57718be8SEnji Cooper mutex3_threadfunc(void *arg) 173*57718be8SEnji Cooper { 174*57718be8SEnji Cooper long count = *(int *)arg; 175*57718be8SEnji Cooper 176*57718be8SEnji Cooper printf("2: Second thread (%p). Count is %ld\n", pthread_self(), count); 177*57718be8SEnji Cooper 178*57718be8SEnji Cooper while (count--) { 179*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_lock(&static_mutex)); 180*57718be8SEnji Cooper global_x++; 181*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex)); 182*57718be8SEnji Cooper } 183*57718be8SEnji Cooper 184*57718be8SEnji Cooper return (void *)count; 185*57718be8SEnji Cooper } 186*57718be8SEnji Cooper 187*57718be8SEnji Cooper ATF_TC(mutex3); 188*57718be8SEnji Cooper ATF_TC_HEAD(mutex3, tc) 189*57718be8SEnji Cooper { 190*57718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Checks mutexes using a static " 191*57718be8SEnji Cooper "initializer"); 192*57718be8SEnji Cooper #if defined(__powerpc__) 193*57718be8SEnji Cooper atf_tc_set_md_var(tc, "timeout", "40"); 194*57718be8SEnji Cooper #endif 195*57718be8SEnji Cooper } 196*57718be8SEnji Cooper ATF_TC_BODY(mutex3, tc) 197*57718be8SEnji Cooper { 198*57718be8SEnji Cooper int count, count2; 199*57718be8SEnji Cooper pthread_t new; 200*57718be8SEnji Cooper void *joinval; 201*57718be8SEnji Cooper 202*57718be8SEnji Cooper printf("1: Mutex-test 3\n"); 203*57718be8SEnji Cooper 204*57718be8SEnji Cooper #if defined(__powerpc__) 205*57718be8SEnji Cooper atf_tc_expect_timeout("PR port-powerpc/44387"); 206*57718be8SEnji Cooper #endif 207*57718be8SEnji Cooper 208*57718be8SEnji Cooper global_x = 0; 209*57718be8SEnji Cooper count = count2 = 10000000; 210*57718be8SEnji Cooper 211*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_lock(&static_mutex)); 212*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_create(&new, NULL, mutex3_threadfunc, &count2)); 213*57718be8SEnji Cooper 214*57718be8SEnji Cooper printf("1: Thread %p\n", pthread_self()); 215*57718be8SEnji Cooper 216*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex)); 217*57718be8SEnji Cooper 218*57718be8SEnji Cooper while (count--) { 219*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_lock(&static_mutex)); 220*57718be8SEnji Cooper global_x++; 221*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex)); 222*57718be8SEnji Cooper } 223*57718be8SEnji Cooper 224*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_join(new, &joinval)); 225*57718be8SEnji Cooper 226*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_lock(&static_mutex)); 227*57718be8SEnji Cooper printf("1: Thread joined. X was %d. Return value (long) was %ld\n", 228*57718be8SEnji Cooper global_x, (long)joinval); 229*57718be8SEnji Cooper ATF_REQUIRE_EQ(global_x, 20000000); 230*57718be8SEnji Cooper 231*57718be8SEnji Cooper #if defined(__powerpc__) 232*57718be8SEnji Cooper /* XXX force a timeout in ppc case since an un-triggered race 233*57718be8SEnji Cooper otherwise looks like a "failure" */ 234*57718be8SEnji Cooper /* We sleep for longer than the timeout to make ATF not 235*57718be8SEnji Cooper complain about unexpected success */ 236*57718be8SEnji Cooper sleep(41); 237*57718be8SEnji Cooper #endif 238*57718be8SEnji Cooper } 239*57718be8SEnji Cooper 240*57718be8SEnji Cooper static void * 241*57718be8SEnji Cooper mutex4_threadfunc(void *arg) 242*57718be8SEnji Cooper { 243*57718be8SEnji Cooper int *param; 244*57718be8SEnji Cooper 245*57718be8SEnji Cooper printf("2: Second thread.\n"); 246*57718be8SEnji Cooper 247*57718be8SEnji Cooper param = arg; 248*57718be8SEnji Cooper printf("2: Locking mutex\n"); 249*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_lock(&mutex)); 250*57718be8SEnji Cooper printf("2: Got mutex. *param = %d\n", *param); 251*57718be8SEnji Cooper (*param)++; 252*57718be8SEnji Cooper 253*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex)); 254*57718be8SEnji Cooper 255*57718be8SEnji Cooper return param; 256*57718be8SEnji Cooper } 257*57718be8SEnji Cooper 258*57718be8SEnji Cooper ATF_TC(mutex4); 259*57718be8SEnji Cooper ATF_TC_HEAD(mutex4, tc) 260*57718be8SEnji Cooper { 261*57718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Checks mutexes"); 262*57718be8SEnji Cooper } 263*57718be8SEnji Cooper ATF_TC_BODY(mutex4, tc) 264*57718be8SEnji Cooper { 265*57718be8SEnji Cooper int x; 266*57718be8SEnji Cooper pthread_t new; 267*57718be8SEnji Cooper pthread_mutexattr_t mattr; 268*57718be8SEnji Cooper void *joinval; 269*57718be8SEnji Cooper 270*57718be8SEnji Cooper printf("1: Mutex-test 4\n"); 271*57718be8SEnji Cooper 272*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutexattr_init(&mattr)); 273*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_RECURSIVE)); 274*57718be8SEnji Cooper 275*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_init(&mutex, &mattr)); 276*57718be8SEnji Cooper 277*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutexattr_destroy(&mattr)); 278*57718be8SEnji Cooper 279*57718be8SEnji Cooper x = 1; 280*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_lock(&mutex)); 281*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_create(&new, NULL, mutex4_threadfunc, &x)); 282*57718be8SEnji Cooper 283*57718be8SEnji Cooper printf("1: Before recursively acquiring the mutex.\n"); 284*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_lock(&mutex)); 285*57718be8SEnji Cooper 286*57718be8SEnji Cooper printf("1: Before releasing the mutex once.\n"); 287*57718be8SEnji Cooper sleep(2); 288*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex)); 289*57718be8SEnji Cooper printf("1: After releasing the mutex once.\n"); 290*57718be8SEnji Cooper 291*57718be8SEnji Cooper x = 20; 292*57718be8SEnji Cooper 293*57718be8SEnji Cooper printf("1: Before releasing the mutex twice.\n"); 294*57718be8SEnji Cooper sleep(2); 295*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex)); 296*57718be8SEnji Cooper printf("1: After releasing the mutex twice.\n"); 297*57718be8SEnji Cooper 298*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_join(new, &joinval)); 299*57718be8SEnji Cooper 300*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_lock(&mutex)); 301*57718be8SEnji Cooper printf("1: Thread joined. X was %d. Return value (int) was %d\n", 302*57718be8SEnji Cooper x, *(int *)joinval); 303*57718be8SEnji Cooper ATF_REQUIRE_EQ(x, 21); 304*57718be8SEnji Cooper ATF_REQUIRE_EQ(*(int *)joinval, 21); 305*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex)); 306*57718be8SEnji Cooper } 307*57718be8SEnji Cooper 308*57718be8SEnji Cooper ATF_TP_ADD_TCS(tp) 309*57718be8SEnji Cooper { 310*57718be8SEnji Cooper ATF_TP_ADD_TC(tp, mutex1); 311*57718be8SEnji Cooper ATF_TP_ADD_TC(tp, mutex2); 312*57718be8SEnji Cooper ATF_TP_ADD_TC(tp, mutex3); 313*57718be8SEnji Cooper ATF_TP_ADD_TC(tp, mutex4); 314*57718be8SEnji Cooper 315*57718be8SEnji Cooper return atf_no_error(); 316*57718be8SEnji Cooper } 317