1 1.8 ad /* $NetBSD: t_cond.c,v 1.8 2020/06/10 21:46:50 ad Exp $ */ 2 1.1 jmmv 3 1.1 jmmv /* 4 1.1 jmmv * Copyright (c) 2008 The NetBSD Foundation, Inc. 5 1.1 jmmv * All rights reserved. 6 1.1 jmmv * 7 1.1 jmmv * Redistribution and use in source and binary forms, with or without 8 1.1 jmmv * modification, are permitted provided that the following conditions 9 1.1 jmmv * are met: 10 1.1 jmmv * 1. Redistributions of source code must retain the above copyright 11 1.1 jmmv * notice, this list of conditions and the following disclaimer. 12 1.1 jmmv * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 jmmv * notice, this list of conditions and the following disclaimer in the 14 1.1 jmmv * documentation and/or other materials provided with the distribution. 15 1.1 jmmv * 16 1.1 jmmv * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 17 1.1 jmmv * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18 1.1 jmmv * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 1.1 jmmv * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 20 1.1 jmmv * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 1.1 jmmv * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 1.1 jmmv * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 1.1 jmmv * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 1.1 jmmv * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 1.1 jmmv * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 1.1 jmmv * POSSIBILITY OF SUCH DAMAGE. 27 1.1 jmmv */ 28 1.1 jmmv 29 1.1 jmmv #include <sys/cdefs.h> 30 1.1 jmmv __COPYRIGHT("@(#) Copyright (c) 2008\ 31 1.1 jmmv The NetBSD Foundation, inc. All rights reserved."); 32 1.8 ad __RCSID("$NetBSD: t_cond.c,v 1.8 2020/06/10 21:46:50 ad Exp $"); 33 1.1 jmmv 34 1.1 jmmv #include <sys/time.h> 35 1.1 jmmv 36 1.1 jmmv #include <errno.h> 37 1.1 jmmv #include <pthread.h> 38 1.1 jmmv #include <stdio.h> 39 1.1 jmmv #include <unistd.h> 40 1.1 jmmv 41 1.1 jmmv #include <atf-c.h> 42 1.1 jmmv 43 1.1 jmmv #include "h_common.h" 44 1.1 jmmv 45 1.1 jmmv static pthread_mutex_t mutex; 46 1.1 jmmv static pthread_cond_t cond; 47 1.1 jmmv static pthread_mutex_t static_mutex = PTHREAD_MUTEX_INITIALIZER; 48 1.1 jmmv static pthread_cond_t static_cond = PTHREAD_COND_INITIALIZER; 49 1.1 jmmv static int count, share, toggle, total; 50 1.1 jmmv 51 1.1 jmmv static void * 52 1.1 jmmv signal_delay_wait_threadfunc(void *arg) 53 1.1 jmmv { 54 1.2 christos int *shared = (int *) arg; 55 1.1 jmmv 56 1.1 jmmv printf("2: Second thread.\n"); 57 1.1 jmmv 58 1.1 jmmv printf("2: Locking mutex\n"); 59 1.1 jmmv PTHREAD_REQUIRE(pthread_mutex_lock(&mutex)); 60 1.1 jmmv printf("2: Got mutex.\n"); 61 1.2 christos printf("Shared value: %d. Changing to 0.\n", *shared); 62 1.2 christos *shared = 0; 63 1.1 jmmv 64 1.1 jmmv PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex)); 65 1.1 jmmv PTHREAD_REQUIRE(pthread_cond_signal(&cond)); 66 1.1 jmmv 67 1.1 jmmv return NULL; 68 1.1 jmmv } 69 1.1 jmmv 70 1.1 jmmv ATF_TC(signal_delay_wait); 71 1.1 jmmv ATF_TC_HEAD(signal_delay_wait, tc) 72 1.1 jmmv { 73 1.1 jmmv atf_tc_set_md_var(tc, "descr", "Checks condition variables"); 74 1.1 jmmv } 75 1.1 jmmv ATF_TC_BODY(signal_delay_wait, tc) 76 1.1 jmmv { 77 1.1 jmmv pthread_t new; 78 1.1 jmmv void *joinval; 79 1.1 jmmv int sharedval; 80 1.1 jmmv 81 1.1 jmmv printf("1: condition variable test 1\n"); 82 1.1 jmmv 83 1.1 jmmv PTHREAD_REQUIRE(pthread_mutex_init(&mutex, NULL)); 84 1.1 jmmv PTHREAD_REQUIRE(pthread_cond_init(&cond, NULL)); 85 1.1 jmmv 86 1.1 jmmv PTHREAD_REQUIRE(pthread_mutex_lock(&mutex)); 87 1.1 jmmv 88 1.1 jmmv sharedval = 1; 89 1.1 jmmv 90 1.1 jmmv PTHREAD_REQUIRE(pthread_create(&new, NULL, signal_delay_wait_threadfunc, 91 1.1 jmmv &sharedval)); 92 1.1 jmmv 93 1.1 jmmv printf("1: Before waiting.\n"); 94 1.1 jmmv do { 95 1.1 jmmv sleep(2); 96 1.1 jmmv PTHREAD_REQUIRE(pthread_cond_wait(&cond, &mutex)); 97 1.1 jmmv printf("1: After waiting, in loop.\n"); 98 1.1 jmmv } while (sharedval != 0); 99 1.1 jmmv 100 1.1 jmmv printf("1: After the loop.\n"); 101 1.1 jmmv 102 1.1 jmmv PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex)); 103 1.1 jmmv 104 1.1 jmmv printf("1: After releasing the mutex.\n"); 105 1.1 jmmv PTHREAD_REQUIRE(pthread_join(new, &joinval)); 106 1.1 jmmv 107 1.1 jmmv printf("1: Thread joined.\n"); 108 1.1 jmmv } 109 1.1 jmmv 110 1.1 jmmv static void * 111 1.1 jmmv signal_before_unlock_threadfunc(void *arg) 112 1.1 jmmv { 113 1.2 christos int *shared = (int *) arg; 114 1.1 jmmv 115 1.1 jmmv printf("2: Second thread.\n"); 116 1.1 jmmv 117 1.1 jmmv printf("2: Locking mutex\n"); 118 1.1 jmmv PTHREAD_REQUIRE(pthread_mutex_lock(&mutex)); 119 1.1 jmmv printf("2: Got mutex.\n"); 120 1.2 christos printf("Shared value: %d. Changing to 0.\n", *shared); 121 1.2 christos *shared = 0; 122 1.1 jmmv 123 1.1 jmmv /* Signal first, then unlock, for a different test than #1. */ 124 1.1 jmmv PTHREAD_REQUIRE(pthread_cond_signal(&cond)); 125 1.1 jmmv PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex)); 126 1.1 jmmv 127 1.1 jmmv return NULL; 128 1.1 jmmv } 129 1.1 jmmv 130 1.1 jmmv ATF_TC(signal_before_unlock); 131 1.1 jmmv ATF_TC_HEAD(signal_before_unlock, tc) 132 1.1 jmmv { 133 1.1 jmmv atf_tc_set_md_var(tc, "descr", 134 1.1 jmmv "Checks condition variables: signal before unlocking mutex"); 135 1.1 jmmv } 136 1.1 jmmv ATF_TC_BODY(signal_before_unlock, tc) 137 1.1 jmmv { 138 1.1 jmmv pthread_t new; 139 1.1 jmmv void *joinval; 140 1.1 jmmv int sharedval; 141 1.1 jmmv 142 1.1 jmmv printf("1: condition variable test 2\n"); 143 1.1 jmmv 144 1.1 jmmv PTHREAD_REQUIRE(pthread_mutex_init(&mutex, NULL)); 145 1.1 jmmv PTHREAD_REQUIRE(pthread_cond_init(&cond, NULL)); 146 1.1 jmmv 147 1.1 jmmv PTHREAD_REQUIRE(pthread_mutex_lock(&mutex)); 148 1.1 jmmv 149 1.1 jmmv sharedval = 1; 150 1.1 jmmv 151 1.1 jmmv PTHREAD_REQUIRE(pthread_create(&new, NULL, 152 1.1 jmmv signal_before_unlock_threadfunc, &sharedval)); 153 1.1 jmmv 154 1.1 jmmv printf("1: Before waiting.\n"); 155 1.1 jmmv do { 156 1.1 jmmv sleep(2); 157 1.1 jmmv PTHREAD_REQUIRE(pthread_cond_wait(&cond, &mutex)); 158 1.1 jmmv printf("1: After waiting, in loop.\n"); 159 1.1 jmmv } while (sharedval != 0); 160 1.1 jmmv 161 1.1 jmmv printf("1: After the loop.\n"); 162 1.1 jmmv 163 1.1 jmmv PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex)); 164 1.1 jmmv 165 1.1 jmmv printf("1: After releasing the mutex.\n"); 166 1.1 jmmv PTHREAD_REQUIRE(pthread_join(new, &joinval)); 167 1.1 jmmv 168 1.1 jmmv printf("1: Thread joined.\n"); 169 1.1 jmmv } 170 1.1 jmmv 171 1.1 jmmv static void * 172 1.1 jmmv signal_before_unlock_static_init_threadfunc(void *arg) 173 1.1 jmmv { 174 1.2 christos int *shared = (int *) arg; 175 1.1 jmmv 176 1.1 jmmv printf("2: Second thread.\n"); 177 1.1 jmmv 178 1.1 jmmv printf("2: Locking mutex\n"); 179 1.1 jmmv PTHREAD_REQUIRE(pthread_mutex_lock(&static_mutex)); 180 1.1 jmmv printf("2: Got mutex.\n"); 181 1.2 christos printf("Shared value: %d. Changing to 0.\n", *shared); 182 1.2 christos *shared = 0; 183 1.1 jmmv 184 1.1 jmmv /* Signal first, then unlock, for a different test than #1. */ 185 1.1 jmmv PTHREAD_REQUIRE(pthread_cond_signal(&static_cond)); 186 1.1 jmmv PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex)); 187 1.1 jmmv 188 1.1 jmmv return NULL; 189 1.1 jmmv } 190 1.1 jmmv 191 1.1 jmmv ATF_TC(signal_before_unlock_static_init); 192 1.1 jmmv ATF_TC_HEAD(signal_before_unlock_static_init, tc) 193 1.1 jmmv { 194 1.1 jmmv atf_tc_set_md_var(tc, "descr", 195 1.1 jmmv "Checks condition variables: signal before unlocking " 196 1.1 jmmv "mutex, use static initializers"); 197 1.1 jmmv } 198 1.1 jmmv ATF_TC_BODY(signal_before_unlock_static_init, tc) 199 1.1 jmmv { 200 1.1 jmmv pthread_t new; 201 1.1 jmmv void *joinval; 202 1.1 jmmv int sharedval; 203 1.1 jmmv 204 1.1 jmmv printf("1: condition variable test 3\n"); 205 1.1 jmmv 206 1.1 jmmv PTHREAD_REQUIRE(pthread_mutex_lock(&static_mutex)); 207 1.1 jmmv 208 1.1 jmmv sharedval = 1; 209 1.1 jmmv 210 1.1 jmmv PTHREAD_REQUIRE(pthread_create(&new, NULL, 211 1.1 jmmv signal_before_unlock_static_init_threadfunc, &sharedval)); 212 1.1 jmmv 213 1.1 jmmv printf("1: Before waiting.\n"); 214 1.1 jmmv do { 215 1.1 jmmv sleep(2); 216 1.1 jmmv PTHREAD_REQUIRE(pthread_cond_wait(&static_cond, &static_mutex)); 217 1.1 jmmv printf("1: After waiting, in loop.\n"); 218 1.1 jmmv } while (sharedval != 0); 219 1.1 jmmv 220 1.1 jmmv printf("1: After the loop.\n"); 221 1.1 jmmv 222 1.1 jmmv PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex)); 223 1.1 jmmv 224 1.1 jmmv printf("1: After releasing the mutex.\n"); 225 1.1 jmmv PTHREAD_REQUIRE(pthread_join(new, &joinval)); 226 1.1 jmmv 227 1.1 jmmv printf("1: Thread joined.\n"); 228 1.1 jmmv } 229 1.1 jmmv 230 1.1 jmmv static void * 231 1.1 jmmv signal_wait_race_threadfunc(void *arg) 232 1.1 jmmv { 233 1.1 jmmv printf("2: Second thread.\n"); 234 1.1 jmmv PTHREAD_REQUIRE(pthread_mutex_lock(&static_mutex)); 235 1.1 jmmv printf("2: Before the loop.\n"); 236 1.1 jmmv while (count>0) { 237 1.1 jmmv count--; 238 1.1 jmmv total++; 239 1.1 jmmv toggle = 0; 240 1.1 jmmv /* printf("2: Before signal %d.\n", count); */ 241 1.1 jmmv PTHREAD_REQUIRE(pthread_cond_signal(&static_cond)); 242 1.1 jmmv do { 243 1.1 jmmv PTHREAD_REQUIRE(pthread_cond_wait(&static_cond, 244 1.1 jmmv &static_mutex)); 245 1.1 jmmv } while (toggle != 1); 246 1.1 jmmv } 247 1.1 jmmv printf("2: After the loop.\n"); 248 1.1 jmmv PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex)); 249 1.1 jmmv 250 1.1 jmmv return NULL; 251 1.1 jmmv } 252 1.1 jmmv 253 1.1 jmmv ATF_TC(signal_wait_race); 254 1.1 jmmv ATF_TC_HEAD(signal_wait_race, tc) 255 1.1 jmmv { 256 1.1 jmmv atf_tc_set_md_var(tc, "descr", "Checks condition variables"); 257 1.1 jmmv } 258 1.1 jmmv ATF_TC_BODY(signal_wait_race, tc) 259 1.1 jmmv { 260 1.1 jmmv pthread_t new; 261 1.1 jmmv void *joinval; 262 1.1 jmmv int sharedval; 263 1.1 jmmv 264 1.1 jmmv printf("1: condition variable test 4\n"); 265 1.1 jmmv 266 1.1 jmmv PTHREAD_REQUIRE(pthread_mutex_lock(&static_mutex)); 267 1.1 jmmv 268 1.1 jmmv count = 50000; 269 1.1 jmmv toggle = 0; 270 1.1 jmmv 271 1.1 jmmv PTHREAD_REQUIRE(pthread_create(&new, NULL, signal_wait_race_threadfunc, 272 1.1 jmmv &sharedval)); 273 1.1 jmmv 274 1.1 jmmv printf("1: Before waiting.\n"); 275 1.1 jmmv while (count>0) { 276 1.1 jmmv count--; 277 1.1 jmmv total++; 278 1.1 jmmv toggle = 1; 279 1.1 jmmv /* printf("1: Before signal %d.\n", count); */ 280 1.1 jmmv PTHREAD_REQUIRE(pthread_cond_signal(&static_cond)); 281 1.1 jmmv do { 282 1.1 jmmv PTHREAD_REQUIRE(pthread_cond_wait(&static_cond, 283 1.1 jmmv &static_mutex)); 284 1.1 jmmv } while (toggle != 0); 285 1.1 jmmv } 286 1.1 jmmv printf("1: After the loop.\n"); 287 1.1 jmmv 288 1.1 jmmv toggle = 1; 289 1.1 jmmv PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex)); 290 1.1 jmmv PTHREAD_REQUIRE(pthread_cond_signal(&static_cond)); 291 1.1 jmmv 292 1.1 jmmv printf("1: After releasing the mutex.\n"); 293 1.1 jmmv PTHREAD_REQUIRE(pthread_join(new, &joinval)); 294 1.1 jmmv 295 1.1 jmmv printf("1: Thread joined. Final count = %d, total = %d\n", 296 1.1 jmmv count, total); 297 1.1 jmmv 298 1.1 jmmv ATF_REQUIRE_EQ(count, 0); 299 1.1 jmmv ATF_REQUIRE_EQ(total, 50000); 300 1.1 jmmv } 301 1.1 jmmv 302 1.1 jmmv static void * 303 1.3 jruoho pthread_cond_timedwait_func(void *arg) 304 1.3 jruoho { 305 1.3 jruoho struct timespec ts; 306 1.3 jruoho size_t i = 0; 307 1.3 jruoho int rv; 308 1.3 jruoho 309 1.3 jruoho for (;;) { 310 1.3 jruoho 311 1.3 jruoho if (i++ >= 10000) 312 1.3 jruoho pthread_exit(NULL); 313 1.3 jruoho 314 1.3 jruoho (void)memset(&ts, 0, sizeof(struct timespec)); 315 1.3 jruoho 316 1.3 jruoho ATF_REQUIRE(clock_gettime(CLOCK_REALTIME, &ts) == 0); 317 1.3 jruoho 318 1.3 jruoho /* 319 1.3 jruoho * Set to one second in the past: 320 1.3 jruoho * pthread_cond_timedwait(3) should 321 1.3 jruoho * return ETIMEDOUT immediately. 322 1.3 jruoho */ 323 1.3 jruoho ts.tv_sec = ts.tv_sec - 1; 324 1.3 jruoho 325 1.3 jruoho PTHREAD_REQUIRE(pthread_mutex_lock(&static_mutex)); 326 1.3 jruoho rv = pthread_cond_timedwait(&static_cond, &static_mutex, &ts); 327 1.3 jruoho 328 1.3 jruoho /* 329 1.3 jruoho * Sometimes we catch ESRCH. 330 1.3 jruoho * This should never happen. 331 1.3 jruoho */ 332 1.8 ad ATF_REQUIRE(rv == ETIMEDOUT || rv == 0); 333 1.3 jruoho PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex)); 334 1.3 jruoho } 335 1.3 jruoho } 336 1.3 jruoho 337 1.3 jruoho ATF_TC(cond_timedwait_race); 338 1.3 jruoho ATF_TC_HEAD(cond_timedwait_race, tc) 339 1.3 jruoho { 340 1.3 jruoho atf_tc_set_md_var(tc, "descr", "Test pthread_cond_timedwait(3)"); 341 1.3 jruoho 342 1.3 jruoho } 343 1.3 jruoho ATF_TC_BODY(cond_timedwait_race, tc) 344 1.3 jruoho { 345 1.3 jruoho pthread_t tid[64]; 346 1.6 gson size_t i; 347 1.3 jruoho 348 1.6 gson for (i = 0; i < __arraycount(tid); i++) { 349 1.3 jruoho 350 1.6 gson PTHREAD_REQUIRE(pthread_create(&tid[i], NULL, 351 1.6 gson pthread_cond_timedwait_func, NULL)); 352 1.6 gson } 353 1.6 gson 354 1.6 gson for (i = 0; i < __arraycount(tid); i++) { 355 1.3 jruoho 356 1.6 gson PTHREAD_REQUIRE(pthread_join(tid[i], NULL)); 357 1.3 jruoho } 358 1.3 jruoho } 359 1.3 jruoho 360 1.3 jruoho static void * 361 1.1 jmmv broadcast_threadfunc(void *arg) 362 1.1 jmmv { 363 1.1 jmmv printf("2: Second thread.\n"); 364 1.1 jmmv 365 1.1 jmmv PTHREAD_REQUIRE(pthread_mutex_lock(&static_mutex)); 366 1.1 jmmv while (count>0) { 367 1.1 jmmv count--; 368 1.1 jmmv total++; 369 1.1 jmmv toggle = 0; 370 1.1 jmmv PTHREAD_REQUIRE(pthread_cond_signal(&static_cond)); 371 1.1 jmmv do { 372 1.1 jmmv PTHREAD_REQUIRE(pthread_cond_wait(&static_cond, 373 1.1 jmmv &static_mutex)); 374 1.1 jmmv } while (toggle != 1); 375 1.1 jmmv } 376 1.1 jmmv printf("2: After the loop.\n"); 377 1.1 jmmv PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex)); 378 1.1 jmmv 379 1.1 jmmv return NULL; 380 1.1 jmmv } 381 1.1 jmmv 382 1.1 jmmv 383 1.1 jmmv ATF_TC(broadcast); 384 1.1 jmmv ATF_TC_HEAD(broadcast, tc) 385 1.1 jmmv { 386 1.1 jmmv atf_tc_set_md_var(tc, "descr", 387 1.1 jmmv "Checks condition variables: use pthread_cond_broadcast()"); 388 1.1 jmmv } 389 1.1 jmmv ATF_TC_BODY(broadcast, tc) 390 1.1 jmmv { 391 1.1 jmmv pthread_t new; 392 1.1 jmmv void *joinval; 393 1.1 jmmv int sharedval; 394 1.1 jmmv 395 1.1 jmmv printf("1: condition variable test 5\n"); 396 1.1 jmmv 397 1.1 jmmv PTHREAD_REQUIRE(pthread_mutex_lock(&static_mutex)); 398 1.1 jmmv 399 1.1 jmmv count = 50000; 400 1.1 jmmv toggle = 0; 401 1.1 jmmv 402 1.1 jmmv PTHREAD_REQUIRE(pthread_create(&new, NULL, broadcast_threadfunc, 403 1.1 jmmv &sharedval)); 404 1.1 jmmv 405 1.1 jmmv printf("1: Before waiting.\n"); 406 1.1 jmmv while (count>0) { 407 1.1 jmmv count--; 408 1.1 jmmv total++; 409 1.1 jmmv toggle = 1; 410 1.1 jmmv PTHREAD_REQUIRE(pthread_cond_broadcast(&static_cond)); 411 1.1 jmmv do { 412 1.1 jmmv PTHREAD_REQUIRE(pthread_cond_wait(&static_cond, 413 1.1 jmmv &static_mutex)); 414 1.1 jmmv } while (toggle != 0); 415 1.1 jmmv } 416 1.1 jmmv printf("1: After the loop.\n"); 417 1.1 jmmv 418 1.1 jmmv toggle = 1; 419 1.1 jmmv PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex)); 420 1.1 jmmv PTHREAD_REQUIRE(pthread_cond_signal(&static_cond)); 421 1.1 jmmv 422 1.1 jmmv printf("1: After releasing the mutex.\n"); 423 1.1 jmmv PTHREAD_REQUIRE(pthread_join(new, &joinval)); 424 1.1 jmmv 425 1.1 jmmv printf("1: Thread joined. Final count = %d, total = %d\n", count, 426 1.1 jmmv total); 427 1.1 jmmv 428 1.1 jmmv ATF_REQUIRE_EQ(count, 0); 429 1.1 jmmv ATF_REQUIRE_EQ(total, 50000); 430 1.1 jmmv } 431 1.1 jmmv 432 1.1 jmmv static void * 433 1.1 jmmv bogus_timedwaits_threadfunc(void *arg) 434 1.1 jmmv { 435 1.1 jmmv return NULL; 436 1.1 jmmv } 437 1.1 jmmv 438 1.1 jmmv ATF_TC(bogus_timedwaits); 439 1.1 jmmv ATF_TC_HEAD(bogus_timedwaits, tc) 440 1.1 jmmv { 441 1.1 jmmv atf_tc_set_md_var(tc, "descr", 442 1.1 jmmv "Checks condition variables: bogus timedwaits"); 443 1.1 jmmv } 444 1.1 jmmv ATF_TC_BODY(bogus_timedwaits, tc) 445 1.1 jmmv { 446 1.1 jmmv pthread_t new; 447 1.1 jmmv struct timespec ts; 448 1.1 jmmv struct timeval tv; 449 1.1 jmmv 450 1.1 jmmv printf("condition variable test 6: bogus timedwaits\n"); 451 1.1 jmmv 452 1.1 jmmv PTHREAD_REQUIRE(pthread_mutex_lock(&static_mutex)); 453 1.1 jmmv 454 1.1 jmmv printf("unthreaded test (past)\n"); 455 1.1 jmmv gettimeofday(&tv, NULL); 456 1.1 jmmv tv.tv_sec -= 2; /* Place the time in the past */ 457 1.1 jmmv TIMEVAL_TO_TIMESPEC(&tv, &ts); 458 1.1 jmmv 459 1.1 jmmv ATF_REQUIRE_EQ_MSG(pthread_cond_timedwait(&static_cond, &static_mutex, 460 1.1 jmmv &ts), ETIMEDOUT, "pthread_cond_timedwait() (unthreaded) in the " 461 1.1 jmmv "past"); 462 1.1 jmmv 463 1.1 jmmv printf("unthreaded test (zero time)\n"); 464 1.1 jmmv tv.tv_sec = 0; 465 1.1 jmmv tv.tv_usec = 0; 466 1.1 jmmv TIMEVAL_TO_TIMESPEC(&tv, &ts); 467 1.1 jmmv 468 1.1 jmmv ATF_REQUIRE_EQ_MSG(pthread_cond_timedwait(&static_cond, &static_mutex, 469 1.1 jmmv &ts), ETIMEDOUT, "pthread_cond_timedwait() (unthreaded) with zero " 470 1.1 jmmv "time"); 471 1.1 jmmv 472 1.1 jmmv PTHREAD_REQUIRE(pthread_create(&new, NULL, bogus_timedwaits_threadfunc, 473 1.1 jmmv NULL)); 474 1.1 jmmv PTHREAD_REQUIRE(pthread_join(new, NULL)); 475 1.1 jmmv 476 1.1 jmmv printf("threaded test\n"); 477 1.1 jmmv gettimeofday(&tv, NULL); 478 1.1 jmmv tv.tv_sec -= 2; /* Place the time in the past */ 479 1.1 jmmv TIMEVAL_TO_TIMESPEC(&tv, &ts); 480 1.1 jmmv 481 1.1 jmmv ATF_REQUIRE_EQ_MSG(pthread_cond_timedwait(&static_cond, &static_mutex, 482 1.1 jmmv &ts), ETIMEDOUT, "pthread_cond_timedwait() (threaded) in the past"); 483 1.1 jmmv 484 1.1 jmmv printf("threaded test (zero time)\n"); 485 1.1 jmmv tv.tv_sec = 0; 486 1.1 jmmv tv.tv_usec = 0; 487 1.1 jmmv TIMEVAL_TO_TIMESPEC(&tv, &ts); 488 1.1 jmmv 489 1.1 jmmv ATF_REQUIRE_EQ_MSG(pthread_cond_timedwait(&static_cond, &static_mutex, 490 1.1 jmmv &ts), ETIMEDOUT, "pthread_cond_timedwait() (threaded) with zero " 491 1.1 jmmv "time"); 492 1.1 jmmv 493 1.1 jmmv PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex)); 494 1.1 jmmv } 495 1.1 jmmv 496 1.1 jmmv static void 497 1.1 jmmv unlock(void *arg) 498 1.1 jmmv { 499 1.1 jmmv pthread_mutex_unlock((pthread_mutex_t *)arg); 500 1.1 jmmv } 501 1.1 jmmv 502 1.1 jmmv static void * 503 1.1 jmmv destroy_after_cancel_threadfunc(void *arg) 504 1.1 jmmv { 505 1.1 jmmv PTHREAD_REQUIRE(pthread_mutex_lock(&mutex)); 506 1.1 jmmv 507 1.1 jmmv pthread_cleanup_push(unlock, &mutex); 508 1.1 jmmv 509 1.1 jmmv while (1) { 510 1.1 jmmv share = 1; 511 1.1 jmmv PTHREAD_REQUIRE(pthread_cond_broadcast(&cond)); 512 1.1 jmmv PTHREAD_REQUIRE(pthread_cond_wait(&cond, &mutex)); 513 1.1 jmmv } 514 1.1 jmmv 515 1.1 jmmv pthread_cleanup_pop(0); 516 1.1 jmmv PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex)); 517 1.1 jmmv 518 1.1 jmmv return NULL; 519 1.1 jmmv } 520 1.1 jmmv 521 1.1 jmmv ATF_TC(destroy_after_cancel); 522 1.1 jmmv ATF_TC_HEAD(destroy_after_cancel, tc) 523 1.1 jmmv { 524 1.1 jmmv atf_tc_set_md_var(tc, "descr", "Checks destroying a condition variable " 525 1.1 jmmv "after cancelling a wait"); 526 1.1 jmmv } 527 1.1 jmmv ATF_TC_BODY(destroy_after_cancel, tc) 528 1.1 jmmv { 529 1.1 jmmv pthread_t thread; 530 1.1 jmmv 531 1.1 jmmv PTHREAD_REQUIRE(pthread_mutex_init(&mutex, NULL)); 532 1.1 jmmv PTHREAD_REQUIRE(pthread_cond_init(&cond, NULL)); 533 1.1 jmmv PTHREAD_REQUIRE(pthread_mutex_lock(&mutex)); 534 1.1 jmmv PTHREAD_REQUIRE(pthread_create(&thread, NULL, 535 1.1 jmmv destroy_after_cancel_threadfunc, NULL)); 536 1.1 jmmv 537 1.1 jmmv while (share == 0) { 538 1.1 jmmv PTHREAD_REQUIRE(pthread_cond_wait(&cond, &mutex)); 539 1.1 jmmv } 540 1.1 jmmv 541 1.1 jmmv PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex)); 542 1.1 jmmv PTHREAD_REQUIRE(pthread_cancel(thread)); 543 1.1 jmmv 544 1.1 jmmv PTHREAD_REQUIRE(pthread_join(thread, NULL)); 545 1.1 jmmv PTHREAD_REQUIRE(pthread_cond_destroy(&cond)); 546 1.1 jmmv 547 1.1 jmmv PTHREAD_REQUIRE(pthread_mutex_destroy(&mutex)); 548 1.1 jmmv } 549 1.1 jmmv 550 1.7 christos ATF_TC(condattr); 551 1.7 christos ATF_TC_HEAD(condattr, tc) 552 1.7 christos { 553 1.7 christos atf_tc_set_md_var(tc, "descr", "Checks Condattr"); 554 1.7 christos } 555 1.7 christos ATF_TC_BODY(condattr, tc) 556 1.7 christos { 557 1.7 christos pthread_condattr_t condattr; 558 1.7 christos clockid_t clockid; 559 1.7 christos 560 1.7 christos PTHREAD_REQUIRE(pthread_condattr_init(&condattr)); 561 1.7 christos PTHREAD_REQUIRE(pthread_condattr_setclock(&condattr, CLOCK_REALTIME)); 562 1.7 christos PTHREAD_REQUIRE(pthread_condattr_getclock(&condattr, &clockid)); 563 1.7 christos ATF_REQUIRE_EQ(clockid, CLOCK_REALTIME); 564 1.7 christos 565 1.7 christos PTHREAD_REQUIRE(pthread_condattr_setclock(&condattr, CLOCK_MONOTONIC)); 566 1.7 christos PTHREAD_REQUIRE(pthread_condattr_getclock(&condattr, &clockid)); 567 1.7 christos ATF_REQUIRE_EQ(clockid, CLOCK_MONOTONIC); 568 1.7 christos } 569 1.7 christos 570 1.1 jmmv ATF_TP_ADD_TCS(tp) 571 1.1 jmmv { 572 1.1 jmmv 573 1.1 jmmv ATF_TP_ADD_TC(tp, signal_delay_wait); 574 1.1 jmmv ATF_TP_ADD_TC(tp, signal_before_unlock); 575 1.1 jmmv ATF_TP_ADD_TC(tp, signal_before_unlock_static_init); 576 1.1 jmmv ATF_TP_ADD_TC(tp, signal_wait_race); 577 1.3 jruoho ATF_TP_ADD_TC(tp, cond_timedwait_race); 578 1.1 jmmv ATF_TP_ADD_TC(tp, broadcast); 579 1.1 jmmv ATF_TP_ADD_TC(tp, bogus_timedwaits); 580 1.1 jmmv ATF_TP_ADD_TC(tp, destroy_after_cancel); 581 1.7 christos ATF_TP_ADD_TC(tp, condattr); 582 1.1 jmmv 583 1.1 jmmv return atf_no_error(); 584 1.1 jmmv } 585