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