1 /* $NetBSD: t_mutex.c,v 1.15 2017/01/16 16:23:41 christos 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.15 2017/01/16 16:23:41 christos Exp $"); 33 34 #include <sys/time.h> /* For timespecadd */ 35 #include <inttypes.h> /* For UINT16_MAX */ 36 #include <pthread.h> 37 #include <stdio.h> 38 #ifdef __FreeBSD__ 39 #include <stdlib.h> 40 #endif 41 #include <string.h> 42 #include <errno.h> 43 #include <time.h> 44 #include <unistd.h> 45 #include <sys/sched.h> 46 #include <sys/param.h> 47 48 #include <atf-c.h> 49 50 #include "h_common.h" 51 52 static pthread_mutex_t mutex; 53 static pthread_mutex_t static_mutex = PTHREAD_MUTEX_INITIALIZER; 54 static int global_x; 55 56 #ifdef TIMEDMUTEX 57 /* This code is used for verifying non-timed specific code */ 58 static struct timespec ts_lengthy = { 59 .tv_sec = UINT16_MAX, 60 .tv_nsec = 0 61 }; 62 /* This code is used for verifying timed-only specific code */ 63 static struct timespec ts_shortlived = { 64 .tv_sec = 0, 65 .tv_nsec = 120 66 }; 67 68 static int 69 mutex_lock(pthread_mutex_t *m, const struct timespec *ts) 70 { 71 struct timespec ts_wait; 72 ATF_REQUIRE(clock_gettime(CLOCK_REALTIME, &ts_wait) != -1); 73 timespecadd(&ts_wait, ts, &ts_wait); 74 75 return pthread_mutex_timedlock(m, &ts_wait); 76 } 77 #else 78 #define mutex_lock(a, b) pthread_mutex_lock(a) 79 #endif 80 81 static void * 82 mutex1_threadfunc(void *arg) 83 { 84 int *param; 85 86 printf("2: Second thread.\n"); 87 88 param = arg; 89 printf("2: Locking mutex\n"); 90 mutex_lock(&mutex, &ts_lengthy); 91 printf("2: Got mutex. *param = %d\n", *param); 92 ATF_REQUIRE_EQ(*param, 20); 93 (*param)++; 94 95 pthread_mutex_unlock(&mutex); 96 97 return param; 98 } 99 100 ATF_TC(mutex1); 101 ATF_TC_HEAD(mutex1, tc) 102 { 103 atf_tc_set_md_var(tc, "descr", "Checks mutexes"); 104 } 105 ATF_TC_BODY(mutex1, tc) 106 { 107 int x; 108 pthread_t new; 109 void *joinval; 110 111 printf("1: Mutex-test 1\n"); 112 113 PTHREAD_REQUIRE(pthread_mutex_init(&mutex, NULL)); 114 x = 1; 115 PTHREAD_REQUIRE(mutex_lock(&mutex, &ts_lengthy)); 116 PTHREAD_REQUIRE(pthread_create(&new, NULL, mutex1_threadfunc, &x)); 117 printf("1: Before changing the value.\n"); 118 sleep(2); 119 x = 20; 120 printf("1: Before releasing the mutex.\n"); 121 sleep(2); 122 PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex)); 123 printf("1: After releasing the mutex.\n"); 124 PTHREAD_REQUIRE(pthread_join(new, &joinval)); 125 126 PTHREAD_REQUIRE(mutex_lock(&mutex, &ts_lengthy)); 127 printf("1: Thread joined. X was %d. Return value (int) was %d\n", 128 x, *(int *)joinval); 129 ATF_REQUIRE_EQ(x, 21); 130 ATF_REQUIRE_EQ(*(int *)joinval, 21); 131 PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex)); 132 } 133 134 #ifdef __FreeBSD__ 135 /* 136 * Increment the value using a noinline function that includes a small delay 137 * to increase the window for the RMW data race. 138 */ 139 __noinline static int 140 increment(int value) 141 { 142 for (volatile int i = 0; i < 100; i++) { 143 /* Small delay between read+write to increase chance of race */ 144 __compiler_membar(); 145 } 146 return value + 1; 147 } 148 149 static volatile bool thread2_started = false; 150 #endif 151 152 static void * 153 mutex2_threadfunc(void *arg) 154 { 155 long count = *(int *)arg; 156 157 #ifdef __FreeBSD__ 158 thread2_started = true; 159 #endif 160 printf("2: Second thread (%p). Count is %ld\n", pthread_self(), count); 161 162 while (count--) { 163 PTHREAD_REQUIRE(mutex_lock(&mutex, &ts_lengthy)); 164 #ifdef __FreeBSD__ 165 global_x = increment(global_x); 166 #else 167 global_x++; 168 #endif 169 PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex)); 170 } 171 172 return (void *)count; 173 } 174 175 ATF_TC(mutex2); 176 ATF_TC_HEAD(mutex2, tc) 177 { 178 atf_tc_set_md_var(tc, "descr", "Checks mutexes"); 179 #ifdef __NetBSD__ 180 #if defined(__powerpc__) 181 atf_tc_set_md_var(tc, "timeout", "40"); 182 #endif 183 #endif 184 } 185 ATF_TC_BODY(mutex2, tc) 186 { 187 int count, count2; 188 #ifdef __FreeBSD__ 189 int num_increments; 190 #endif 191 pthread_t new; 192 void *joinval; 193 194 printf("1: Mutex-test 2\n"); 195 196 #ifdef __NetBSD__ 197 #if defined(__powerpc__) 198 atf_tc_expect_timeout("PR port-powerpc/44387"); 199 #endif 200 #endif 201 202 PTHREAD_REQUIRE(pthread_mutex_init(&mutex, NULL)); 203 204 global_x = 0; 205 #ifdef __FreeBSD__ 206 num_increments = count = count2 = 1000; 207 if (getenv("NUM_ITERATIONS") != NULL) { 208 num_increments = count = count2 = 209 MIN(INT_MAX, strtoul(getenv("NUM_ITERATIONS"), NULL, 10)); 210 } 211 printf("Will use %d iterations\n", num_increments); 212 #else 213 count = count2 = 10000000; 214 #endif 215 216 PTHREAD_REQUIRE(mutex_lock(&mutex, &ts_lengthy)); 217 #ifdef __FreeBSD__ 218 thread2_started = false; 219 #endif 220 PTHREAD_REQUIRE(pthread_create(&new, NULL, mutex2_threadfunc, &count2)); 221 222 printf("1: Thread %p\n", pthread_self()); 223 #ifdef __FreeBSD__ 224 while (!thread2_started) { 225 /* Wait for thread 2 to start to increase chance of race */ 226 } 227 printf("1: Unlocking to start increment loop %p\n", pthread_self()); 228 #endif 229 PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex)); 230 231 while (count--) { 232 PTHREAD_REQUIRE(mutex_lock(&mutex, &ts_lengthy)); 233 #ifdef __FreeBSD__ 234 global_x = increment(global_x); 235 #else 236 global_x++; 237 #endif 238 PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex)); 239 } 240 241 PTHREAD_REQUIRE(pthread_join(new, &joinval)); 242 243 PTHREAD_REQUIRE(mutex_lock(&mutex, &ts_lengthy)); 244 printf("1: Thread joined. X was %d. Return value (long) was %ld\n", 245 global_x, (long)joinval); 246 #ifdef __FreeBSD__ 247 ATF_REQUIRE_EQ_MSG(count, -1, "%d", count); 248 ATF_REQUIRE_EQ_MSG((long)joinval, -1, "%ld", (long)joinval); 249 ATF_REQUIRE_EQ_MSG(global_x, num_increments * 2, "%d vs %d", global_x, 250 num_increments * 2); 251 #else 252 ATF_REQUIRE_EQ(global_x, 20000000); 253 #endif 254 255 #ifdef __NetBSD__ 256 #if defined(__powerpc__) 257 /* XXX force a timeout in ppc case since an un-triggered race 258 otherwise looks like a "failure" */ 259 /* We sleep for longer than the timeout to make ATF not 260 complain about unexpected success */ 261 sleep(41); 262 #endif 263 #endif 264 } 265 266 #ifdef __FreeBSD__ 267 static volatile bool thread3_started = false; 268 #endif 269 270 static void * 271 mutex3_threadfunc(void *arg) 272 { 273 long count = *(int *)arg; 274 275 #ifdef __FreeBSD__ 276 thread3_started = true; 277 #endif 278 printf("2: Second thread (%p). Count is %ld\n", pthread_self(), count); 279 280 while (count--) { 281 PTHREAD_REQUIRE(mutex_lock(&static_mutex, &ts_lengthy)); 282 #ifdef __FreeBSD__ 283 global_x = increment(global_x); 284 #else 285 global_x++; 286 #endif 287 PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex)); 288 } 289 290 return (void *)count; 291 } 292 293 ATF_TC(mutex3); 294 ATF_TC_HEAD(mutex3, tc) 295 { 296 atf_tc_set_md_var(tc, "descr", "Checks mutexes using a static " 297 "initializer"); 298 #ifdef __NetBSD__ 299 #if defined(__powerpc__) 300 atf_tc_set_md_var(tc, "timeout", "40"); 301 #endif 302 #endif 303 } 304 ATF_TC_BODY(mutex3, tc) 305 { 306 int count, count2; 307 #ifdef __FreeBSD__ 308 int num_increments; 309 #endif 310 pthread_t new; 311 void *joinval; 312 313 printf("1: Mutex-test 3\n"); 314 315 #ifdef __NetBSD__ 316 #if defined(__powerpc__) 317 atf_tc_expect_timeout("PR port-powerpc/44387"); 318 #endif 319 #endif 320 321 global_x = 0; 322 #ifdef __FreeBSD__ 323 num_increments = count = count2 = 1000; 324 if (getenv("NUM_ITERATIONS") != NULL) { 325 num_increments = count = count2 = 326 MIN(INT_MAX, strtoul(getenv("NUM_ITERATIONS"), NULL, 10)); 327 } 328 printf("Will use %d iterations\n", num_increments); 329 #else 330 count = count2 = 10000000; 331 #endif 332 333 PTHREAD_REQUIRE(mutex_lock(&static_mutex, &ts_lengthy)); 334 PTHREAD_REQUIRE(pthread_create(&new, NULL, mutex3_threadfunc, &count2)); 335 336 printf("1: Thread %p\n", pthread_self()); 337 #ifdef __FreeBSD__ 338 while (!thread3_started) { 339 /* Wait for thread 3 to start to increase chance of race */ 340 } 341 printf("1: Unlocking to start increment loop %p\n", pthread_self()); 342 #endif 343 PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex)); 344 345 while (count--) { 346 PTHREAD_REQUIRE(mutex_lock(&static_mutex, &ts_lengthy)); 347 #ifdef __FreeBSD__ 348 global_x = increment(global_x); 349 #else 350 global_x++; 351 #endif 352 PTHREAD_REQUIRE(pthread_mutex_unlock(&static_mutex)); 353 } 354 355 PTHREAD_REQUIRE(pthread_join(new, &joinval)); 356 357 PTHREAD_REQUIRE(mutex_lock(&static_mutex, &ts_lengthy)); 358 printf("1: Thread joined. X was %d. Return value (long) was %ld\n", 359 global_x, (long)joinval); 360 #ifdef __FreeBSD__ 361 ATF_REQUIRE_EQ_MSG(count, -1, "%d", count); 362 ATF_REQUIRE_EQ_MSG((long)joinval, -1, "%ld", (long)joinval); 363 ATF_REQUIRE_EQ_MSG(global_x, num_increments * 2, "%d vs %d", global_x, 364 num_increments * 2); 365 #else 366 ATF_REQUIRE_EQ(global_x, 20000000); 367 #endif 368 #ifdef __NetBSD__ 369 #if defined(__powerpc__) 370 /* XXX force a timeout in ppc case since an un-triggered race 371 otherwise looks like a "failure" */ 372 /* We sleep for longer than the timeout to make ATF not 373 complain about unexpected success */ 374 sleep(41); 375 #endif 376 #endif 377 } 378 379 static void * 380 mutex4_threadfunc(void *arg) 381 { 382 int *param; 383 384 printf("2: Second thread.\n"); 385 386 param = arg; 387 printf("2: Locking mutex\n"); 388 PTHREAD_REQUIRE(mutex_lock(&mutex, &ts_lengthy)); 389 printf("2: Got mutex. *param = %d\n", *param); 390 (*param)++; 391 392 PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex)); 393 394 return param; 395 } 396 397 ATF_TC(mutex4); 398 ATF_TC_HEAD(mutex4, tc) 399 { 400 atf_tc_set_md_var(tc, "descr", "Checks mutexes"); 401 } 402 ATF_TC_BODY(mutex4, tc) 403 { 404 int x; 405 pthread_t new; 406 pthread_mutexattr_t mattr; 407 void *joinval; 408 409 printf("1: Mutex-test 4\n"); 410 411 PTHREAD_REQUIRE(pthread_mutexattr_init(&mattr)); 412 PTHREAD_REQUIRE(pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_RECURSIVE)); 413 414 PTHREAD_REQUIRE(pthread_mutex_init(&mutex, &mattr)); 415 416 PTHREAD_REQUIRE(pthread_mutexattr_destroy(&mattr)); 417 418 x = 1; 419 PTHREAD_REQUIRE(mutex_lock(&mutex, &ts_lengthy)); 420 PTHREAD_REQUIRE(pthread_create(&new, NULL, mutex4_threadfunc, &x)); 421 422 printf("1: Before recursively acquiring the mutex.\n"); 423 PTHREAD_REQUIRE(mutex_lock(&mutex, &ts_lengthy)); 424 425 printf("1: Before releasing the mutex once.\n"); 426 sleep(2); 427 PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex)); 428 printf("1: After releasing the mutex once.\n"); 429 430 x = 20; 431 432 printf("1: Before releasing the mutex twice.\n"); 433 sleep(2); 434 PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex)); 435 printf("1: After releasing the mutex twice.\n"); 436 437 PTHREAD_REQUIRE(pthread_join(new, &joinval)); 438 439 PTHREAD_REQUIRE(mutex_lock(&mutex, &ts_lengthy)); 440 printf("1: Thread joined. X was %d. Return value (int) was %d\n", 441 x, *(int *)joinval); 442 ATF_REQUIRE_EQ(x, 21); 443 ATF_REQUIRE_EQ(*(int *)joinval, 21); 444 PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex)); 445 } 446 447 #ifdef __NetBSD__ 448 static pthread_mutexattr_t attr5; 449 static pthread_mutex_t mutex5; 450 static int min_fifo_prio, max_fifo_prio; 451 452 static void * 453 child_func(void* arg) 454 { 455 int res; 456 457 printf("child is waiting\n"); 458 res = _sched_protect(-2); 459 ATF_REQUIRE_EQ_MSG(res, -1, "sched_protect returned %d", res); 460 ATF_REQUIRE_EQ(errno, ENOENT); 461 PTHREAD_REQUIRE(mutex_lock(&mutex5, &ts_lengthy)); 462 printf("child is owning resource\n"); 463 res = _sched_protect(-2); 464 ATF_REQUIRE_EQ(res, max_fifo_prio); 465 PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex5)); 466 printf("child is done\n"); 467 468 return 0; 469 } 470 471 ATF_TC(mutex5); 472 ATF_TC_HEAD(mutex5, tc) 473 { 474 atf_tc_set_md_var(tc, "descr", "Checks mutexes for priority setting"); 475 atf_tc_set_md_var(tc, "require.user", "root"); 476 } 477 478 ATF_TC_BODY(mutex5, tc) 479 { 480 int res; 481 struct sched_param param; 482 pthread_t child; 483 484 min_fifo_prio = sched_get_priority_min(SCHED_FIFO); 485 max_fifo_prio = sched_get_priority_max(SCHED_FIFO); 486 printf("min prio for FIFO = %d\n", min_fifo_prio); 487 param.sched_priority = min_fifo_prio; 488 489 /* = 0 OTHER, 1 FIFO, 2 RR, -1 NONE */ 490 res = sched_setscheduler(getpid(), SCHED_FIFO, ¶m); 491 printf("previous policy used = %d\n", res); 492 493 res = sched_getscheduler(getpid()); 494 ATF_REQUIRE_EQ_MSG(res, SCHED_FIFO, "sched %d != FIFO %d", res, 495 SCHED_FIFO); 496 497 PTHREAD_REQUIRE(pthread_mutexattr_init(&attr5)); 498 PTHREAD_REQUIRE(pthread_mutexattr_setprotocol(&attr5, 499 PTHREAD_PRIO_PROTECT)); 500 PTHREAD_REQUIRE(pthread_mutexattr_setprioceiling(&attr5, 501 max_fifo_prio)); 502 503 PTHREAD_REQUIRE(pthread_mutex_init(&mutex5, &attr5)); 504 PTHREAD_REQUIRE(mutex_lock(&mutex5, &ts_lengthy)); 505 printf("enter critical section for main\n"); 506 PTHREAD_REQUIRE(pthread_create(&child, NULL, child_func, NULL)); 507 printf("main starts to sleep\n"); 508 sleep(10); 509 printf("main completes\n"); 510 PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex5)); 511 PTHREAD_REQUIRE(pthread_join(child, NULL)); 512 } 513 514 static pthread_mutex_t mutex6; 515 static int start = 0; 516 static uintmax_t high_cnt = 0, low_cnt = 0, MAX_LOOP = 100000000; 517 518 static void * 519 high_prio(void* arg) 520 { 521 struct sched_param param; 522 int policy; 523 param.sched_priority = min_fifo_prio + 10; 524 pthread_t childid = pthread_self(); 525 526 PTHREAD_REQUIRE(pthread_setschedparam(childid, 1, ¶m)); 527 PTHREAD_REQUIRE(pthread_getschedparam(childid, &policy, ¶m)); 528 printf("high protect = %d, prio = %d\n", 529 _sched_protect(-2), param.sched_priority); 530 ATF_REQUIRE_EQ(policy, 1); 531 printf("high prio = %d\n", param.sched_priority); 532 sleep(1); 533 long tmp = 0; 534 for (int i = 0; i < 20; i++) { 535 while (high_cnt < MAX_LOOP) { 536 tmp += (123456789 % 1234) * (987654321 % 54321); 537 high_cnt += 1; 538 } 539 high_cnt = 0; 540 sleep(1); 541 } 542 PTHREAD_REQUIRE(mutex_lock(&mutex6, &ts_lengthy)); 543 if (start == 0) start = 2; 544 PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex6)); 545 546 return 0; 547 } 548 549 static void * 550 low_prio(void* arg) 551 { 552 struct sched_param param; 553 int policy; 554 param.sched_priority = min_fifo_prio; 555 pthread_t childid = pthread_self(); 556 int res = _sched_protect(max_fifo_prio); 557 ATF_REQUIRE_EQ(res, 0); 558 PTHREAD_REQUIRE(pthread_setschedparam(childid, 1, ¶m)); 559 PTHREAD_REQUIRE(pthread_getschedparam(childid, &policy, ¶m)); 560 printf("low protect = %d, prio = %d\n", _sched_protect(-2), 561 param.sched_priority); 562 ATF_REQUIRE_EQ(policy, 1); 563 printf("low prio = %d\n", param.sched_priority); 564 sleep(1); 565 long tmp = 0; 566 for (int i = 0; i < 20; i++) { 567 while (low_cnt < MAX_LOOP) { 568 tmp += (123456789 % 1234) * (987654321 % 54321); 569 low_cnt += 1; 570 } 571 low_cnt = 0; 572 sleep(1); 573 } 574 PTHREAD_REQUIRE(mutex_lock(&mutex6, &ts_lengthy)); 575 if (start == 0) 576 start = 1; 577 PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex6)); 578 579 return 0; 580 } 581 582 ATF_TC(mutex6); 583 ATF_TC_HEAD(mutex6, tc) 584 { 585 atf_tc_set_md_var(tc, "descr", 586 "Checks scheduling for priority ceiling"); 587 atf_tc_set_md_var(tc, "require.user", "root"); 588 } 589 590 /* 591 * 1. main thread sets itself to be a realtime task and launched two tasks, 592 * one has higher priority and the other has lower priority. 593 * 2. each child thread(low and high priority thread) sets its scheduler and 594 * priority. 595 * 3. each child thread did several rounds of computation, after each round it 596 * sleep 1 second. 597 * 4. the child thread with low priority will call _sched_protect to increase 598 * its protect priority. 599 * 5. We verify the thread with low priority runs first. 600 * 601 * Why does it work? From the main thread, we launched the high 602 * priority thread first. This gives this thread the benefit of 603 * starting first. The low priority thread did not call _sched_protect(2). 604 * The high priority thread should finish the task first. After each 605 * round of computation, we call sleep, to put the task into the 606 * sleep queue, and wake up again after the timer expires. This 607 * gives the scheduler the chance to decide which task to run. So, 608 * the thread with real high priority will always block the thread 609 * with real low priority. 610 * 611 */ 612 ATF_TC_BODY(mutex6, tc) 613 { 614 struct sched_param param; 615 int res; 616 pthread_t high, low; 617 618 min_fifo_prio = sched_get_priority_min(SCHED_FIFO); 619 max_fifo_prio = sched_get_priority_max(SCHED_FIFO); 620 PTHREAD_REQUIRE(pthread_mutex_init(&mutex, NULL)); 621 printf("min_fifo_prio = %d, max_fifo_info = %d\n", min_fifo_prio, 622 max_fifo_prio); 623 624 param.sched_priority = min_fifo_prio; 625 res = sched_setscheduler(getpid(), SCHED_FIFO, ¶m); 626 printf("previous policy used = %d\n", res); 627 628 res = sched_getscheduler(getpid()); 629 ATF_REQUIRE_EQ(res, 1); 630 PTHREAD_REQUIRE(pthread_create(&high, NULL, high_prio, NULL)); 631 PTHREAD_REQUIRE(pthread_create(&low, NULL, low_prio, NULL)); 632 sleep(5); 633 PTHREAD_REQUIRE(pthread_join(low, NULL)); 634 PTHREAD_REQUIRE(pthread_join(high, NULL)); 635 636 ATF_REQUIRE_EQ(start, 1); 637 } 638 #endif 639 640 ATF_TC(mutexattr1); 641 ATF_TC_HEAD(mutexattr1, tc) 642 { 643 atf_tc_set_md_var(tc, "descr", "Checks mutexattr"); 644 } 645 646 ATF_TC_BODY(mutexattr1, tc) 647 { 648 pthread_mutexattr_t mattr; 649 int protocol, target; 650 651 PTHREAD_REQUIRE(pthread_mutexattr_init(&mattr)); 652 653 target = PTHREAD_PRIO_NONE; 654 PTHREAD_REQUIRE(pthread_mutexattr_setprotocol(&mattr, target)); 655 PTHREAD_REQUIRE(pthread_mutexattr_getprotocol(&mattr, &protocol)); 656 ATF_REQUIRE_EQ(protocol, target); 657 658 /* 659 target = PTHREAD_PRIO_INHERIT; 660 PTHREAD_REQUIRE(pthread_mutexattr_setprotocol(&mattr, target)); 661 PTHREAD_REQUIRE(pthread_mutexattr_getprotocol(&mattr, &protocol)); 662 ATF_REQUIRE_EQ(protocol, target); 663 */ 664 665 target = PTHREAD_PRIO_PROTECT; 666 PTHREAD_REQUIRE(pthread_mutexattr_setprotocol(&mattr, target)); 667 PTHREAD_REQUIRE(pthread_mutexattr_getprotocol(&mattr, &protocol)); 668 ATF_REQUIRE_EQ(protocol, target); 669 } 670 671 ATF_TC(mutexattr2); 672 ATF_TC_HEAD(mutexattr2, tc) 673 { 674 atf_tc_set_md_var(tc, "descr", "Checks mutexattr"); 675 } 676 677 ATF_TC_BODY(mutexattr2, tc) 678 { 679 pthread_mutexattr_t mattr; 680 681 #ifdef __FreeBSD__ 682 atf_tc_expect_fail("fails on i == 0 with: " 683 "pthread_mutexattr_setprioceiling(&mattr, i): Invalid argument " 684 "-- PR # 211802"); 685 #endif 686 687 PTHREAD_REQUIRE(pthread_mutexattr_init(&mattr)); 688 int max_prio = sched_get_priority_max(SCHED_FIFO); 689 int min_prio = sched_get_priority_min(SCHED_FIFO); 690 for (int i = min_prio; i <= max_prio; i++) { 691 int prioceiling; 692 int protocol; 693 694 PTHREAD_REQUIRE(pthread_mutexattr_getprotocol(&mattr, 695 &protocol)); 696 697 printf("priority: %d\nprotocol: %d\n", i, protocol); 698 PTHREAD_REQUIRE(pthread_mutexattr_setprioceiling(&mattr, i)); 699 PTHREAD_REQUIRE(pthread_mutexattr_getprioceiling(&mattr, 700 &prioceiling)); 701 printf("prioceiling: %d\n", prioceiling); 702 ATF_REQUIRE_EQ(i, prioceiling); 703 } 704 } 705 706 #ifdef TIMEDMUTEX 707 ATF_TC(timedmutex1); 708 ATF_TC_HEAD(timedmutex1, tc) 709 { 710 atf_tc_set_md_var(tc, "descr", "Checks timeout on selflock"); 711 } 712 713 ATF_TC_BODY(timedmutex1, tc) 714 { 715 716 printf("Timed mutex-test 1\n"); 717 718 PTHREAD_REQUIRE(pthread_mutex_init(&mutex, NULL)); 719 720 printf("Before acquiring mutex\n"); 721 PTHREAD_REQUIRE(pthread_mutex_lock(&mutex)); 722 723 printf("Before endeavor to reacquire timed-mutex (timeout expected)\n"); 724 PTHREAD_REQUIRE_STATUS(mutex_lock(&mutex, &ts_shortlived), 725 ETIMEDOUT); 726 727 printf("Unlocking mutex\n"); 728 PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex)); 729 } 730 731 ATF_TC(timedmutex2); 732 ATF_TC_HEAD(timedmutex2, tc) 733 { 734 atf_tc_set_md_var(tc, "descr", 735 "Checks timeout on selflock with timedlock"); 736 } 737 738 ATF_TC_BODY(timedmutex2, tc) 739 { 740 741 printf("Timed mutex-test 2\n"); 742 743 PTHREAD_REQUIRE(pthread_mutex_init(&mutex, NULL)); 744 745 printf("Before acquiring mutex with timedlock\n"); 746 PTHREAD_REQUIRE(mutex_lock(&mutex, &ts_lengthy)); 747 748 printf("Before endeavor to reacquire timed-mutex (timeout expected)\n"); 749 PTHREAD_REQUIRE_STATUS(mutex_lock(&mutex, &ts_shortlived), 750 ETIMEDOUT); 751 752 printf("Unlocking mutex\n"); 753 PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex)); 754 } 755 756 ATF_TC(timedmutex3); 757 ATF_TC_HEAD(timedmutex3, tc) 758 { 759 atf_tc_set_md_var(tc, "descr", 760 "Checks timeout on selflock in a new thread"); 761 } 762 763 static void * 764 timedmtx_thrdfunc(void *arg) 765 { 766 printf("Before endeavor to reacquire timed-mutex (timeout expected)\n"); 767 PTHREAD_REQUIRE_STATUS(mutex_lock(&mutex, &ts_shortlived), 768 ETIMEDOUT); 769 770 return NULL; 771 } 772 773 ATF_TC_BODY(timedmutex3, tc) 774 { 775 pthread_t new; 776 777 printf("Timed mutex-test 3\n"); 778 779 PTHREAD_REQUIRE(pthread_mutex_init(&mutex, NULL)); 780 781 printf("Before acquiring mutex with timedlock\n"); 782 PTHREAD_REQUIRE(pthread_mutex_lock(&mutex)); 783 784 printf("Before creating new thread\n"); 785 PTHREAD_REQUIRE(pthread_create(&new, NULL, timedmtx_thrdfunc, NULL)); 786 787 printf("Before joining the mutex\n"); 788 PTHREAD_REQUIRE(pthread_join(new, NULL)); 789 790 printf("Unlocking mutex\n"); 791 PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex)); 792 } 793 794 ATF_TC(timedmutex4); 795 ATF_TC_HEAD(timedmutex4, tc) 796 { 797 atf_tc_set_md_var(tc, "descr", 798 "Checks timeout on selflock with timedlock in a new thread"); 799 } 800 801 ATF_TC_BODY(timedmutex4, tc) 802 { 803 pthread_t new; 804 805 printf("Timed mutex-test 4\n"); 806 807 PTHREAD_REQUIRE(pthread_mutex_init(&mutex, NULL)); 808 809 printf("Before acquiring mutex with timedlock\n"); 810 PTHREAD_REQUIRE(mutex_lock(&mutex, &ts_lengthy)); 811 812 printf("Before creating new thread\n"); 813 PTHREAD_REQUIRE(pthread_create(&new, NULL, timedmtx_thrdfunc, NULL)); 814 815 printf("Before joining the mutex\n"); 816 PTHREAD_REQUIRE(pthread_join(new, NULL)); 817 818 printf("Unlocking mutex\n"); 819 PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex)); 820 } 821 #endif 822 823 ATF_TP_ADD_TCS(tp) 824 { 825 ATF_TP_ADD_TC(tp, mutex1); 826 ATF_TP_ADD_TC(tp, mutex2); 827 ATF_TP_ADD_TC(tp, mutex3); 828 ATF_TP_ADD_TC(tp, mutex4); 829 #ifdef __NetBSD__ 830 ATF_TP_ADD_TC(tp, mutex5); 831 ATF_TP_ADD_TC(tp, mutex6); 832 #endif 833 ATF_TP_ADD_TC(tp, mutexattr1); 834 ATF_TP_ADD_TC(tp, mutexattr2); 835 836 #ifdef TIMEDMUTEX 837 ATF_TP_ADD_TC(tp, timedmutex1); 838 ATF_TP_ADD_TC(tp, timedmutex2); 839 ATF_TP_ADD_TC(tp, timedmutex3); 840 ATF_TP_ADD_TC(tp, timedmutex4); 841 #endif 842 843 return atf_no_error(); 844 } 845