1 /* 2 * Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 #include <errno.h> 7 #include <fcntl.h> 8 #include <stdint.h> 9 #include <stdio.h> 10 #include <stdlib.h> 11 #include <string.h> 12 #include <unistd.h> 13 #include <semaphore.h> 14 #include <sys/mman.h> 15 #include <sys/stat.h> 16 #include <sys/time.h> 17 #include <sys/wait.h> 18 #include <time.h> 19 20 21 #ifdef __HAIKU__ 22 # include <OS.h> 23 #else 24 25 typedef int64_t bigtime_t; 26 27 static bigtime_t 28 system_time() 29 { 30 timeval tv; 31 gettimeofday(&tv, NULL); 32 return (bigtime_t)tv.tv_sec * 1000000 + tv.tv_usec; 33 } 34 35 36 #endif // !__HAIKU__ 37 38 39 static timespec* 40 absolute_timeout(timespec& timeout, bigtime_t relativeTimeout) 41 { 42 timeval tv; 43 gettimeofday(&tv, NULL); 44 timeout.tv_sec = tv.tv_sec + relativeTimeout / 1000000; 45 timeout.tv_nsec = (tv.tv_usec + relativeTimeout % 1000000) * 1000; 46 if (timeout.tv_nsec > 1000000000) { 47 timeout.tv_sec++; 48 timeout.tv_nsec -= 1000000000; 49 } 50 51 return &timeout; 52 } 53 54 55 template<typename Type> 56 static void 57 _assert_equals(const char* test, const Type& expected, const Type& actual, 58 int lineNumber) 59 { 60 if (actual == expected) 61 return; 62 63 fprintf(stderr, "%s FAILED in line %d\n", test, lineNumber); 64 exit(1); 65 } 66 67 68 template<typename Type> 69 static void 70 _assert_equals_not(const char* test, const Type& unexpected, const Type& actual, 71 int lineNumber) 72 { 73 if (actual != unexpected) 74 return; 75 76 fprintf(stderr, "%s FAILED in line %d\n", test, lineNumber); 77 exit(1); 78 } 79 80 81 static void 82 _assert_time_equals(const char* test, bigtime_t expected, 83 bigtime_t actual, int lineNumber) 84 { 85 // allow 5% deviation 86 bigtime_t diff = actual > expected ? actual - expected : expected - actual; 87 if (diff <= expected / 20) 88 return; 89 90 fprintf(stderr, "%s FAILED in line %d: expected time: %lld, actual: %lld\n", 91 test, lineNumber, (long long)expected, (long long)actual); 92 exit(1); 93 } 94 95 96 static void 97 _assert_posix_bool_success(const char* test, bool success, int lineNumber) 98 { 99 if (success) 100 return; 101 102 fprintf(stderr, "%s FAILED in line %d: %s\n", test, lineNumber, 103 strerror(errno)); 104 exit(1); 105 } 106 107 108 static void 109 _assert_posix_bool_error(const char* test, int expectedError, bool success, 110 int lineNumber) 111 { 112 if (success) { 113 fprintf(stderr, "%s FAILED in line %d: call succeeded unexpectedly\n", 114 test, lineNumber); 115 exit(1); 116 } 117 118 if (errno != expectedError) { 119 fprintf(stderr, "%s FAILED in line %d: call set unexpected error " 120 "code \"%s\" (0x%x), expected: \"%s\" (0x%x)\n", test, lineNumber, 121 strerror(errno), errno, strerror(expectedError), expectedError); 122 exit(1); 123 } 124 } 125 126 127 static void 128 test_set(const char* testSet) 129 { 130 printf("\nTEST SET: %s\n", testSet); 131 } 132 133 134 static void 135 test_ok(const char* test) 136 { 137 if (test != NULL) 138 printf("%s OK\n", test); 139 } 140 141 142 static void 143 _wait_for_child(const char* test, pid_t child, int lineNumber) 144 { 145 int status; 146 pid_t result = wait(&status); 147 _assert_posix_bool_success(test, result >= 0, lineNumber); 148 _assert_equals(test, child, result, lineNumber); 149 _assert_equals(test, 0, status, lineNumber); 150 } 151 152 153 #if 0 154 static void 155 dump_sem(const char* name, sem_t* sem) 156 { 157 printf("%s, %p: ", name, sem); 158 for (size_t i = 0; i < sizeof(sem_t); i++) 159 printf("%02x", ((char*)sem)[i]); 160 printf("\n"); 161 } 162 #endif 163 164 165 #define TEST_SET(testSet) test_set(testSet) 166 #define TEST(test) test_ok(currentTest); currentTest = (test) 167 168 #define assert_equals(expected, actual) \ 169 _assert_equals(currentTest, (expected), (actual), __LINE__) 170 171 #define assert_equals_not(expected, actual) \ 172 _assert_equals_not(currentTest, (expected), (actual), __LINE__) 173 174 #define assert_time_equals(expected, actual) \ 175 _assert_time_equals(currentTest, (expected), (actual), __LINE__) 176 177 #define assert_posix_bool_success(success) \ 178 _assert_posix_bool_success(currentTest, (success), __LINE__) 179 180 #define assert_posix_success(result) \ 181 _assert_posix_bool_success(currentTest, (result) == 0, __LINE__) 182 183 #define assert_posix_bool_error(expectedError, success) \ 184 _assert_posix_bool_error(currentTest, (expectedError), (success), __LINE__) 185 186 #define assert_posix_error(expectedError, result) \ 187 _assert_posix_bool_error(currentTest, (expectedError), (result) == 0, \ 188 __LINE__) 189 190 #define wait_for_child(child) \ 191 _wait_for_child(currentTest, (child), __LINE__) 192 193 194 static const char* const kSemName1 = "/test_sem1"; 195 196 197 static void 198 test_open_close_unlink() 199 { 200 TEST_SET("sem_{open,close,unlink}()"); 201 202 const char* currentTest = NULL; 203 204 // open non-existing with O_CREAT 205 TEST("sem_open(O_CREAT) non-existing"); 206 sem_t* sem = sem_open(kSemName1, O_CREAT, S_IRUSR | S_IWUSR, 1); 207 assert_posix_bool_success(sem != SEM_FAILED); 208 209 // close 210 TEST("sem_close()"); 211 assert_posix_success(sem_close(sem)); 212 213 // open existing with O_CREAT 214 TEST("sem_open(O_CREAT) existing"); 215 sem = sem_open(kSemName1, O_CREAT, S_IRUSR | S_IWUSR, 1); 216 assert_posix_bool_success(sem != SEM_FAILED); 217 218 // close 219 TEST("sem_close()"); 220 assert_posix_success(sem_close(sem)); 221 222 // open existing without O_CREAT 223 TEST("sem_open() existing"); 224 sem = sem_open(kSemName1, 0); 225 assert_posix_bool_success(sem != SEM_FAILED); 226 227 // re-open existing without O_CREAT 228 TEST("sem_open() existing"); 229 sem_t* sem2 = sem_open(kSemName1, 0); 230 assert_posix_bool_success(sem2 != SEM_FAILED); 231 assert_equals(sem, sem2); 232 233 // close 234 TEST("sem_close()"); 235 assert_posix_success(sem_close(sem)); 236 237 // close 238 TEST("sem_close()"); 239 assert_posix_success(sem_close(sem)); 240 241 // open existing with O_CREAT | O_EXCL 242 TEST("sem_open(O_CREAT | O_EXCL) existing"); 243 sem = sem_open(kSemName1, O_CREAT | O_EXCL, S_IRUSR | S_IWUSR, 1); 244 assert_posix_bool_error(EEXIST, sem != SEM_FAILED); 245 246 // open existing without O_CREAT 247 TEST("sem_open() existing"); 248 sem = sem_open(kSemName1, 0); 249 assert_posix_bool_success(sem != SEM_FAILED); 250 251 // unlink 252 TEST("unlink() existing"); 253 assert_posix_success(sem_unlink(kSemName1)); 254 255 // open non-existing with O_CREAT | O_EXCL 256 TEST("sem_open(O_CREAT | O_EXCL) non-existing"); 257 sem2 = sem_open(kSemName1, O_CREAT | O_EXCL, S_IRUSR | S_IWUSR, 2); 258 assert_posix_bool_success(sem2 != SEM_FAILED); 259 assert_equals_not(sem, sem2); 260 261 // unlink 262 TEST("unlink() existing"); 263 assert_posix_success(sem_unlink(kSemName1)); 264 265 // unlink 266 TEST("unlink() non-existing"); 267 assert_posix_error(ENOENT, sem_unlink(kSemName1)); 268 269 // close 270 TEST("sem_close()"); 271 assert_posix_success(sem_close(sem)); 272 273 // close 274 TEST("sem_close()"); 275 assert_posix_success(sem_close(sem2)); 276 277 TEST("done"); 278 } 279 280 281 static void 282 test_init_destroy() 283 { 284 TEST_SET("sem_{init,destroy}()"); 285 286 const char* currentTest = NULL; 287 288 // init 289 TEST("sem_init()"); 290 sem_t sem; 291 assert_posix_success(sem_init(&sem, 0, 1)); 292 293 // destroy 294 TEST("sem_destroy()"); 295 assert_posix_success(sem_destroy(&sem)); 296 297 // init 298 TEST("sem_init()"); 299 assert_posix_success(sem_init(&sem, 0, 1)); 300 301 // init 302 TEST("sem_init()"); 303 sem_t sem2; 304 assert_posix_success(sem_init(&sem2, 0, 2)); 305 306 // destroy 307 TEST("sem_destroy()"); 308 assert_posix_success(sem_destroy(&sem)); 309 310 // destroy 311 TEST("sem_destroy()"); 312 assert_posix_success(sem_destroy(&sem2)); 313 314 TEST("done"); 315 } 316 317 318 static void 319 test_open_close_fork() 320 { 321 TEST_SET("sem_{open,close}() with fork()"); 322 323 const char* currentTest = NULL; 324 325 // open non-existing with O_CREAT 326 TEST("sem_open(O_CREAT) non-existing"); 327 sem_t* sem = sem_open(kSemName1, O_CREAT, S_IRUSR | S_IWUSR, 1); 328 assert_posix_bool_success(sem != SEM_FAILED); 329 330 TEST("close_sem() forked"); 331 pid_t child = fork(); 332 assert_posix_bool_success(child >= 0); 333 334 if (child == 0) { 335 // child 336 assert_posix_success(sem_close(sem)); 337 exit(0); 338 } else { 339 // parent 340 assert_posix_success(sem_close(sem)); 341 wait_for_child(child); 342 } 343 344 TEST("sem_open() existing forked"); 345 child = fork(); 346 assert_posix_bool_success(child >= 0); 347 348 if (child == 0) { 349 // child 350 sem = sem_open(kSemName1, O_CREAT); 351 assert_posix_bool_success(sem != SEM_FAILED); 352 exit(0); 353 } else { 354 // parent 355 sem = sem_open(kSemName1, O_CREAT); 356 wait_for_child(child); 357 assert_posix_success(sem_close(sem)); 358 } 359 360 TEST("done"); 361 } 362 363 364 static void 365 test_init_destroy_fork() 366 { 367 TEST_SET("sem_{init,destroy}() with fork()"); 368 369 const char* currentTest = NULL; 370 371 // init 372 TEST("sem_init()"); 373 sem_t sem; 374 assert_posix_success(sem_init(&sem, 0, 1)); 375 376 // destroy 377 TEST("sem_destroy() forked"); 378 pid_t child = fork(); 379 assert_posix_bool_success(child >= 0); 380 381 if (child == 0) { 382 // child 383 assert_posix_success(sem_destroy(&sem)); 384 exit(0); 385 } else { 386 // parent 387 assert_posix_success(sem_destroy(&sem)); 388 wait_for_child(child); 389 } 390 391 TEST("done"); 392 } 393 394 395 static void 396 test_post_wait_named() 397 { 398 TEST_SET("sem_{post,wait,trywait,timedwait}() named semaphore"); 399 400 const char* currentTest = NULL; 401 402 // make sure the sem doesn't exist yet 403 sem_unlink(kSemName1); 404 405 // open non-existing with O_CREAT 406 TEST("sem_open(O_CREAT) non-existing"); 407 sem_t* sem = sem_open(kSemName1, O_CREAT, S_IRUSR | S_IWUSR, 1); 408 assert_posix_bool_success(sem != SEM_FAILED); 409 410 TEST("sem_getvalue()"); 411 int value; 412 assert_posix_success(sem_getvalue(sem, &value)); 413 assert_equals(1, value); 414 415 // post 416 TEST("sem_post() no waiting"); 417 assert_posix_success(sem_post(sem)); 418 419 TEST("sem_getvalue()"); 420 assert_posix_success(sem_getvalue(sem, &value)); 421 assert_equals(2, value); 422 423 // wait 424 TEST("sem_wait() non-blocking"); 425 assert_posix_success(sem_wait(sem)); 426 427 TEST("sem_getvalue()"); 428 assert_posix_success(sem_getvalue(sem, &value)); 429 assert_equals(1, value); 430 431 // wait 432 TEST("sem_wait() non-blocking"); 433 assert_posix_success(sem_wait(sem)); 434 435 TEST("sem_getvalue()"); 436 assert_posix_success(sem_getvalue(sem, &value)); 437 assert_equals(0, value); 438 439 // close 440 TEST("sem_close()"); 441 assert_posix_success(sem_close(sem)); 442 443 // re-open existing 444 TEST("sem_open() existing"); 445 sem = sem_open(kSemName1, 0); 446 assert_posix_bool_success(sem != SEM_FAILED); 447 448 TEST("sem_getvalue()"); 449 assert_posix_success(sem_getvalue(sem, &value)); 450 assert_equals(0, value); 451 452 // post 453 TEST("sem_post() no waiting"); 454 assert_posix_success(sem_post(sem)); 455 456 TEST("sem_getvalue()"); 457 assert_posix_success(sem_getvalue(sem, &value)); 458 assert_equals(1, value); 459 460 // post 461 TEST("sem_post() no waiting"); 462 assert_posix_success(sem_post(sem)); 463 464 TEST("sem_getvalue()"); 465 assert_posix_success(sem_getvalue(sem, &value)); 466 assert_equals(2, value); 467 468 // trywait 469 TEST("sem_trywait() success"); 470 assert_posix_success(sem_trywait(sem)); 471 472 TEST("sem_getvalue()"); 473 assert_posix_success(sem_getvalue(sem, &value)); 474 assert_equals(1, value); 475 476 // trywait 477 TEST("sem_trywait() success"); 478 assert_posix_success(sem_trywait(sem)); 479 480 TEST("sem_getvalue()"); 481 assert_posix_success(sem_getvalue(sem, &value)); 482 assert_equals(0, value); 483 484 // trywait failure 485 TEST("sem_trywait() failure"); 486 assert_posix_error(EAGAIN, sem_trywait(sem)); 487 488 TEST("sem_getvalue()"); 489 assert_posix_success(sem_getvalue(sem, &value)); 490 assert_equals(0, value); 491 492 // post 493 TEST("sem_post() no waiting"); 494 assert_posix_success(sem_post(sem)); 495 496 TEST("sem_getvalue()"); 497 assert_posix_success(sem_getvalue(sem, &value)); 498 assert_equals(1, value); 499 500 // post 501 TEST("sem_post() no waiting"); 502 assert_posix_success(sem_post(sem)); 503 504 TEST("sem_getvalue()"); 505 assert_posix_success(sem_getvalue(sem, &value)); 506 assert_equals(2, value); 507 508 // timedwait 509 TEST("sem_timedwait() success"); 510 timespec timeout; 511 assert_posix_success(sem_timedwait(sem, 512 absolute_timeout(timeout, 1000000))); 513 514 TEST("sem_getvalue()"); 515 assert_posix_success(sem_getvalue(sem, &value)); 516 assert_equals(1, value); 517 518 TEST("sem_timedwait() success"); 519 assert_posix_success(sem_timedwait(sem, 520 absolute_timeout(timeout, 1000000))); 521 522 TEST("sem_getvalue()"); 523 assert_posix_success(sem_getvalue(sem, &value)); 524 assert_equals(0, value); 525 526 TEST("sem_timedwait() timeout"); 527 bigtime_t startTime = system_time(); 528 assert_posix_error(ETIMEDOUT, sem_timedwait(sem, 529 absolute_timeout(timeout, 1000000))); 530 bigtime_t diffTime = system_time() - startTime; 531 assert_time_equals(1000000, diffTime); 532 533 TEST("sem_getvalue()"); 534 assert_posix_success(sem_getvalue(sem, &value)); 535 assert_equals(0, value); 536 537 // close 538 TEST("sem_close()"); 539 assert_posix_success(sem_close(sem)); 540 541 TEST("done"); 542 } 543 544 545 static void 546 test_post_wait_unnamed() 547 { 548 TEST_SET("sem_{post,wait,trywait,timedwait}() unnamed semaphore"); 549 550 const char* currentTest = NULL; 551 552 // init 553 TEST("sem_init()"); 554 sem_t _sem; 555 assert_posix_success(sem_init(&_sem, 0, 1)); 556 sem_t* sem = &_sem; 557 558 TEST("sem_getvalue()"); 559 int value; 560 assert_posix_success(sem_getvalue(sem, &value)); 561 assert_equals(1, value); 562 563 // post 564 TEST("sem_post() no waiting"); 565 assert_posix_success(sem_post(sem)); 566 567 TEST("sem_getvalue()"); 568 assert_posix_success(sem_getvalue(sem, &value)); 569 assert_equals(2, value); 570 571 // wait 572 TEST("sem_wait() non-blocking"); 573 assert_posix_success(sem_wait(sem)); 574 575 TEST("sem_getvalue()"); 576 assert_posix_success(sem_getvalue(sem, &value)); 577 assert_equals(1, value); 578 579 // wait 580 TEST("sem_wait() non-blocking"); 581 assert_posix_success(sem_wait(sem)); 582 583 TEST("sem_getvalue()"); 584 assert_posix_success(sem_getvalue(sem, &value)); 585 assert_equals(0, value); 586 587 // post 588 TEST("sem_post() no waiting"); 589 assert_posix_success(sem_post(sem)); 590 591 TEST("sem_getvalue()"); 592 assert_posix_success(sem_getvalue(sem, &value)); 593 assert_equals(1, value); 594 595 // post 596 TEST("sem_post() no waiting"); 597 assert_posix_success(sem_post(sem)); 598 599 TEST("sem_getvalue()"); 600 assert_posix_success(sem_getvalue(sem, &value)); 601 assert_equals(2, value); 602 603 // trywait 604 TEST("sem_trywait() success"); 605 assert_posix_success(sem_trywait(sem)); 606 607 TEST("sem_getvalue()"); 608 assert_posix_success(sem_getvalue(sem, &value)); 609 assert_equals(1, value); 610 611 // trywait 612 TEST("sem_trywait() success"); 613 assert_posix_success(sem_trywait(sem)); 614 615 TEST("sem_getvalue()"); 616 assert_posix_success(sem_getvalue(sem, &value)); 617 assert_equals(0, value); 618 619 // trywait failure 620 TEST("sem_trywait() failure"); 621 assert_posix_error(EAGAIN, sem_trywait(sem)); 622 623 TEST("sem_getvalue()"); 624 assert_posix_success(sem_getvalue(sem, &value)); 625 assert_equals(0, value); 626 627 // post 628 TEST("sem_post() no waiting"); 629 assert_posix_success(sem_post(sem)); 630 631 TEST("sem_getvalue()"); 632 assert_posix_success(sem_getvalue(sem, &value)); 633 assert_equals(1, value); 634 635 // post 636 TEST("sem_post() no waiting"); 637 assert_posix_success(sem_post(sem)); 638 639 TEST("sem_getvalue()"); 640 assert_posix_success(sem_getvalue(sem, &value)); 641 assert_equals(2, value); 642 643 // timedwait 644 TEST("sem_timedwait() success"); 645 timespec timeout; 646 assert_posix_success(sem_timedwait(sem, 647 absolute_timeout(timeout, 1000000))); 648 649 TEST("sem_getvalue()"); 650 assert_posix_success(sem_getvalue(sem, &value)); 651 assert_equals(1, value); 652 653 TEST("sem_timedwait() success"); 654 assert_posix_success(sem_timedwait(sem, 655 absolute_timeout(timeout, 1000000))); 656 657 TEST("sem_getvalue()"); 658 assert_posix_success(sem_getvalue(sem, &value)); 659 assert_equals(0, value); 660 661 TEST("sem_timedwait() timeout"); 662 bigtime_t startTime = system_time(); 663 assert_posix_error(ETIMEDOUT, sem_timedwait(sem, 664 absolute_timeout(timeout, 1000000))); 665 bigtime_t diffTime = system_time() - startTime; 666 assert_time_equals(1000000, diffTime); 667 668 TEST("sem_getvalue()"); 669 assert_posix_success(sem_getvalue(sem, &value)); 670 assert_equals(0, value); 671 672 // destroy 673 TEST("sem_destroy()"); 674 assert_posix_success(sem_destroy(sem)); 675 676 TEST("done"); 677 } 678 679 680 static void 681 test_post_wait_named_fork() 682 { 683 TEST_SET("sem_{post,wait,trywait,timedwait}() named semaphore with fork()"); 684 685 const char* currentTest = NULL; 686 687 // make sure the sem doesn't exist yet 688 sem_unlink(kSemName1); 689 690 // open non-existing with O_CREAT 691 TEST("sem_open(O_CREAT) non-existing"); 692 sem_t* sem = sem_open(kSemName1, O_CREAT, S_IRUSR | S_IWUSR, 0); 693 assert_posix_bool_success(sem != SEM_FAILED); 694 695 TEST("sem_getvalue()"); 696 int value; 697 assert_posix_success(sem_getvalue(sem, &value)); 698 assert_equals(0, value); 699 700 TEST("unblock child after wait"); 701 pid_t child = fork(); 702 assert_posix_bool_success(child >= 0); 703 704 if (child == 0) { 705 // child 706 bigtime_t startTime = system_time(); 707 assert_posix_success(sem_wait(sem)); 708 bigtime_t diffTime = system_time() - startTime; 709 assert_time_equals(1000000, diffTime); 710 711 exit(0); 712 } else { 713 // parent 714 sleep(1); 715 assert_posix_success(sem_post(sem)); 716 wait_for_child(child); 717 } 718 719 TEST("sem_getvalue()"); 720 assert_posix_success(sem_getvalue(sem, &value)); 721 assert_equals(0, value); 722 723 TEST("unblock parent after wait"); 724 child = fork(); 725 assert_posix_bool_success(child >= 0); 726 727 if (child == 0) { 728 // child 729 sleep(1); 730 assert_posix_success(sem_post(sem)); 731 732 exit(0); 733 } else { 734 // parent 735 bigtime_t startTime = system_time(); 736 assert_posix_success(sem_wait(sem)); 737 bigtime_t diffTime = system_time() - startTime; 738 assert_time_equals(1000000, diffTime); 739 740 wait_for_child(child); 741 } 742 743 TEST("sem_getvalue()"); 744 assert_posix_success(sem_getvalue(sem, &value)); 745 assert_equals(0, value); 746 747 TEST("unblock child after wait before timeout"); 748 child = fork(); 749 assert_posix_bool_success(child >= 0); 750 751 if (child == 0) { 752 // child 753 timespec timeout; 754 bigtime_t startTime = system_time(); 755 assert_posix_success(sem_timedwait(sem, 756 absolute_timeout(timeout, 2000000))); 757 bigtime_t diffTime = system_time() - startTime; 758 assert_time_equals(1000000, diffTime); 759 760 exit(0); 761 } else { 762 // parent 763 sleep(1); 764 assert_posix_success(sem_post(sem)); 765 wait_for_child(child); 766 } 767 768 TEST("sem_getvalue()"); 769 assert_posix_success(sem_getvalue(sem, &value)); 770 assert_equals(0, value); 771 772 TEST("unblock child after wait after timeout"); 773 child = fork(); 774 assert_posix_bool_success(child >= 0); 775 776 if (child == 0) { 777 // child 778 timespec timeout; 779 bigtime_t startTime = system_time(); 780 assert_posix_error(ETIMEDOUT, sem_timedwait(sem, 781 absolute_timeout(timeout, 1000000))); 782 bigtime_t diffTime = system_time() - startTime; 783 assert_time_equals(1000000, diffTime); 784 785 exit(0); 786 } else { 787 // parent 788 sleep(2); 789 assert_posix_success(sem_post(sem)); 790 wait_for_child(child); 791 } 792 793 TEST("sem_getvalue()"); 794 assert_posix_success(sem_getvalue(sem, &value)); 795 assert_equals(1, value); 796 797 // close 798 TEST("sem_close()"); 799 assert_posix_success(sem_close(sem)); 800 801 TEST("done"); 802 } 803 804 805 static void 806 test_post_wait_named_fork2() 807 { 808 TEST_SET("sem_{post,wait,trywait,timedwait}() named semaphore open after " 809 "fork"); 810 811 const char* currentTest = NULL; 812 813 // make sure the sem doesn't exist yet 814 sem_unlink(kSemName1); 815 816 // open non-existing with O_CREAT 817 TEST("sem_open(O_CREAT) non-existing"); 818 sem_t* sem = sem_open(kSemName1, O_CREAT, S_IRUSR | S_IWUSR, 0); 819 assert_posix_bool_success(sem != SEM_FAILED); 820 821 TEST("sem_getvalue()"); 822 int value; 823 assert_posix_success(sem_getvalue(sem, &value)); 824 assert_equals(0, value); 825 826 // close 827 TEST("sem_close()"); 828 assert_posix_success(sem_close(sem)); 829 sem = NULL; 830 831 TEST("unblock child after wait"); 832 pid_t child = fork(); 833 assert_posix_bool_success(child >= 0); 834 835 if (child == 0) { 836 // child 837 sem = sem_open(kSemName1, 0); 838 assert_posix_bool_success(sem != SEM_FAILED); 839 840 bigtime_t startTime = system_time(); 841 assert_posix_success(sem_wait(sem)); 842 bigtime_t diffTime = system_time() - startTime; 843 assert_time_equals(1000000, diffTime); 844 845 exit(0); 846 } else { 847 // parent 848 sem = sem_open(kSemName1, 0); 849 assert_posix_bool_success(sem != SEM_FAILED); 850 851 sleep(1); 852 assert_posix_success(sem_post(sem)); 853 wait_for_child(child); 854 } 855 856 TEST("sem_getvalue()"); 857 assert_posix_success(sem_getvalue(sem, &value)); 858 assert_equals(0, value); 859 860 // close 861 TEST("sem_close()"); 862 assert_posix_success(sem_close(sem)); 863 sem = NULL; 864 865 TEST("unblock child after wait before timeout"); 866 child = fork(); 867 assert_posix_bool_success(child >= 0); 868 869 if (child == 0) { 870 // child 871 sem = sem_open(kSemName1, 0); 872 assert_posix_bool_success(sem != SEM_FAILED); 873 874 timespec timeout; 875 bigtime_t startTime = system_time(); 876 assert_posix_success(sem_timedwait(sem, 877 absolute_timeout(timeout, 2000000))); 878 bigtime_t diffTime = system_time() - startTime; 879 assert_time_equals(1000000, diffTime); 880 881 exit(0); 882 } else { 883 // parent 884 sem = sem_open(kSemName1, 0); 885 assert_posix_bool_success(sem != SEM_FAILED); 886 887 sleep(1); 888 assert_posix_success(sem_post(sem)); 889 wait_for_child(child); 890 } 891 892 TEST("sem_getvalue()"); 893 assert_posix_success(sem_getvalue(sem, &value)); 894 assert_equals(0, value); 895 896 // close 897 TEST("sem_close()"); 898 assert_posix_success(sem_close(sem)); 899 sem = NULL; 900 901 TEST("unblock child after wait after timeout"); 902 child = fork(); 903 assert_posix_bool_success(child >= 0); 904 905 if (child == 0) { 906 // child 907 sem = sem_open(kSemName1, 0); 908 assert_posix_bool_success(sem != SEM_FAILED); 909 910 timespec timeout; 911 bigtime_t startTime = system_time(); 912 assert_posix_error(ETIMEDOUT, sem_timedwait(sem, 913 absolute_timeout(timeout, 1000000))); 914 bigtime_t diffTime = system_time() - startTime; 915 assert_time_equals(1000000, diffTime); 916 917 exit(0); 918 } else { 919 // parent 920 sem = sem_open(kSemName1, 0); 921 assert_posix_bool_success(sem != SEM_FAILED); 922 923 sleep(2); 924 assert_posix_success(sem_post(sem)); 925 wait_for_child(child); 926 } 927 928 TEST("sem_getvalue()"); 929 assert_posix_success(sem_getvalue(sem, &value)); 930 assert_equals(1, value); 931 932 // close 933 TEST("sem_close()"); 934 assert_posix_success(sem_close(sem)); 935 936 TEST("done"); 937 } 938 939 940 static void 941 test_post_wait_unnamed_fork() 942 { 943 TEST_SET("sem_{post,wait,trywait,timedwait}() unnamed semaphore with " 944 "fork()"); 945 946 const char* currentTest = NULL; 947 948 // init 949 TEST("sem_init()"); 950 sem_t _sem; 951 assert_posix_success(sem_init(&_sem, 0, 1)); 952 sem_t* sem = &_sem; 953 954 TEST("sem_getvalue()"); 955 int value; 956 assert_posix_success(sem_getvalue(sem, &value)); 957 assert_equals(1, value); 958 959 TEST("sem_wait() on fork()ed unnamed sem in parent and child"); 960 pid_t child = fork(); 961 assert_posix_bool_success(child >= 0); 962 963 if (child == 0) { 964 // child 965 sleep(1); 966 assert_posix_success(sem_wait(sem)); 967 968 assert_posix_success(sem_getvalue(sem, &value)); 969 assert_equals(0, value); 970 971 exit(0); 972 } else { 973 // parent 974 assert_posix_success(sem_wait(sem)); 975 assert_posix_success(sem_getvalue(sem, &value)); 976 assert_equals(0, value); 977 978 wait_for_child(child); 979 } 980 981 TEST("sem_getvalue()"); 982 assert_posix_success(sem_getvalue(sem, &value)); 983 assert_equals(0, value); 984 985 TEST("sem_post() on fork()ed unnamed sem in parent and child"); 986 child = fork(); 987 assert_posix_bool_success(child >= 0); 988 989 if (child == 0) { 990 // child 991 assert_posix_success(sem_post(sem)); 992 993 assert_posix_success(sem_getvalue(sem, &value)); 994 assert_equals(1, value); 995 996 exit(0); 997 } else { 998 // parent 999 assert_posix_success(sem_post(sem)); 1000 assert_posix_success(sem_getvalue(sem, &value)); 1001 assert_equals(1, value); 1002 1003 wait_for_child(child); 1004 } 1005 1006 TEST("sem_getvalue()"); 1007 assert_posix_success(sem_getvalue(sem, &value)); 1008 assert_equals(1, value); 1009 1010 // destroy 1011 TEST("sem_destroy()"); 1012 assert_posix_success(sem_destroy(sem)); 1013 1014 TEST("done"); 1015 } 1016 1017 1018 static void 1019 test_post_wait_unnamed_fork_shared() 1020 { 1021 TEST_SET("sem_{post,wait,trywait,timedwait}() unnamed semaphore with " 1022 "fork() in shared memory"); 1023 1024 const char* currentTest = NULL; 1025 1026 // create shared memory area 1027 void* address = mmap(NULL, 4096, PROT_READ | PROT_WRITE, 1028 MAP_SHARED | MAP_ANON, -1, 0); 1029 assert_posix_bool_success(address != MAP_FAILED); 1030 1031 // init 1032 TEST("sem_init()"); 1033 sem_t* sem = (sem_t*)address; 1034 assert_posix_success(sem_init(sem, 1, 0)); 1035 1036 TEST("sem_getvalue()"); 1037 int value; 1038 assert_posix_success(sem_getvalue(sem, &value)); 1039 assert_equals(0, value); 1040 1041 TEST("unblock child after wait"); 1042 pid_t child = fork(); 1043 assert_posix_bool_success(child >= 0); 1044 1045 if (child == 0) { 1046 // child 1047 bigtime_t startTime = system_time(); 1048 assert_posix_success(sem_wait(sem)); 1049 bigtime_t diffTime = system_time() - startTime; 1050 assert_time_equals(1000000, diffTime); 1051 1052 exit(0); 1053 } else { 1054 // parent 1055 sleep(1); 1056 assert_posix_success(sem_post(sem)); 1057 wait_for_child(child); 1058 } 1059 1060 TEST("sem_getvalue()"); 1061 assert_posix_success(sem_getvalue(sem, &value)); 1062 assert_equals(0, value); 1063 1064 TEST("unblock parent after wait"); 1065 child = fork(); 1066 assert_posix_bool_success(child >= 0); 1067 1068 if (child == 0) { 1069 // child 1070 sleep(1); 1071 assert_posix_success(sem_post(sem)); 1072 1073 exit(0); 1074 } else { 1075 // parent 1076 bigtime_t startTime = system_time(); 1077 assert_posix_success(sem_wait(sem)); 1078 bigtime_t diffTime = system_time() - startTime; 1079 assert_time_equals(1000000, diffTime); 1080 1081 wait_for_child(child); 1082 } 1083 1084 TEST("sem_getvalue()"); 1085 assert_posix_success(sem_getvalue(sem, &value)); 1086 assert_equals(0, value); 1087 1088 TEST("unblock child after wait before timeout"); 1089 child = fork(); 1090 assert_posix_bool_success(child >= 0); 1091 1092 if (child == 0) { 1093 // child 1094 timespec timeout; 1095 bigtime_t startTime = system_time(); 1096 assert_posix_success(sem_timedwait(sem, 1097 absolute_timeout(timeout, 2000000))); 1098 bigtime_t diffTime = system_time() - startTime; 1099 assert_time_equals(1000000, diffTime); 1100 1101 exit(0); 1102 } else { 1103 // parent 1104 sleep(1); 1105 assert_posix_success(sem_post(sem)); 1106 wait_for_child(child); 1107 } 1108 1109 TEST("sem_getvalue()"); 1110 assert_posix_success(sem_getvalue(sem, &value)); 1111 assert_equals(0, value); 1112 1113 TEST("unblock child after wait after timeout"); 1114 child = fork(); 1115 assert_posix_bool_success(child >= 0); 1116 1117 if (child == 0) { 1118 // child 1119 timespec timeout; 1120 bigtime_t startTime = system_time(); 1121 assert_posix_error(ETIMEDOUT, sem_timedwait(sem, 1122 absolute_timeout(timeout, 1000000))); 1123 bigtime_t diffTime = system_time() - startTime; 1124 assert_time_equals(1000000, diffTime); 1125 1126 exit(0); 1127 } else { 1128 // parent 1129 sleep(2); 1130 assert_posix_success(sem_post(sem)); 1131 wait_for_child(child); 1132 } 1133 1134 TEST("sem_getvalue()"); 1135 assert_posix_success(sem_getvalue(sem, &value)); 1136 assert_equals(1, value); 1137 1138 // destroy 1139 TEST("sem_destroy()"); 1140 assert_posix_success(sem_destroy(sem)); 1141 1142 // unmap memory 1143 assert_posix_success(munmap(address, 4096)); 1144 1145 TEST("done"); 1146 } 1147 1148 1149 int 1150 main() 1151 { 1152 test_open_close_unlink(); 1153 test_init_destroy(); 1154 test_open_close_fork(); 1155 test_init_destroy_fork(); 1156 test_post_wait_named(); 1157 test_post_wait_unnamed(); 1158 test_post_wait_named_fork(); 1159 test_post_wait_named_fork2(); 1160 test_post_wait_unnamed_fork(); 1161 test_post_wait_unnamed_fork_shared(); 1162 1163 printf("\nall tests OK\n"); 1164 } 1165