1272343Sngie/* $NetBSD: t_cond.c,v 1.6 2014/09/03 16:23:24 gson Exp $ */ 2272343Sngie 3272343Sngie/* 4272343Sngie * Copyright (c) 2008 The NetBSD Foundation, Inc. 5272343Sngie * All rights reserved. 6272343Sngie * 7272343Sngie * Redistribution and use in source and binary forms, with or without 8272343Sngie * modification, are permitted provided that the following conditions 9272343Sngie * are met: 10272343Sngie * 1. Redistributions of source code must retain the above copyright 11272343Sngie * notice, this list of conditions and the following disclaimer. 12272343Sngie * 2. Redistributions in binary form must reproduce the above copyright 13272343Sngie * notice, this list of conditions and the following disclaimer in the 14272343Sngie * documentation and/or other materials provided with the distribution. 15272343Sngie * 16272343Sngie * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 17272343Sngie * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18272343Sngie * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19272343Sngie * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 20272343Sngie * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21272343Sngie * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22272343Sngie * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23272343Sngie * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24272343Sngie * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25272343Sngie * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26272343Sngie * POSSIBILITY OF SUCH DAMAGE. 27272343Sngie */ 28272343Sngie 29272343Sngie#include <sys/cdefs.h> 30272343Sngie__COPYRIGHT("@(#) Copyright (c) 2008\ 31272343Sngie The NetBSD Foundation, inc. All rights reserved."); 32272343Sngie__RCSID("$NetBSD: t_cond.c,v 1.6 2014/09/03 16:23:24 gson Exp $"); 33272343Sngie 34272343Sngie#include <sys/time.h> 35272343Sngie 36272343Sngie#include <errno.h> 37272343Sngie#include <pthread.h> 38272343Sngie#include <stdio.h> 39272343Sngie#include <unistd.h> 40272343Sngie 41272343Sngie#include <atf-c.h> 42272343Sngie 43272343Sngie#include "h_common.h" 44272343Sngie 45272343Sngiestatic pthread_mutex_t mutex; 46272343Sngiestatic pthread_cond_t cond; 47272343Sngiestatic pthread_mutex_t static_mutex = PTHREAD_MUTEX_INITIALIZER; 48272343Sngiestatic pthread_cond_t static_cond = PTHREAD_COND_INITIALIZER; 49272343Sngiestatic int count, share, toggle, total; 50272343Sngie 51272343Sngiestatic void * 52272343Sngiesignal_delay_wait_threadfunc(void *arg) 53272343Sngie{ 54272343Sngie int *shared = (int *) arg; 55272343Sngie 56272343Sngie printf("2: Second thread.\n"); 57272343Sngie 58272343Sngie printf("2: Locking mutex\n"); 59272343Sngie PTHREAD_REQUIRE(pthread_mutex_lock(&mutex)); 60272343Sngie printf("2: Got mutex.\n"); 61272343Sngie printf("Shared value: %d. Changing to 0.\n", *shared); 62272343Sngie *shared = 0; 63272343Sngie 64272343Sngie PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex)); 65272343Sngie PTHREAD_REQUIRE(pthread_cond_signal(&cond)); 66272343Sngie 67272343Sngie return NULL; 68272343Sngie} 69272343Sngie 70272343SngieATF_TC(signal_delay_wait); 71272343SngieATF_TC_HEAD(signal_delay_wait, tc) 72272343Sngie{ 73272343Sngie atf_tc_set_md_var(tc, "descr", "Checks condition variables"); 74272343Sngie} 75272343SngieATF_TC_BODY(signal_delay_wait, tc) 76272343Sngie{ 77272343Sngie pthread_t new; 78272343Sngie void *joinval; 79272343Sngie int sharedval; 80272343Sngie 81272343Sngie printf("1: condition variable test 1\n"); 82272343Sngie 83272343Sngie PTHREAD_REQUIRE(pthread_mutex_init(&mutex, NULL)); 84272343Sngie PTHREAD_REQUIRE(pthread_cond_init(&cond, NULL)); 85272343Sngie 86272343Sngie PTHREAD_REQUIRE(pthread_mutex_lock(&mutex)); 87272343Sngie 88272343Sngie sharedval = 1; 89272343Sngie 90272343Sngie PTHREAD_REQUIRE(pthread_create(&new, NULL, signal_delay_wait_threadfunc, 91272343Sngie &sharedval)); 92272343Sngie 93272343Sngie printf("1: Before waiting.\n"); 94272343Sngie do { 95272343Sngie sleep(2); 96272343Sngie PTHREAD_REQUIRE(pthread_cond_wait(&cond, &mutex)); 97272343Sngie printf("1: After waiting, in loop.\n"); 98272343Sngie } while (sharedval != 0); 99272343Sngie 100272343Sngie printf("1: After the loop.\n"); 101272343Sngie 102272343Sngie PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex)); 103272343Sngie 104272343Sngie printf("1: After releasing the mutex.\n"); 105272343Sngie PTHREAD_REQUIRE(pthread_join(new, &joinval)); 106272343Sngie 107272343Sngie printf("1: Thread joined.\n"); 108272343Sngie} 109272343Sngie 110272343Sngiestatic void * 111272343Sngiesignal_before_unlock_threadfunc(void *arg) 112272343Sngie{ 113272343Sngie int *shared = (int *) arg; 114272343Sngie 115272343Sngie printf("2: Second thread.\n"); 116272343Sngie 117272343Sngie printf("2: Locking mutex\n"); 118272343Sngie PTHREAD_REQUIRE(pthread_mutex_lock(&mutex)); 119272343Sngie printf("2: Got mutex.\n"); 120272343Sngie printf("Shared value: %d. Changing to 0.\n", *shared); 121272343Sngie *shared = 0; 122272343Sngie 123272343Sngie /* Signal first, then unlock, for a different test than #1. */ 124272343Sngie PTHREAD_REQUIRE(pthread_cond_signal(&cond)); 125272343Sngie PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex)); 126272343Sngie 127272343Sngie return NULL; 128272343Sngie} 129272343Sngie 130272343SngieATF_TC(signal_before_unlock); 131272343SngieATF_TC_HEAD(signal_before_unlock, tc) 132272343Sngie{ 133272343Sngie atf_tc_set_md_var(tc, "descr", 134272343Sngie "Checks condition variables: signal before unlocking mutex"); 135272343Sngie} 136272343SngieATF_TC_BODY(signal_before_unlock, tc) 137272343Sngie{ 138272343Sngie pthread_t new; 139272343Sngie void *joinval; 140272343Sngie int sharedval; 141272343Sngie 142272343Sngie printf("1: condition variable test 2\n"); 143272343Sngie 144272343Sngie PTHREAD_REQUIRE(pthread_mutex_init(&mutex, NULL)); 145272343Sngie PTHREAD_REQUIRE(pthread_cond_init(&cond, NULL)); 146272343Sngie 147272343Sngie PTHREAD_REQUIRE(pthread_mutex_lock(&mutex)); 148272343Sngie 149272343Sngie sharedval = 1; 150272343Sngie 151272343Sngie PTHREAD_REQUIRE(pthread_create(&new, NULL, 152272343Sngie signal_before_unlock_threadfunc, &sharedval)); 153272343Sngie 154272343Sngie printf("1: Before waiting.\n"); 155272343Sngie do { 156272343Sngie sleep(2); 157272343Sngie PTHREAD_REQUIRE(pthread_cond_wait(&cond, &mutex)); 158272343Sngie printf("1: After waiting, in loop.\n"); 159272343Sngie } while (sharedval != 0); 160272343Sngie 161272343Sngie printf("1: After the loop.\n"); 162272343Sngie 163272343Sngie PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex)); 164272343Sngie 165272343Sngie printf("1: After releasing the mutex.\n"); 166272343Sngie PTHREAD_REQUIRE(pthread_join(new, &joinval)); 167272343Sngie 168272343Sngie printf("1: Thread joined.\n"); 169272343Sngie} 170272343Sngie 171272343Sngiestatic void * 172272343Sngiesignal_before_unlock_static_init_threadfunc(void *arg) 173272343Sngie{ 174272343Sngie int *shared = (int *) arg; 175272343Sngie 176272343Sngie printf("2: Second thread.\n"); 177272343Sngie 178272343Sngie printf("2: Locking mutex\n"); 179272343Sngie PTHREAD_REQUIRE(pthread_mutex_lock(&static_mutex)); 180272343Sngie printf("2: Got mutex.\n"); 181272343Sngie printf("Shared value: %d. Changing to 0.\n", *shared); 182272343Sngie *shared = 0; 183272343Sngie 184272343Sngie /* Signal first, then unlock, for a different test than #1. */ 185272343Sngie PTHREAD_REQUIRE(pthread_cond_signal(&static_cond)); 186272343Sngie PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex)); 187272343Sngie 188272343Sngie return NULL; 189272343Sngie} 190272343Sngie 191272343SngieATF_TC(signal_before_unlock_static_init); 192272343SngieATF_TC_HEAD(signal_before_unlock_static_init, tc) 193272343Sngie{ 194272343Sngie atf_tc_set_md_var(tc, "descr", 195272343Sngie "Checks condition variables: signal before unlocking " 196272343Sngie "mutex, use static initializers"); 197272343Sngie} 198272343SngieATF_TC_BODY(signal_before_unlock_static_init, tc) 199272343Sngie{ 200272343Sngie pthread_t new; 201272343Sngie void *joinval; 202272343Sngie int sharedval; 203272343Sngie 204272343Sngie printf("1: condition variable test 3\n"); 205272343Sngie 206272343Sngie PTHREAD_REQUIRE(pthread_mutex_lock(&static_mutex)); 207272343Sngie 208272343Sngie sharedval = 1; 209272343Sngie 210272343Sngie PTHREAD_REQUIRE(pthread_create(&new, NULL, 211272343Sngie signal_before_unlock_static_init_threadfunc, &sharedval)); 212272343Sngie 213272343Sngie printf("1: Before waiting.\n"); 214272343Sngie do { 215272343Sngie sleep(2); 216272343Sngie PTHREAD_REQUIRE(pthread_cond_wait(&static_cond, &static_mutex)); 217272343Sngie printf("1: After waiting, in loop.\n"); 218272343Sngie } while (sharedval != 0); 219272343Sngie 220272343Sngie printf("1: After the loop.\n"); 221272343Sngie 222272343Sngie PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex)); 223272343Sngie 224272343Sngie printf("1: After releasing the mutex.\n"); 225272343Sngie PTHREAD_REQUIRE(pthread_join(new, &joinval)); 226272343Sngie 227272343Sngie printf("1: Thread joined.\n"); 228272343Sngie} 229272343Sngie 230272343Sngiestatic void * 231272343Sngiesignal_wait_race_threadfunc(void *arg) 232272343Sngie{ 233272343Sngie printf("2: Second thread.\n"); 234272343Sngie PTHREAD_REQUIRE(pthread_mutex_lock(&static_mutex)); 235272343Sngie printf("2: Before the loop.\n"); 236272343Sngie while (count>0) { 237272343Sngie count--; 238272343Sngie total++; 239272343Sngie toggle = 0; 240272343Sngie /* printf("2: Before signal %d.\n", count); */ 241272343Sngie PTHREAD_REQUIRE(pthread_cond_signal(&static_cond)); 242272343Sngie do { 243272343Sngie PTHREAD_REQUIRE(pthread_cond_wait(&static_cond, 244272343Sngie &static_mutex)); 245272343Sngie } while (toggle != 1); 246272343Sngie } 247272343Sngie printf("2: After the loop.\n"); 248272343Sngie PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex)); 249272343Sngie 250272343Sngie return NULL; 251272343Sngie} 252272343Sngie 253272343SngieATF_TC(signal_wait_race); 254272343SngieATF_TC_HEAD(signal_wait_race, tc) 255272343Sngie{ 256272343Sngie atf_tc_set_md_var(tc, "descr", "Checks condition variables"); 257272343Sngie} 258272343SngieATF_TC_BODY(signal_wait_race, tc) 259272343Sngie{ 260272343Sngie pthread_t new; 261272343Sngie void *joinval; 262272343Sngie int sharedval; 263272343Sngie 264272343Sngie printf("1: condition variable test 4\n"); 265272343Sngie 266272343Sngie PTHREAD_REQUIRE(pthread_mutex_lock(&static_mutex)); 267272343Sngie 268272343Sngie count = 50000; 269272343Sngie toggle = 0; 270272343Sngie 271272343Sngie PTHREAD_REQUIRE(pthread_create(&new, NULL, signal_wait_race_threadfunc, 272272343Sngie &sharedval)); 273272343Sngie 274272343Sngie printf("1: Before waiting.\n"); 275272343Sngie while (count>0) { 276272343Sngie count--; 277272343Sngie total++; 278272343Sngie toggle = 1; 279272343Sngie /* printf("1: Before signal %d.\n", count); */ 280272343Sngie PTHREAD_REQUIRE(pthread_cond_signal(&static_cond)); 281272343Sngie do { 282272343Sngie PTHREAD_REQUIRE(pthread_cond_wait(&static_cond, 283272343Sngie &static_mutex)); 284272343Sngie } while (toggle != 0); 285272343Sngie } 286272343Sngie printf("1: After the loop.\n"); 287272343Sngie 288272343Sngie toggle = 1; 289272343Sngie PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex)); 290272343Sngie PTHREAD_REQUIRE(pthread_cond_signal(&static_cond)); 291272343Sngie 292272343Sngie printf("1: After releasing the mutex.\n"); 293272343Sngie PTHREAD_REQUIRE(pthread_join(new, &joinval)); 294272343Sngie 295272343Sngie printf("1: Thread joined. Final count = %d, total = %d\n", 296272343Sngie count, total); 297272343Sngie 298272343Sngie ATF_REQUIRE_EQ(count, 0); 299272343Sngie ATF_REQUIRE_EQ(total, 50000); 300272343Sngie} 301272343Sngie 302272343Sngiestatic void * 303272343Sngiepthread_cond_timedwait_func(void *arg) 304272343Sngie{ 305272343Sngie struct timespec ts; 306272343Sngie size_t i = 0; 307272343Sngie int rv; 308272343Sngie 309272343Sngie for (;;) { 310272343Sngie 311272343Sngie if (i++ >= 10000) 312272343Sngie pthread_exit(NULL); 313272343Sngie 314272343Sngie (void)memset(&ts, 0, sizeof(struct timespec)); 315272343Sngie 316272343Sngie ATF_REQUIRE(clock_gettime(CLOCK_REALTIME, &ts) == 0); 317272343Sngie 318272343Sngie /* 319272343Sngie * Set to one second in the past: 320272343Sngie * pthread_cond_timedwait(3) should 321272343Sngie * return ETIMEDOUT immediately. 322272343Sngie */ 323272343Sngie ts.tv_sec = ts.tv_sec - 1; 324272343Sngie 325272343Sngie PTHREAD_REQUIRE(pthread_mutex_lock(&static_mutex)); 326272343Sngie rv = pthread_cond_timedwait(&static_cond, &static_mutex, &ts); 327272343Sngie 328272343Sngie /* 329272343Sngie * Sometimes we catch ESRCH. 330272343Sngie * This should never happen. 331272343Sngie */ 332272343Sngie ATF_REQUIRE(rv == ETIMEDOUT); 333272343Sngie PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex)); 334272343Sngie } 335272343Sngie} 336272343Sngie 337272343SngieATF_TC(cond_timedwait_race); 338272343SngieATF_TC_HEAD(cond_timedwait_race, tc) 339272343Sngie{ 340272343Sngie atf_tc_set_md_var(tc, "descr", "Test pthread_cond_timedwait(3)"); 341272343Sngie 342272343Sngie} 343272343SngieATF_TC_BODY(cond_timedwait_race, tc) 344272343Sngie{ 345272343Sngie pthread_t tid[64]; 346272343Sngie size_t i; 347272343Sngie 348272343Sngie for (i = 0; i < __arraycount(tid); i++) { 349272343Sngie 350272343Sngie PTHREAD_REQUIRE(pthread_create(&tid[i], NULL, 351272343Sngie pthread_cond_timedwait_func, NULL)); 352272343Sngie } 353272343Sngie 354272343Sngie for (i = 0; i < __arraycount(tid); i++) { 355272343Sngie 356272343Sngie PTHREAD_REQUIRE(pthread_join(tid[i], NULL)); 357272343Sngie } 358272343Sngie} 359272343Sngie 360272343Sngiestatic void * 361272343Sngiebroadcast_threadfunc(void *arg) 362272343Sngie{ 363272343Sngie printf("2: Second thread.\n"); 364272343Sngie 365272343Sngie PTHREAD_REQUIRE(pthread_mutex_lock(&static_mutex)); 366272343Sngie while (count>0) { 367272343Sngie count--; 368272343Sngie total++; 369272343Sngie toggle = 0; 370272343Sngie PTHREAD_REQUIRE(pthread_cond_signal(&static_cond)); 371272343Sngie do { 372272343Sngie PTHREAD_REQUIRE(pthread_cond_wait(&static_cond, 373272343Sngie &static_mutex)); 374272343Sngie } while (toggle != 1); 375272343Sngie } 376272343Sngie printf("2: After the loop.\n"); 377272343Sngie PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex)); 378272343Sngie 379272343Sngie return NULL; 380272343Sngie} 381272343Sngie 382272343Sngie 383272343SngieATF_TC(broadcast); 384272343SngieATF_TC_HEAD(broadcast, tc) 385272343Sngie{ 386272343Sngie atf_tc_set_md_var(tc, "descr", 387272343Sngie "Checks condition variables: use pthread_cond_broadcast()"); 388272343Sngie} 389272343SngieATF_TC_BODY(broadcast, tc) 390272343Sngie{ 391272343Sngie pthread_t new; 392272343Sngie void *joinval; 393272343Sngie int sharedval; 394272343Sngie 395272343Sngie printf("1: condition variable test 5\n"); 396272343Sngie 397272343Sngie PTHREAD_REQUIRE(pthread_mutex_lock(&static_mutex)); 398272343Sngie 399272343Sngie count = 50000; 400272343Sngie toggle = 0; 401272343Sngie 402272343Sngie PTHREAD_REQUIRE(pthread_create(&new, NULL, broadcast_threadfunc, 403272343Sngie &sharedval)); 404272343Sngie 405272343Sngie printf("1: Before waiting.\n"); 406272343Sngie while (count>0) { 407272343Sngie count--; 408272343Sngie total++; 409272343Sngie toggle = 1; 410272343Sngie PTHREAD_REQUIRE(pthread_cond_broadcast(&static_cond)); 411272343Sngie do { 412272343Sngie PTHREAD_REQUIRE(pthread_cond_wait(&static_cond, 413272343Sngie &static_mutex)); 414272343Sngie } while (toggle != 0); 415272343Sngie } 416272343Sngie printf("1: After the loop.\n"); 417272343Sngie 418272343Sngie toggle = 1; 419272343Sngie PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex)); 420272343Sngie PTHREAD_REQUIRE(pthread_cond_signal(&static_cond)); 421272343Sngie 422272343Sngie printf("1: After releasing the mutex.\n"); 423272343Sngie PTHREAD_REQUIRE(pthread_join(new, &joinval)); 424272343Sngie 425272343Sngie printf("1: Thread joined. Final count = %d, total = %d\n", count, 426272343Sngie total); 427272343Sngie 428272343Sngie ATF_REQUIRE_EQ(count, 0); 429272343Sngie ATF_REQUIRE_EQ(total, 50000); 430272343Sngie} 431272343Sngie 432272343Sngiestatic void * 433272343Sngiebogus_timedwaits_threadfunc(void *arg) 434272343Sngie{ 435272343Sngie return NULL; 436272343Sngie} 437272343Sngie 438272343SngieATF_TC(bogus_timedwaits); 439272343SngieATF_TC_HEAD(bogus_timedwaits, tc) 440272343Sngie{ 441272343Sngie atf_tc_set_md_var(tc, "descr", 442272343Sngie "Checks condition variables: bogus timedwaits"); 443272343Sngie} 444272343SngieATF_TC_BODY(bogus_timedwaits, tc) 445272343Sngie{ 446272343Sngie pthread_t new; 447272343Sngie struct timespec ts; 448272343Sngie struct timeval tv; 449272343Sngie 450272343Sngie printf("condition variable test 6: bogus timedwaits\n"); 451272343Sngie 452272343Sngie PTHREAD_REQUIRE(pthread_mutex_lock(&static_mutex)); 453272343Sngie 454272343Sngie printf("unthreaded test (past)\n"); 455272343Sngie gettimeofday(&tv, NULL); 456272343Sngie tv.tv_sec -= 2; /* Place the time in the past */ 457272343Sngie TIMEVAL_TO_TIMESPEC(&tv, &ts); 458272343Sngie 459272343Sngie ATF_REQUIRE_EQ_MSG(pthread_cond_timedwait(&static_cond, &static_mutex, 460272343Sngie &ts), ETIMEDOUT, "pthread_cond_timedwait() (unthreaded) in the " 461272343Sngie "past"); 462272343Sngie 463272343Sngie printf("unthreaded test (zero time)\n"); 464272343Sngie tv.tv_sec = 0; 465272343Sngie tv.tv_usec = 0; 466272343Sngie TIMEVAL_TO_TIMESPEC(&tv, &ts); 467272343Sngie 468272343Sngie ATF_REQUIRE_EQ_MSG(pthread_cond_timedwait(&static_cond, &static_mutex, 469272343Sngie &ts), ETIMEDOUT, "pthread_cond_timedwait() (unthreaded) with zero " 470272343Sngie "time"); 471272343Sngie 472272343Sngie PTHREAD_REQUIRE(pthread_create(&new, NULL, bogus_timedwaits_threadfunc, 473272343Sngie NULL)); 474272343Sngie PTHREAD_REQUIRE(pthread_join(new, NULL)); 475272343Sngie 476272343Sngie printf("threaded test\n"); 477272343Sngie gettimeofday(&tv, NULL); 478272343Sngie tv.tv_sec -= 2; /* Place the time in the past */ 479272343Sngie TIMEVAL_TO_TIMESPEC(&tv, &ts); 480272343Sngie 481272343Sngie ATF_REQUIRE_EQ_MSG(pthread_cond_timedwait(&static_cond, &static_mutex, 482272343Sngie &ts), ETIMEDOUT, "pthread_cond_timedwait() (threaded) in the past"); 483272343Sngie 484272343Sngie printf("threaded test (zero time)\n"); 485272343Sngie tv.tv_sec = 0; 486272343Sngie tv.tv_usec = 0; 487272343Sngie TIMEVAL_TO_TIMESPEC(&tv, &ts); 488272343Sngie 489272343Sngie ATF_REQUIRE_EQ_MSG(pthread_cond_timedwait(&static_cond, &static_mutex, 490272343Sngie &ts), ETIMEDOUT, "pthread_cond_timedwait() (threaded) with zero " 491272343Sngie "time"); 492272343Sngie 493272343Sngie PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex)); 494272343Sngie} 495272343Sngie 496272343Sngiestatic void 497272343Sngieunlock(void *arg) 498272343Sngie{ 499272343Sngie pthread_mutex_unlock((pthread_mutex_t *)arg); 500272343Sngie} 501272343Sngie 502272343Sngiestatic void * 503272343Sngiedestroy_after_cancel_threadfunc(void *arg) 504272343Sngie{ 505272343Sngie PTHREAD_REQUIRE(pthread_mutex_lock(&mutex)); 506272343Sngie 507272343Sngie pthread_cleanup_push(unlock, &mutex); 508272343Sngie 509272343Sngie while (1) { 510272343Sngie share = 1; 511272343Sngie PTHREAD_REQUIRE(pthread_cond_broadcast(&cond)); 512272343Sngie PTHREAD_REQUIRE(pthread_cond_wait(&cond, &mutex)); 513272343Sngie } 514272343Sngie 515272343Sngie pthread_cleanup_pop(0); 516272343Sngie PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex)); 517272343Sngie 518272343Sngie return NULL; 519272343Sngie} 520272343Sngie 521272343SngieATF_TC(destroy_after_cancel); 522272343SngieATF_TC_HEAD(destroy_after_cancel, tc) 523272343Sngie{ 524272343Sngie atf_tc_set_md_var(tc, "descr", "Checks destroying a condition variable " 525272343Sngie "after cancelling a wait"); 526272343Sngie} 527272343SngieATF_TC_BODY(destroy_after_cancel, tc) 528272343Sngie{ 529272343Sngie pthread_t thread; 530272343Sngie 531272343Sngie PTHREAD_REQUIRE(pthread_mutex_init(&mutex, NULL)); 532272343Sngie PTHREAD_REQUIRE(pthread_cond_init(&cond, NULL)); 533272343Sngie PTHREAD_REQUIRE(pthread_mutex_lock(&mutex)); 534272343Sngie PTHREAD_REQUIRE(pthread_create(&thread, NULL, 535272343Sngie destroy_after_cancel_threadfunc, NULL)); 536272343Sngie 537272343Sngie while (share == 0) { 538272343Sngie PTHREAD_REQUIRE(pthread_cond_wait(&cond, &mutex)); 539272343Sngie } 540272343Sngie 541272343Sngie PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex)); 542272343Sngie PTHREAD_REQUIRE(pthread_cancel(thread)); 543272343Sngie 544272343Sngie PTHREAD_REQUIRE(pthread_join(thread, NULL)); 545272343Sngie PTHREAD_REQUIRE(pthread_cond_destroy(&cond)); 546272343Sngie 547272343Sngie PTHREAD_REQUIRE(pthread_mutex_destroy(&mutex)); 548272343Sngie} 549272343Sngie 550272343SngieATF_TP_ADD_TCS(tp) 551272343Sngie{ 552272343Sngie 553272343Sngie ATF_TP_ADD_TC(tp, signal_delay_wait); 554272343Sngie ATF_TP_ADD_TC(tp, signal_before_unlock); 555272343Sngie ATF_TP_ADD_TC(tp, signal_before_unlock_static_init); 556272343Sngie ATF_TP_ADD_TC(tp, signal_wait_race); 557272343Sngie ATF_TP_ADD_TC(tp, cond_timedwait_race); 558272343Sngie ATF_TP_ADD_TC(tp, broadcast); 559272343Sngie ATF_TP_ADD_TC(tp, bogus_timedwaits); 560272343Sngie ATF_TP_ADD_TC(tp, destroy_after_cancel); 561272343Sngie 562272343Sngie return atf_no_error(); 563272343Sngie} 564