1*57718be8SEnji Cooper /* $NetBSD: t_cond.c,v 1.6 2014/09/03 16:23:24 gson 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_cond.c,v 1.6 2014/09/03 16:23:24 gson Exp $"); 33*57718be8SEnji Cooper 34*57718be8SEnji Cooper #include <sys/time.h> 35*57718be8SEnji Cooper 36*57718be8SEnji Cooper #include <errno.h> 37*57718be8SEnji Cooper #include <pthread.h> 38*57718be8SEnji Cooper #include <stdio.h> 39*57718be8SEnji Cooper #include <unistd.h> 40*57718be8SEnji Cooper 41*57718be8SEnji Cooper #include <atf-c.h> 42*57718be8SEnji Cooper 43*57718be8SEnji Cooper #include "h_common.h" 44*57718be8SEnji Cooper 45*57718be8SEnji Cooper static pthread_mutex_t mutex; 46*57718be8SEnji Cooper static pthread_cond_t cond; 47*57718be8SEnji Cooper static pthread_mutex_t static_mutex = PTHREAD_MUTEX_INITIALIZER; 48*57718be8SEnji Cooper static pthread_cond_t static_cond = PTHREAD_COND_INITIALIZER; 49*57718be8SEnji Cooper static int count, share, toggle, total; 50*57718be8SEnji Cooper 51*57718be8SEnji Cooper static void * 52*57718be8SEnji Cooper signal_delay_wait_threadfunc(void *arg) 53*57718be8SEnji Cooper { 54*57718be8SEnji Cooper int *shared = (int *) arg; 55*57718be8SEnji Cooper 56*57718be8SEnji Cooper printf("2: Second thread.\n"); 57*57718be8SEnji Cooper 58*57718be8SEnji Cooper printf("2: Locking mutex\n"); 59*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_lock(&mutex)); 60*57718be8SEnji Cooper printf("2: Got mutex.\n"); 61*57718be8SEnji Cooper printf("Shared value: %d. Changing to 0.\n", *shared); 62*57718be8SEnji Cooper *shared = 0; 63*57718be8SEnji Cooper 64*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex)); 65*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_cond_signal(&cond)); 66*57718be8SEnji Cooper 67*57718be8SEnji Cooper return NULL; 68*57718be8SEnji Cooper } 69*57718be8SEnji Cooper 70*57718be8SEnji Cooper ATF_TC(signal_delay_wait); 71*57718be8SEnji Cooper ATF_TC_HEAD(signal_delay_wait, tc) 72*57718be8SEnji Cooper { 73*57718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Checks condition variables"); 74*57718be8SEnji Cooper } 75*57718be8SEnji Cooper ATF_TC_BODY(signal_delay_wait, tc) 76*57718be8SEnji Cooper { 77*57718be8SEnji Cooper pthread_t new; 78*57718be8SEnji Cooper void *joinval; 79*57718be8SEnji Cooper int sharedval; 80*57718be8SEnji Cooper 81*57718be8SEnji Cooper printf("1: condition variable test 1\n"); 82*57718be8SEnji Cooper 83*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_init(&mutex, NULL)); 84*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_cond_init(&cond, NULL)); 85*57718be8SEnji Cooper 86*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_lock(&mutex)); 87*57718be8SEnji Cooper 88*57718be8SEnji Cooper sharedval = 1; 89*57718be8SEnji Cooper 90*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_create(&new, NULL, signal_delay_wait_threadfunc, 91*57718be8SEnji Cooper &sharedval)); 92*57718be8SEnji Cooper 93*57718be8SEnji Cooper printf("1: Before waiting.\n"); 94*57718be8SEnji Cooper do { 95*57718be8SEnji Cooper sleep(2); 96*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_cond_wait(&cond, &mutex)); 97*57718be8SEnji Cooper printf("1: After waiting, in loop.\n"); 98*57718be8SEnji Cooper } while (sharedval != 0); 99*57718be8SEnji Cooper 100*57718be8SEnji Cooper printf("1: After the loop.\n"); 101*57718be8SEnji Cooper 102*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex)); 103*57718be8SEnji Cooper 104*57718be8SEnji Cooper printf("1: After releasing the mutex.\n"); 105*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_join(new, &joinval)); 106*57718be8SEnji Cooper 107*57718be8SEnji Cooper printf("1: Thread joined.\n"); 108*57718be8SEnji Cooper } 109*57718be8SEnji Cooper 110*57718be8SEnji Cooper static void * 111*57718be8SEnji Cooper signal_before_unlock_threadfunc(void *arg) 112*57718be8SEnji Cooper { 113*57718be8SEnji Cooper int *shared = (int *) arg; 114*57718be8SEnji Cooper 115*57718be8SEnji Cooper printf("2: Second thread.\n"); 116*57718be8SEnji Cooper 117*57718be8SEnji Cooper printf("2: Locking mutex\n"); 118*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_lock(&mutex)); 119*57718be8SEnji Cooper printf("2: Got mutex.\n"); 120*57718be8SEnji Cooper printf("Shared value: %d. Changing to 0.\n", *shared); 121*57718be8SEnji Cooper *shared = 0; 122*57718be8SEnji Cooper 123*57718be8SEnji Cooper /* Signal first, then unlock, for a different test than #1. */ 124*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_cond_signal(&cond)); 125*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex)); 126*57718be8SEnji Cooper 127*57718be8SEnji Cooper return NULL; 128*57718be8SEnji Cooper } 129*57718be8SEnji Cooper 130*57718be8SEnji Cooper ATF_TC(signal_before_unlock); 131*57718be8SEnji Cooper ATF_TC_HEAD(signal_before_unlock, tc) 132*57718be8SEnji Cooper { 133*57718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", 134*57718be8SEnji Cooper "Checks condition variables: signal before unlocking mutex"); 135*57718be8SEnji Cooper } 136*57718be8SEnji Cooper ATF_TC_BODY(signal_before_unlock, tc) 137*57718be8SEnji Cooper { 138*57718be8SEnji Cooper pthread_t new; 139*57718be8SEnji Cooper void *joinval; 140*57718be8SEnji Cooper int sharedval; 141*57718be8SEnji Cooper 142*57718be8SEnji Cooper printf("1: condition variable test 2\n"); 143*57718be8SEnji Cooper 144*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_init(&mutex, NULL)); 145*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_cond_init(&cond, NULL)); 146*57718be8SEnji Cooper 147*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_lock(&mutex)); 148*57718be8SEnji Cooper 149*57718be8SEnji Cooper sharedval = 1; 150*57718be8SEnji Cooper 151*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_create(&new, NULL, 152*57718be8SEnji Cooper signal_before_unlock_threadfunc, &sharedval)); 153*57718be8SEnji Cooper 154*57718be8SEnji Cooper printf("1: Before waiting.\n"); 155*57718be8SEnji Cooper do { 156*57718be8SEnji Cooper sleep(2); 157*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_cond_wait(&cond, &mutex)); 158*57718be8SEnji Cooper printf("1: After waiting, in loop.\n"); 159*57718be8SEnji Cooper } while (sharedval != 0); 160*57718be8SEnji Cooper 161*57718be8SEnji Cooper printf("1: After the loop.\n"); 162*57718be8SEnji Cooper 163*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex)); 164*57718be8SEnji Cooper 165*57718be8SEnji Cooper printf("1: After releasing the mutex.\n"); 166*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_join(new, &joinval)); 167*57718be8SEnji Cooper 168*57718be8SEnji Cooper printf("1: Thread joined.\n"); 169*57718be8SEnji Cooper } 170*57718be8SEnji Cooper 171*57718be8SEnji Cooper static void * 172*57718be8SEnji Cooper signal_before_unlock_static_init_threadfunc(void *arg) 173*57718be8SEnji Cooper { 174*57718be8SEnji Cooper int *shared = (int *) arg; 175*57718be8SEnji Cooper 176*57718be8SEnji Cooper printf("2: Second thread.\n"); 177*57718be8SEnji Cooper 178*57718be8SEnji Cooper printf("2: Locking mutex\n"); 179*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_lock(&static_mutex)); 180*57718be8SEnji Cooper printf("2: Got mutex.\n"); 181*57718be8SEnji Cooper printf("Shared value: %d. Changing to 0.\n", *shared); 182*57718be8SEnji Cooper *shared = 0; 183*57718be8SEnji Cooper 184*57718be8SEnji Cooper /* Signal first, then unlock, for a different test than #1. */ 185*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_cond_signal(&static_cond)); 186*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex)); 187*57718be8SEnji Cooper 188*57718be8SEnji Cooper return NULL; 189*57718be8SEnji Cooper } 190*57718be8SEnji Cooper 191*57718be8SEnji Cooper ATF_TC(signal_before_unlock_static_init); 192*57718be8SEnji Cooper ATF_TC_HEAD(signal_before_unlock_static_init, tc) 193*57718be8SEnji Cooper { 194*57718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", 195*57718be8SEnji Cooper "Checks condition variables: signal before unlocking " 196*57718be8SEnji Cooper "mutex, use static initializers"); 197*57718be8SEnji Cooper } 198*57718be8SEnji Cooper ATF_TC_BODY(signal_before_unlock_static_init, tc) 199*57718be8SEnji Cooper { 200*57718be8SEnji Cooper pthread_t new; 201*57718be8SEnji Cooper void *joinval; 202*57718be8SEnji Cooper int sharedval; 203*57718be8SEnji Cooper 204*57718be8SEnji Cooper printf("1: condition variable test 3\n"); 205*57718be8SEnji Cooper 206*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_lock(&static_mutex)); 207*57718be8SEnji Cooper 208*57718be8SEnji Cooper sharedval = 1; 209*57718be8SEnji Cooper 210*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_create(&new, NULL, 211*57718be8SEnji Cooper signal_before_unlock_static_init_threadfunc, &sharedval)); 212*57718be8SEnji Cooper 213*57718be8SEnji Cooper printf("1: Before waiting.\n"); 214*57718be8SEnji Cooper do { 215*57718be8SEnji Cooper sleep(2); 216*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_cond_wait(&static_cond, &static_mutex)); 217*57718be8SEnji Cooper printf("1: After waiting, in loop.\n"); 218*57718be8SEnji Cooper } while (sharedval != 0); 219*57718be8SEnji Cooper 220*57718be8SEnji Cooper printf("1: After the loop.\n"); 221*57718be8SEnji Cooper 222*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex)); 223*57718be8SEnji Cooper 224*57718be8SEnji Cooper printf("1: After releasing the mutex.\n"); 225*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_join(new, &joinval)); 226*57718be8SEnji Cooper 227*57718be8SEnji Cooper printf("1: Thread joined.\n"); 228*57718be8SEnji Cooper } 229*57718be8SEnji Cooper 230*57718be8SEnji Cooper static void * 231*57718be8SEnji Cooper signal_wait_race_threadfunc(void *arg) 232*57718be8SEnji Cooper { 233*57718be8SEnji Cooper printf("2: Second thread.\n"); 234*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_lock(&static_mutex)); 235*57718be8SEnji Cooper printf("2: Before the loop.\n"); 236*57718be8SEnji Cooper while (count>0) { 237*57718be8SEnji Cooper count--; 238*57718be8SEnji Cooper total++; 239*57718be8SEnji Cooper toggle = 0; 240*57718be8SEnji Cooper /* printf("2: Before signal %d.\n", count); */ 241*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_cond_signal(&static_cond)); 242*57718be8SEnji Cooper do { 243*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_cond_wait(&static_cond, 244*57718be8SEnji Cooper &static_mutex)); 245*57718be8SEnji Cooper } while (toggle != 1); 246*57718be8SEnji Cooper } 247*57718be8SEnji Cooper printf("2: After the loop.\n"); 248*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex)); 249*57718be8SEnji Cooper 250*57718be8SEnji Cooper return NULL; 251*57718be8SEnji Cooper } 252*57718be8SEnji Cooper 253*57718be8SEnji Cooper ATF_TC(signal_wait_race); 254*57718be8SEnji Cooper ATF_TC_HEAD(signal_wait_race, tc) 255*57718be8SEnji Cooper { 256*57718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Checks condition variables"); 257*57718be8SEnji Cooper } 258*57718be8SEnji Cooper ATF_TC_BODY(signal_wait_race, tc) 259*57718be8SEnji Cooper { 260*57718be8SEnji Cooper pthread_t new; 261*57718be8SEnji Cooper void *joinval; 262*57718be8SEnji Cooper int sharedval; 263*57718be8SEnji Cooper 264*57718be8SEnji Cooper printf("1: condition variable test 4\n"); 265*57718be8SEnji Cooper 266*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_lock(&static_mutex)); 267*57718be8SEnji Cooper 268*57718be8SEnji Cooper count = 50000; 269*57718be8SEnji Cooper toggle = 0; 270*57718be8SEnji Cooper 271*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_create(&new, NULL, signal_wait_race_threadfunc, 272*57718be8SEnji Cooper &sharedval)); 273*57718be8SEnji Cooper 274*57718be8SEnji Cooper printf("1: Before waiting.\n"); 275*57718be8SEnji Cooper while (count>0) { 276*57718be8SEnji Cooper count--; 277*57718be8SEnji Cooper total++; 278*57718be8SEnji Cooper toggle = 1; 279*57718be8SEnji Cooper /* printf("1: Before signal %d.\n", count); */ 280*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_cond_signal(&static_cond)); 281*57718be8SEnji Cooper do { 282*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_cond_wait(&static_cond, 283*57718be8SEnji Cooper &static_mutex)); 284*57718be8SEnji Cooper } while (toggle != 0); 285*57718be8SEnji Cooper } 286*57718be8SEnji Cooper printf("1: After the loop.\n"); 287*57718be8SEnji Cooper 288*57718be8SEnji Cooper toggle = 1; 289*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex)); 290*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_cond_signal(&static_cond)); 291*57718be8SEnji Cooper 292*57718be8SEnji Cooper printf("1: After releasing the mutex.\n"); 293*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_join(new, &joinval)); 294*57718be8SEnji Cooper 295*57718be8SEnji Cooper printf("1: Thread joined. Final count = %d, total = %d\n", 296*57718be8SEnji Cooper count, total); 297*57718be8SEnji Cooper 298*57718be8SEnji Cooper ATF_REQUIRE_EQ(count, 0); 299*57718be8SEnji Cooper ATF_REQUIRE_EQ(total, 50000); 300*57718be8SEnji Cooper } 301*57718be8SEnji Cooper 302*57718be8SEnji Cooper static void * 303*57718be8SEnji Cooper pthread_cond_timedwait_func(void *arg) 304*57718be8SEnji Cooper { 305*57718be8SEnji Cooper struct timespec ts; 306*57718be8SEnji Cooper size_t i = 0; 307*57718be8SEnji Cooper int rv; 308*57718be8SEnji Cooper 309*57718be8SEnji Cooper for (;;) { 310*57718be8SEnji Cooper 311*57718be8SEnji Cooper if (i++ >= 10000) 312*57718be8SEnji Cooper pthread_exit(NULL); 313*57718be8SEnji Cooper 314*57718be8SEnji Cooper (void)memset(&ts, 0, sizeof(struct timespec)); 315*57718be8SEnji Cooper 316*57718be8SEnji Cooper ATF_REQUIRE(clock_gettime(CLOCK_REALTIME, &ts) == 0); 317*57718be8SEnji Cooper 318*57718be8SEnji Cooper /* 319*57718be8SEnji Cooper * Set to one second in the past: 320*57718be8SEnji Cooper * pthread_cond_timedwait(3) should 321*57718be8SEnji Cooper * return ETIMEDOUT immediately. 322*57718be8SEnji Cooper */ 323*57718be8SEnji Cooper ts.tv_sec = ts.tv_sec - 1; 324*57718be8SEnji Cooper 325*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_lock(&static_mutex)); 326*57718be8SEnji Cooper rv = pthread_cond_timedwait(&static_cond, &static_mutex, &ts); 327*57718be8SEnji Cooper 328*57718be8SEnji Cooper /* 329*57718be8SEnji Cooper * Sometimes we catch ESRCH. 330*57718be8SEnji Cooper * This should never happen. 331*57718be8SEnji Cooper */ 332*57718be8SEnji Cooper ATF_REQUIRE(rv == ETIMEDOUT); 333*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex)); 334*57718be8SEnji Cooper } 335*57718be8SEnji Cooper } 336*57718be8SEnji Cooper 337*57718be8SEnji Cooper ATF_TC(cond_timedwait_race); 338*57718be8SEnji Cooper ATF_TC_HEAD(cond_timedwait_race, tc) 339*57718be8SEnji Cooper { 340*57718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Test pthread_cond_timedwait(3)"); 341*57718be8SEnji Cooper 342*57718be8SEnji Cooper } 343*57718be8SEnji Cooper ATF_TC_BODY(cond_timedwait_race, tc) 344*57718be8SEnji Cooper { 345*57718be8SEnji Cooper pthread_t tid[64]; 346*57718be8SEnji Cooper size_t i; 347*57718be8SEnji Cooper 348*57718be8SEnji Cooper for (i = 0; i < __arraycount(tid); i++) { 349*57718be8SEnji Cooper 350*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_create(&tid[i], NULL, 351*57718be8SEnji Cooper pthread_cond_timedwait_func, NULL)); 352*57718be8SEnji Cooper } 353*57718be8SEnji Cooper 354*57718be8SEnji Cooper for (i = 0; i < __arraycount(tid); i++) { 355*57718be8SEnji Cooper 356*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_join(tid[i], NULL)); 357*57718be8SEnji Cooper } 358*57718be8SEnji Cooper } 359*57718be8SEnji Cooper 360*57718be8SEnji Cooper static void * 361*57718be8SEnji Cooper broadcast_threadfunc(void *arg) 362*57718be8SEnji Cooper { 363*57718be8SEnji Cooper printf("2: Second thread.\n"); 364*57718be8SEnji Cooper 365*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_lock(&static_mutex)); 366*57718be8SEnji Cooper while (count>0) { 367*57718be8SEnji Cooper count--; 368*57718be8SEnji Cooper total++; 369*57718be8SEnji Cooper toggle = 0; 370*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_cond_signal(&static_cond)); 371*57718be8SEnji Cooper do { 372*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_cond_wait(&static_cond, 373*57718be8SEnji Cooper &static_mutex)); 374*57718be8SEnji Cooper } while (toggle != 1); 375*57718be8SEnji Cooper } 376*57718be8SEnji Cooper printf("2: After the loop.\n"); 377*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex)); 378*57718be8SEnji Cooper 379*57718be8SEnji Cooper return NULL; 380*57718be8SEnji Cooper } 381*57718be8SEnji Cooper 382*57718be8SEnji Cooper 383*57718be8SEnji Cooper ATF_TC(broadcast); 384*57718be8SEnji Cooper ATF_TC_HEAD(broadcast, tc) 385*57718be8SEnji Cooper { 386*57718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", 387*57718be8SEnji Cooper "Checks condition variables: use pthread_cond_broadcast()"); 388*57718be8SEnji Cooper } 389*57718be8SEnji Cooper ATF_TC_BODY(broadcast, tc) 390*57718be8SEnji Cooper { 391*57718be8SEnji Cooper pthread_t new; 392*57718be8SEnji Cooper void *joinval; 393*57718be8SEnji Cooper int sharedval; 394*57718be8SEnji Cooper 395*57718be8SEnji Cooper printf("1: condition variable test 5\n"); 396*57718be8SEnji Cooper 397*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_lock(&static_mutex)); 398*57718be8SEnji Cooper 399*57718be8SEnji Cooper count = 50000; 400*57718be8SEnji Cooper toggle = 0; 401*57718be8SEnji Cooper 402*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_create(&new, NULL, broadcast_threadfunc, 403*57718be8SEnji Cooper &sharedval)); 404*57718be8SEnji Cooper 405*57718be8SEnji Cooper printf("1: Before waiting.\n"); 406*57718be8SEnji Cooper while (count>0) { 407*57718be8SEnji Cooper count--; 408*57718be8SEnji Cooper total++; 409*57718be8SEnji Cooper toggle = 1; 410*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_cond_broadcast(&static_cond)); 411*57718be8SEnji Cooper do { 412*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_cond_wait(&static_cond, 413*57718be8SEnji Cooper &static_mutex)); 414*57718be8SEnji Cooper } while (toggle != 0); 415*57718be8SEnji Cooper } 416*57718be8SEnji Cooper printf("1: After the loop.\n"); 417*57718be8SEnji Cooper 418*57718be8SEnji Cooper toggle = 1; 419*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex)); 420*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_cond_signal(&static_cond)); 421*57718be8SEnji Cooper 422*57718be8SEnji Cooper printf("1: After releasing the mutex.\n"); 423*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_join(new, &joinval)); 424*57718be8SEnji Cooper 425*57718be8SEnji Cooper printf("1: Thread joined. Final count = %d, total = %d\n", count, 426*57718be8SEnji Cooper total); 427*57718be8SEnji Cooper 428*57718be8SEnji Cooper ATF_REQUIRE_EQ(count, 0); 429*57718be8SEnji Cooper ATF_REQUIRE_EQ(total, 50000); 430*57718be8SEnji Cooper } 431*57718be8SEnji Cooper 432*57718be8SEnji Cooper static void * 433*57718be8SEnji Cooper bogus_timedwaits_threadfunc(void *arg) 434*57718be8SEnji Cooper { 435*57718be8SEnji Cooper return NULL; 436*57718be8SEnji Cooper } 437*57718be8SEnji Cooper 438*57718be8SEnji Cooper ATF_TC(bogus_timedwaits); 439*57718be8SEnji Cooper ATF_TC_HEAD(bogus_timedwaits, tc) 440*57718be8SEnji Cooper { 441*57718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", 442*57718be8SEnji Cooper "Checks condition variables: bogus timedwaits"); 443*57718be8SEnji Cooper } 444*57718be8SEnji Cooper ATF_TC_BODY(bogus_timedwaits, tc) 445*57718be8SEnji Cooper { 446*57718be8SEnji Cooper pthread_t new; 447*57718be8SEnji Cooper struct timespec ts; 448*57718be8SEnji Cooper struct timeval tv; 449*57718be8SEnji Cooper 450*57718be8SEnji Cooper printf("condition variable test 6: bogus timedwaits\n"); 451*57718be8SEnji Cooper 452*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_lock(&static_mutex)); 453*57718be8SEnji Cooper 454*57718be8SEnji Cooper printf("unthreaded test (past)\n"); 455*57718be8SEnji Cooper gettimeofday(&tv, NULL); 456*57718be8SEnji Cooper tv.tv_sec -= 2; /* Place the time in the past */ 457*57718be8SEnji Cooper TIMEVAL_TO_TIMESPEC(&tv, &ts); 458*57718be8SEnji Cooper 459*57718be8SEnji Cooper ATF_REQUIRE_EQ_MSG(pthread_cond_timedwait(&static_cond, &static_mutex, 460*57718be8SEnji Cooper &ts), ETIMEDOUT, "pthread_cond_timedwait() (unthreaded) in the " 461*57718be8SEnji Cooper "past"); 462*57718be8SEnji Cooper 463*57718be8SEnji Cooper printf("unthreaded test (zero time)\n"); 464*57718be8SEnji Cooper tv.tv_sec = 0; 465*57718be8SEnji Cooper tv.tv_usec = 0; 466*57718be8SEnji Cooper TIMEVAL_TO_TIMESPEC(&tv, &ts); 467*57718be8SEnji Cooper 468*57718be8SEnji Cooper ATF_REQUIRE_EQ_MSG(pthread_cond_timedwait(&static_cond, &static_mutex, 469*57718be8SEnji Cooper &ts), ETIMEDOUT, "pthread_cond_timedwait() (unthreaded) with zero " 470*57718be8SEnji Cooper "time"); 471*57718be8SEnji Cooper 472*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_create(&new, NULL, bogus_timedwaits_threadfunc, 473*57718be8SEnji Cooper NULL)); 474*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_join(new, NULL)); 475*57718be8SEnji Cooper 476*57718be8SEnji Cooper printf("threaded test\n"); 477*57718be8SEnji Cooper gettimeofday(&tv, NULL); 478*57718be8SEnji Cooper tv.tv_sec -= 2; /* Place the time in the past */ 479*57718be8SEnji Cooper TIMEVAL_TO_TIMESPEC(&tv, &ts); 480*57718be8SEnji Cooper 481*57718be8SEnji Cooper ATF_REQUIRE_EQ_MSG(pthread_cond_timedwait(&static_cond, &static_mutex, 482*57718be8SEnji Cooper &ts), ETIMEDOUT, "pthread_cond_timedwait() (threaded) in the past"); 483*57718be8SEnji Cooper 484*57718be8SEnji Cooper printf("threaded test (zero time)\n"); 485*57718be8SEnji Cooper tv.tv_sec = 0; 486*57718be8SEnji Cooper tv.tv_usec = 0; 487*57718be8SEnji Cooper TIMEVAL_TO_TIMESPEC(&tv, &ts); 488*57718be8SEnji Cooper 489*57718be8SEnji Cooper ATF_REQUIRE_EQ_MSG(pthread_cond_timedwait(&static_cond, &static_mutex, 490*57718be8SEnji Cooper &ts), ETIMEDOUT, "pthread_cond_timedwait() (threaded) with zero " 491*57718be8SEnji Cooper "time"); 492*57718be8SEnji Cooper 493*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex)); 494*57718be8SEnji Cooper } 495*57718be8SEnji Cooper 496*57718be8SEnji Cooper static void 497*57718be8SEnji Cooper unlock(void *arg) 498*57718be8SEnji Cooper { 499*57718be8SEnji Cooper pthread_mutex_unlock((pthread_mutex_t *)arg); 500*57718be8SEnji Cooper } 501*57718be8SEnji Cooper 502*57718be8SEnji Cooper static void * 503*57718be8SEnji Cooper destroy_after_cancel_threadfunc(void *arg) 504*57718be8SEnji Cooper { 505*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_lock(&mutex)); 506*57718be8SEnji Cooper 507*57718be8SEnji Cooper pthread_cleanup_push(unlock, &mutex); 508*57718be8SEnji Cooper 509*57718be8SEnji Cooper while (1) { 510*57718be8SEnji Cooper share = 1; 511*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_cond_broadcast(&cond)); 512*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_cond_wait(&cond, &mutex)); 513*57718be8SEnji Cooper } 514*57718be8SEnji Cooper 515*57718be8SEnji Cooper pthread_cleanup_pop(0); 516*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex)); 517*57718be8SEnji Cooper 518*57718be8SEnji Cooper return NULL; 519*57718be8SEnji Cooper } 520*57718be8SEnji Cooper 521*57718be8SEnji Cooper ATF_TC(destroy_after_cancel); 522*57718be8SEnji Cooper ATF_TC_HEAD(destroy_after_cancel, tc) 523*57718be8SEnji Cooper { 524*57718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Checks destroying a condition variable " 525*57718be8SEnji Cooper "after cancelling a wait"); 526*57718be8SEnji Cooper } 527*57718be8SEnji Cooper ATF_TC_BODY(destroy_after_cancel, tc) 528*57718be8SEnji Cooper { 529*57718be8SEnji Cooper pthread_t thread; 530*57718be8SEnji Cooper 531*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_init(&mutex, NULL)); 532*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_cond_init(&cond, NULL)); 533*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_lock(&mutex)); 534*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_create(&thread, NULL, 535*57718be8SEnji Cooper destroy_after_cancel_threadfunc, NULL)); 536*57718be8SEnji Cooper 537*57718be8SEnji Cooper while (share == 0) { 538*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_cond_wait(&cond, &mutex)); 539*57718be8SEnji Cooper } 540*57718be8SEnji Cooper 541*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex)); 542*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_cancel(thread)); 543*57718be8SEnji Cooper 544*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_join(thread, NULL)); 545*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_cond_destroy(&cond)); 546*57718be8SEnji Cooper 547*57718be8SEnji Cooper PTHREAD_REQUIRE(pthread_mutex_destroy(&mutex)); 548*57718be8SEnji Cooper } 549*57718be8SEnji Cooper 550*57718be8SEnji Cooper ATF_TP_ADD_TCS(tp) 551*57718be8SEnji Cooper { 552*57718be8SEnji Cooper 553*57718be8SEnji Cooper ATF_TP_ADD_TC(tp, signal_delay_wait); 554*57718be8SEnji Cooper ATF_TP_ADD_TC(tp, signal_before_unlock); 555*57718be8SEnji Cooper ATF_TP_ADD_TC(tp, signal_before_unlock_static_init); 556*57718be8SEnji Cooper ATF_TP_ADD_TC(tp, signal_wait_race); 557*57718be8SEnji Cooper ATF_TP_ADD_TC(tp, cond_timedwait_race); 558*57718be8SEnji Cooper ATF_TP_ADD_TC(tp, broadcast); 559*57718be8SEnji Cooper ATF_TP_ADD_TC(tp, bogus_timedwaits); 560*57718be8SEnji Cooper ATF_TP_ADD_TC(tp, destroy_after_cancel); 561*57718be8SEnji Cooper 562*57718be8SEnji Cooper return atf_no_error(); 563*57718be8SEnji Cooper } 564