1 /* 2 This file is part of Valgrind, a dynamic binary instrumentation 3 framework. 4 5 Copyright (C) 2008-2008 Google Inc 6 opensource (at) google.com 7 8 This program is free software; you can redistribute it and/or 9 modify it under the terms of the GNU General Public License as 10 published by the Free Software Foundation; either version 2 of the 11 License, or (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, but 14 WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program; if not, write to the Free Software 20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 21 02111-1307, USA. 22 23 The GNU General Public License is contained in the file COPYING. 24 */ 25 26 /* Author: Konstantin Serebryany <opensource (at) google.com> 27 28 This file contains a set of unit tests for a data race detection tool. 29 30 These tests can be compiled with pthreads (default) or 31 with any other library that supports threads, locks, cond vars, etc. 32 33 */ 34 35 #include <fcntl.h> 36 #include <signal.h> 37 #include <stdlib.h> 38 #include <string.h> 39 40 #include <string> 41 #include <queue> 42 #include <vector> 43 44 #include "old_test_suite.h" 45 #include "test_utils.h" 46 47 #include <gtest/gtest.h> 48 #include "gtest_fixture_injection.h" 49 50 // The tests are 51 // - Stability tests (marked STAB) 52 // - Performance tests (marked PERF) 53 // - Feature tests 54 // - TN (true negative) : no race exists and the tool is silent. 55 // - TP (true positive) : a race exists and reported. 56 // - FN (false negative): a race exists but not reported. 57 // - FP (false positive): no race exists but the tool reports it. 58 // 59 // The feature tests are marked according to the behavior of ThreadSanitizer. 60 // 61 // TP and FP tests are annotated with ANNOTATE_EXPECT_RACE, 62 // so, no error reports should be seen when running under ThreadSanitizer. 63 // 64 // When some of the FP cases are fixed in helgrind we'll need 65 // to update these tests. 66 // 67 // Each test resides in its own namespace. 68 // Namespaces are named test01, test02, ... 69 // Please, *DO NOT* change the logic of existing tests nor rename them. 70 // Create a new test instead. 71 // 72 // Some tests use sleep()/usleep(). 73 // This is not a synchronization, but a simple way to trigger 74 // some specific behaviour of the race detector's scheduler. 75 76 // Globals and utilities used by several tests. {{{1 77 static CondVar CV; 78 static int COND = 0; 79 80 // test00: {{{1 81 namespace test00 { 82 int GLOB = 0; 83 void Run() { 84 printf("test00: negative\n"); 85 printf("\tGLOB=%d\n", GLOB); 86 } 87 REGISTER_TEST(Run, 00) 88 } // namespace test00 89 90 91 // test01: TP. Simple race (write vs write). {{{1 92 namespace test01 { 93 int GLOB = 0; 94 95 void Worker1() { 96 GLOB = 1; 97 } 98 99 void Worker2() { 100 GLOB = 2; 101 } 102 103 void Run() { 104 ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test01. TP."); 105 ANNOTATE_TRACE_MEMORY(&GLOB); 106 printf("test01: positive\n"); 107 MyThreadArray t(Worker1, Worker2); 108 t.Start(); 109 t.Join(); 110 printf("\tGLOB=%d\n", GLOB); 111 } 112 REGISTER_TEST(Run, 1); 113 } // namespace test01 114 115 116 // test02: TN. Synchronization via CondVar. {{{1 117 namespace test02 { 118 int GLOB = 0; 119 // Two write accesses to GLOB are synchronized because 120 // the pair of CV.Signal() and CV.Wait() establish happens-before relation. 121 // 122 // Waiter: Waker: 123 // 1. COND = 0 124 // 2. Start(Waker) 125 // 3. MU.Lock() a. write(GLOB) 126 // b. MU.Lock() 127 // c. COND = 1 128 // /--- d. CV.Signal() 129 // 4. while(COND) / e. MU.Unlock() 130 // CV.Wait(MU) <---/ 131 // 5. MU.Unlock() 132 // 6. write(GLOB) 133 Mutex MU; 134 135 void Waker() { 136 usleep(200000); // Make sure the waiter blocks. 137 GLOB = 1; 138 139 MU.Lock(); 140 COND = 1; 141 CV.Signal(); 142 MU.Unlock(); 143 } 144 145 void Waiter() { 146 ThreadPool pool(1); 147 pool.StartWorkers(); 148 COND = 0; 149 pool.Add(NewCallback(Waker)); 150 MU.Lock(); 151 while(COND != 1) 152 CV.Wait(&MU); 153 MU.Unlock(); 154 GLOB = 2; 155 } 156 void Run() { 157 printf("test02: negative\n"); 158 Waiter(); 159 printf("\tGLOB=%d\n", GLOB); 160 } 161 REGISTER_TEST(Run, 2); 162 } // namespace test02 163 164 165 // test03: TN. Synchronization via LockWhen, signaller gets there first. {{{1 166 namespace test03 { 167 int GLOB = 0; 168 // Two write accesses to GLOB are synchronized via conditional critical section. 169 // Note that LockWhen() happens first (we use sleep(1) to make sure)! 170 // 171 // Waiter: Waker: 172 // 1. COND = 0 173 // 2. Start(Waker) 174 // a. write(GLOB) 175 // b. MU.Lock() 176 // c. COND = 1 177 // /--- d. MU.Unlock() 178 // 3. MU.LockWhen(COND==1) <---/ 179 // 4. MU.Unlock() 180 // 5. write(GLOB) 181 Mutex MU; 182 183 void Waker() { 184 usleep(100000); // Make sure the waiter blocks. 185 GLOB = 1; 186 187 MU.Lock(); 188 COND = 1; // We are done! Tell the Waiter. 189 MU.Unlock(); // calls ANNOTATE_CONDVAR_SIGNAL; 190 } 191 void Waiter() { 192 ThreadPool pool(1); 193 pool.StartWorkers(); 194 COND = 0; 195 pool.Add(NewCallback(Waker)); 196 MU.LockWhen(Condition(&ArgIsOne, &COND)); // calls ANNOTATE_CONDVAR_WAIT 197 MU.Unlock(); // Waker is done! 198 199 GLOB = 2; 200 } 201 void Run() { 202 printf("test03: negative\n"); 203 Waiter(); 204 printf("\tGLOB=%d\n", GLOB); 205 } 206 REGISTER_TEST2(Run, 3, FEATURE|NEEDS_ANNOTATIONS); 207 } // namespace test03 208 209 // test04: TN. Synchronization via PCQ. {{{1 210 namespace test04 { 211 int GLOB = 0; 212 ProducerConsumerQueue Q(INT_MAX); 213 // Two write accesses to GLOB are separated by PCQ Put/Get. 214 // 215 // Putter: Getter: 216 // 1. write(GLOB) 217 // 2. Q.Put() ---------\ . 218 // \-------> a. Q.Get() 219 // b. write(GLOB) 220 221 222 void Putter() { 223 GLOB = 1; 224 Q.Put(NULL); 225 } 226 227 void Getter() { 228 Q.Get(); 229 GLOB = 2; 230 } 231 232 void Run() { 233 printf("test04: negative\n"); 234 MyThreadArray t(Putter, Getter); 235 t.Start(); 236 t.Join(); 237 printf("\tGLOB=%d\n", GLOB); 238 } 239 REGISTER_TEST(Run, 4); 240 } // namespace test04 241 242 243 // test05: FP. Synchronization via CondVar, but waiter does not block. {{{1 244 // Since CondVar::Wait() is not called, we get a false positive. 245 namespace test05 { 246 int GLOB = 0; 247 // Two write accesses to GLOB are synchronized via CondVar. 248 // But race detector can not see it. 249 // See this for details: 250 // http://www.valgrind.org/docs/manual/hg-manual.html#hg-manual.effective-use. 251 // 252 // Waiter: Waker: 253 // 1. COND = 0 254 // 2. Start(Waker) 255 // 3. MU.Lock() a. write(GLOB) 256 // b. MU.Lock() 257 // c. COND = 1 258 // d. CV.Signal() 259 // 4. while(COND) e. MU.Unlock() 260 // CV.Wait(MU) <<< not called 261 // 5. MU.Unlock() 262 // 6. write(GLOB) 263 Mutex MU; 264 265 void Waker() { 266 GLOB = 1; 267 MU.Lock(); 268 COND = 1; 269 CV.Signal(); 270 MU.Unlock(); 271 } 272 273 void Waiter() { 274 usleep(100000); // Make sure the signaller gets first. 275 MU.Lock(); 276 while(COND != 1) 277 CV.Wait(&MU); 278 MU.Unlock(); 279 GLOB = 2; 280 } 281 void Run() { 282 printf("test05: unavoidable false positive\n"); 283 COND = 0; 284 if (!Tsan_PureHappensBefore()) 285 ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test05. FP. Unavoidable in hybrid scheme."); 286 MyThreadArray t(Waker, Waiter); 287 t.Start(); 288 t.Join(); 289 printf("\tGLOB=%d\n", GLOB); 290 } 291 REGISTER_TEST(Run, 5); 292 } // namespace test05 293 294 295 // test06: TN. Synchronization via CondVar, but Waker gets there first. {{{1 296 namespace test06 { 297 int GLOB = 0; 298 // Same as test05 but we annotated the Wait() loop. 299 // 300 // Waiter: Waker: 301 // 1. COND = 0 302 // 2. Start(Waker) 303 // 3. MU.Lock() a. write(GLOB) 304 // b. MU.Lock() 305 // c. COND = 1 306 // /------- d. CV.Signal() 307 // 4. while(COND) / e. MU.Unlock() 308 // CV.Wait(MU) <<< not called / 309 // 6. ANNOTATE_CONDVAR_WAIT(CV, MU) <----/ 310 // 5. MU.Unlock() 311 // 6. write(GLOB) 312 313 Mutex MU; 314 315 void Waker() { 316 GLOB = 1; 317 MU.Lock(); 318 COND = 1; 319 CV.Signal(); 320 MU.Unlock(); 321 } 322 323 void Waiter() { 324 ThreadPool pool(1); 325 pool.StartWorkers(); 326 COND = 0; 327 pool.Add(NewCallback(Waker)); 328 usleep(500000); // Make sure the signaller gets first. 329 MU.Lock(); 330 while(COND != 1) 331 CV.Wait(&MU); 332 ANNOTATE_CONDVAR_LOCK_WAIT(&CV, &MU); 333 334 MU.Unlock(); 335 GLOB = 2; 336 } 337 void Run() { 338 printf("test06: negative\n"); 339 Waiter(); 340 printf("\tGLOB=%d\n", GLOB); 341 } 342 REGISTER_TEST2(Run, 6, FEATURE|NEEDS_ANNOTATIONS); 343 } // namespace test06 344 345 346 // test07: TN. Synchronization via LockWhen(), Signaller is observed first. {{{1 347 namespace test07 { 348 int GLOB = 0; 349 bool COND = 0; 350 // Two write accesses to GLOB are synchronized via conditional critical section. 351 // LockWhen() is observed after COND has been set (due to sleep). 352 // Unlock() calls ANNOTATE_CONDVAR_SIGNAL(). 353 // 354 // Waiter: Signaller: 355 // 1. COND = 0 356 // 2. Start(Signaller) 357 // a. write(GLOB) 358 // b. MU.Lock() 359 // c. COND = 1 360 // /--- d. MU.Unlock calls ANNOTATE_CONDVAR_SIGNAL 361 // 3. MU.LockWhen(COND==1) <---/ 362 // 4. MU.Unlock() 363 // 5. write(GLOB) 364 365 Mutex MU; 366 void Signaller() { 367 GLOB = 1; 368 MU.Lock(); 369 COND = true; // We are done! Tell the Waiter. 370 MU.Unlock(); // calls ANNOTATE_CONDVAR_SIGNAL; 371 } 372 void Waiter() { 373 COND = false; 374 MyThread t(Signaller); 375 t.Start(); 376 usleep(100000); // Make sure the signaller gets there first. 377 378 MU.LockWhen(Condition(&ArgIsTrue, &COND)); // calls ANNOTATE_CONDVAR_WAIT 379 MU.Unlock(); // Signaller is done! 380 381 GLOB = 2; // If LockWhen didn't catch the signal, a race may be reported here. 382 t.Join(); 383 } 384 void Run() { 385 printf("test07: negative\n"); 386 Waiter(); 387 printf("\tGLOB=%d\n", GLOB); 388 } 389 REGISTER_TEST2(Run, 7, FEATURE|NEEDS_ANNOTATIONS); 390 } // namespace test07 391 392 // test08: TN. Synchronization via thread start/join. {{{1 393 namespace test08 { 394 int GLOB = 0; 395 // Three accesses to GLOB are separated by thread start/join. 396 // 397 // Parent: Worker: 398 // 1. write(GLOB) 399 // 2. Start(Worker) ------------> 400 // a. write(GLOB) 401 // 3. Join(Worker) <------------ 402 // 4. write(GLOB) 403 void Worker() { 404 GLOB = 2; 405 } 406 407 void Parent() { 408 MyThread t(Worker); 409 GLOB = 1; 410 t.Start(); 411 t.Join(); 412 GLOB = 3; 413 } 414 void Run() { 415 printf("test08: negative\n"); 416 Parent(); 417 printf("\tGLOB=%d\n", GLOB); 418 } 419 REGISTER_TEST(Run, 8); 420 } // namespace test08 421 422 423 // test09: TP. Simple race (read vs write). {{{1 424 namespace test09 { 425 int GLOB = 0; 426 // A simple data race between writer and reader. 427 // Write happens after read (enforced by sleep). 428 // Usually, easily detectable by a race detector. 429 void Writer() { 430 usleep(100000); 431 GLOB = 3; 432 } 433 void Reader() { 434 CHECK(GLOB != -777); 435 } 436 437 void Run() { 438 ANNOTATE_TRACE_MEMORY(&GLOB); 439 ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test09. TP."); 440 printf("test09: positive\n"); 441 MyThreadArray t(Writer, Reader); 442 t.Start(); 443 t.Join(); 444 printf("\tGLOB=%d\n", GLOB); 445 } 446 REGISTER_TEST(Run, 9); 447 } // namespace test09 448 449 450 // test10: FN. Simple race (write vs read). {{{1 451 namespace test10 { 452 int GLOB = 0; 453 // A simple data race between writer and reader. 454 // Write happens before Read (enforced by sleep), 455 // otherwise this test is the same as test09. 456 // 457 // Writer: Reader: 458 // 1. write(GLOB) a. sleep(long enough so that GLOB 459 // is most likely initialized by Writer) 460 // b. read(GLOB) 461 // 462 // 463 // Eraser algorithm does not detect the race here, 464 // see Section 2.2 of http://citeseer.ist.psu.edu/savage97eraser.html. 465 // 466 void Writer() { 467 GLOB = 3; 468 } 469 void Reader() { 470 usleep(100000); 471 CHECK(GLOB != -777); 472 } 473 474 void Run() { 475 ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test10. TP. FN in MSMHelgrind."); 476 printf("test10: positive\n"); 477 MyThreadArray t(Writer, Reader); 478 t.Start(); 479 t.Join(); 480 printf("\tGLOB=%d\n", GLOB); 481 } 482 REGISTER_TEST(Run, 10); 483 } // namespace test10 484 485 486 // test12: FP. Synchronization via Mutex, then via PCQ. {{{1 487 namespace test12 { 488 int GLOB = 0; 489 // This test is properly synchronized, but currently (Dec 2007) 490 // helgrind reports a false positive. 491 // 492 // First, we write to GLOB under MU, then we synchronize via PCQ, 493 // which is essentially a semaphore. 494 // 495 // Putter: Getter: 496 // 1. MU.Lock() a. MU.Lock() 497 // 2. write(GLOB) <---- MU ----> b. write(GLOB) 498 // 3. MU.Unlock() c. MU.Unlock() 499 // 4. Q.Put() ---------------> d. Q.Get() 500 // e. write(GLOB) 501 502 ProducerConsumerQueue Q(INT_MAX); 503 Mutex MU; 504 505 void Putter() { 506 MU.Lock(); 507 GLOB++; 508 MU.Unlock(); 509 510 Q.Put(NULL); 511 } 512 513 void Getter() { 514 MU.Lock(); 515 GLOB++; 516 MU.Unlock(); 517 518 Q.Get(); 519 GLOB++; 520 } 521 522 void Run() { 523 // ANNOTATE_EXPECT_RACE(&GLOB, "test12. FP. Fixed by MSMProp1."); 524 printf("test12: negative\n"); 525 MyThreadArray t(Putter, Getter); 526 t.Start(); 527 t.Join(); 528 printf("\tGLOB=%d\n", GLOB); 529 } 530 REGISTER_TEST(Run, 12); 531 } // namespace test12 532 533 534 // test13: FP. Synchronization via Mutex, then via LockWhen. {{{1 535 namespace test13 { 536 int GLOB = 0; 537 // This test is essentially the same as test12, but uses LockWhen 538 // instead of PCQ. 539 // 540 // Waker: Waiter: 541 // 1. MU.Lock() a. MU.Lock() 542 // 2. write(GLOB) <---------- MU ----------> b. write(GLOB) 543 // 3. MU.Unlock() c. MU.Unlock() 544 // 4. MU.Lock() . 545 // 5. COND = 1 . 546 // 6. ANNOTATE_CONDVAR_SIGNAL -------\ . 547 // 7. MU.Unlock() \ . 548 // \----> d. MU.LockWhen(COND == 1) 549 // e. MU.Unlock() 550 // f. write(GLOB) 551 Mutex MU; 552 553 void Waker() { 554 MU.Lock(); 555 GLOB++; 556 MU.Unlock(); 557 558 MU.Lock(); 559 COND = 1; 560 ANNOTATE_CONDVAR_SIGNAL(&MU); 561 MU.Unlock(); 562 } 563 564 void Waiter() { 565 MU.Lock(); 566 GLOB++; 567 MU.Unlock(); 568 569 MU.LockWhen(Condition(&ArgIsOne, &COND)); 570 MU.Unlock(); 571 GLOB++; 572 } 573 574 void Run() { 575 // ANNOTATE_EXPECT_RACE(&GLOB, "test13. FP. Fixed by MSMProp1."); 576 printf("test13: negative\n"); 577 COND = 0; 578 579 MyThreadArray t(Waker, Waiter); 580 t.Start(); 581 t.Join(); 582 583 printf("\tGLOB=%d\n", GLOB); 584 } 585 REGISTER_TEST2(Run, 13, FEATURE|NEEDS_ANNOTATIONS); 586 } // namespace test13 587 588 589 // test14: FP. Synchronization via PCQ, reads, 2 workers. {{{1 590 namespace test14 { 591 int GLOB = 0; 592 // This test is properly synchronized, but currently (Dec 2007) 593 // helgrind reports a false positive. 594 // 595 // This test is similar to test11, but uses PCQ (semaphore). 596 // 597 // Putter2: Putter1: Getter: 598 // 1. read(GLOB) a. read(GLOB) 599 // 2. Q2.Put() ----\ b. Q1.Put() -----\ . 600 // \ \--------> A. Q1.Get() 601 // \----------------------------------> B. Q2.Get() 602 // C. write(GLOB) 603 ProducerConsumerQueue Q1(INT_MAX), Q2(INT_MAX); 604 605 void Putter1() { 606 CHECK(GLOB != 777); 607 Q1.Put(NULL); 608 } 609 void Putter2() { 610 CHECK(GLOB != 777); 611 Q2.Put(NULL); 612 } 613 void Getter() { 614 Q1.Get(); 615 Q2.Get(); 616 GLOB++; 617 } 618 void Run() { 619 // ANNOTATE_EXPECT_RACE(&GLOB, "test14. FP. Fixed by MSMProp1."); 620 printf("test14: negative\n"); 621 MyThreadArray t(Getter, Putter1, Putter2); 622 t.Start(); 623 t.Join(); 624 printf("\tGLOB=%d\n", GLOB); 625 } 626 REGISTER_TEST(Run, 14); 627 } // namespace test14 628 629 630 // test15: TN. Synchronization via LockWhen. One waker and 2 waiters. {{{1 631 namespace test15 { 632 // Waker: Waiter1, Waiter2: 633 // 1. write(GLOB) 634 // 2. MU.Lock() 635 // 3. COND = 1 636 // 4. ANNOTATE_CONDVAR_SIGNAL ------------> a. MU.LockWhen(COND == 1) 637 // 5. MU.Unlock() b. MU.Unlock() 638 // c. read(GLOB) 639 640 int GLOB = 0; 641 Mutex MU; 642 643 void Waker() { 644 GLOB = 2; 645 646 MU.Lock(); 647 COND = 1; 648 ANNOTATE_CONDVAR_SIGNAL(&MU); 649 MU.Unlock(); 650 }; 651 652 void Waiter() { 653 MU.LockWhen(Condition(&ArgIsOne, &COND)); 654 MU.Unlock(); 655 CHECK(GLOB != 777); 656 } 657 658 659 void Run() { 660 COND = 0; 661 printf("test15: negative\n"); 662 MyThreadArray t(Waker, Waiter, Waiter); 663 t.Start(); 664 t.Join(); 665 printf("\tGLOB=%d\n", GLOB); 666 } 667 REGISTER_TEST(Run, 15); 668 } // namespace test15 669 670 671 // test16: FP. Barrier (emulated by CV), 2 threads. {{{1 672 namespace test16 { 673 // Worker1: Worker2: 674 // 1. MU.Lock() a. MU.Lock() 675 // 2. write(GLOB) <------------ MU ----------> b. write(GLOB) 676 // 3. MU.Unlock() c. MU.Unlock() 677 // 4. MU2.Lock() d. MU2.Lock() 678 // 5. COND-- e. COND-- 679 // 6. ANNOTATE_CONDVAR_SIGNAL(MU2) ---->V . 680 // 7. MU2.Await(COND == 0) <------------+------ f. ANNOTATE_CONDVAR_SIGNAL(MU2) 681 // 8. MU2.Unlock() V-----> g. MU2.Await(COND == 0) 682 // 9. read(GLOB) h. MU2.Unlock() 683 // i. read(GLOB) 684 // 685 // 686 // TODO: This way we may create too many edges in happens-before graph. 687 // Arndt Mhlenfeld in his PhD (TODO: link) suggests creating special nodes in 688 // happens-before graph to reduce the total number of edges. 689 // See figure 3.14. 690 // 691 // 692 int GLOB = 0; 693 Mutex MU; 694 Mutex MU2; 695 696 void Worker() { 697 MU.Lock(); 698 GLOB++; 699 MU.Unlock(); 700 701 MU2.Lock(); 702 COND--; 703 ANNOTATE_CONDVAR_SIGNAL(&MU2); 704 MU2.Await(Condition(&ArgIsZero, &COND)); 705 MU2.Unlock(); 706 707 CHECK(GLOB == 2); 708 } 709 710 void Run() { 711 // ANNOTATE_EXPECT_RACE(&GLOB, "test16. FP. Fixed by MSMProp1 + Barrier support."); 712 COND = 2; 713 printf("test16: negative\n"); 714 MyThreadArray t(Worker, Worker); 715 t.Start(); 716 t.Join(); 717 printf("\tGLOB=%d\n", GLOB); 718 } 719 REGISTER_TEST2(Run, 16, FEATURE|NEEDS_ANNOTATIONS); 720 } // namespace test16 721 722 723 // test17: FP. Barrier (emulated by CV), 3 threads. {{{1 724 namespace test17 { 725 // Same as test16, but with 3 threads. 726 int GLOB = 0; 727 Mutex MU; 728 Mutex MU2; 729 730 void Worker() { 731 MU.Lock(); 732 GLOB++; 733 MU.Unlock(); 734 735 MU2.Lock(); 736 COND--; 737 ANNOTATE_CONDVAR_SIGNAL(&MU2); 738 MU2.Await(Condition(&ArgIsZero, &COND)); 739 MU2.Unlock(); 740 741 CHECK(GLOB == 3); 742 } 743 744 void Run() { 745 COND = 3; 746 printf("test17: negative\n"); 747 MyThreadArray t(Worker, Worker, Worker); 748 t.Start(); 749 t.Join(); 750 printf("\tGLOB=%d\n", GLOB); 751 } 752 REGISTER_TEST2(Run, 17, FEATURE|NEEDS_ANNOTATIONS); 753 } // namespace test17 754 755 756 // test18: TN. Synchronization via Await(), signaller gets there first. {{{1 757 namespace test18 { 758 int GLOB = 0; 759 Mutex MU; 760 // Same as test03, but uses Mutex::Await() instead of Mutex::LockWhen(). 761 762 void Waker() { 763 usleep(100000); // Make sure the waiter blocks. 764 GLOB = 1; 765 766 MU.Lock(); 767 COND = 1; // We are done! Tell the Waiter. 768 MU.Unlock(); // calls ANNOTATE_CONDVAR_SIGNAL; 769 } 770 void Waiter() { 771 ThreadPool pool(1); 772 pool.StartWorkers(); 773 COND = 0; 774 pool.Add(NewCallback(Waker)); 775 776 MU.Lock(); 777 MU.Await(Condition(&ArgIsOne, &COND)); // calls ANNOTATE_CONDVAR_WAIT 778 MU.Unlock(); // Waker is done! 779 780 GLOB = 2; 781 } 782 void Run() { 783 printf("test18: negative\n"); 784 Waiter(); 785 printf("\tGLOB=%d\n", GLOB); 786 } 787 REGISTER_TEST2(Run, 18, FEATURE|NEEDS_ANNOTATIONS); 788 } // namespace test18 789 790 // test19: TN. Synchronization via AwaitWithTimeout(). {{{1 791 namespace test19 { 792 int GLOB = 0; 793 // Same as test18, but with AwaitWithTimeout. Do not timeout. 794 Mutex MU; 795 void Waker() { 796 usleep(100000); // Make sure the waiter blocks. 797 GLOB = 1; 798 799 MU.Lock(); 800 COND = 1; // We are done! Tell the Waiter. 801 MU.Unlock(); // calls ANNOTATE_CONDVAR_SIGNAL; 802 } 803 void Waiter() { 804 ThreadPool pool(1); 805 pool.StartWorkers(); 806 COND = 0; 807 pool.Add(NewCallback(Waker)); 808 809 MU.Lock(); 810 CHECK(MU.AwaitWithTimeout(Condition(&ArgIsOne, &COND), INT_MAX)); 811 MU.Unlock(); 812 813 GLOB = 2; 814 } 815 void Run() { 816 printf("test19: negative\n"); 817 Waiter(); 818 printf("\tGLOB=%d\n", GLOB); 819 } 820 REGISTER_TEST2(Run, 19, FEATURE|NEEDS_ANNOTATIONS); 821 } // namespace test19 822 823 // test20: TP. Incorrect synchronization via AwaitWhen(), timeout. {{{1 824 namespace test20 { 825 int GLOB = 0; 826 Mutex MU; 827 // True race. We timeout in AwaitWhen. 828 void Waker() { 829 GLOB = 1; 830 usleep(100 * 1000); 831 } 832 void Waiter() { 833 MU.Lock(); 834 CHECK(!MU.AwaitWithTimeout(Condition(&ArgIsOne, &COND), 100)); 835 MU.Unlock(); 836 837 GLOB = 2; 838 } 839 void Run() { 840 printf("test20: positive\n"); 841 COND = 0; 842 ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test20. TP."); 843 MyThreadArray t(Waker, Waiter); 844 t.Start(); 845 t.Join(); 846 printf("\tGLOB=%d\n", GLOB); 847 } 848 REGISTER_TEST2(Run, 20, FEATURE|NEEDS_ANNOTATIONS); 849 } // namespace test20 850 851 // test21: TP. Incorrect synchronization via LockWhenWithTimeout(). {{{1 852 namespace test21 { 853 int GLOB = 0; 854 // True race. We timeout in LockWhenWithTimeout(). 855 Mutex MU; 856 void Waker() { 857 GLOB = 1; 858 usleep(100 * 1000); 859 } 860 void Waiter() { 861 CHECK(!MU.LockWhenWithTimeout(Condition(&ArgIsOne, &COND), 100)); 862 MU.Unlock(); 863 864 GLOB = 2; 865 } 866 void Run() { 867 printf("test21: positive\n"); 868 COND = 0; 869 ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test21. TP."); 870 MyThreadArray t(Waker, Waiter); 871 t.Start(); 872 t.Join(); 873 printf("\tGLOB=%d\n", GLOB); 874 } 875 REGISTER_TEST2(Run, 21, FEATURE|NEEDS_ANNOTATIONS); 876 } // namespace test21 877 878 // test22: TP. Incorrect synchronization via CondVar::WaitWithTimeout(). {{{1 879 namespace test22 { 880 int GLOB = 0; 881 Mutex MU; 882 // True race. We timeout in CondVar::WaitWithTimeout(). 883 void Waker() { 884 GLOB = 1; 885 usleep(100 * 1000); 886 } 887 void Waiter() { 888 int ms_left_to_wait = 100; 889 int deadline_ms = GetTimeInMs() + ms_left_to_wait; 890 MU.Lock(); 891 while(COND != 1 && ms_left_to_wait > 0) { 892 CV.WaitWithTimeout(&MU, ms_left_to_wait); 893 ms_left_to_wait = deadline_ms - GetTimeInMs(); 894 } 895 MU.Unlock(); 896 897 GLOB = 2; 898 } 899 void Run() { 900 printf("test22: positive\n"); 901 COND = 0; 902 ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test22. TP."); 903 MyThreadArray t(Waker, Waiter); 904 t.Start(); 905 t.Join(); 906 printf("\tGLOB=%d\n", GLOB); 907 } 908 REGISTER_TEST(Run, 22); 909 } // namespace test22 910 911 // test23: TN. TryLock, ReaderLock, ReaderTryLock. {{{1 912 namespace test23 { 913 // Correct synchronization with TryLock, Lock, ReaderTryLock, ReaderLock. 914 int GLOB = 0; 915 Mutex MU; 916 void Worker_TryLock() { 917 for (int i = 0; i < 20; i++) { 918 while (true) { 919 if (MU.TryLock()) { 920 GLOB++; 921 MU.Unlock(); 922 break; 923 } 924 usleep(1000); 925 } 926 } 927 } 928 929 void Worker_ReaderTryLock() { 930 for (int i = 0; i < 20; i++) { 931 while (true) { 932 if (MU.ReaderTryLock()) { 933 CHECK(GLOB != 777); 934 MU.ReaderUnlock(); 935 break; 936 } 937 usleep(1000); 938 } 939 } 940 } 941 942 void Worker_ReaderLock() { 943 for (int i = 0; i < 20; i++) { 944 MU.ReaderLock(); 945 CHECK(GLOB != 777); 946 MU.ReaderUnlock(); 947 usleep(1000); 948 } 949 } 950 951 void Worker_Lock() { 952 for (int i = 0; i < 20; i++) { 953 MU.Lock(); 954 GLOB++; 955 MU.Unlock(); 956 usleep(1000); 957 } 958 } 959 960 void Run() { 961 printf("test23: negative\n"); 962 MyThreadArray t(Worker_TryLock, 963 Worker_ReaderTryLock, 964 Worker_ReaderLock, 965 Worker_Lock 966 ); 967 t.Start(); 968 t.Join(); 969 printf("\tGLOB=%d\n", GLOB); 970 } 971 REGISTER_TEST(Run, 23); 972 } // namespace test23 973 974 // test24: TN. Synchronization via ReaderLockWhen(). {{{1 975 namespace test24 { 976 int GLOB = 0; 977 Mutex MU; 978 // Same as test03, but uses ReaderLockWhen(). 979 980 void Waker() { 981 usleep(100000); // Make sure the waiter blocks. 982 GLOB = 1; 983 984 MU.Lock(); 985 COND = 1; // We are done! Tell the Waiter. 986 MU.Unlock(); // calls ANNOTATE_CONDVAR_SIGNAL; 987 } 988 void Waiter() { 989 ThreadPool pool(1); 990 pool.StartWorkers(); 991 COND = 0; 992 pool.Add(NewCallback(Waker)); 993 MU.ReaderLockWhen(Condition(&ArgIsOne, &COND)); 994 MU.ReaderUnlock(); 995 996 GLOB = 2; 997 } 998 void Run() { 999 printf("test24: negative\n"); 1000 Waiter(); 1001 printf("\tGLOB=%d\n", GLOB); 1002 } 1003 REGISTER_TEST2(Run, 24, FEATURE|NEEDS_ANNOTATIONS); 1004 } // namespace test24 1005 1006 // test25: TN. Synchronization via ReaderLockWhenWithTimeout(). {{{1 1007 namespace test25 { 1008 int GLOB = 0; 1009 Mutex MU; 1010 // Same as test24, but uses ReaderLockWhenWithTimeout(). 1011 // We do not timeout. 1012 1013 void Waker() { 1014 usleep(100000); // Make sure the waiter blocks. 1015 GLOB = 1; 1016 1017 MU.Lock(); 1018 COND = 1; // We are done! Tell the Waiter. 1019 MU.Unlock(); // calls ANNOTATE_CONDVAR_SIGNAL; 1020 } 1021 void Waiter() { 1022 ThreadPool pool(1); 1023 pool.StartWorkers(); 1024 COND = 0; 1025 pool.Add(NewCallback(Waker)); 1026 CHECK(MU.ReaderLockWhenWithTimeout(Condition(&ArgIsOne, &COND), INT_MAX)); 1027 MU.ReaderUnlock(); 1028 1029 GLOB = 2; 1030 } 1031 void Run() { 1032 printf("test25: negative\n"); 1033 Waiter(); 1034 printf("\tGLOB=%d\n", GLOB); 1035 } 1036 REGISTER_TEST2(Run, 25, FEATURE|NEEDS_ANNOTATIONS); 1037 } // namespace test25 1038 1039 // test26: TP. Incorrect synchronization via ReaderLockWhenWithTimeout(). {{{1 1040 namespace test26 { 1041 int GLOB = 0; 1042 Mutex MU; 1043 // Same as test25, but we timeout and incorrectly assume happens-before. 1044 1045 void Waker() { 1046 GLOB = 1; 1047 usleep(10000); 1048 } 1049 void Waiter() { 1050 CHECK(!MU.ReaderLockWhenWithTimeout(Condition(&ArgIsOne, &COND), 100)); 1051 MU.ReaderUnlock(); 1052 1053 GLOB = 2; 1054 } 1055 void Run() { 1056 printf("test26: positive\n"); 1057 COND = 0; 1058 ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test26. TP"); 1059 MyThreadArray t(Waker, Waiter); 1060 t.Start(); 1061 t.Join(); 1062 printf("\tGLOB=%d\n", GLOB); 1063 } 1064 REGISTER_TEST2(Run, 26, FEATURE|NEEDS_ANNOTATIONS); 1065 } // namespace test26 1066 1067 1068 // test27: TN. Simple synchronization via SpinLock. {{{1 1069 namespace test27 { 1070 #ifndef NO_SPINLOCK 1071 int GLOB = 0; 1072 SpinLock MU; 1073 void Worker() { 1074 MU.Lock(); 1075 GLOB++; 1076 MU.Unlock(); 1077 usleep(10000); 1078 } 1079 1080 void Run() { 1081 printf("test27: negative\n"); 1082 MyThreadArray t(Worker, Worker, Worker, Worker); 1083 t.Start(); 1084 t.Join(); 1085 printf("\tGLOB=%d\n", GLOB); 1086 } 1087 REGISTER_TEST2(Run, 27, FEATURE|NEEDS_ANNOTATIONS); 1088 #endif 1089 } // namespace test27 1090 1091 1092 // test28: TN. Synchronization via Mutex, then PCQ. 3 threads {{{1 1093 namespace test28 { 1094 // Putter1: Getter: Putter2: 1095 // 1. MU.Lock() A. MU.Lock() 1096 // 2. write(GLOB) B. write(GLOB) 1097 // 3. MU.Unlock() C. MU.Unlock() 1098 // 4. Q.Put() ---------\ /------- D. Q.Put() 1099 // 5. MU.Lock() \-------> a. Q.Get() / E. MU.Lock() 1100 // 6. read(GLOB) b. Q.Get() <---------/ F. read(GLOB) 1101 // 7. MU.Unlock() (sleep) G. MU.Unlock() 1102 // c. read(GLOB) 1103 ProducerConsumerQueue Q(INT_MAX); 1104 int GLOB = 0; 1105 Mutex MU; 1106 1107 void Putter() { 1108 MU.Lock(); 1109 GLOB++; 1110 MU.Unlock(); 1111 1112 Q.Put(NULL); 1113 1114 MU.Lock(); 1115 CHECK(GLOB != 777); 1116 MU.Unlock(); 1117 } 1118 1119 void Getter() { 1120 Q.Get(); 1121 Q.Get(); 1122 usleep(100000); 1123 CHECK(GLOB == 2); 1124 } 1125 1126 void Run() { 1127 printf("test28: negative\n"); 1128 MyThreadArray t(Getter, Putter, Putter); 1129 t.Start(); 1130 t.Join(); 1131 printf("\tGLOB=%d\n", GLOB); 1132 } 1133 REGISTER_TEST(Run, 28); 1134 } // namespace test28 1135 1136 1137 // test29: TN. Synchronization via Mutex, then PCQ. 4 threads. {{{1 1138 namespace test29 { 1139 // Similar to test28, but has two Getters and two PCQs. 1140 ProducerConsumerQueue *Q1, *Q2; 1141 Mutex MU; 1142 int GLOB = 0; 1143 1144 void Putter(ProducerConsumerQueue *q) { 1145 MU.Lock(); 1146 GLOB++; 1147 MU.Unlock(); 1148 1149 q->Put(NULL); 1150 q->Put(NULL); 1151 1152 MU.Lock(); 1153 CHECK(GLOB != 777); 1154 MU.Unlock(); 1155 1156 } 1157 1158 void Putter1() { Putter(Q1); } 1159 void Putter2() { Putter(Q2); } 1160 1161 void Getter() { 1162 Q1->Get(); 1163 Q2->Get(); 1164 usleep(100000); 1165 CHECK(GLOB == 2); 1166 usleep(48000); // TODO: remove this when FP in test32 is fixed. 1167 } 1168 1169 void Run() { 1170 printf("test29: negative\n"); 1171 Q1 = new ProducerConsumerQueue(INT_MAX); 1172 Q2 = new ProducerConsumerQueue(INT_MAX); 1173 MyThreadArray t(Getter, Getter, Putter1, Putter2); 1174 t.Start(); 1175 t.Join(); 1176 printf("\tGLOB=%d\n", GLOB); 1177 delete Q1; 1178 delete Q2; 1179 } 1180 REGISTER_TEST(Run, 29); 1181 } // namespace test29 1182 1183 1184 // test30: TN. Synchronization via 'safe' race. Writer vs multiple Readers. {{{1 1185 namespace test30 { 1186 // This test shows a very risky kind of synchronization which is very easy 1187 // to get wrong. Actually, I am not sure I've got it right. 1188 // 1189 // Writer: Reader1, Reader2, ..., ReaderN: 1190 // 1. write(GLOB[i]: i >= BOUNDARY) a. n = BOUNDARY 1191 // 2. HAPPENS_BEFORE(BOUNDARY+1) -------> b. HAPPENS_AFTER(n) 1192 // 3. BOUNDARY++; c. read(GLOB[i]: i < n) 1193 // 1194 // Here we have a 'safe' race on accesses to BOUNDARY and 1195 // no actual races on accesses to GLOB[]: 1196 // Writer writes to GLOB[i] where i>=BOUNDARY and then increments BOUNDARY. 1197 // Readers read BOUNDARY and read GLOB[i] where i<BOUNDARY. 1198 // 1199 // I am not completely sure that this scheme guaranties no race between 1200 // accesses to GLOB since compilers and CPUs 1201 // are free to rearrange memory operations. 1202 // I am actually sure that this scheme is wrong unless we use 1203 // some smart memory fencing... 1204 1205 1206 const int N = 48; 1207 static int GLOB[N]; 1208 volatile int BOUNDARY = 0; 1209 1210 void Writer() { 1211 for (int i = 0; i < N; i++) { 1212 CHECK(BOUNDARY == i); 1213 for (int j = i; j < N; j++) { 1214 GLOB[j] = j; 1215 } 1216 ANNOTATE_HAPPENS_BEFORE(reinterpret_cast<void*>(BOUNDARY+1)); 1217 BOUNDARY++; 1218 usleep(1000); 1219 } 1220 } 1221 1222 void Reader() { 1223 int n; 1224 do { 1225 n = BOUNDARY; 1226 if (n == 0) continue; 1227 ANNOTATE_HAPPENS_AFTER(reinterpret_cast<void*>(n)); 1228 for (int i = 0; i < n; i++) { 1229 CHECK(GLOB[i] == i); 1230 } 1231 usleep(100); 1232 } while(n < N); 1233 } 1234 1235 void Run() { 1236 ANNOTATE_EXPECT_RACE((void*)(&BOUNDARY), "test30. Sync via 'safe' race."); 1237 printf("test30: negative\n"); 1238 MyThreadArray t(Writer, Reader, Reader, Reader); 1239 t.Start(); 1240 t.Join(); 1241 printf("\tGLOB=%d\n", GLOB[N-1]); 1242 } 1243 REGISTER_TEST2(Run, 30, FEATURE|NEEDS_ANNOTATIONS); 1244 } // namespace test30 1245 1246 1247 // test31: TN. Synchronization via 'safe' race. Writer vs Writer. {{{1 1248 namespace test31 { 1249 // This test is similar to test30, but 1250 // it has one Writer instead of mulitple Readers. 1251 // 1252 // Writer1: Writer2 1253 // 1. write(GLOB[i]: i >= BOUNDARY) a. n = BOUNDARY 1254 // 2. HAPPENS_BEFORE(BOUNDARY+1) -------> b. HAPPENS_AFTER(n) 1255 // 3. BOUNDARY++; c. write(GLOB[i]: i < n) 1256 // 1257 1258 const int N = 48; 1259 static int GLOB[N]; 1260 volatile int BOUNDARY = 0; 1261 1262 void Writer1() { 1263 for (int i = 0; i < N; i++) { 1264 CHECK(BOUNDARY == i); 1265 for (int j = i; j < N; j++) { 1266 GLOB[j] = j; 1267 } 1268 ANNOTATE_HAPPENS_BEFORE(reinterpret_cast<void*>(BOUNDARY+1)); 1269 BOUNDARY++; 1270 usleep(1000); 1271 } 1272 } 1273 1274 void Writer2() { 1275 int n; 1276 do { 1277 n = BOUNDARY; 1278 if (n == 0) continue; 1279 ANNOTATE_HAPPENS_AFTER(reinterpret_cast<void*>(n)); 1280 for (int i = 0; i < n; i++) { 1281 if(GLOB[i] == i) { 1282 GLOB[i]++; 1283 } 1284 } 1285 usleep(100); 1286 } while(n < N); 1287 } 1288 1289 void Run() { 1290 ANNOTATE_EXPECT_RACE((void*)(&BOUNDARY), "test31. Sync via 'safe' race."); 1291 printf("test31: negative\n"); 1292 MyThreadArray t(Writer1, Writer2); 1293 t.Start(); 1294 t.Join(); 1295 printf("\tGLOB=%d\n", GLOB[N-1]); 1296 } 1297 REGISTER_TEST2(Run, 31, FEATURE|NEEDS_ANNOTATIONS); 1298 } // namespace test31 1299 1300 1301 // test32: FP. Synchronization via thread create/join. W/R. {{{1 1302 namespace test32 { 1303 // This test is well synchronized but helgrind 3.3.0 reports a race. 1304 // 1305 // Parent: Writer: Reader: 1306 // 1. Start(Reader) -----------------------\ . 1307 // \ . 1308 // 2. Start(Writer) ---\ \ . 1309 // \---> a. MU.Lock() \--> A. sleep(long enough) 1310 // b. write(GLOB) 1311 // /---- c. MU.Unlock() 1312 // 3. Join(Writer) <---/ 1313 // B. MU.Lock() 1314 // C. read(GLOB) 1315 // /------------ D. MU.Unlock() 1316 // 4. Join(Reader) <----------------/ 1317 // 5. write(GLOB) 1318 // 1319 // 1320 // The call to sleep() in Reader is not part of synchronization, 1321 // it is required to trigger the false positive in helgrind 3.3.0. 1322 // 1323 int GLOB = 0; 1324 Mutex MU; 1325 1326 void Writer() { 1327 MU.Lock(); 1328 GLOB = 1; 1329 MU.Unlock(); 1330 } 1331 1332 void Reader() { 1333 usleep(480000); 1334 MU.Lock(); 1335 CHECK(GLOB != 777); 1336 MU.Unlock(); 1337 } 1338 1339 void Parent() { 1340 MyThread r(Reader); 1341 MyThread w(Writer); 1342 r.Start(); 1343 w.Start(); 1344 1345 w.Join(); // 'w' joins first. 1346 r.Join(); 1347 1348 GLOB = 2; 1349 } 1350 1351 void Run() { 1352 // ANNOTATE_EXPECT_RACE(&GLOB, "test32. FP. Fixed by MSMProp1."); 1353 printf("test32: negative\n"); 1354 Parent(); 1355 printf("\tGLOB=%d\n", GLOB); 1356 } 1357 1358 REGISTER_TEST(Run, 32); 1359 } // namespace test32 1360 1361 1362 // test33: STAB. Stress test for the number of thread sets (TSETs). {{{1 1363 namespace test33 { 1364 int GLOB = 0; 1365 // Here we access N memory locations from within log(N) threads. 1366 // We do it in such a way that helgrind creates nearly all possible TSETs. 1367 // Then we join all threads and start again (N_iter times). 1368 const int N_iter = 48; 1369 const int Nlog = 15; 1370 const int N = 1 << Nlog; 1371 static int ARR[N]; 1372 Mutex MU; 1373 1374 void Worker() { 1375 MU.Lock(); 1376 int n = ++GLOB; 1377 MU.Unlock(); 1378 1379 n %= Nlog; 1380 for (int i = 0; i < N; i++) { 1381 // ARR[i] is accessed by threads from i-th subset 1382 if (i & (1 << n)) { 1383 CHECK(ARR[i] == 0); 1384 } 1385 } 1386 } 1387 1388 void Run() { 1389 printf("test33:\n"); 1390 1391 std::vector<MyThread*> vec(Nlog); 1392 1393 for (int j = 0; j < N_iter; j++) { 1394 // Create and start Nlog threads 1395 for (int i = 0; i < Nlog; i++) { 1396 vec[i] = new MyThread(Worker); 1397 } 1398 for (int i = 0; i < Nlog; i++) { 1399 vec[i]->Start(); 1400 } 1401 // Join all threads. 1402 for (int i = 0; i < Nlog; i++) { 1403 vec[i]->Join(); 1404 delete vec[i]; 1405 } 1406 printf("------------------\n"); 1407 } 1408 1409 printf("\tGLOB=%d; ARR[1]=%d; ARR[7]=%d; ARR[N-1]=%d\n", 1410 GLOB, ARR[1], ARR[7], ARR[N-1]); 1411 } 1412 REGISTER_TEST2(Run, 33, STABILITY|EXCLUDE_FROM_ALL); 1413 } // namespace test33 1414 1415 1416 // test34: STAB. Stress test for the number of locks sets (LSETs). {{{1 1417 namespace test34 { 1418 // Similar to test33, but for lock sets. 1419 int GLOB = 0; 1420 const int N_iter = 48; 1421 const int Nlog = 10; 1422 const int N = 1 << Nlog; 1423 static int ARR[N]; 1424 static Mutex *MUs[Nlog]; 1425 1426 void Worker() { 1427 for (int i = 0; i < N; i++) { 1428 // ARR[i] is protected by MUs from i-th subset of all MUs 1429 for (int j = 0; j < Nlog; j++) if (i & (1 << j)) MUs[j]->Lock(); 1430 CHECK(ARR[i] == 0); 1431 for (int j = 0; j < Nlog; j++) if (i & (1 << j)) MUs[j]->Unlock(); 1432 } 1433 } 1434 1435 void Run() { 1436 printf("test34:\n"); 1437 for (int iter = 0; iter < N_iter; iter++) { 1438 for (int i = 0; i < Nlog; i++) { 1439 MUs[i] = new Mutex; 1440 } 1441 MyThreadArray t(Worker, Worker); 1442 t.Start(); 1443 t.Join(); 1444 for (int i = 0; i < Nlog; i++) { 1445 delete MUs[i]; 1446 } 1447 printf("------------------\n"); 1448 } 1449 printf("\tGLOB=%d\n", GLOB); 1450 } 1451 REGISTER_TEST2(Run, 34, STABILITY|EXCLUDE_FROM_ALL); 1452 } // namespace test34 1453 1454 1455 // test35: PERF. Lots of mutexes and lots of call to free(). {{{1 1456 namespace test35 { 1457 // Helgrind 3.3.0 has very slow in shadow_mem_make_NoAccess(). Fixed locally. 1458 // With the fix helgrind runs this test about a minute. 1459 // Without the fix -- about 5 minutes. (on c2d 2.4GHz). 1460 // 1461 // TODO: need to figure out the best way for performance testing. 1462 int **ARR; 1463 const int N_mu = 25000; 1464 const int N_free = 48000; 1465 1466 void Worker() { 1467 for (int i = 0; i < N_free; i++) 1468 CHECK(777 == *ARR[i]); 1469 } 1470 1471 void Run() { 1472 printf("test35:\n"); 1473 std::vector<Mutex*> mus; 1474 1475 ARR = new int *[N_free]; 1476 for (int i = 0; i < N_free; i++) { 1477 const int c = N_free / N_mu; 1478 if ((i % c) == 0) { 1479 mus.push_back(new Mutex); 1480 mus.back()->Lock(); 1481 mus.back()->Unlock(); 1482 } 1483 ARR[i] = new int(777); 1484 } 1485 1486 // Need to put all ARR[i] into shared state in order 1487 // to trigger the performance bug. 1488 MyThreadArray t(Worker, Worker); 1489 t.Start(); 1490 t.Join(); 1491 1492 for (int i = 0; i < N_free; i++) delete ARR[i]; 1493 delete [] ARR; 1494 1495 for (size_t i = 0; i < mus.size(); i++) { 1496 delete mus[i]; 1497 } 1498 } 1499 REGISTER_TEST2(Run, 35, PERFORMANCE|EXCLUDE_FROM_ALL); 1500 } // namespace test35 1501 1502 1503 // test36: TN. Synchronization via Mutex, then PCQ. 3 threads. W/W {{{1 1504 namespace test36 { 1505 // variation of test28 (W/W instead of W/R) 1506 1507 // Putter1: Getter: Putter2: 1508 // 1. MU.Lock(); A. MU.Lock() 1509 // 2. write(GLOB) B. write(GLOB) 1510 // 3. MU.Unlock() C. MU.Unlock() 1511 // 4. Q.Put() ---------\ /------- D. Q.Put() 1512 // 5. MU1.Lock() \-------> a. Q.Get() / E. MU1.Lock() 1513 // 6. MU.Lock() b. Q.Get() <---------/ F. MU.Lock() 1514 // 7. write(GLOB) G. write(GLOB) 1515 // 8. MU.Unlock() H. MU.Unlock() 1516 // 9. MU1.Unlock() (sleep) I. MU1.Unlock() 1517 // c. MU1.Lock() 1518 // d. write(GLOB) 1519 // e. MU1.Unlock() 1520 ProducerConsumerQueue Q(INT_MAX); 1521 int GLOB = 0; 1522 Mutex MU, MU1; 1523 1524 void Putter() { 1525 MU.Lock(); 1526 GLOB++; 1527 MU.Unlock(); 1528 1529 Q.Put(NULL); 1530 1531 MU1.Lock(); 1532 MU.Lock(); 1533 GLOB++; 1534 MU.Unlock(); 1535 MU1.Unlock(); 1536 } 1537 1538 void Getter() { 1539 Q.Get(); 1540 Q.Get(); 1541 usleep(100000); 1542 MU1.Lock(); 1543 GLOB++; 1544 MU1.Unlock(); 1545 } 1546 1547 void Run() { 1548 printf("test36: negative \n"); 1549 MyThreadArray t(Getter, Putter, Putter); 1550 t.Start(); 1551 t.Join(); 1552 printf("\tGLOB=%d\n", GLOB); 1553 } 1554 REGISTER_TEST(Run, 36); 1555 } // namespace test36 1556 1557 1558 // test37: TN. Simple synchronization (write vs read). {{{1 1559 namespace test37 { 1560 int GLOB = 0; 1561 Mutex MU; 1562 // Similar to test10, but properly locked. 1563 // Writer: Reader: 1564 // 1. MU.Lock() 1565 // 2. write 1566 // 3. MU.Unlock() 1567 // a. MU.Lock() 1568 // b. read 1569 // c. MU.Unlock(); 1570 1571 void Writer() { 1572 MU.Lock(); 1573 GLOB = 3; 1574 MU.Unlock(); 1575 } 1576 void Reader() { 1577 usleep(100000); 1578 MU.Lock(); 1579 CHECK(GLOB != -777); 1580 MU.Unlock(); 1581 } 1582 1583 void Run() { 1584 printf("test37: negative\n"); 1585 MyThreadArray t(Writer, Reader); 1586 t.Start(); 1587 t.Join(); 1588 printf("\tGLOB=%d\n", GLOB); 1589 } 1590 REGISTER_TEST(Run, 37); 1591 } // namespace test37 1592 1593 1594 // test38: TN. Synchronization via Mutexes and PCQ. 4 threads. W/W {{{1 1595 namespace test38 { 1596 // Fusion of test29 and test36. 1597 1598 // Putter1: Putter2: Getter1: Getter2: 1599 // MU1.Lock() MU1.Lock() 1600 // write(GLOB) write(GLOB) 1601 // MU1.Unlock() MU1.Unlock() 1602 // Q1.Put() Q2.Put() 1603 // Q1.Put() Q2.Put() 1604 // MU1.Lock() MU1.Lock() 1605 // MU2.Lock() MU2.Lock() 1606 // write(GLOB) write(GLOB) 1607 // MU2.Unlock() MU2.Unlock() 1608 // MU1.Unlock() MU1.Unlock() sleep sleep 1609 // Q1.Get() Q1.Get() 1610 // Q2.Get() Q2.Get() 1611 // MU2.Lock() MU2.Lock() 1612 // write(GLOB) write(GLOB) 1613 // MU2.Unlock() MU2.Unlock() 1614 // 1615 1616 1617 ProducerConsumerQueue *Q1, *Q2; 1618 int GLOB = 0; 1619 Mutex MU, MU1, MU2; 1620 1621 void Putter(ProducerConsumerQueue *q) { 1622 MU1.Lock(); 1623 GLOB++; 1624 MU1.Unlock(); 1625 1626 q->Put(NULL); 1627 q->Put(NULL); 1628 1629 MU1.Lock(); 1630 MU2.Lock(); 1631 GLOB++; 1632 MU2.Unlock(); 1633 MU1.Unlock(); 1634 1635 } 1636 1637 void Putter1() { Putter(Q1); } 1638 void Putter2() { Putter(Q2); } 1639 1640 void Getter() { 1641 usleep(100000); 1642 Q1->Get(); 1643 Q2->Get(); 1644 1645 MU2.Lock(); 1646 GLOB++; 1647 MU2.Unlock(); 1648 1649 usleep(48000); // TODO: remove this when FP in test32 is fixed. 1650 } 1651 1652 void Run() { 1653 printf("test38: negative\n"); 1654 Q1 = new ProducerConsumerQueue(INT_MAX); 1655 Q2 = new ProducerConsumerQueue(INT_MAX); 1656 MyThreadArray t(Getter, Getter, Putter1, Putter2); 1657 t.Start(); 1658 t.Join(); 1659 printf("\tGLOB=%d\n", GLOB); 1660 delete Q1; 1661 delete Q2; 1662 } 1663 REGISTER_TEST(Run, 38); 1664 } // namespace test38 1665 1666 namespace NegativeTests_Barrier { // {{{1 1667 #ifndef NO_BARRIER 1668 // Same as test17 but uses Barrier class (pthread_barrier_t). 1669 int GLOB = 0; 1670 const int N_threads = 3; 1671 Barrier barrier(N_threads); 1672 Mutex MU; 1673 1674 void Worker() { 1675 MU.Lock(); 1676 GLOB++; 1677 MU.Unlock(); 1678 barrier.Block(); 1679 CHECK(GLOB == N_threads); 1680 } 1681 1682 TEST(NegativeTests, Barrier) { 1683 ANNOTATE_TRACE_MEMORY(&GLOB); 1684 { 1685 ThreadPool pool(N_threads); 1686 pool.StartWorkers(); 1687 for (int i = 0; i < N_threads; i++) { 1688 pool.Add(NewCallback(Worker)); 1689 } 1690 } // all folks are joined here. 1691 CHECK(GLOB == 3); 1692 } 1693 #endif // NO_BARRIER 1694 } // namespace test39 1695 1696 1697 // test40: FP. Synchronization via Mutexes and PCQ. 4 threads. W/W {{{1 1698 namespace test40 { 1699 // Similar to test38 but with different order of events (due to sleep). 1700 1701 // Putter1: Putter2: Getter1: Getter2: 1702 // MU1.Lock() MU1.Lock() 1703 // write(GLOB) write(GLOB) 1704 // MU1.Unlock() MU1.Unlock() 1705 // Q1.Put() Q2.Put() 1706 // Q1.Put() Q2.Put() 1707 // Q1.Get() Q1.Get() 1708 // Q2.Get() Q2.Get() 1709 // MU2.Lock() MU2.Lock() 1710 // write(GLOB) write(GLOB) 1711 // MU2.Unlock() MU2.Unlock() 1712 // 1713 // MU1.Lock() MU1.Lock() 1714 // MU2.Lock() MU2.Lock() 1715 // write(GLOB) write(GLOB) 1716 // MU2.Unlock() MU2.Unlock() 1717 // MU1.Unlock() MU1.Unlock() 1718 1719 1720 ProducerConsumerQueue *Q1, *Q2; 1721 int GLOB = 0; 1722 Mutex MU, MU1, MU2; 1723 1724 void Putter(ProducerConsumerQueue *q) { 1725 MU1.Lock(); 1726 GLOB++; 1727 MU1.Unlock(); 1728 1729 q->Put(NULL); 1730 q->Put(NULL); 1731 usleep(100000); 1732 1733 MU1.Lock(); 1734 MU2.Lock(); 1735 GLOB++; 1736 MU2.Unlock(); 1737 MU1.Unlock(); 1738 1739 } 1740 1741 void Putter1() { Putter(Q1); } 1742 void Putter2() { Putter(Q2); } 1743 1744 void Getter() { 1745 Q1->Get(); 1746 Q2->Get(); 1747 1748 MU2.Lock(); 1749 GLOB++; 1750 MU2.Unlock(); 1751 1752 usleep(48000); // TODO: remove this when FP in test32 is fixed. 1753 } 1754 1755 void Run() { 1756 // ANNOTATE_EXPECT_RACE(&GLOB, "test40. FP. Fixed by MSMProp1. Complex Stuff."); 1757 printf("test40: negative\n"); 1758 Q1 = new ProducerConsumerQueue(INT_MAX); 1759 Q2 = new ProducerConsumerQueue(INT_MAX); 1760 MyThreadArray t(Getter, Getter, Putter1, Putter2); 1761 t.Start(); 1762 t.Join(); 1763 printf("\tGLOB=%d\n", GLOB); 1764 delete Q1; 1765 delete Q2; 1766 } 1767 REGISTER_TEST(Run, 40); 1768 } // namespace test40 1769 1770 // test41: TN. Test for race that appears when loading a dynamic symbol. {{{1 1771 namespace test41 { 1772 void Worker() { 1773 ANNOTATE_NO_OP(NULL); // An empty function, loaded from dll. 1774 } 1775 void Run() { 1776 printf("test41: negative\n"); 1777 MyThreadArray t(Worker, Worker, Worker); 1778 t.Start(); 1779 t.Join(); 1780 } 1781 REGISTER_TEST2(Run, 41, FEATURE|NEEDS_ANNOTATIONS); 1782 } // namespace test41 1783 1784 1785 // test42: TN. Using the same cond var several times. {{{1 1786 namespace test42 { 1787 int GLOB = 0; 1788 int COND = 0; 1789 int N_threads = 3; 1790 Mutex MU; 1791 1792 void Worker1() { 1793 GLOB=1; 1794 1795 MU.Lock(); 1796 COND = 1; 1797 CV.Signal(); 1798 MU.Unlock(); 1799 1800 MU.Lock(); 1801 while (COND != 0) 1802 CV.Wait(&MU); 1803 ANNOTATE_CONDVAR_LOCK_WAIT(&CV, &MU); 1804 MU.Unlock(); 1805 1806 GLOB=3; 1807 1808 } 1809 1810 void Worker2() { 1811 1812 MU.Lock(); 1813 while (COND != 1) 1814 CV.Wait(&MU); 1815 ANNOTATE_CONDVAR_LOCK_WAIT(&CV, &MU); 1816 MU.Unlock(); 1817 1818 GLOB=2; 1819 1820 MU.Lock(); 1821 COND = 0; 1822 CV.Signal(); 1823 MU.Unlock(); 1824 1825 } 1826 1827 void Run() { 1828 // ANNOTATE_EXPECT_RACE(&GLOB, "test42. TN. debugging."); 1829 printf("test42: negative\n"); 1830 MyThreadArray t(Worker1, Worker2); 1831 t.Start(); 1832 t.Join(); 1833 printf("\tGLOB=%d\n", GLOB); 1834 } 1835 REGISTER_TEST2(Run, 42, FEATURE|NEEDS_ANNOTATIONS); 1836 } // namespace test42 1837 1838 1839 1840 // test43: TN. {{{1 1841 namespace test43 { 1842 // 1843 // Putter: Getter: 1844 // 1. write 1845 // 2. Q.Put() --\ . 1846 // 3. read \--> a. Q.Get() 1847 // b. read 1848 int GLOB = 0; 1849 ProducerConsumerQueue Q(INT_MAX); 1850 void Putter() { 1851 GLOB = 1; 1852 Q.Put(NULL); 1853 CHECK(GLOB == 1); 1854 } 1855 void Getter() { 1856 Q.Get(); 1857 usleep(100000); 1858 CHECK(GLOB == 1); 1859 } 1860 void Run() { 1861 printf("test43: negative\n"); 1862 MyThreadArray t(Putter, Getter); 1863 t.Start(); 1864 t.Join(); 1865 printf("\tGLOB=%d\n", GLOB); 1866 } 1867 REGISTER_TEST(Run, 43) 1868 } // namespace test43 1869 1870 1871 // test44: FP. {{{1 1872 namespace test44 { 1873 // 1874 // Putter: Getter: 1875 // 1. read 1876 // 2. Q.Put() --\ . 1877 // 3. MU.Lock() \--> a. Q.Get() 1878 // 4. write 1879 // 5. MU.Unlock() 1880 // b. MU.Lock() 1881 // c. write 1882 // d. MU.Unlock(); 1883 int GLOB = 0; 1884 Mutex MU; 1885 ProducerConsumerQueue Q(INT_MAX); 1886 void Putter() { 1887 CHECK(GLOB == 0); 1888 Q.Put(NULL); 1889 MU.Lock(); 1890 GLOB = 1; 1891 MU.Unlock(); 1892 } 1893 void Getter() { 1894 Q.Get(); 1895 usleep(100000); 1896 MU.Lock(); 1897 GLOB = 1; 1898 MU.Unlock(); 1899 } 1900 void Run() { 1901 // ANNOTATE_EXPECT_RACE(&GLOB, "test44. FP. Fixed by MSMProp1."); 1902 printf("test44: negative\n"); 1903 MyThreadArray t(Putter, Getter); 1904 t.Start(); 1905 t.Join(); 1906 printf("\tGLOB=%d\n", GLOB); 1907 } 1908 REGISTER_TEST(Run, 44) 1909 } // namespace test44 1910 1911 1912 // test45: TN. {{{1 1913 namespace test45 { 1914 // 1915 // Putter: Getter: 1916 // 1. read 1917 // 2. Q.Put() --\ . 1918 // 3. MU.Lock() \--> a. Q.Get() 1919 // 4. write 1920 // 5. MU.Unlock() 1921 // b. MU.Lock() 1922 // c. read 1923 // d. MU.Unlock(); 1924 int GLOB = 0; 1925 Mutex MU; 1926 ProducerConsumerQueue Q(INT_MAX); 1927 void Putter() { 1928 CHECK(GLOB == 0); 1929 Q.Put(NULL); 1930 MU.Lock(); 1931 GLOB++; 1932 MU.Unlock(); 1933 } 1934 void Getter() { 1935 Q.Get(); 1936 usleep(100000); 1937 MU.Lock(); 1938 CHECK(GLOB <= 1); 1939 MU.Unlock(); 1940 } 1941 void Run() { 1942 printf("test45: negative\n"); 1943 MyThreadArray t(Putter, Getter); 1944 t.Start(); 1945 t.Join(); 1946 printf("\tGLOB=%d\n", GLOB); 1947 } 1948 REGISTER_TEST(Run, 45) 1949 } // namespace test45 1950 1951 1952 // test46: FN. {{{1 1953 namespace test46 { 1954 // 1955 // First: Second: 1956 // 1. write 1957 // 2. MU.Lock() 1958 // 3. write 1959 // 4. MU.Unlock() (sleep) 1960 // a. MU.Lock() 1961 // b. write 1962 // c. MU.Unlock(); 1963 int GLOB = 0; 1964 Mutex MU; 1965 void First() { 1966 GLOB++; 1967 MU.Lock(); 1968 GLOB++; 1969 MU.Unlock(); 1970 } 1971 void Second() { 1972 usleep(480000); 1973 MU.Lock(); 1974 GLOB++; 1975 MU.Unlock(); 1976 1977 // just a print. 1978 // If we move it to Run() we will get report in MSMHelgrind 1979 // due to its false positive (test32). 1980 MU.Lock(); 1981 printf("\tGLOB=%d\n", GLOB); 1982 MU.Unlock(); 1983 } 1984 void Run() { 1985 ANNOTATE_TRACE_MEMORY(&GLOB); 1986 MyThreadArray t(First, Second); 1987 t.Start(); 1988 t.Join(); 1989 } 1990 REGISTER_TEST(Run, 46) 1991 } // namespace test46 1992 1993 1994 // test47: TP. Not detected by pure happens-before detectors. {{{1 1995 namespace test47 { 1996 // A true race that can not be detected by a pure happens-before 1997 // race detector. 1998 // 1999 // First: Second: 2000 // 1. write 2001 // 2. MU.Lock() 2002 // 3. MU.Unlock() (sleep) 2003 // a. MU.Lock() 2004 // b. MU.Unlock(); 2005 // c. write 2006 int GLOB = 0; 2007 Mutex MU; 2008 void First() { 2009 GLOB=1; 2010 MU.Lock(); 2011 MU.Unlock(); 2012 } 2013 void Second() { 2014 usleep(480000); 2015 MU.Lock(); 2016 MU.Unlock(); 2017 GLOB++; 2018 } 2019 void Run() { 2020 if (!Tsan_PureHappensBefore()) 2021 ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test47. TP. Not detected by pure HB."); 2022 printf("test47: positive\n"); 2023 MyThreadArray t(First, Second); 2024 t.Start(); 2025 t.Join(); 2026 printf("\tGLOB=%d\n", GLOB); 2027 } 2028 REGISTER_TEST(Run, 47) 2029 } // namespace test47 2030 2031 2032 // test48: FN. Simple race (single write vs multiple reads). {{{1 2033 namespace test48 { 2034 int GLOB = 0; 2035 // same as test10 but with single writer and multiple readers 2036 // A simple data race between single writer and multiple readers. 2037 // Write happens before Reads (enforced by sleep(1)), 2038 2039 // 2040 // Writer: Readers: 2041 // 1. write(GLOB) a. sleep(long enough so that GLOB 2042 // is most likely initialized by Writer) 2043 // b. read(GLOB) 2044 // 2045 // 2046 // Eraser algorithm does not detect the race here, 2047 // see Section 2.2 of http://citeseer.ist.psu.edu/savage97eraser.html. 2048 // 2049 void Writer() { 2050 GLOB = 3; 2051 } 2052 void Reader() { 2053 usleep(100000); 2054 CHECK(GLOB != -777); 2055 } 2056 2057 void Run() { 2058 ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test48. TP. FN in MSMHelgrind."); 2059 printf("test48: positive\n"); 2060 MyThreadArray t(Writer, Reader,Reader,Reader); 2061 t.Start(); 2062 t.Join(); 2063 printf("\tGLOB=%d\n", GLOB); 2064 } 2065 REGISTER_TEST(Run, 48) 2066 } // namespace test48 2067 2068 2069 // test49: FN. Simple race (single write vs multiple reads). {{{1 2070 namespace test49 { 2071 int GLOB = 0; 2072 // same as test10 but with multiple read operations done by a single reader 2073 // A simple data race between writer and readers. 2074 // Write happens before Read (enforced by sleep(1)), 2075 // 2076 // Writer: Reader: 2077 // 1. write(GLOB) a. sleep(long enough so that GLOB 2078 // is most likely initialized by Writer) 2079 // b. read(GLOB) 2080 // c. read(GLOB) 2081 // d. read(GLOB) 2082 // e. read(GLOB) 2083 // 2084 // 2085 // Eraser algorithm does not detect the race here, 2086 // see Section 2.2 of http://citeseer.ist.psu.edu/savage97eraser.html. 2087 // 2088 void Writer() { 2089 GLOB = 3; 2090 } 2091 void Reader() { 2092 usleep(100000); 2093 CHECK(GLOB != -777); 2094 CHECK(GLOB != -777); 2095 CHECK(GLOB != -777); 2096 CHECK(GLOB != -777); 2097 } 2098 2099 void Run() { 2100 ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test49. TP. FN in MSMHelgrind."); 2101 printf("test49: positive\n"); 2102 MyThreadArray t(Writer, Reader); 2103 t.Start(); 2104 t.Join(); 2105 printf("\tGLOB=%d\n", GLOB); 2106 } 2107 REGISTER_TEST(Run, 49); 2108 } // namespace test49 2109 2110 2111 // test50: TP. Synchronization via CondVar. {{{1 2112 namespace test50 { 2113 int GLOB = 0; 2114 Mutex MU; 2115 // Two last write accesses to GLOB are not synchronized 2116 // 2117 // Waiter: Waker: 2118 // 1. COND = 0 2119 // 2. Start(Waker) 2120 // 3. MU.Lock() a. write(GLOB) 2121 // b. MU.Lock() 2122 // c. COND = 1 2123 // /--- d. CV.Signal() 2124 // 4. while(COND != 1) / e. MU.Unlock() 2125 // CV.Wait(MU) <---/ 2126 // 5. MU.Unlock() 2127 // 6. write(GLOB) f. MU.Lock() 2128 // g. write(GLOB) 2129 // h. MU.Unlock() 2130 2131 2132 void Waker() { 2133 usleep(100000); // Make sure the waiter blocks. 2134 2135 GLOB = 1; 2136 2137 MU.Lock(); 2138 COND = 1; 2139 CV.Signal(); 2140 MU.Unlock(); 2141 2142 usleep(100000); 2143 MU.Lock(); 2144 GLOB = 3; 2145 MU.Unlock(); 2146 } 2147 2148 void Waiter() { 2149 MU.Lock(); 2150 while(COND != 1) 2151 CV.Wait(&MU); 2152 ANNOTATE_CONDVAR_LOCK_WAIT(&CV, &MU); 2153 MU.Unlock(); 2154 2155 GLOB = 2; 2156 } 2157 void Run() { 2158 printf("test50: positive\n"); 2159 COND = 0; 2160 ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test50. TP."); 2161 MyThreadArray t(Waker, Waiter); 2162 t.Start(); 2163 t.Join(); 2164 printf("\tGLOB=%d\n", GLOB); 2165 } 2166 REGISTER_TEST2(Run, 50, FEATURE|NEEDS_ANNOTATIONS); 2167 } // namespace test50 2168 2169 2170 // test51: TP. Synchronization via CondVar: problem with several signals. {{{1 2171 namespace test51 { 2172 int GLOB = 0; 2173 int COND = 0; 2174 Mutex MU; 2175 StealthNotification n1, n2; 2176 2177 // scheduler dependent results because of several signals 2178 // second signal will be lost 2179 // 2180 // Waiter: Waker: 2181 // 1. Start(Waker) 2182 // 2. MU.Lock() 2183 // 3. while(COND) 2184 // CV.Wait(MU)<-\ . 2185 // 4. MU.Unlock() \ . 2186 // 5. write(GLOB) \ a. write(GLOB) 2187 // \ b. MU.Lock() 2188 // \ c. COND = 1 2189 // \--- d. CV.Signal() 2190 // e. MU.Unlock() 2191 // 2192 // f. write(GLOB) 2193 // 2194 // g. MU.Lock() 2195 // h. COND = 1 2196 // LOST<---- i. CV.Signal() 2197 // j. MU.Unlock() 2198 2199 void Waker() { 2200 n1.wait(); // Make sure the waiter blocks. 2201 2202 GLOB = 1; 2203 2204 MU.Lock(); 2205 COND = 1; 2206 CV.Signal(); 2207 MU.Unlock(); 2208 2209 n2.wait(); // Make sure the waiter continued. 2210 2211 GLOB = 2; 2212 2213 MU.Lock(); 2214 COND = 1; 2215 CV.Signal(); //Lost Signal 2216 MU.Unlock(); 2217 } 2218 2219 void Waiter() { 2220 MU.Lock(); 2221 n1.signal(); // Ready to get the first signal. 2222 while(COND != 1) 2223 CV.Wait(&MU); 2224 MU.Unlock(); 2225 2226 GLOB = 3; 2227 n2.signal(); // Ready to miss the second signal. 2228 } 2229 void Run() { 2230 ANNOTATE_EXPECT_RACE(&GLOB, "test51. TP."); 2231 printf("test51: positive\n"); 2232 MyThreadArray t(Waiter, Waker); 2233 t.Start(); 2234 t.Join(); 2235 printf("\tGLOB=%d\n", GLOB); 2236 } 2237 REGISTER_TEST(Run, 51); 2238 } // namespace test51 2239 2240 2241 // test52: TP. Synchronization via CondVar: problem with several signals. {{{1 2242 namespace test52 { 2243 int GLOB = 0; 2244 int COND = 0; 2245 Mutex MU; 2246 StealthNotification n1, n2; 2247 2248 // same as test51 but the first signal will be lost 2249 // scheduler dependent results because of several signals 2250 // 2251 // Waiter: Waker: 2252 // 1. Start(Waker) 2253 // a. write(GLOB) 2254 // b. MU.Lock() 2255 // c. COND = 1 2256 // LOST<---- d. CV.Signal() 2257 // e. MU.Unlock() 2258 // 2259 // 2. MU.Lock() 2260 // 3. while(COND) 2261 // CV.Wait(MU)<-\ . 2262 // 4. MU.Unlock() \ f. write(GLOB) 2263 // 5. write(GLOB) \ . 2264 // \ g. MU.Lock() 2265 // \ h. COND = 1 2266 // \--- i. CV.Signal() 2267 // j. MU.Unlock() 2268 2269 void Waker() { 2270 2271 GLOB = 1; 2272 2273 MU.Lock(); 2274 COND = 1; 2275 CV.Signal(); //lost signal 2276 MU.Unlock(); 2277 2278 n1.signal(); // Ok, now we may block. 2279 n2.wait(); // We blocked. 2280 2281 GLOB = 2; 2282 2283 MU.Lock(); 2284 COND = 1; 2285 CV.Signal(); 2286 MU.Unlock(); 2287 } 2288 2289 void Waiter() { 2290 n1.wait(); // The first signal is lost. 2291 2292 MU.Lock(); 2293 n2.signal(); // The 2-nd signal may go. 2294 while(COND != 1) 2295 CV.Wait(&MU); 2296 MU.Unlock(); 2297 2298 GLOB = 3; 2299 } 2300 void Run() { 2301 printf("test52: positive\n"); 2302 ANNOTATE_EXPECT_RACE(&GLOB, "test52. TP."); 2303 MyThreadArray t(Waker, Waiter); 2304 t.Start(); 2305 t.Join(); 2306 printf("\tGLOB=%d\n", GLOB); 2307 } 2308 REGISTER_TEST(Run, 52); 2309 } // namespace test52 2310 2311 2312 // test53: FP. Synchronization via implicit semaphore. {{{1 2313 namespace test53 { 2314 // Correctly synchronized test, but the common lockset is empty. 2315 // The variable FLAG works as an implicit semaphore. 2316 // MSMHelgrind still does not complain since it does not maintain the lockset 2317 // at the exclusive state. But MSMProp1 does complain. 2318 // See also test54. 2319 // 2320 // 2321 // Initializer: Users 2322 // 1. MU1.Lock() 2323 // 2. write(GLOB) 2324 // 3. FLAG = true 2325 // 4. MU1.Unlock() 2326 // a. MU1.Lock() 2327 // b. f = FLAG; 2328 // c. MU1.Unlock() 2329 // d. if (!f) goto a. 2330 // e. MU2.Lock() 2331 // f. write(GLOB) 2332 // g. MU2.Unlock() 2333 // 2334 2335 int GLOB = 0; 2336 bool FLAG = false; 2337 Mutex MU1, MU2; 2338 2339 void Initializer() { 2340 MU1.Lock(); 2341 GLOB = 1000; 2342 FLAG = true; 2343 MU1.Unlock(); 2344 usleep(100000); // just in case 2345 } 2346 2347 void User() { 2348 bool f = false; 2349 while(!f) { 2350 MU1.Lock(); 2351 f = FLAG; 2352 MU1.Unlock(); 2353 usleep(10000); 2354 } 2355 // at this point Initializer will not access GLOB again 2356 MU2.Lock(); 2357 CHECK(GLOB >= 1000); 2358 GLOB++; 2359 MU2.Unlock(); 2360 } 2361 2362 void Run() { 2363 if (!Tsan_PureHappensBefore()) 2364 ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test53. FP. Implicit semaphore"); 2365 printf("test53: FP. false positive, Implicit semaphore\n"); 2366 MyThreadArray t(Initializer, User, User); 2367 t.Start(); 2368 t.Join(); 2369 printf("\tGLOB=%d\n", GLOB); 2370 } 2371 REGISTER_TEST(Run, 53) 2372 } // namespace test53 2373 2374 2375 // test54: TN. Synchronization via implicit semaphore. Annotated {{{1 2376 namespace test54 { 2377 // Same as test53, but annotated. 2378 int GLOB = 0; 2379 bool FLAG = false; 2380 Mutex MU1, MU2; 2381 2382 void Initializer() { 2383 MU1.Lock(); 2384 GLOB = 1000; 2385 FLAG = true; 2386 ANNOTATE_CONDVAR_SIGNAL(&GLOB); 2387 MU1.Unlock(); 2388 usleep(100000); // just in case 2389 } 2390 2391 void User() { 2392 bool f = false; 2393 while(!f) { 2394 MU1.Lock(); 2395 f = FLAG; 2396 MU1.Unlock(); 2397 usleep(10000); 2398 } 2399 // at this point Initializer will not access GLOB again 2400 ANNOTATE_CONDVAR_WAIT(&GLOB); 2401 MU2.Lock(); 2402 CHECK(GLOB >= 1000); 2403 GLOB++; 2404 MU2.Unlock(); 2405 } 2406 2407 void Run() { 2408 printf("test54: negative\n"); 2409 MyThreadArray t(Initializer, User, User); 2410 t.Start(); 2411 t.Join(); 2412 printf("\tGLOB=%d\n", GLOB); 2413 } 2414 REGISTER_TEST2(Run, 54, FEATURE|NEEDS_ANNOTATIONS) 2415 } // namespace test54 2416 2417 2418 // test55: FP. Synchronization with TryLock. Not easy for race detectors {{{1 2419 namespace test55 { 2420 // "Correct" synchronization with TryLock and Lock. 2421 // 2422 // This scheme is actually very risky. 2423 // It is covered in detail in this video: 2424 // http://youtube.com/watch?v=mrvAqvtWYb4 (slide 36, near 50-th minute). 2425 int GLOB = 0; 2426 Mutex MU; 2427 2428 void Worker_Lock() { 2429 GLOB = 1; 2430 MU.Lock(); 2431 } 2432 2433 void Worker_TryLock() { 2434 while (true) { 2435 if (!MU.TryLock()) { 2436 MU.Unlock(); 2437 break; 2438 } 2439 else 2440 MU.Unlock(); 2441 usleep(100); 2442 } 2443 GLOB = 2; 2444 } 2445 2446 void Run() { 2447 printf("test55:\n"); 2448 MyThreadArray t(Worker_Lock, Worker_TryLock); 2449 t.Start(); 2450 t.Join(); 2451 printf("\tGLOB=%d\n", GLOB); 2452 } 2453 REGISTER_TEST2(Run, 55, FEATURE|EXCLUDE_FROM_ALL); 2454 } // namespace test55 2455 2456 2457 2458 // test56: TP. Use of ANNOTATE_BENIGN_RACE. {{{1 2459 namespace test56 { 2460 // For whatever reason the user wants to treat 2461 // a race on GLOB as a benign race. 2462 int GLOB = 0; 2463 int GLOB2 = 0; 2464 2465 void Worker() { 2466 GLOB++; 2467 } 2468 2469 void Run() { 2470 ANNOTATE_BENIGN_RACE(&GLOB, "test56. Use of ANNOTATE_BENIGN_RACE."); 2471 ANNOTATE_BENIGN_RACE(&GLOB2, "No race. The tool should be silent"); 2472 printf("test56: positive\n"); 2473 MyThreadArray t(Worker, Worker, Worker, Worker); 2474 t.Start(); 2475 t.Join(); 2476 printf("\tGLOB=%d\n", GLOB); 2477 } 2478 REGISTER_TEST2(Run, 56, FEATURE|NEEDS_ANNOTATIONS) 2479 } // namespace test56 2480 2481 2482 // test57: TN: Correct use of atomics. {{{1 2483 namespace test57 { 2484 int GLOB = 0; 2485 void Writer() { 2486 for (int i = 0; i < 10; i++) { 2487 AtomicIncrement(&GLOB, 1); 2488 usleep(1000); 2489 } 2490 } 2491 void Reader() { 2492 while (GLOB < 20) usleep(1000); 2493 } 2494 void Run() { 2495 printf("test57: negative\n"); 2496 MyThreadArray t(Writer, Writer, Reader, Reader); 2497 t.Start(); 2498 t.Join(); 2499 CHECK(GLOB == 20); 2500 printf("\tGLOB=%d\n", GLOB); 2501 } 2502 REGISTER_TEST(Run, 57) 2503 } // namespace test57 2504 2505 2506 // test58: TN. User defined synchronization. {{{1 2507 namespace test58 { 2508 int GLOB1 = 1; 2509 int GLOB2 = 2; 2510 int FLAG1 = 0; 2511 int FLAG2 = 0; 2512 2513 // Correctly synchronized test, but the common lockset is empty. 2514 // The variables FLAG1 and FLAG2 used for synchronization and as 2515 // temporary variables for swapping two global values. 2516 // Such kind of synchronization is rarely used (Excluded from all tests??). 2517 2518 void Worker2() { 2519 FLAG1=GLOB2; 2520 2521 while(!FLAG2) 2522 ; 2523 GLOB2=FLAG2; 2524 } 2525 2526 void Worker1() { 2527 FLAG2=GLOB1; 2528 2529 while(!FLAG1) 2530 ; 2531 GLOB1=FLAG1; 2532 } 2533 2534 void Run() { 2535 printf("test58:\n"); 2536 MyThreadArray t(Worker1, Worker2); 2537 t.Start(); 2538 t.Join(); 2539 printf("\tGLOB1=%d\n", GLOB1); 2540 printf("\tGLOB2=%d\n", GLOB2); 2541 } 2542 REGISTER_TEST2(Run, 58, FEATURE|EXCLUDE_FROM_ALL) 2543 } // namespace test58 2544 2545 2546 2547 // test59: TN. User defined synchronization. Annotated {{{1 2548 namespace test59 { 2549 int COND1 = 0; 2550 int COND2 = 0; 2551 int GLOB1 = 1; 2552 int GLOB2 = 2; 2553 int FLAG1 = 0; 2554 int FLAG2 = 0; 2555 // same as test 58 but annotated 2556 2557 void Worker2() { 2558 FLAG1=GLOB2; 2559 ANNOTATE_CONDVAR_SIGNAL(&COND2); 2560 while(!FLAG2) usleep(1); 2561 ANNOTATE_CONDVAR_WAIT(&COND1); 2562 GLOB2=FLAG2; 2563 } 2564 2565 void Worker1() { 2566 FLAG2=GLOB1; 2567 ANNOTATE_CONDVAR_SIGNAL(&COND1); 2568 while(!FLAG1) usleep(1); 2569 ANNOTATE_CONDVAR_WAIT(&COND2); 2570 GLOB1=FLAG1; 2571 } 2572 2573 void Run() { 2574 printf("test59: negative\n"); 2575 ANNOTATE_BENIGN_RACE(&FLAG1, "synchronization via 'safe' race"); 2576 ANNOTATE_BENIGN_RACE(&FLAG2, "synchronization via 'safe' race"); 2577 MyThreadArray t(Worker1, Worker2); 2578 t.Start(); 2579 t.Join(); 2580 printf("\tGLOB1=%d\n", GLOB1); 2581 printf("\tGLOB2=%d\n", GLOB2); 2582 } 2583 REGISTER_TEST2(Run, 59, FEATURE|NEEDS_ANNOTATIONS) 2584 } // namespace test59 2585 2586 2587 // test60: TN. Correct synchronization using signal-wait {{{1 2588 namespace test60 { 2589 int COND1 = 0; 2590 int COND2 = 0; 2591 int GLOB1 = 1; 2592 int GLOB2 = 2; 2593 int FLAG2 = 0; 2594 int FLAG1 = 0; 2595 Mutex MU; 2596 // same as test 59 but synchronized with signal-wait. 2597 2598 void Worker2() { 2599 FLAG1=GLOB2; 2600 2601 MU.Lock(); 2602 COND1 = 1; 2603 CV.Signal(); 2604 MU.Unlock(); 2605 2606 MU.Lock(); 2607 while(COND2 != 1) 2608 CV.Wait(&MU); 2609 ANNOTATE_CONDVAR_LOCK_WAIT(&CV, &MU); 2610 MU.Unlock(); 2611 2612 GLOB2=FLAG2; 2613 } 2614 2615 void Worker1() { 2616 FLAG2=GLOB1; 2617 2618 MU.Lock(); 2619 COND2 = 1; 2620 CV.Signal(); 2621 MU.Unlock(); 2622 2623 MU.Lock(); 2624 while(COND1 != 1) 2625 CV.Wait(&MU); 2626 ANNOTATE_CONDVAR_LOCK_WAIT(&CV, &MU); 2627 MU.Unlock(); 2628 2629 GLOB1=FLAG1; 2630 } 2631 2632 void Run() { 2633 printf("test60: negative\n"); 2634 MyThreadArray t(Worker1, Worker2); 2635 t.Start(); 2636 t.Join(); 2637 printf("\tGLOB1=%d\n", GLOB1); 2638 printf("\tGLOB2=%d\n", GLOB2); 2639 } 2640 REGISTER_TEST2(Run, 60, FEATURE|NEEDS_ANNOTATIONS) 2641 } // namespace test60 2642 2643 2644 // test61: TN. Synchronization via Mutex as in happens-before, annotated. {{{1 2645 namespace test61 { 2646 Mutex MU; 2647 int GLOB = 0; 2648 int *P1 = NULL, *P2 = NULL; 2649 2650 // In this test Mutex lock/unlock operations introduce happens-before relation. 2651 // We annotate the code so that MU is treated as in pure happens-before detector. 2652 2653 2654 void Putter() { 2655 ANNOTATE_PURE_HAPPENS_BEFORE_MUTEX(&MU); 2656 MU.Lock(); 2657 if (P1 == NULL) { 2658 P1 = &GLOB; 2659 *P1 = 1; 2660 } 2661 MU.Unlock(); 2662 } 2663 2664 void Getter() { 2665 bool done = false; 2666 while (!done) { 2667 MU.Lock(); 2668 if (P1) { 2669 done = true; 2670 P2 = P1; 2671 P1 = NULL; 2672 } 2673 MU.Unlock(); 2674 } 2675 *P2 = 2; 2676 } 2677 2678 2679 void Run() { 2680 printf("test61: negative\n"); 2681 MyThreadArray t(Putter, Getter); 2682 t.Start(); 2683 t.Join(); 2684 printf("\tGLOB=%d\n", GLOB); 2685 } 2686 REGISTER_TEST2(Run, 61, FEATURE|NEEDS_ANNOTATIONS) 2687 } // namespace test61 2688 2689 2690 // test62: STAB. Create as many segments as possible. {{{1 2691 namespace test62 { 2692 // Helgrind 3.3.0 will fail as it has a hard limit of < 2^24 segments. 2693 // A better scheme is to implement garbage collection for segments. 2694 ProducerConsumerQueue Q(INT_MAX); 2695 const int N = 1 << 22; 2696 2697 void Putter() { 2698 for (int i = 0; i < N; i++){ 2699 if ((i % (N / 8)) == 0) { 2700 printf("i=%d\n", i); 2701 } 2702 Q.Put(NULL); 2703 } 2704 } 2705 2706 void Getter() { 2707 for (int i = 0; i < N; i++) 2708 Q.Get(); 2709 } 2710 2711 void Run() { 2712 printf("test62:\n"); 2713 MyThreadArray t(Putter, Getter); 2714 t.Start(); 2715 t.Join(); 2716 } 2717 REGISTER_TEST2(Run, 62, STABILITY|EXCLUDE_FROM_ALL) 2718 } // namespace test62 2719 2720 2721 // test63: STAB. Create as many segments as possible and do it fast. {{{1 2722 namespace test63 { 2723 // Helgrind 3.3.0 will fail as it has a hard limit of < 2^24 segments. 2724 // A better scheme is to implement garbage collection for segments. 2725 const int N = 1 << 24; 2726 int C = 0; 2727 2728 void Putter() { 2729 for (int i = 0; i < N; i++){ 2730 if ((i % (N / 8)) == 0) { 2731 printf("i=%d\n", i); 2732 } 2733 ANNOTATE_CONDVAR_SIGNAL(&C); 2734 } 2735 } 2736 2737 void Getter() { 2738 } 2739 2740 void Run() { 2741 printf("test63:\n"); 2742 MyThreadArray t(Putter, Getter); 2743 t.Start(); 2744 t.Join(); 2745 } 2746 REGISTER_TEST2(Run, 63, STABILITY|EXCLUDE_FROM_ALL) 2747 } // namespace test63 2748 2749 2750 // test64: TP. T2 happens-before T3, but T1 is independent. Reads in T1/T2. {{{1 2751 namespace test64 { 2752 // True race between T1 and T3: 2753 // 2754 // T1: T2: T3: 2755 // 1. read(GLOB) (sleep) 2756 // a. read(GLOB) 2757 // b. Q.Put() -----> A. Q.Get() 2758 // B. write(GLOB) 2759 // 2760 // 2761 2762 int GLOB = 0; 2763 ProducerConsumerQueue Q(INT_MAX); 2764 2765 void T1() { 2766 CHECK(GLOB == 0); 2767 } 2768 2769 void T2() { 2770 usleep(100000); 2771 CHECK(GLOB == 0); 2772 Q.Put(NULL); 2773 } 2774 2775 void T3() { 2776 Q.Get(); 2777 GLOB = 1; 2778 } 2779 2780 2781 void Run() { 2782 ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test64: TP."); 2783 printf("test64: positive\n"); 2784 MyThreadArray t(T1, T2, T3); 2785 t.Start(); 2786 t.Join(); 2787 printf("\tGLOB=%d\n", GLOB); 2788 } 2789 REGISTER_TEST(Run, 64) 2790 } // namespace test64 2791 2792 2793 // test65: TP. T2 happens-before T3, but T1 is independent. Writes in T1/T2. {{{1 2794 namespace test65 { 2795 // Similar to test64. 2796 // True race between T1 and T3: 2797 // 2798 // T1: T2: T3: 2799 // 1. MU.Lock() 2800 // 2. write(GLOB) 2801 // 3. MU.Unlock() (sleep) 2802 // a. MU.Lock() 2803 // b. write(GLOB) 2804 // c. MU.Unlock() 2805 // d. Q.Put() -----> A. Q.Get() 2806 // B. write(GLOB) 2807 // 2808 // 2809 2810 int GLOB = 0; 2811 Mutex MU; 2812 ProducerConsumerQueue Q(INT_MAX); 2813 2814 void T1() { 2815 MU.Lock(); 2816 GLOB++; 2817 MU.Unlock(); 2818 } 2819 2820 void T2() { 2821 usleep(100000); 2822 MU.Lock(); 2823 GLOB++; 2824 MU.Unlock(); 2825 Q.Put(NULL); 2826 } 2827 2828 void T3() { 2829 Q.Get(); 2830 GLOB = 1; 2831 } 2832 2833 2834 void Run() { 2835 if (!Tsan_PureHappensBefore()) 2836 ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test65. TP."); 2837 printf("test65: positive\n"); 2838 MyThreadArray t(T1, T2, T3); 2839 t.Start(); 2840 t.Join(); 2841 printf("\tGLOB=%d\n", GLOB); 2842 } 2843 REGISTER_TEST(Run, 65) 2844 } // namespace test65 2845 2846 2847 // test66: TN. Two separate pairs of signaller/waiter using the same CV. {{{1 2848 namespace test66 { 2849 int GLOB1 = 0; 2850 int GLOB2 = 0; 2851 int C1 = 0; 2852 int C2 = 0; 2853 Mutex MU; 2854 2855 void Signaller1() { 2856 GLOB1 = 1; 2857 MU.Lock(); 2858 C1 = 1; 2859 CV.Signal(); 2860 MU.Unlock(); 2861 } 2862 2863 void Signaller2() { 2864 GLOB2 = 1; 2865 usleep(100000); 2866 MU.Lock(); 2867 C2 = 1; 2868 CV.Signal(); 2869 MU.Unlock(); 2870 } 2871 2872 void Waiter1() { 2873 MU.Lock(); 2874 while (C1 != 1) CV.Wait(&MU); 2875 ANNOTATE_CONDVAR_WAIT(&CV); 2876 MU.Unlock(); 2877 GLOB1 = 2; 2878 } 2879 2880 void Waiter2() { 2881 MU.Lock(); 2882 while (C2 != 1) CV.Wait(&MU); 2883 ANNOTATE_CONDVAR_WAIT(&CV); 2884 MU.Unlock(); 2885 GLOB2 = 2; 2886 } 2887 2888 void Run() { 2889 printf("test66: negative\n"); 2890 MyThreadArray t(Signaller1, Signaller2, Waiter1, Waiter2); 2891 t.Start(); 2892 t.Join(); 2893 printf("\tGLOB=%d/%d\n", GLOB1, GLOB2); 2894 } 2895 REGISTER_TEST2(Run, 66, FEATURE|NEEDS_ANNOTATIONS) 2896 } // namespace test66 2897 2898 2899 // test67: FN. Race between Signaller1 and Waiter2 {{{1 2900 namespace test67 { 2901 // Similar to test66, but there is a real race here. 2902 // 2903 // Here we create a happens-before arc between Signaller1 and Waiter2 2904 // even though there should be no such arc. 2905 // However, it's probably improssible (or just very hard) to avoid it. 2906 int GLOB = 0; 2907 int C1 = 0; 2908 int C2 = 0; 2909 Mutex MU; 2910 2911 void Signaller1() { 2912 GLOB = 1; 2913 MU.Lock(); 2914 C1 = 1; 2915 CV.Signal(); 2916 MU.Unlock(); 2917 } 2918 2919 void Signaller2() { 2920 usleep(100000); 2921 MU.Lock(); 2922 C2 = 1; 2923 CV.Signal(); 2924 MU.Unlock(); 2925 } 2926 2927 void Waiter1() { 2928 MU.Lock(); 2929 while (C1 != 1) CV.Wait(&MU); 2930 ANNOTATE_CONDVAR_WAIT(&CV); 2931 MU.Unlock(); 2932 } 2933 2934 void Waiter2() { 2935 MU.Lock(); 2936 while (C2 != 1) CV.Wait(&MU); 2937 ANNOTATE_CONDVAR_WAIT(&CV); 2938 MU.Unlock(); 2939 GLOB = 2; 2940 } 2941 2942 void Run() { 2943 ANNOTATE_EXPECT_RACE(&GLOB, "test67. FN. Race between Signaller1 and Waiter2"); 2944 printf("test67: positive\n"); 2945 MyThreadArray t(Signaller1, Signaller2, Waiter1, Waiter2); 2946 t.Start(); 2947 t.Join(); 2948 printf("\tGLOB=%d\n", GLOB); 2949 } 2950 REGISTER_TEST2(Run, 67, FEATURE|NEEDS_ANNOTATIONS|EXCLUDE_FROM_ALL) 2951 } // namespace test67 2952 2953 2954 // test68: TP. Writes are protected by MU, reads are not. {{{1 2955 namespace test68 { 2956 // In this test, all writes to GLOB are protected by a mutex 2957 // but some reads go unprotected. 2958 // This is certainly a race, but in some cases such code could occur in 2959 // a correct program. For example, the unprotected reads may be used 2960 // for showing statistics and are not required to be precise. 2961 int GLOB = 0; 2962 int COND = 0; 2963 const int N_writers = 3; 2964 Mutex MU, MU1; 2965 2966 void Writer() { 2967 for (int i = 0; i < 100; i++) { 2968 MU.Lock(); 2969 GLOB++; 2970 MU.Unlock(); 2971 } 2972 2973 // we are done 2974 MU1.Lock(); 2975 COND++; 2976 MU1.Unlock(); 2977 } 2978 2979 void Reader() { 2980 bool cont = true; 2981 while (cont) { 2982 CHECK(GLOB >= 0); 2983 2984 // are we done? 2985 MU1.Lock(); 2986 if (COND == N_writers) 2987 cont = false; 2988 MU1.Unlock(); 2989 usleep(100); 2990 } 2991 } 2992 2993 void Run() { 2994 ANNOTATE_EXPECT_RACE(&GLOB, "TP. Writes are protected, reads are not."); 2995 printf("test68: positive\n"); 2996 MyThreadArray t(Reader, Writer, Writer, Writer); 2997 t.Start(); 2998 t.Join(); 2999 printf("\tGLOB=%d\n", GLOB); 3000 } 3001 REGISTER_TEST(Run, 68) 3002 } // namespace test68 3003 3004 3005 // test69: {{{1 3006 namespace test69 { 3007 // This is the same as test68, but annotated. 3008 // We do not want to annotate GLOB as a benign race 3009 // because we want to allow racy reads only in certain places. 3010 // 3011 // TODO: 3012 int GLOB = 0; 3013 int COND = 0; 3014 const int N_writers = 3; 3015 int FAKE_MU = 0; 3016 Mutex MU, MU1; 3017 3018 void Writer() { 3019 for (int i = 0; i < 10; i++) { 3020 MU.Lock(); 3021 GLOB++; 3022 MU.Unlock(); 3023 } 3024 3025 // we are done 3026 MU1.Lock(); 3027 COND++; 3028 MU1.Unlock(); 3029 } 3030 3031 void Reader() { 3032 bool cont = true; 3033 while (cont) { 3034 ANNOTATE_IGNORE_READS_BEGIN(); 3035 CHECK(GLOB >= 0); 3036 ANNOTATE_IGNORE_READS_END(); 3037 3038 // are we done? 3039 MU1.Lock(); 3040 if (COND == N_writers) 3041 cont = false; 3042 MU1.Unlock(); 3043 usleep(100); 3044 } 3045 } 3046 3047 void Run() { 3048 printf("test69: negative\n"); 3049 MyThreadArray t(Reader, Writer, Writer, Writer); 3050 t.Start(); 3051 t.Join(); 3052 printf("\tGLOB=%d\n", GLOB); 3053 } 3054 REGISTER_TEST(Run, 69) 3055 } // namespace test69 3056 3057 // test70: STAB. Check that TRACE_MEMORY works. {{{1 3058 namespace test70 { 3059 int GLOB = 0; 3060 void Run() { 3061 printf("test70: negative\n"); 3062 ANNOTATE_TRACE_MEMORY(&GLOB); 3063 GLOB = 1; 3064 printf("\tGLOB=%d\n", GLOB); 3065 } 3066 REGISTER_TEST(Run, 70) 3067 } // namespace test70 3068 3069 3070 3071 namespace NegativeTests_Strlen { // {{{1 3072 // This test is a reproducer for a benign race in strlen (as well as index, etc). 3073 // Some implementations of strlen may read up to 7 bytes past the end of the string 3074 // thus touching memory which may not belong to this string. 3075 // Such race is benign because the data read past the end of the string is not used. 3076 // 3077 // Here, we allocate a 8-byte aligned string str and initialize first 5 bytes. 3078 // Then one thread calls strlen(str) (as well as index & rindex) 3079 // and another thread initializes str[5]..str[7]. 3080 // 3081 // This can be fixed in Helgrind by intercepting strlen and replacing it 3082 // with a simpler implementation. 3083 3084 char *str; 3085 char *tmp2; 3086 void WorkerX() { 3087 usleep(100000); 3088 ASSERT_TRUE(strlen(str) == 4); 3089 #ifndef WIN32 3090 EXPECT_TRUE(index(str, 'X') == str); 3091 EXPECT_TRUE(index(str, 'x') == str+1); 3092 EXPECT_TRUE(index(str, 'Y') == NULL); 3093 #ifndef ANDROID 3094 EXPECT_TRUE(rindex(str, 'X') == str+2); 3095 EXPECT_TRUE(rindex(str, 'x') == str+3); 3096 EXPECT_TRUE(rindex(str, 'Y') == NULL); 3097 #endif 3098 #else 3099 EXPECT_TRUE(lstrlenA(NULL) == 0); 3100 EXPECT_TRUE(lstrlenW(NULL) == 0); 3101 #endif 3102 EXPECT_TRUE(strchr(str, 'X') == str); 3103 EXPECT_TRUE(strchr(str, 'x') == str+1); 3104 EXPECT_TRUE(strchr(str, 'Y') == NULL); 3105 EXPECT_TRUE(memchr(str, 'X', 8) == str); 3106 EXPECT_TRUE(memchr(str, 'x', 8) == str+1); 3107 char tmp[100] = "Zzz"; 3108 EXPECT_TRUE(memmove(tmp, str, strlen(str) + 1) == tmp); 3109 EXPECT_TRUE(strcmp(tmp,str) == 0); 3110 EXPECT_TRUE(strncmp(tmp,str, 4) == 0); 3111 EXPECT_TRUE(memmove(str, tmp, strlen(tmp) + 1) == str); 3112 #ifndef WIN32 3113 #ifndef ANDROID 3114 EXPECT_TRUE(stpcpy(tmp2, str) == tmp2+4); 3115 #endif 3116 EXPECT_TRUE(strcpy(tmp2, str) == tmp2); 3117 EXPECT_TRUE(strncpy(tmp, str, 4) == tmp); 3118 // These may not be properly intercepted since gcc -O1 may inline 3119 // strcpy/stpcpy in presence of a statically sized array. Damn. 3120 // EXPECT_TRUE(stpcpy(tmp, str) == tmp+4); 3121 // EXPECT_TRUE(strcpy(tmp, str) == tmp); 3122 #endif 3123 EXPECT_TRUE(strrchr(str, 'X') == str+2); 3124 EXPECT_TRUE(strrchr(str, 'x') == str+3); 3125 EXPECT_TRUE(strrchr(str, 'Y') == NULL); 3126 } 3127 void WorkerY() { 3128 str[5] = 'Y'; 3129 str[6] = 'Y'; 3130 str[7] = '\0'; 3131 } 3132 3133 TEST(NegativeTests, StrlenAndFriends) { 3134 str = new char[8]; 3135 tmp2 = new char[8]; 3136 str[0] = 'X'; 3137 str[1] = 'x'; 3138 str[2] = 'X'; 3139 str[3] = 'x'; 3140 str[4] = '\0'; 3141 MyThread t1(WorkerY); 3142 MyThread t2(WorkerX); 3143 t1.Start(); 3144 t2.Start(); 3145 t1.Join(); 3146 t2.Join(); 3147 ASSERT_STREQ("XxXx", str); 3148 ASSERT_STREQ("YY", str+5); 3149 3150 char foo[8] = {10, 20, 127, (char)128, (char)250, -50, 0}; 3151 EXPECT_TRUE(strchr(foo, 10) != 0); 3152 EXPECT_TRUE(strchr(foo, 127) != 0); 3153 EXPECT_TRUE(strchr(foo, 128) != 0); 3154 EXPECT_TRUE(strchr(foo, 250) != 0); 3155 EXPECT_TRUE(strchr(foo, -50) != 0); 3156 EXPECT_TRUE(strchr(foo, -60) == 0); 3157 EXPECT_TRUE(strchr(foo, 0) != 0); 3158 EXPECT_TRUE(strchr(foo, 0) == foo + strlen(foo)); 3159 EXPECT_TRUE(strrchr(foo, 10) != 0); 3160 EXPECT_TRUE(strrchr(foo, 0) != 0); 3161 EXPECT_TRUE(strrchr(foo, 0) == foo + strlen(foo)); 3162 EXPECT_TRUE(strrchr(foo, 250) != 0); 3163 EXPECT_TRUE(strrchr(foo, -60) == 0); 3164 delete [] str; 3165 delete [] tmp2; 3166 // TODO(kcc): add more tests to check that interceptors are correct. 3167 } 3168 } // namespace test71 3169 3170 namespace NegativeTests_EmptyRep { // {{{1 3171 void Worker() { 3172 string s; 3173 s.erase(); 3174 } 3175 3176 TEST(NegativeTests, DISABLED_EmptyRepTest) { 3177 // This is a test for the reports on an internal race in std::string implementation. 3178 // See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=40518 3179 // ThreadSanitizer should be silent on this, but currently it is silent 3180 // only on Valgrind/Linux. 3181 MyThreadArray mta(Worker, Worker); 3182 mta.Start(); 3183 mta.Join(); 3184 } 3185 } //namespace NegativeTests_EmptyRep 3186 3187 namespace NegativeTests_StdStringDtor { // {{{1 3188 // Some implementations of std::string (including the one on Linux) 3189 // are unfriendly to race detectors since they use atomic reference counting 3190 // in a way that race detectors can not understand. 3191 // 3192 // See http://code.google.com/p/data-race-test/issues/detail?id=40 3193 string *s = NULL; 3194 BlockingCounter *counter = NULL; 3195 3196 void DestroyWorker() { 3197 string x = *s; // force string copy (increments ref count). 3198 counter->DecrementCount(); 3199 // x is destructed, ref count is decremented. 3200 } 3201 3202 void AssignWorker() { 3203 string x = *s; // force string copy (increments ref count). 3204 counter->DecrementCount(); 3205 // x is assigned, the ref count is decremented. 3206 usleep(100000); 3207 x = "ZZZ"; 3208 } 3209 3210 TEST(NegativeTests, StdStringDtorVsDtor) { 3211 MyThreadArray mta(DestroyWorker, DestroyWorker, DestroyWorker); 3212 counter = new BlockingCounter(3); 3213 s = new string ("foo"); 3214 mta.Start(); 3215 3216 counter->Wait(); 3217 3218 delete s; // ref count becomes zero and the object is destroyed. 3219 mta.Join(); 3220 delete counter; 3221 } 3222 3223 TEST(NegativeTests, DISABLED_StdStringDtorVsAssign) { 3224 MyThreadArray mta(AssignWorker, AssignWorker, AssignWorker); 3225 counter = new BlockingCounter(3); 3226 s = new string ("foo"); 3227 mta.Start(); 3228 3229 counter->Wait(); 3230 3231 delete s; // ref count becomes zero and the object is destroyed. 3232 mta.Join(); 3233 delete counter; 3234 } 3235 } //namespace NegativeTests_EmptyRep 3236 3237 namespace PositiveTests_MutexDtorNoSync { 3238 // Check that Mutex::~Mutex() doesn't introduce h-b arcs. 3239 int *GLOB = NULL; 3240 3241 void WriteThenScopedLocalMutex() { 3242 *GLOB = 1; 3243 { 3244 Mutex l; 3245 } 3246 } 3247 3248 void ScopedLocalMutexThenWrite() { 3249 { 3250 Mutex l; 3251 } 3252 *GLOB = 2; 3253 } 3254 3255 TEST(PositiveTests, MutexDtorNoSyncTest) { 3256 GLOB = new int(0); 3257 ANNOTATE_EXPECT_RACE(GLOB, "TP: PositiveTests.MutexDtorNoSyncTest"); 3258 MyThreadArray t(WriteThenScopedLocalMutex, 3259 ScopedLocalMutexThenWrite); 3260 t.Start(); 3261 t.Join(); 3262 delete GLOB; 3263 } 3264 3265 void WriteThenScopedLocalMutexLockUnlock() { 3266 *GLOB = 1; 3267 { 3268 Mutex l; 3269 l.Lock(); 3270 l.Unlock(); 3271 } 3272 } 3273 3274 void ScopedLocalMutexLockUnlockThenWrite() { 3275 { 3276 Mutex l; 3277 l.Lock(); 3278 l.Unlock(); 3279 } 3280 *GLOB = 2; 3281 } 3282 3283 TEST(PositiveTests, MutexDtorNoSyncTest2) { 3284 GLOB = new int(0); 3285 ANNOTATE_EXPECT_RACE(GLOB, "TP: PositiveTests.MutexDtorNoSyncTest2"); 3286 MyThreadArray t(WriteThenScopedLocalMutexLockUnlock, 3287 ScopedLocalMutexLockUnlockThenWrite); 3288 t.Start(); 3289 t.Join(); 3290 delete GLOB; 3291 } 3292 3293 } // namespace PositiveTests_MutexDtorSync 3294 3295 namespace PositiveTests_FprintfThreadCreateTest { 3296 // Check that fprintf doesn't introduce h-b with the start of the 3297 // following thread 3298 int *GLOB; 3299 StealthNotification *n; 3300 3301 void Worker1() { 3302 *GLOB = 1; 3303 fprintf(stdout, "Hello, world!\n"); 3304 n->signal(); 3305 } 3306 3307 void Worker2() { 3308 *GLOB = 2; 3309 } 3310 3311 #if !defined(_MSC_VER) 3312 // TODO(timurrrr): investigate Windows FN and un-#if 3313 TEST(PositiveTests, FprintfThreadCreateTest) { 3314 GLOB = new int; 3315 ANNOTATE_EXPECT_RACE(GLOB, "TP: PositiveTests.FprintfThreadCreateTest"); 3316 n = new StealthNotification; 3317 MyThread t1(Worker1); 3318 t1.Start(); 3319 n->wait(); 3320 MyThread t2(Worker2); 3321 t2.Start(); 3322 t2.Join(); 3323 t1.Join(); 3324 delete n; 3325 delete GLOB; 3326 } 3327 #endif 3328 3329 } // namespace PositiveTests_FprintfThreadCreateTest 3330 3331 // test72: STAB. Stress test for the number of segment sets (SSETs). {{{1 3332 namespace test72 { 3333 #ifndef NO_BARRIER 3334 // Variation of test33. 3335 // Instead of creating Nlog*N_iter threads, 3336 // we create Nlog threads and do N_iter barriers. 3337 int GLOB = 0; 3338 const int N_iter = 30; 3339 const int Nlog = 16; 3340 const int N = 1 << Nlog; 3341 static int64_t ARR1[N]; 3342 static int64_t ARR2[N]; 3343 Barrier *barriers[N_iter]; 3344 Mutex MU; 3345 3346 void Worker() { 3347 MU.Lock(); 3348 int n = ++GLOB; 3349 MU.Unlock(); 3350 3351 n %= Nlog; 3352 3353 for (int it = 0; it < N_iter; it++) { 3354 // Iterate N_iter times, block on barrier after each iteration. 3355 // This way Helgrind will create new segments after each barrier. 3356 3357 for (int x = 0; x < 2; x++) { 3358 // run the inner loop twice. 3359 // When a memory location is accessed second time it is likely 3360 // that the state (SVal) will be unchanged. 3361 // The memory machine may optimize this case. 3362 for (int i = 0; i < N; i++) { 3363 // ARR1[i] and ARR2[N-1-i] are accessed by threads from i-th subset 3364 if (i & (1 << n)) { 3365 CHECK(ARR1[i] == 0); 3366 CHECK(ARR2[N-1-i] == 0); 3367 } 3368 } 3369 } 3370 barriers[it]->Block(); 3371 } 3372 } 3373 3374 3375 void Run() { 3376 printf("test72:\n"); 3377 3378 std::vector<MyThread*> vec(Nlog); 3379 3380 for (int i = 0; i < N_iter; i++) 3381 barriers[i] = new Barrier(Nlog); 3382 3383 // Create and start Nlog threads 3384 for (int i = 0; i < Nlog; i++) { 3385 vec[i] = new MyThread(Worker); 3386 vec[i]->Start(); 3387 } 3388 3389 // Join all threads. 3390 for (int i = 0; i < Nlog; i++) { 3391 vec[i]->Join(); 3392 delete vec[i]; 3393 } 3394 for (int i = 0; i < N_iter; i++) 3395 delete barriers[i]; 3396 3397 /*printf("\tGLOB=%d; ARR[1]=%d; ARR[7]=%d; ARR[N-1]=%d\n", 3398 GLOB, (int)ARR1[1], (int)ARR1[7], (int)ARR1[N-1]);*/ 3399 } 3400 REGISTER_TEST2(Run, 72, STABILITY|PERFORMANCE|EXCLUDE_FROM_ALL); 3401 #endif // NO_BARRIER 3402 } // namespace test72 3403 3404 3405 // test73: STAB. Stress test for the number of (SSETs), different access sizes. {{{1 3406 namespace test73 { 3407 #ifndef NO_BARRIER 3408 // Variation of test72. 3409 // We perform accesses of different sizes to the same location. 3410 int GLOB = 0; 3411 const int N_iter = 2; 3412 const int Nlog = 16; 3413 const int N = 1 << Nlog; 3414 static int64_t ARR1[N]; 3415 static int ARR2[N]; 3416 Barrier *barriers[N_iter]; 3417 Mutex MU; 3418 3419 void Worker() { 3420 MU.Lock(); 3421 int n = ++GLOB; 3422 MU.Unlock(); 3423 3424 n %= Nlog; 3425 3426 for (int it = 0; it < N_iter; it++) { 3427 // Iterate N_iter times, block on barrier after each iteration. 3428 // This way Helgrind will create new segments after each barrier. 3429 3430 for (int x = 0; x < 4; x++) { 3431 for (int i = 0; i < N; i++) { 3432 // ARR1[i] are accessed by threads from i-th subset 3433 if (i & (1 << n)) { 3434 for (int off = 0; off < (1 << x); off++) { 3435 switch(x) { 3436 case 0: CHECK( ARR1 [i * (1<<x) + off] == 0); break; 3437 case 1: CHECK(((int*) (ARR1))[i * (1<<x) + off] == 0); break; 3438 case 2: CHECK(((short*)(ARR1))[i * (1<<x) + off] == 0); break; 3439 case 3: CHECK(((char*) (ARR1))[i * (1<<x) + off] == 0); break; 3440 } 3441 switch(x) { 3442 case 1: CHECK(((int*) (ARR2))[i * (1<<x) + off] == 0); break; 3443 case 2: CHECK(((short*)(ARR2))[i * (1<<x) + off] == 0); break; 3444 case 3: CHECK(((char*) (ARR2))[i * (1<<x) + off] == 0); break; 3445 } 3446 } 3447 } 3448 } 3449 } 3450 barriers[it]->Block(); 3451 } 3452 } 3453 3454 3455 3456 void Run() { 3457 printf("test73:\n"); 3458 3459 std::vector<MyThread*> vec(Nlog); 3460 3461 for (int i = 0; i < N_iter; i++) 3462 barriers[i] = new Barrier(Nlog); 3463 3464 // Create and start Nlog threads 3465 for (int i = 0; i < Nlog; i++) { 3466 vec[i] = new MyThread(Worker); 3467 vec[i]->Start(); 3468 } 3469 3470 // Join all threads. 3471 for (int i = 0; i < Nlog; i++) { 3472 vec[i]->Join(); 3473 delete vec[i]; 3474 } 3475 for (int i = 0; i < N_iter; i++) 3476 delete barriers[i]; 3477 3478 /*printf("\tGLOB=%d; ARR[1]=%d; ARR[7]=%d; ARR[N-1]=%d\n", 3479 GLOB, (int)ARR1[1], (int)ARR1[7], (int)ARR1[N-1]);*/ 3480 } 3481 REGISTER_TEST2(Run, 73, STABILITY|PERFORMANCE|EXCLUDE_FROM_ALL); 3482 #endif // NO_BARRIER 3483 } // namespace test73 3484 3485 3486 // test74: PERF. A lot of lock/unlock calls. {{{1 3487 namespace test74 { 3488 const int N = 100000; 3489 Mutex MU; 3490 TEST(StressTests, ManyLocksUnlocks) { 3491 for (int i = 0; i < N; i++ ) { 3492 MU.Lock(); 3493 MU.Unlock(); 3494 } 3495 } 3496 } // namespace test74 3497 3498 // RefCountedClass {{{1 3499 struct RefCountedClass { 3500 public: 3501 RefCountedClass() { 3502 annotate_unref_ = false; 3503 ref_ = 0; 3504 data_ = 0; 3505 } 3506 3507 ~RefCountedClass() { 3508 CHECK(ref_ == 0); // race may be reported here 3509 int data_val = data_; // and here 3510 // if MU is not annotated 3511 data_ = 0; 3512 ref_ = -1; 3513 printf("\tRefCountedClass::data_ = %d\n", data_val); 3514 } 3515 3516 void AccessData() { 3517 this->mu_.Lock(); 3518 this->data_++; 3519 this->mu_.Unlock(); 3520 } 3521 3522 void Ref() { 3523 MU.Lock(); 3524 CHECK(ref_ >= 0); 3525 ref_++; 3526 MU.Unlock(); 3527 } 3528 3529 void Unref() { 3530 MU.Lock(); 3531 CHECK(ref_ > 0); 3532 ref_--; 3533 bool do_delete = ref_ == 0; 3534 if (annotate_unref_) { 3535 ANNOTATE_HAPPENS_BEFORE(this); 3536 } 3537 MU.Unlock(); 3538 if (do_delete) { 3539 if (annotate_unref_) { 3540 ANNOTATE_HAPPENS_AFTER(this); 3541 } 3542 delete this; 3543 } 3544 } 3545 3546 static void Annotate_MU() { 3547 ANNOTATE_PURE_HAPPENS_BEFORE_MUTEX(&MU); 3548 } 3549 void AnnotateUnref() { 3550 annotate_unref_ = true; 3551 } 3552 void Annotate_Race() { 3553 ANNOTATE_BENIGN_RACE_SIZED(this, sizeof(*this), "needs annotation"); 3554 } 3555 private: 3556 bool annotate_unref_; 3557 3558 int data_; 3559 Mutex mu_; // protects data_ 3560 3561 int ref_; 3562 static Mutex MU; // protects ref_ 3563 }; 3564 3565 Mutex RefCountedClass::MU; 3566 3567 // test76: FP. Ref counting, no annotations. {{{1 3568 namespace test76 { 3569 #ifndef NO_BARRIER 3570 int GLOB = 0; 3571 Barrier barrier(4); 3572 RefCountedClass *object = NULL; 3573 void Worker() { 3574 object->Ref(); 3575 barrier.Block(); 3576 object->AccessData(); 3577 object->Unref(); 3578 } 3579 void Run() { 3580 printf("test76: false positive (ref counting)\n"); 3581 object = new RefCountedClass; 3582 object->Annotate_Race(); 3583 MyThreadArray t(Worker, Worker, Worker, Worker); 3584 t.Start(); 3585 t.Join(); 3586 } 3587 REGISTER_TEST2(Run, 76, FEATURE) 3588 #endif // NO_BARRIER 3589 } // namespace test76 3590 3591 3592 3593 // test77: TN. Ref counting, MU is annotated. {{{1 3594 namespace test77 { 3595 #ifndef NO_BARRIER 3596 // same as test76, but RefCountedClass::MU is annotated. 3597 int GLOB = 0; 3598 Barrier barrier(4); 3599 RefCountedClass *object = NULL; 3600 void Worker() { 3601 object->Ref(); 3602 barrier.Block(); 3603 object->AccessData(); 3604 object->Unref(); 3605 } 3606 void Run() { 3607 printf("test77: true negative (ref counting), mutex is annotated\n"); 3608 RefCountedClass::Annotate_MU(); 3609 object = new RefCountedClass; 3610 MyThreadArray t(Worker, Worker, Worker, Worker); 3611 t.Start(); 3612 t.Join(); 3613 } 3614 REGISTER_TEST(Run, 77) 3615 #endif // NO_BARRIER 3616 } // namespace test77 3617 3618 3619 3620 // test78: TN. Ref counting, Unref is annotated. {{{1 3621 namespace test78 { 3622 #ifndef NO_BARRIER 3623 // same as test76, but RefCountedClass::Unref is annotated. 3624 int GLOB = 0; 3625 Barrier barrier(4); 3626 RefCountedClass *object = NULL; 3627 void Worker() { 3628 object->Ref(); 3629 barrier.Block(); 3630 object->AccessData(); 3631 object->Unref(); 3632 } 3633 void Run() { 3634 printf("test78: true negative (ref counting), Unref is annotated\n"); 3635 RefCountedClass::Annotate_MU(); 3636 object = new RefCountedClass; 3637 MyThreadArray t(Worker, Worker, Worker, Worker); 3638 t.Start(); 3639 t.Join(); 3640 } 3641 REGISTER_TEST(Run, 78) 3642 #endif // NO_BARRIER 3643 } // namespace test78 3644 3645 3646 3647 // test79 TN. Swap. {{{1 3648 namespace test79 { 3649 #if 0 3650 typedef __gnu_cxx::hash_map<int, int> map_t; 3651 #else 3652 typedef std::map<int, int> map_t; 3653 #endif 3654 map_t MAP; 3655 Mutex MU; 3656 3657 // Here we use swap to pass MAP between threads. 3658 // The synchronization is correct, but w/o ANNOTATE_PURE_HAPPENS_BEFORE_MUTEX 3659 // Helgrind will complain. 3660 3661 void Worker1() { 3662 map_t tmp; 3663 MU.Lock(); 3664 // We swap the new empty map 'tmp' with 'MAP'. 3665 MAP.swap(tmp); 3666 MU.Unlock(); 3667 // tmp (which is the old version of MAP) is destroyed here. 3668 } 3669 3670 void Worker2() { 3671 MU.Lock(); 3672 MAP[1]++; // Just update MAP under MU. 3673 MU.Unlock(); 3674 } 3675 3676 void Worker3() { Worker1(); } 3677 void Worker4() { Worker2(); } 3678 3679 void Run() { 3680 ANNOTATE_PURE_HAPPENS_BEFORE_MUTEX(&MU); 3681 printf("test79: negative\n"); 3682 MyThreadArray t(Worker1, Worker2, Worker3, Worker4); 3683 t.Start(); 3684 t.Join(); 3685 } 3686 REGISTER_TEST(Run, 79) 3687 } // namespace test79 3688 3689 3690 // AtomicRefCountedClass. {{{1 3691 // Same as RefCountedClass, but using atomic ops instead of mutex. 3692 struct AtomicRefCountedClass { 3693 public: 3694 AtomicRefCountedClass() { 3695 annotate_unref_ = false; 3696 ref_ = 0; 3697 data_ = 0; 3698 } 3699 3700 ~AtomicRefCountedClass() { 3701 CHECK(ref_ == 0); // race may be reported here 3702 int data_val = data_; // and here 3703 data_ = 0; 3704 ref_ = -1; 3705 printf("\tRefCountedClass::data_ = %d\n", data_val); 3706 } 3707 3708 void AccessData() { 3709 this->mu_.Lock(); 3710 this->data_++; 3711 this->mu_.Unlock(); 3712 } 3713 3714 void Ref() { 3715 AtomicIncrement(&ref_, 1); 3716 } 3717 3718 void Unref() { 3719 // DISCLAIMER: I am not sure I've implemented this correctly 3720 // (might require some memory barrier, etc). 3721 // But this implementation of reference counting is enough for 3722 // the purpose of Helgrind demonstration. 3723 AtomicIncrement(&ref_, -1); 3724 if (annotate_unref_) { ANNOTATE_HAPPENS_BEFORE(this); } 3725 if (ref_ == 0) { 3726 if (annotate_unref_) { ANNOTATE_HAPPENS_AFTER(this); } 3727 delete this; 3728 } 3729 } 3730 3731 void AnnotateUnref() { 3732 annotate_unref_ = true; 3733 } 3734 void Annotate_Race() { 3735 ANNOTATE_BENIGN_RACE(&this->data_, "needs annotation"); 3736 } 3737 private: 3738 bool annotate_unref_; 3739 3740 Mutex mu_; 3741 int data_; // under mu_ 3742 3743 int ref_; // used in atomic ops. 3744 }; 3745 3746 // test80: FP. Ref counting with atomics, no annotations. {{{1 3747 namespace test80 { 3748 #ifndef NO_BARRIER 3749 int GLOB = 0; 3750 Barrier barrier(4); 3751 AtomicRefCountedClass *object = NULL; 3752 void Worker() { 3753 object->Ref(); 3754 barrier.Block(); 3755 object->AccessData(); 3756 object->Unref(); // All the tricky stuff is here. 3757 } 3758 void Run() { 3759 printf("test80: false positive (ref counting)\n"); 3760 object = new AtomicRefCountedClass; 3761 object->Annotate_Race(); 3762 MyThreadArray t(Worker, Worker, Worker, Worker); 3763 t.Start(); 3764 t.Join(); 3765 } 3766 REGISTER_TEST2(Run, 80, FEATURE|EXCLUDE_FROM_ALL) 3767 #endif // NO_BARRIER 3768 } // namespace test80 3769 3770 3771 // test81: TN. Ref counting with atomics, Unref is annotated. {{{1 3772 namespace test81 { 3773 #ifndef NO_BARRIER 3774 // same as test80, but Unref is annotated. 3775 int GLOB = 0; 3776 Barrier barrier(4); 3777 AtomicRefCountedClass *object = NULL; 3778 void Worker() { 3779 object->Ref(); 3780 barrier.Block(); 3781 object->AccessData(); 3782 object->Unref(); // All the tricky stuff is here. 3783 } 3784 void Run() { 3785 printf("test81: negative (annotated ref counting)\n"); 3786 object = new AtomicRefCountedClass; 3787 object->AnnotateUnref(); 3788 MyThreadArray t(Worker, Worker, Worker, Worker); 3789 t.Start(); 3790 t.Join(); 3791 } 3792 REGISTER_TEST2(Run, 81, FEATURE|EXCLUDE_FROM_ALL) 3793 #endif // NO_BARRIER 3794 } // namespace test81 3795 3796 3797 // test82: Object published w/o synchronization. {{{1 3798 namespace test82 { 3799 3800 // Writer creates a new object and makes the pointer visible to the Reader. 3801 // Reader waits until the object pointer is non-null and reads the object. 3802 // 3803 // On Core 2 Duo this test will sometimes (quite rarely) fail in 3804 // the CHECK below, at least if compiled with -O2. 3805 // 3806 // The sequence of events:: 3807 // Thread1: Thread2: 3808 // a. arr_[...] = ... 3809 // b. foo[i] = ... 3810 // A. ... = foo[i]; // non NULL 3811 // B. ... = arr_[...]; 3812 // 3813 // Since there is no proper synchronization, during the even (B) 3814 // Thread2 may not see the result of the event (a). 3815 // On x86 and x86_64 this happens due to compiler reordering instructions. 3816 // On other arcitectures it may also happen due to cashe inconsistency. 3817 3818 class FOO { 3819 public: 3820 FOO() { 3821 idx_ = rand() % 1024; 3822 arr_[idx_] = 77777; 3823 // __asm__ __volatile__("" : : : "memory"); // this fixes! 3824 } 3825 static void check(volatile FOO *foo) { 3826 CHECK(foo->arr_[foo->idx_] == 77777); 3827 } 3828 private: 3829 int idx_; 3830 int arr_[1024]; 3831 }; 3832 3833 const int N = 100000; 3834 static volatile FOO *foo[N]; 3835 Mutex MU; 3836 3837 void Writer() { 3838 for (int i = 0; i < N; i++) { 3839 foo[i] = new FOO; 3840 usleep(100); 3841 } 3842 } 3843 3844 void Reader() { 3845 for (int i = 0; i < N; i++) { 3846 while (!foo[i]) { 3847 MU.Lock(); // this is NOT a synchronization, 3848 MU.Unlock(); // it just helps foo[i] to become visible in Reader. 3849 } 3850 if ((i % 100) == 0) { 3851 printf("rd %d\n", i); 3852 } 3853 // At this point Reader() sees the new value of foo[i] 3854 // but in very rare cases will not see the new value of foo[i]->arr_. 3855 // Thus this CHECK will sometimes fail. 3856 FOO::check(foo[i]); 3857 } 3858 } 3859 3860 void Run() { 3861 printf("test82: positive\n"); 3862 MyThreadArray t(Writer, Reader); 3863 t.Start(); 3864 t.Join(); 3865 } 3866 REGISTER_TEST2(Run, 82, FEATURE|EXCLUDE_FROM_ALL) 3867 } // namespace test82 3868 3869 3870 // test83: Object published w/o synchronization (simple version){{{1 3871 namespace test83 { 3872 // A simplified version of test83 (example of a wrong code). 3873 // This test, though incorrect, will almost never fail. 3874 volatile static int *ptr = NULL; 3875 Mutex MU; 3876 3877 void Writer() { 3878 usleep(100); 3879 ptr = new int(777); 3880 } 3881 3882 void Reader() { 3883 while(!ptr) { 3884 MU.Lock(); // Not a synchronization! 3885 MU.Unlock(); 3886 } 3887 CHECK(*ptr == 777); 3888 } 3889 3890 void Run() { 3891 // printf("test83: positive\n"); 3892 MyThreadArray t(Writer, Reader); 3893 t.Start(); 3894 t.Join(); 3895 } 3896 REGISTER_TEST2(Run, 83, FEATURE|EXCLUDE_FROM_ALL) 3897 } // namespace test83 3898 3899 3900 // test84: TP. True race (regression test for a bug related to atomics){{{1 3901 namespace test84 { 3902 // Helgrind should not create HB arcs for the bus lock even when 3903 // --pure-happens-before=yes is used. 3904 // Bug found in by Bart Van Assche, the test is taken from 3905 // valgrind file drd/tests/atomic_var.c. 3906 static int s_x = 0; 3907 /* s_dummy[] ensures that s_x and s_y are not in the same cache line. */ 3908 static char s_dummy[512] = {0}; 3909 static int s_y; 3910 3911 void thread_func_1() 3912 { 3913 s_y = 1; 3914 AtomicIncrement(&s_x, 1); 3915 } 3916 3917 void thread_func_2() 3918 { 3919 while (AtomicIncrement(&s_x, 0) == 0) 3920 ; 3921 printf("y = %d\n", s_y); 3922 } 3923 3924 3925 void Run() { 3926 CHECK(s_dummy[0] == 0); // Avoid compiler warning about 's_dummy unused'. 3927 printf("test84: positive\n"); 3928 ANNOTATE_EXPECT_RACE_FOR_TSAN(&s_y, "test84: TP. true race."); 3929 MyThreadArray t(thread_func_1, thread_func_2); 3930 t.Start(); 3931 t.Join(); 3932 } 3933 REGISTER_TEST(Run, 84) 3934 } // namespace test84 3935 3936 3937 // Test for RunningOnValgrind(). {{{1 3938 TEST(NegativeTests, RunningOnValgrindTest) { 3939 printf("RunningOnValgrind() = %d\n", RunningOnValgrind()); 3940 } 3941 3942 namespace NegativeTests_BenignRaceInDtor { // {{{ 3943 // Test for race inside DTOR: racey write to vptr. Benign. 3944 // This test shows a racey access to vptr (the pointer to vtbl). 3945 // We have class A and class B derived from A. 3946 // Both classes have a virtual function f() and a virtual DTOR. 3947 // We create an object 'A *a = new B' 3948 // and pass this object from Thread1 to Thread2. 3949 // Thread2 calls a->f(). This call reads a->vtpr. 3950 // Thread1 deletes the object. B::~B waits untill the object can be destroyed 3951 // (flag_stopped == true) but at the very beginning of B::~B 3952 // a->vptr is written to. 3953 // So, we have a race on a->vptr. 3954 // On this particular test this race is benign, but HarmfulRaceInDtor shows 3955 // how such race could harm. 3956 // 3957 // 3958 // 3959 // Threa1: Thread2: 3960 // 1. A a* = new B; 3961 // 2. Q.Put(a); ------------\ . 3962 // \--------------------> a. a = Q.Get(); 3963 // b. a->f(); 3964 // /--------- c. flag_stopped = true; 3965 // 3. delete a; / 3966 // waits untill flag_stopped <------/ 3967 // inside the dtor 3968 // 3969 3970 bool flag_stopped = false; 3971 Mutex mu; 3972 3973 ProducerConsumerQueue Q(INT_MAX); // Used to pass A* between threads. 3974 3975 struct A { 3976 A() { printf("A::A()\n"); } 3977 virtual ~A() { printf("A::~A()\n"); } 3978 virtual void f() { } 3979 3980 uintptr_t padding[15]; 3981 } ALIGNED(64); 3982 3983 struct B: A { 3984 B() { printf("B::B()\n"); } 3985 virtual ~B() { 3986 // The race is here. <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 3987 printf("B::~B()\n"); 3988 // wait until flag_stopped is true. 3989 mu.LockWhen(Condition(&ArgIsTrue, &flag_stopped)); 3990 mu.Unlock(); 3991 printf("B::~B() done\n"); 3992 } 3993 virtual void f() { } 3994 }; 3995 3996 void Waiter() { 3997 A *a = new B; 3998 printf("Waiter: B created\n"); 3999 Q.Put(a); 4000 usleep(100000); // so that Worker calls a->f() first. 4001 printf("Waiter: deleting B\n"); 4002 delete a; 4003 printf("Waiter: B deleted\n"); 4004 usleep(100000); 4005 printf("Waiter: done\n"); 4006 } 4007 4008 void Worker() { 4009 A *a = reinterpret_cast<A*>(Q.Get()); 4010 printf("Worker: got A\n"); 4011 a->f(); 4012 4013 mu.Lock(); 4014 flag_stopped = true; 4015 mu.Unlock(); 4016 usleep(200000); 4017 printf("Worker: done\n"); 4018 } 4019 4020 TEST(NegativeTests, BenignRaceInDtor) { 4021 MyThreadArray t(Waiter, Worker); 4022 t.Start(); 4023 t.Join(); 4024 } 4025 } // namespace 4026 4027 4028 namespace PositiveTests_HarmfulRaceInDtor { // {{{ 4029 // A variation of BenignRaceInDtor where the race is harmful. 4030 // Race on vptr. Will run A::F() or B::F() depending on the timing. 4031 class A { 4032 public: 4033 A() : done_(false) { 4034 // W/o this annotation tsan may produce additional warnings in hybrid mode. 4035 ANNOTATE_PURE_HAPPENS_BEFORE_MUTEX(&mu_); 4036 } 4037 virtual void F() { 4038 printf ("A::F()\n"); 4039 } 4040 void Done() { 4041 MutexLock lock(&mu_); 4042 done_ = true; 4043 } 4044 virtual ~A() { 4045 while (true) { 4046 { 4047 MutexLock lock(&mu_); 4048 if (done_) break; 4049 } 4050 usleep(10); // yield. 4051 } 4052 } 4053 private: 4054 Mutex mu_; 4055 bool done_; 4056 }; 4057 4058 class B : public A { 4059 public: 4060 virtual void F() { 4061 // TODO(kcc): enable this printf back once issue 57 is fixed. 4062 // printf ("B::F()\n"); 4063 } 4064 }; 4065 4066 static A *a; 4067 4068 void Thread1() { 4069 a->F(); 4070 a->Done(); 4071 sleep(1); 4072 }; 4073 4074 void Thread2() { 4075 delete a; 4076 } 4077 TEST(PositiveTests, HarmfulRaceInDtorB) { 4078 ANNOTATE_FLUSH_EXPECTED_RACES(); 4079 // Will print B::F() 4080 a = new B; 4081 ANNOTATE_EXPECT_RACE(a, "HarmfulRaceInDtor #1: expected race on a->vptr"); 4082 ANNOTATE_TRACE_MEMORY(a); 4083 MyThreadArray t(Thread1, Thread2); 4084 t.Start(); 4085 t.Join(); 4086 ANNOTATE_FLUSH_EXPECTED_RACES(); 4087 } 4088 4089 TEST(PositiveTests, HarmfulRaceInDtorA) { 4090 ANNOTATE_FLUSH_EXPECTED_RACES(); 4091 // Will print A::F() 4092 a = new B; 4093 ANNOTATE_EXPECT_RACE(a, "HarmfulRaceInDtor #2: expected race on a->vptr"); 4094 ANNOTATE_TRACE_MEMORY(a); 4095 MyThreadArray t(Thread2, Thread1); 4096 t.Start(); 4097 t.Join(); 4098 ANNOTATE_FLUSH_EXPECTED_RACES(); 4099 } 4100 4101 } // namespace 4102 4103 4104 namespace AnnotateIgnoreTests { // {{{1 4105 4106 int racey_write = 0; 4107 4108 void RaceyWriter() { 4109 ANNOTATE_IGNORE_WRITES_BEGIN(); 4110 racey_write = 1; 4111 ANNOTATE_IGNORE_WRITES_END(); 4112 } 4113 4114 TEST(NegativeTests, AnnotateIgnoreWritesTest) { 4115 MyThread t(RaceyWriter); 4116 t.Start(); 4117 racey_write = 1; 4118 t.Join(); 4119 } 4120 4121 int racey_read = 0; 4122 4123 void RaceyReader1() { 4124 ANNOTATE_IGNORE_READS_BEGIN(); 4125 CHECK(racey_read != 777); 4126 ANNOTATE_IGNORE_READS_END(); 4127 } 4128 4129 void RaceyReader2() { 4130 CHECK(ANNOTATE_UNPROTECTED_READ(racey_read) != 777); 4131 } 4132 4133 TEST(NegativeTests, AnnotateIgnoreReadsTest) { 4134 MyThreadArray t(RaceyReader1, RaceyReader2); 4135 t.Start(); 4136 racey_read = 1; 4137 t.Join(); 4138 } 4139 4140 int incorrectly_annotated_racey_write = 0; 4141 4142 void IncorrectlyAnnotatedRaceyWriter() { 4143 ANNOTATE_IGNORE_READS_BEGIN(); 4144 incorrectly_annotated_racey_write = 1; 4145 ANNOTATE_IGNORE_READS_END(); 4146 } 4147 4148 TEST(PositiveTests, AnnotateIgnoreReadsOnWriteTest) { 4149 ANNOTATE_EXPECT_RACE(&incorrectly_annotated_racey_write, "expected race"); 4150 MyThread t(IncorrectlyAnnotatedRaceyWriter); 4151 t.Start(); 4152 incorrectly_annotated_racey_write = 1; 4153 t.Join(); 4154 ANNOTATE_FLUSH_EXPECTED_RACES(); 4155 } 4156 4157 int incorrectly_annotated_racey_read = 0; 4158 4159 void IncorrectlyAnnotatedRaceyReader() { 4160 ANNOTATE_IGNORE_WRITES_BEGIN(); 4161 CHECK(incorrectly_annotated_racey_read != 777); 4162 ANNOTATE_IGNORE_WRITES_END(); 4163 } 4164 4165 TEST(PositiveTests, AnnotateIgnoreWritesOnReadTest) { 4166 ANNOTATE_EXPECT_RACE(&incorrectly_annotated_racey_read, "expected race"); 4167 MyThread t(IncorrectlyAnnotatedRaceyReader); 4168 t.Start(); 4169 incorrectly_annotated_racey_read = 1; 4170 t.Join(); 4171 ANNOTATE_FLUSH_EXPECTED_RACES(); 4172 } 4173 4174 } // namespace 4175 4176 4177 // test89: Test for debug info. {{{1 4178 namespace test89 { 4179 // Simlpe races with different objects (stack, heap globals; scalars, structs). 4180 // Also, if run with --trace-level=2 this test will show a sequence of 4181 // CTOR and DTOR calls. 4182 struct STRUCT { 4183 int a, b, c; 4184 }; 4185 4186 struct A { 4187 int a; 4188 A() { 4189 ANNOTATE_TRACE_MEMORY(&a); 4190 a = 1; 4191 } 4192 virtual ~A() { 4193 a = 4; 4194 } 4195 }; 4196 4197 struct B : A { 4198 B() { CHECK(a == 1); } 4199 virtual ~B() { CHECK(a == 3); } 4200 }; 4201 struct C : B { 4202 C() { a = 2; } 4203 virtual ~C() { a = 3; } 4204 }; 4205 4206 int GLOBAL = 0; 4207 int *STACK = 0; 4208 STRUCT GLOB_STRUCT; 4209 STRUCT *STACK_STRUCT; 4210 STRUCT *HEAP_STRUCT; 4211 4212 void Worker() { 4213 GLOBAL = 1; 4214 *STACK = 1; 4215 GLOB_STRUCT.b = 1; 4216 STACK_STRUCT->b = 1; 4217 HEAP_STRUCT->b = 1; 4218 } 4219 4220 void Run() { 4221 int stack_var = 0; 4222 STACK = &stack_var; 4223 4224 STRUCT stack_struct; 4225 STACK_STRUCT = &stack_struct; 4226 4227 HEAP_STRUCT = new STRUCT; 4228 4229 printf("test89: negative\n"); 4230 MyThreadArray t(Worker, Worker); 4231 t.Start(); 4232 t.Join(); 4233 4234 delete HEAP_STRUCT; 4235 4236 A *a = new C; 4237 printf("Using 'a->a': %d\n", a->a); 4238 delete a; 4239 } 4240 REGISTER_TEST2(Run, 89, FEATURE|EXCLUDE_FROM_ALL) 4241 } // namespace test89 4242 4243 4244 // test90: FP. Test for a safely-published pointer (read-only). {{{1 4245 namespace test90 { 4246 // The Publisher creates an object and safely publishes it under a mutex. 4247 // Readers access the object read-only. 4248 // See also test91. 4249 // 4250 // Without annotations Helgrind will issue a false positive in Reader(). 4251 // 4252 // Choices for annotations: 4253 // -- ANNOTATE_CONDVAR_SIGNAL/ANNOTATE_CONDVAR_WAIT 4254 // -- ANNOTATE_PURE_HAPPENS_BEFORE_MUTEX 4255 // -- ANNOTATE_PUBLISH_MEMORY_RANGE. 4256 4257 int *GLOB = 0; 4258 Mutex MU; 4259 4260 StealthNotification n1; 4261 4262 void Publisher() { 4263 MU.Lock(); 4264 GLOB = (int*)malloc(128 * sizeof(int)); 4265 ANNOTATE_TRACE_MEMORY(&GLOB[42]); 4266 GLOB[42] = 777; 4267 if (!Tsan_PureHappensBefore()) 4268 ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB[42], "test90. FP. This is a false positve"); 4269 MU.Unlock(); 4270 n1.signal(); 4271 usleep(200000); 4272 } 4273 4274 void Reader() { 4275 n1.wait(); 4276 while (true) { 4277 MU.Lock(); 4278 int *p = &GLOB[42]; 4279 MU.Unlock(); 4280 if (p) { 4281 CHECK(*p == 777); // Race is reported here. 4282 break; 4283 } 4284 } 4285 } 4286 4287 void Run() { 4288 printf("test90: false positive (safely published pointer).\n"); 4289 MyThreadArray t(Publisher, Reader, Reader, Reader); 4290 t.Start(); 4291 t.Join(); 4292 free(GLOB); 4293 } 4294 REGISTER_TEST(Run, 90) 4295 } // namespace test90 4296 4297 4298 // test91: FP. Test for a safely-published pointer (read-write). {{{1 4299 namespace test91 { 4300 // Similar to test90. 4301 // The Publisher creates an object and safely publishes it under a mutex MU1. 4302 // Accessors get the object under MU1 and access it (read/write) under MU2. 4303 // 4304 // Without annotations Helgrind will issue a false positive in Accessor(). 4305 // 4306 4307 int *GLOB = 0; 4308 Mutex MU, MU1, MU2; 4309 4310 void Publisher() { 4311 MU1.Lock(); 4312 GLOB = (int*)malloc(128 * sizeof(int)); 4313 GLOB[42] = 777; 4314 if (!Tsan_PureHappensBefore()) 4315 ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB[42], "test91. FP. This is a false positve"); 4316 MU1.Unlock(); 4317 } 4318 4319 void Accessor() { 4320 usleep(10000); 4321 while (true) { 4322 MU1.Lock(); 4323 int *p = &GLOB[42]; 4324 MU1.Unlock(); 4325 if (p) { 4326 MU2.Lock(); 4327 (*p)++; // Race is reported here. 4328 CHECK(*p > 777); 4329 MU2.Unlock(); 4330 break; 4331 } 4332 } 4333 } 4334 4335 void Run() { 4336 printf("test91: false positive (safely published pointer, read/write).\n"); 4337 MyThreadArray t(Publisher, Accessor, Accessor, Accessor); 4338 t.Start(); 4339 t.Join(); 4340 free(GLOB); 4341 } 4342 REGISTER_TEST(Run, 91) 4343 } // namespace test91 4344 4345 4346 // test92: TN. Test for a safely-published pointer (read-write), annotated. {{{1 4347 namespace test92 { 4348 // Similar to test91, but annotated with ANNOTATE_PUBLISH_MEMORY_RANGE. 4349 // 4350 // 4351 // Publisher: Accessors: 4352 // 4353 // 1. MU1.Lock() 4354 // 2. Create GLOB. 4355 // 3. ANNOTATE_PUBLISH_...(GLOB) -------\ . 4356 // 4. MU1.Unlock() \ . 4357 // \ a. MU1.Lock() 4358 // \ b. Get GLOB 4359 // \ c. MU1.Unlock() 4360 // \--> d. Access GLOB 4361 // 4362 // A happens-before arc is created between ANNOTATE_PUBLISH_MEMORY_RANGE and 4363 // accesses to GLOB. 4364 4365 struct ObjType { 4366 int arr[10]; 4367 }; 4368 4369 ObjType *GLOB = 0; 4370 Mutex MU, MU1, MU2; 4371 4372 void Publisher() { 4373 MU1.Lock(); 4374 GLOB = new ObjType; 4375 for (int i = 0; i < 10; i++) { 4376 GLOB->arr[i] = 777; 4377 } 4378 // This annotation should go right before the object is published. 4379 ANNOTATE_PUBLISH_MEMORY_RANGE(GLOB, sizeof(*GLOB)); 4380 MU1.Unlock(); 4381 } 4382 4383 void Accessor(int index) { 4384 while (true) { 4385 MU1.Lock(); 4386 ObjType *p = GLOB; 4387 MU1.Unlock(); 4388 if (p) { 4389 MU2.Lock(); 4390 p->arr[index]++; // W/o the annotations the race will be reported here. 4391 CHECK(p->arr[index] == 778); 4392 MU2.Unlock(); 4393 break; 4394 } 4395 } 4396 } 4397 4398 void Accessor0() { Accessor(0); } 4399 void Accessor5() { Accessor(5); } 4400 void Accessor9() { Accessor(9); } 4401 4402 void Run() { 4403 printf("test92: safely published pointer, read/write, annotated.\n"); 4404 MyThreadArray t(Publisher, Accessor0, Accessor5, Accessor9); 4405 t.Start(); 4406 t.Join(); 4407 printf("\t*GLOB=%d\n", GLOB->arr[0]); 4408 } 4409 REGISTER_TEST(Run, 92) 4410 } // namespace test92 4411 4412 4413 // test93: TP. Test for incorrect usage of ANNOTATE_PUBLISH_MEMORY_RANGE. {{{1 4414 namespace test93 { 4415 int GLOB = 0; 4416 4417 void Reader() { 4418 CHECK(GLOB == 0); 4419 } 4420 4421 void Publisher() { 4422 usleep(10000); 4423 // Incorrect, used after the memory has been accessed in another thread. 4424 ANNOTATE_PUBLISH_MEMORY_RANGE(&GLOB, sizeof(GLOB)); 4425 } 4426 4427 void Run() { 4428 printf("test93: positive, misuse of ANNOTATE_PUBLISH_MEMORY_RANGE\n"); 4429 MyThreadArray t(Reader, Publisher); 4430 t.Start(); 4431 t.Join(); 4432 printf("\tGLOB=%d\n", GLOB); 4433 } 4434 REGISTER_TEST2(Run, 93, FEATURE|EXCLUDE_FROM_ALL) 4435 } // namespace test93 4436 4437 4438 // test94: TP. Check do_cv_signal/fake segment logic {{{1 4439 namespace test94 { 4440 int GLOB; 4441 4442 int COND = 0; 4443 int COND2 = 0; 4444 Mutex MU, MU2; 4445 CondVar CV, CV2; 4446 4447 StealthNotification n1, n2, n3; 4448 4449 void Thr1() { 4450 4451 n2.wait(); // Make sure the waiter blocks. 4452 GLOB = 1; // WRITE 4453 4454 MU.Lock(); 4455 COND = 1; 4456 CV.Signal(); 4457 MU.Unlock(); 4458 n1.signal(); 4459 } 4460 void Thr2() { 4461 // Make sure CV2.Signal() "happens after" CV.Signal() 4462 n1.wait(); 4463 // Make sure the waiter blocks. 4464 n3.wait(); 4465 4466 MU2.Lock(); 4467 COND2 = 1; 4468 CV2.Signal(); 4469 MU2.Unlock(); 4470 } 4471 void Thr3() { 4472 MU.Lock(); 4473 n2.signal(); 4474 while(COND != 1) 4475 CV.Wait(&MU); 4476 MU.Unlock(); 4477 } 4478 void Thr4() { 4479 MU2.Lock(); 4480 n3.signal(); 4481 while(COND2 != 1) 4482 CV2.Wait(&MU2); 4483 MU2.Unlock(); 4484 GLOB = 2; // READ: no HB-relation between CV.Signal and CV2.Wait ! 4485 } 4486 void Run() { 4487 ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test94: TP."); 4488 printf("test94: TP. Check do_cv_signal/fake segment logic\n"); 4489 MyThreadArray mta(Thr1, Thr2, Thr3, Thr4); 4490 mta.Start(); 4491 mta.Join(); 4492 printf("\tGLOB=%d\n", GLOB); 4493 } 4494 REGISTER_TEST(Run, 94); 4495 } // namespace test94 4496 4497 // test95: TP. Check do_cv_signal/fake segment logic {{{1 4498 namespace test95 { 4499 int GLOB = 0; 4500 4501 int COND = 0; 4502 int COND2 = 0; 4503 Mutex MU, MU2; 4504 CondVar CV, CV2; 4505 4506 void Thr1() { 4507 usleep(1000*1000); // Make sure CV2.Signal() "happens before" CV.Signal() 4508 usleep(10000); // Make sure the waiter blocks. 4509 4510 GLOB = 1; // WRITE 4511 4512 MU.Lock(); 4513 COND = 1; 4514 CV.Signal(); 4515 MU.Unlock(); 4516 } 4517 void Thr2() { 4518 usleep(10000); // Make sure the waiter blocks. 4519 4520 MU2.Lock(); 4521 COND2 = 1; 4522 CV2.Signal(); 4523 MU2.Unlock(); 4524 } 4525 void Thr3() { 4526 MU.Lock(); 4527 while(COND != 1) 4528 CV.Wait(&MU); 4529 MU.Unlock(); 4530 } 4531 void Thr4() { 4532 MU2.Lock(); 4533 while(COND2 != 1) 4534 CV2.Wait(&MU2); 4535 MU2.Unlock(); 4536 GLOB = 2; // READ: no HB-relation between CV.Signal and CV2.Wait ! 4537 } 4538 void Run() { 4539 ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test95: TP."); 4540 printf("test95: TP. Check do_cv_signal/fake segment logic\n"); 4541 MyThreadArray mta(Thr1, Thr2, Thr3, Thr4); 4542 mta.Start(); 4543 mta.Join(); 4544 printf("\tGLOB=%d\n", GLOB); 4545 } 4546 REGISTER_TEST(Run, 95); 4547 } // namespace test95 4548 4549 // test96: TN. tricky LockSet behaviour {{{1 4550 // 3 threads access the same memory with three different 4551 // locksets: {A, B}, {B, C}, {C, A}. 4552 // These locksets have empty intersection 4553 namespace test96 { 4554 int GLOB = 0; 4555 4556 Mutex A, B, C; 4557 4558 void Thread1() { 4559 MutexLock a(&A); 4560 MutexLock b(&B); 4561 GLOB++; 4562 } 4563 4564 void Thread2() { 4565 MutexLock b(&B); 4566 MutexLock c(&C); 4567 GLOB++; 4568 } 4569 4570 void Thread3() { 4571 MutexLock a(&A); 4572 MutexLock c(&C); 4573 GLOB++; 4574 } 4575 4576 void Run() { 4577 printf("test96: FP. tricky LockSet behaviour\n"); 4578 ANNOTATE_TRACE_MEMORY(&GLOB); 4579 MyThreadArray mta(Thread1, Thread2, Thread3); 4580 mta.Start(); 4581 mta.Join(); 4582 CHECK(GLOB == 3); 4583 printf("\tGLOB=%d\n", GLOB); 4584 } 4585 REGISTER_TEST(Run, 96); 4586 } // namespace test96 4587 4588 namespace FalseNegativeOfFastModeTest { // {{{1 4589 // This test shows false negative with --fast-mode=yes. 4590 const int HG_CACHELINE_SIZE = 64; 4591 4592 StealthNotification n1, n2; 4593 4594 const int ARRAY_SIZE = HG_CACHELINE_SIZE * 4 / sizeof(int); 4595 int array[ARRAY_SIZE]; 4596 int * GLOB = &array[ARRAY_SIZE/2]; 4597 /* 4598 We use sizeof(array) == 4 * HG_CACHELINE_SIZE to be sure that GLOB points 4599 to a memory inside a CacheLineZ which is inside array's memory range 4600 */ 4601 4602 void Reader() { 4603 n1.wait(); 4604 CHECK(0 != *GLOB); 4605 n2.signal(); 4606 } 4607 4608 TEST(PositiveTests, FalseNegativeOfFastModeTest) { 4609 MyThreadArray t(Reader); 4610 ANNOTATE_TRACE_MEMORY(GLOB); 4611 ANNOTATE_EXPECT_RACE_FOR_TSAN(GLOB, __FUNCTION__); 4612 4613 t.Start(); 4614 *GLOB = 0x12345; 4615 n1.signal(); 4616 n2.wait(); 4617 t.Join(); 4618 } 4619 } // namespace 4620 4621 // test99: TP. Unit test for a bug in LockWhen*. {{{1 4622 namespace test99 { 4623 4624 4625 bool GLOB = false; 4626 Mutex mu; 4627 4628 static void Thread1() { 4629 for (int i = 0; i < 100; i++) { 4630 mu.LockWhenWithTimeout(Condition(&ArgIsTrue, &GLOB), 5); 4631 GLOB = false; 4632 mu.Unlock(); 4633 usleep(10000); 4634 } 4635 } 4636 4637 static void Thread2() { 4638 for (int i = 0; i < 100; i++) { 4639 mu.Lock(); 4640 mu.Unlock(); 4641 usleep(10000); 4642 } 4643 } 4644 4645 void Run() { 4646 printf("test99: regression test for LockWhen*\n"); 4647 MyThreadArray t(Thread1, Thread2); 4648 t.Start(); 4649 t.Join(); 4650 } 4651 REGISTER_TEST(Run, 99); 4652 } // namespace test99 4653 4654 4655 // test100: Test for initialization bit. {{{1 4656 namespace test100 { 4657 int G1 = 0; 4658 int G2 = 0; 4659 int G3 = 0; 4660 int G4 = 0; 4661 4662 void Creator() { 4663 G1 = 1; CHECK(G1); 4664 G2 = 1; 4665 G3 = 1; CHECK(G3); 4666 G4 = 1; 4667 } 4668 4669 void Worker1() { 4670 usleep(100000); 4671 CHECK(G1); 4672 CHECK(G2); 4673 G3 = 3; 4674 G4 = 3; 4675 } 4676 4677 void Worker2() { 4678 4679 } 4680 4681 4682 void Run() { 4683 printf("test100: test for initialization bit. \n"); 4684 MyThreadArray t(Creator, Worker1, Worker2); 4685 ANNOTATE_TRACE_MEMORY(&G1); 4686 ANNOTATE_TRACE_MEMORY(&G2); 4687 ANNOTATE_TRACE_MEMORY(&G3); 4688 ANNOTATE_TRACE_MEMORY(&G4); 4689 t.Start(); 4690 t.Join(); 4691 } 4692 REGISTER_TEST2(Run, 100, FEATURE|EXCLUDE_FROM_ALL) 4693 } // namespace test100 4694 4695 4696 // test101: TN. Two signals and two waits. {{{1 4697 namespace test101 { 4698 Mutex MU; 4699 CondVar CV; 4700 int GLOB = 0; 4701 4702 int C1 = 0, C2 = 0; 4703 4704 void Signaller() { 4705 usleep(100000); 4706 MU.Lock(); 4707 C1 = 1; 4708 CV.Signal(); 4709 printf("signal\n"); 4710 MU.Unlock(); 4711 4712 GLOB = 1; 4713 4714 usleep(500000); 4715 MU.Lock(); 4716 C2 = 1; 4717 CV.Signal(); 4718 printf("signal\n"); 4719 MU.Unlock(); 4720 } 4721 4722 void Waiter() { 4723 MU.Lock(); 4724 while(!C1) 4725 CV.Wait(&MU); 4726 printf("wait\n"); 4727 MU.Unlock(); 4728 4729 MU.Lock(); 4730 while(!C2) 4731 CV.Wait(&MU); 4732 printf("wait\n"); 4733 MU.Unlock(); 4734 4735 GLOB = 2; 4736 4737 } 4738 4739 void Run() { 4740 printf("test101: negative\n"); 4741 MyThreadArray t(Waiter, Signaller); 4742 t.Start(); 4743 t.Join(); 4744 printf("\tGLOB=%d\n", GLOB); 4745 } 4746 REGISTER_TEST(Run, 101) 4747 } // namespace test101 4748 4749 // test102: --fast-mode=yes vs. --initialization-bit=yes {{{1 4750 namespace test102 { 4751 const int HG_CACHELINE_SIZE = 64; 4752 4753 Mutex MU; 4754 4755 const int ARRAY_SIZE = HG_CACHELINE_SIZE * 4 / sizeof(int); 4756 int array[ARRAY_SIZE + 1]; 4757 int * GLOB = &array[ARRAY_SIZE/2]; 4758 /* 4759 We use sizeof(array) == 4 * HG_CACHELINE_SIZE to be sure that GLOB points 4760 to a memory inside a CacheLineZ which is inside array's memory range 4761 */ 4762 4763 StealthNotification n1, n2, n3; 4764 4765 void Reader() { 4766 n1.wait(); 4767 CHECK(777 == GLOB[0]); 4768 n2.signal(); 4769 n3.wait(); 4770 CHECK(777 == GLOB[1]); 4771 } 4772 4773 void Run() { 4774 MyThreadArray t(Reader); 4775 ANNOTATE_EXPECT_RACE_FOR_TSAN(GLOB+0, "test102: TP. FN with --fast-mode=yes"); 4776 ANNOTATE_EXPECT_RACE_FOR_TSAN(GLOB+1, "test102: TP"); 4777 printf("test102: --fast-mode=yes vs. --initialization-bit=yes\n"); 4778 4779 t.Start(); 4780 GLOB[0] = 777; 4781 n1.signal(); 4782 n2.wait(); 4783 GLOB[1] = 777; 4784 n3.signal(); 4785 t.Join(); 4786 } 4787 4788 REGISTER_TEST2(Run, 102, FEATURE) 4789 } // namespace test102 4790 4791 // test103: Access different memory locations with different LockSets {{{1 4792 namespace test103 { 4793 const int N_MUTEXES = 6; 4794 const int LOCKSET_INTERSECTION_SIZE = 3; 4795 4796 int data[1 << LOCKSET_INTERSECTION_SIZE] = {0}; 4797 Mutex MU[N_MUTEXES]; 4798 4799 inline int LS_to_idx (int ls) { 4800 return (ls >> (N_MUTEXES - LOCKSET_INTERSECTION_SIZE)) 4801 & ((1 << LOCKSET_INTERSECTION_SIZE) - 1); 4802 } 4803 4804 void Worker() { 4805 for (int ls = 0; ls < (1 << N_MUTEXES); ls++) { 4806 if (LS_to_idx(ls) == 0) 4807 continue; 4808 for (int m = 0; m < N_MUTEXES; m++) 4809 if (ls & (1 << m)) 4810 MU[m].Lock(); 4811 4812 data[LS_to_idx(ls)]++; 4813 4814 for (int m = N_MUTEXES - 1; m >= 0; m--) 4815 if (ls & (1 << m)) 4816 MU[m].Unlock(); 4817 } 4818 } 4819 4820 void Run() { 4821 printf("test103: Access different memory locations with different LockSets\n"); 4822 MyThreadArray t(Worker, Worker, Worker, Worker); 4823 t.Start(); 4824 t.Join(); 4825 } 4826 REGISTER_TEST2(Run, 103, FEATURE) 4827 } // namespace test103 4828 4829 // test104: TP. Simple race (write vs write). Heap mem. {{{1 4830 namespace test104 { 4831 int *GLOB = NULL; 4832 void Worker() { 4833 GLOB[42] = 1; 4834 } 4835 4836 void Parent() { 4837 MyThread t(Worker); 4838 t.Start(); 4839 usleep(100000); 4840 GLOB[42] = 2; 4841 t.Join(); 4842 } 4843 void Run() { 4844 GLOB = (int*)malloc(128 * sizeof(int)); 4845 GLOB[42] = 0; 4846 ANNOTATE_EXPECT_RACE(&GLOB[42], "test104. TP."); 4847 ANNOTATE_TRACE_MEMORY(&GLOB[42]); 4848 printf("test104: positive\n"); 4849 Parent(); 4850 printf("\tGLOB=%d\n", GLOB[42]); 4851 free(GLOB); 4852 } 4853 REGISTER_TEST(Run, 104); 4854 } // namespace test104 4855 4856 4857 // test105: Checks how stack grows. {{{1 4858 namespace test105 { 4859 int GLOB = 0; 4860 4861 void F1() { 4862 int ar[32]; 4863 // ANNOTATE_TRACE_MEMORY(&ar[0]); 4864 // ANNOTATE_TRACE_MEMORY(&ar[31]); 4865 ar[0] = 1; 4866 ar[31] = 1; 4867 CHECK(ar[0] == 1); 4868 } 4869 4870 void Worker() { 4871 int ar[32]; 4872 // ANNOTATE_TRACE_MEMORY(&ar[0]); 4873 // ANNOTATE_TRACE_MEMORY(&ar[31]); 4874 ar[0] = 1; 4875 ar[31] = 1; 4876 CHECK(ar[0] == 1); 4877 F1(); 4878 } 4879 4880 void Run() { 4881 printf("test105: negative\n"); 4882 Worker(); 4883 MyThread t(Worker); 4884 t.Start(); 4885 t.Join(); 4886 printf("\tGLOB=%d\n", GLOB); 4887 } 4888 REGISTER_TEST(Run, 105) 4889 } // namespace test105 4890 4891 4892 // test107: Test for ANNOTATE_EXPECT_RACE {{{1 4893 namespace test107 { 4894 int GLOB = 0; 4895 void Run() { 4896 printf("test107: negative\n"); 4897 ANNOTATE_EXPECT_RACE(&GLOB, "No race in fact. Just checking the tool."); 4898 printf("\tGLOB=%d\n", GLOB); 4899 } 4900 REGISTER_TEST2(Run, 107, FEATURE|EXCLUDE_FROM_ALL) 4901 } // namespace test107 4902 4903 4904 // test108: TN. initialization of static object. {{{1 4905 namespace test108 { 4906 // Here we have a function-level static object. 4907 // Starting from gcc 4 this is therad safe, 4908 // but is is not thread safe with many other compilers. 4909 // 4910 // Helgrind/ThreadSanitizer supports this kind of initialization by 4911 // intercepting __cxa_guard_acquire/__cxa_guard_release 4912 // and ignoring all accesses between them. 4913 // pthread_once is supported in the same manner. 4914 class Foo { 4915 public: 4916 Foo() { 4917 ANNOTATE_TRACE_MEMORY(&a_); 4918 a_ = 42; 4919 } 4920 void Check() const { CHECK(a_ == 42); } 4921 private: 4922 int a_; 4923 }; 4924 4925 const Foo *GetFoo() { 4926 static const Foo *foo = new Foo(); 4927 return foo; 4928 } 4929 void Worker0() { 4930 GetFoo(); 4931 } 4932 4933 void Worker() { 4934 usleep(200000); 4935 const Foo *foo = GetFoo(); 4936 foo->Check(); 4937 } 4938 4939 4940 void Run() { 4941 printf("test108: negative, initialization of static object\n"); 4942 MyThreadArray t(Worker0, Worker, Worker); 4943 t.Start(); 4944 t.Join(); 4945 } 4946 #ifdef __GNUC__ 4947 REGISTER_TEST2(Run, 108, FEATURE) 4948 #endif 4949 } // namespace test108 4950 4951 4952 // test109: TN. Checking happens before between parent and child threads. {{{1 4953 namespace test109 { 4954 // Check that the detector correctly connects 4955 // pthread_create with the new thread 4956 // and 4957 // thread exit with pthread_join 4958 const int N = 32; 4959 static int GLOB[N]; 4960 4961 void Worker(void *a) { 4962 usleep(10000); 4963 // printf("--Worker : %ld %p\n", (int*)a - GLOB, (void*)pthread_self()); 4964 int *arg = (int*)a; 4965 (*arg)++; 4966 } 4967 4968 void Run() { 4969 printf("test109: negative\n"); 4970 MyThread *t[N]; 4971 for (int i = 0; i < N; i++) { 4972 t[i] = new MyThread(Worker, &GLOB[i]); 4973 } 4974 for (int i = 0; i < N; i++) { 4975 ANNOTATE_TRACE_MEMORY(&GLOB[i]); 4976 GLOB[i] = 1; 4977 t[i]->Start(); 4978 // printf("--Started: %p\n", (void*)t[i]->tid()); 4979 } 4980 for (int i = 0; i < N; i++) { 4981 // printf("--Joining: %p\n", (void*)t[i]->tid()); 4982 t[i]->Join(); 4983 // printf("--Joined : %p\n", (void*)t[i]->tid()); 4984 GLOB[i]++; 4985 } 4986 for (int i = 0; i < N; i++) delete t[i]; 4987 4988 printf("\tGLOB=%d\n", GLOB[13]); 4989 } 4990 REGISTER_TEST(Run, 109) 4991 } // namespace test109 4992 4993 4994 // test111: TN. Unit test for a bug related to stack handling. {{{1 4995 namespace test111 { 4996 char *GLOB = 0; 4997 bool COND = false; 4998 Mutex mu; 4999 const int N = 3000; 5000 5001 void write_to_p(char *p, int val) { 5002 for (int i = 0; i < N; i++) 5003 p[i] = val; 5004 } 5005 5006 void f1() { 5007 char some_stack[N]; 5008 write_to_p(some_stack, 1); 5009 mu.LockWhen(Condition(&ArgIsTrue, &COND)); 5010 mu.Unlock(); 5011 } 5012 5013 void f2() { 5014 char some_stack[N]; 5015 char some_more_stack[N]; 5016 write_to_p(some_stack, 2); 5017 write_to_p(some_more_stack, 2); 5018 } 5019 5020 void f0() { f2(); } 5021 5022 void Worker1() { 5023 f0(); 5024 f1(); 5025 f2(); 5026 } 5027 5028 void Worker2() { 5029 usleep(100000); 5030 mu.Lock(); 5031 COND = true; 5032 mu.Unlock(); 5033 } 5034 5035 void Run() { 5036 printf("test111: regression test\n"); 5037 MyThreadArray t(Worker1, Worker1, Worker2); 5038 t.Start(); 5039 t.Join(); 5040 } 5041 REGISTER_TEST2(Run, 111, FEATURE) 5042 } // namespace test111 5043 5044 // test112: STAB. Test for ANNOTATE_PUBLISH_MEMORY_RANGE{{{1 5045 namespace test112 { 5046 char *GLOB = 0; 5047 const int N = 64 * 5; 5048 Mutex mu; 5049 bool ready = false; // under mu 5050 int beg, end; // under mu 5051 5052 Mutex mu1; 5053 5054 void Worker() { 5055 5056 bool is_ready = false; 5057 int b, e; 5058 while (!is_ready) { 5059 mu.Lock(); 5060 is_ready = ready; 5061 b = beg; 5062 e = end; 5063 mu.Unlock(); 5064 usleep(1000); 5065 } 5066 5067 mu1.Lock(); 5068 for (int i = b; i < e; i++) { 5069 GLOB[i]++; 5070 } 5071 mu1.Unlock(); 5072 } 5073 5074 void PublishRange(int b, int e) { 5075 MyThreadArray t(Worker, Worker); 5076 ready = false; // runs before other threads 5077 t.Start(); 5078 5079 ANNOTATE_NEW_MEMORY(GLOB + b, e - b); 5080 ANNOTATE_TRACE_MEMORY(GLOB + b); 5081 for (int j = b; j < e; j++) { 5082 GLOB[j] = 0; 5083 } 5084 ANNOTATE_PUBLISH_MEMORY_RANGE(GLOB + b, e - b); 5085 5086 // hand off 5087 mu.Lock(); 5088 ready = true; 5089 beg = b; 5090 end = e; 5091 mu.Unlock(); 5092 5093 t.Join(); 5094 } 5095 5096 void Run() { 5097 printf("test112: stability (ANNOTATE_PUBLISH_MEMORY_RANGE)\n"); 5098 GLOB = new char [N]; 5099 5100 PublishRange(0, 10); 5101 PublishRange(3, 5); 5102 5103 PublishRange(12, 13); 5104 PublishRange(10, 14); 5105 5106 PublishRange(15, 17); 5107 PublishRange(16, 18); 5108 5109 // do few more random publishes. 5110 for (int i = 0; i < 20; i++) { 5111 const int begin = rand() % N; 5112 const int size = (rand() % (N - begin)) + 1; 5113 CHECK(size > 0); 5114 CHECK(begin + size <= N); 5115 PublishRange(begin, begin + size); 5116 } 5117 5118 printf("GLOB = %d\n", (int)GLOB[0]); 5119 } 5120 REGISTER_TEST2(Run, 112, STABILITY) 5121 } // namespace test112 5122 5123 5124 // test113: PERF. A lot of lock/unlock calls. Many locks {{{1 5125 namespace test113 { 5126 const int kNumIter = 100000; 5127 const int kNumLocks = 7; 5128 Mutex MU[kNumLocks]; 5129 TEST (StressTests, ManyLocksUnlocks2) { 5130 printf("test113: perf\n"); 5131 for (int i = 0; i < kNumIter; i++ ) { 5132 for (int j = 0; j < kNumLocks; j++) { 5133 if (i & (1 << j)) MU[j].Lock(); 5134 } 5135 for (int j = kNumLocks - 1; j >= 0; j--) { 5136 if (i & (1 << j)) MU[j].Unlock(); 5137 } 5138 } 5139 } 5140 } // namespace test113 5141 5142 5143 // test114: STAB. Recursive static initialization. {{{1 5144 namespace test114 { 5145 int Bar() { 5146 static int bar = 1; 5147 return bar; 5148 } 5149 int Foo() { 5150 static int foo = Bar(); 5151 return foo; 5152 } 5153 void Worker() { 5154 static int x = Foo(); 5155 CHECK(x == 1); 5156 } 5157 void Run() { 5158 printf("test114: stab\n"); 5159 MyThreadArray t(Worker, Worker); 5160 t.Start(); 5161 t.Join(); 5162 } 5163 #ifdef __GNUC__ 5164 REGISTER_TEST(Run, 114) 5165 #endif 5166 } // namespace test114 5167 5168 // test116: TN. some operations with string<> objects. {{{1 5169 namespace test116 { 5170 5171 void Worker() { 5172 string A[10], B[10], C[10]; 5173 for (int i = 0; i < 1000; i++) { 5174 for (int j = 0; j < 10; j++) { 5175 string &a = A[j]; 5176 string &b = B[j]; 5177 string &c = C[j]; 5178 a = "sdl;fkjhasdflksj df"; 5179 b = "sdf sdf;ljsd "; 5180 c = "'sfdf df"; 5181 c = b; 5182 a = c; 5183 b = a; 5184 swap(a,b); 5185 swap(b,c); 5186 } 5187 for (int j = 0; j < 10; j++) { 5188 string &a = A[j]; 5189 string &b = B[j]; 5190 string &c = C[j]; 5191 a.clear(); 5192 b.clear(); 5193 c.clear(); 5194 } 5195 } 5196 } 5197 5198 void Run() { 5199 printf("test116: negative (strings)\n"); 5200 MyThreadArray t(Worker, Worker, Worker); 5201 t.Start(); 5202 t.Join(); 5203 } 5204 REGISTER_TEST2(Run, 116, FEATURE|EXCLUDE_FROM_ALL) 5205 } // namespace test116 5206 5207 // test117: TN. Many calls to function-scope static init. {{{1 5208 namespace test117 { 5209 const int N = 50; 5210 5211 int Foo() { 5212 usleep(20000); 5213 return 1; 5214 } 5215 5216 void Worker(void *a) { 5217 static int foo = Foo(); 5218 CHECK(foo == 1); 5219 } 5220 5221 void Run() { 5222 printf("test117: negative\n"); 5223 MyThread *t[N]; 5224 for (int i = 0; i < N; i++) { 5225 t[i] = new MyThread(Worker); 5226 } 5227 for (int i = 0; i < N; i++) { 5228 t[i]->Start(); 5229 } 5230 for (int i = 0; i < N; i++) { 5231 t[i]->Join(); 5232 } 5233 for (int i = 0; i < N; i++) delete t[i]; 5234 } 5235 #ifndef WIN32 5236 // This is racey on Windows! 5237 REGISTER_TEST(Run, 117) 5238 #endif 5239 } // namespace test117 5240 5241 5242 5243 // test118 PERF: One signal, multiple waits. {{{1 5244 namespace test118 { 5245 int GLOB = 0; 5246 const int kNumIter = 2000000; 5247 void Signaller() { 5248 usleep(50000); 5249 ANNOTATE_CONDVAR_SIGNAL(&GLOB); 5250 } 5251 void Waiter() { 5252 for (int i = 0; i < kNumIter; i++) { 5253 ANNOTATE_CONDVAR_WAIT(&GLOB); 5254 if (i == kNumIter / 2) 5255 usleep(100000); 5256 } 5257 } 5258 TEST(StressTests, OneSignalManyWaits) { 5259 printf("test118: perf\n"); 5260 MyThreadArray t(Signaller, Waiter, Signaller, Waiter); 5261 t.Start(); 5262 t.Join(); 5263 printf("\tGLOB=%d\n", GLOB); 5264 } 5265 } // namespace test118 5266 5267 5268 // test119: TP. Testing that malloc does not introduce any HB arc. {{{1 5269 namespace test119 { 5270 int GLOB = 0; 5271 void Worker1() { 5272 GLOB = 1; 5273 free(malloc(123)); 5274 } 5275 void Worker2() { 5276 usleep(100000); 5277 free(malloc(345)); 5278 GLOB = 2; 5279 } 5280 void Run() { 5281 printf("test119: positive (checking if malloc creates HB arcs)\n"); 5282 if (!(Tsan_PureHappensBefore() && kMallocUsesMutex)) 5283 ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "true race"); 5284 MyThreadArray t(Worker1, Worker2); 5285 t.Start(); 5286 t.Join(); 5287 printf("\tGLOB=%d\n", GLOB); 5288 } 5289 REGISTER_TEST(Run, 119) 5290 } // namespace test119 5291 5292 5293 // test120: TP. Thread1: write then read. Thread2: read. {{{1 5294 namespace test120 { 5295 int GLOB = 0; 5296 5297 void Thread1() { 5298 GLOB = 1; // write 5299 CHECK(GLOB); // read 5300 } 5301 5302 void Thread2() { 5303 usleep(100000); 5304 CHECK(GLOB >= 0); // read 5305 } 5306 5307 void Run() { 5308 ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "TP (T1: write then read, T2: read)"); 5309 printf("test120: positive\n"); 5310 MyThreadArray t(Thread1, Thread2); 5311 GLOB = 1; 5312 t.Start(); 5313 t.Join(); 5314 printf("\tGLOB=%d\n", GLOB); 5315 } 5316 REGISTER_TEST(Run, 120) 5317 } // namespace test120 5318 5319 5320 namespace DoubleCheckedLocking { // {{{1 5321 struct Foo { 5322 uintptr_t padding1[16]; 5323 uintptr_t a; 5324 uintptr_t padding2[16]; 5325 }; 5326 5327 static Mutex mu; 5328 static Foo *foo; 5329 5330 void InitMe() { 5331 if (!foo) { 5332 MutexLock lock(&mu); 5333 if (!foo) { 5334 ANNOTATE_EXPECT_RACE_FOR_TSAN(&foo, "Double-checked locking (ptr)"); 5335 foo = new Foo; 5336 if (Tsan_PureHappensBefore()) { 5337 // A pure h-b detector may or may not detect this. 5338 ANNOTATE_BENIGN_RACE(&foo->a, "real race"); 5339 } else { 5340 // ThreadSanitizer in full hybrid mode must detect it. 5341 ANNOTATE_EXPECT_RACE_FOR_TSAN(&foo->a, "Double-checked locking (obj)"); 5342 } 5343 foo->a = 42; 5344 } 5345 } 5346 } 5347 5348 void UseMe() { 5349 InitMe(); 5350 CHECK(foo); 5351 if (foo->a != 42) { 5352 printf("foo->a = %d (should be 42)\n", (int)foo->a); 5353 } 5354 } 5355 5356 void Worker1() { UseMe(); } 5357 void Worker2() { UseMe(); } 5358 void Worker3() { UseMe(); } 5359 5360 5361 TEST(PositiveTests, DoubleCheckedLocking1) { 5362 foo = NULL; 5363 MyThreadArray t1(Worker1, Worker2, Worker3); 5364 t1.Start(); 5365 t1.Join(); 5366 delete foo; 5367 } 5368 } // namespace DoubleCheckedLocking 5369 5370 namespace DoubleCheckedLocking2 { // {{{1 5371 struct Foo { 5372 uintptr_t padding1[16]; 5373 uintptr_t a; 5374 uintptr_t padding2[16]; 5375 }; 5376 5377 Foo *foo; 5378 Mutex mu; 5379 5380 void InitMe() { 5381 if (foo) return; 5382 Foo *x = new Foo; 5383 ANNOTATE_BENIGN_RACE(&x->a, "may or may not detect this race"); 5384 x->a = 42; 5385 { 5386 MutexLock lock(&mu); 5387 if (!foo) { 5388 foo = x; 5389 x = NULL; 5390 } 5391 } 5392 if (x) delete x; 5393 } 5394 5395 void Worker() { 5396 InitMe(); 5397 CHECK(foo); 5398 CHECK(foo->a == 42); 5399 } 5400 5401 TEST(PositiveTests, DoubleCheckedLocking2) { 5402 foo = NULL; 5403 ANNOTATE_EXPECT_RACE(&foo, "real race"); 5404 MyThreadArray t1(Worker, Worker, Worker, Worker); 5405 t1.Start(); 5406 t1.Join(); 5407 delete foo; 5408 } 5409 5410 } // namespace DoubleCheckedLocking2 5411 5412 namespace PositiveTests_DifferentSizeAccessTest { // {{{1 5413 5414 uint64_t arr[1000]; 5415 size_t arr_index = 0; 5416 uint64_t *MEM; 5417 size_t size[3]; 5418 size_t offset[3]; 5419 5420 void GenericWrite(size_t s, size_t off) { 5421 switch(s) { 5422 case 8: 5423 CHECK(off == 0); 5424 ((uint64_t*)MEM)[off] = 1; 5425 break; 5426 case 4: 5427 CHECK(off < 2); 5428 ((uint32_t*)MEM)[off] = 1; 5429 break; 5430 case 2: 5431 CHECK(off < 4); 5432 ((uint16_t*)MEM)[off] = 1; 5433 break; 5434 case 1: 5435 CHECK(off < 8); 5436 ((uint8_t*)MEM)[off] = 1; 5437 break; 5438 default: CHECK(0); break; 5439 } 5440 } 5441 5442 void Thread1() { GenericWrite(size[0], offset[0]); } 5443 void Thread2() { GenericWrite(size[1], offset[1]); } 5444 5445 bool TwoRangesIntersect(size_t beg1, size_t end1, size_t beg2, size_t end2) { 5446 if (beg1 <= beg2 && end1 > beg2) return true; 5447 if (beg2 <= beg1 && end2 > beg1) return true; 5448 return false; 5449 } 5450 5451 void RunTwoThreads(size_t size1, size_t offset1, size_t size2, size_t offset2) { 5452 size[0] = size1; 5453 size[1] = size2; 5454 offset[0] = offset1; 5455 offset[1] = offset2; 5456 long beg1 = offset1 * size1; 5457 long end1 = beg1 + size1; 5458 long beg2 = offset2 * size2; 5459 long end2 = beg2 + size2; 5460 bool have_intersection = TwoRangesIntersect(beg1, end1, beg2, end2); 5461 char descr[1024]; 5462 MEM = &arr[arr_index++]; 5463 sprintf(descr, "Testing: [%ld, %ld) vs [%ld, %ld] (%s intersection); p=%p", 5464 beg1, end1, beg2, end2, have_intersection ? "have" : "no", MEM); 5465 fprintf(stderr, "%s\n", descr); 5466 char *racey_addr_beg = (char*)MEM + max(beg1, beg2); 5467 char *racey_addr_end = (char*)MEM + min(end1, end2); 5468 if (have_intersection) { 5469 ANNOTATE_EXPECT_RACE(racey_addr_beg, descr); 5470 if (racey_addr_end - racey_addr_beg >= 2) { 5471 // We expect a race on the first racey byte, but we may also see some 5472 // races in other bytes (e.g. if a 8-byte store is implemented via two 5473 // 4-byte stores on a 32-bit arch). Ignore these extra races. 5474 ANNOTATE_BENIGN_RACE_SIZED(racey_addr_beg+1, racey_addr_end - racey_addr_beg - 1, 5475 "race"); 5476 } 5477 } 5478 MyThreadArray t1(Thread1, Thread2); 5479 t1.Start(); 5480 t1.Join(); 5481 } 5482 5483 void TestTwoSizes(size_t size1, size_t offset1, size_t size2, size_t offset2) { 5484 RunTwoThreads(size1, offset1, size2, offset2); 5485 RunTwoThreads(size2, offset2, size1, offset1); 5486 } 5487 5488 TEST(PositiveTests, DifferentSizeAccessTest) { 5489 for(int size1_log = 3; size1_log >= 0; size1_log--) { 5490 for (int size2_log = size1_log; size2_log >= 0; size2_log--) { 5491 for (int off1 = 0; off1 < (1 << (3-size1_log)); off1++) { 5492 for (int off2 = 0; off2 < (1 << (3-size2_log)); off2++) { 5493 RunTwoThreads(1 << size1_log, off1, 1 << size2_log, off2); 5494 } 5495 } 5496 } 5497 } 5498 } 5499 5500 5501 const int kStressArrSize = 100; 5502 char stress_arr[kStressArrSize]; 5503 5504 void StressWorker() { 5505 const int n = 100000; 5506 char foo[kStressArrSize]; 5507 memset(foo, 0, sizeof(foo)); 5508 for (int i = 0; i < n; i++) { 5509 memcpy(stress_arr + i % (kStressArrSize / 2), foo, i % (kStressArrSize / 3)); 5510 } 5511 } 5512 5513 TEST(StressTests, DifferentSizeAccessStressTest) { 5514 ANNOTATE_BENIGN_RACE_SIZED(stress_arr, sizeof(stress_arr), "race"); 5515 MyThreadArray t(StressWorker, StressWorker, StressWorker); 5516 t.Start(); 5517 t.Join(); 5518 } 5519 } // namespace 5520 5521 // test124: What happens if we delete an unlocked lock? {{{1 5522 namespace test124 { 5523 // This test does not worg with pthreads (you can't call 5524 // pthread_mutex_destroy on a locked lock). 5525 int GLOB = 0; 5526 const int N = 1000; 5527 void Worker() { 5528 Mutex *a_large_local_array_of_mutexes; 5529 a_large_local_array_of_mutexes = new Mutex[N]; 5530 for (int i = 0; i < N; i++) { 5531 a_large_local_array_of_mutexes[i].Lock(); 5532 } 5533 delete []a_large_local_array_of_mutexes; 5534 GLOB = 1; 5535 } 5536 5537 void Run() { 5538 printf("test124: negative\n"); 5539 MyThreadArray t(Worker, Worker, Worker); 5540 t.Start(); 5541 t.Join(); 5542 printf("\tGLOB=%d\n", GLOB); 5543 } 5544 REGISTER_TEST2(Run, 124, FEATURE|EXCLUDE_FROM_ALL) 5545 } // namespace test124 5546 5547 5548 // test126 TN: test for BlockingCounter {{{1 5549 namespace test126 { 5550 BlockingCounter *blocking_counter; 5551 int GLOB = 0; 5552 void Worker() { 5553 CHECK(blocking_counter); 5554 CHECK(GLOB == 0); 5555 blocking_counter->DecrementCount(); 5556 } 5557 void Run() { 5558 printf("test126: negative\n"); 5559 MyThreadArray t(Worker, Worker, Worker); 5560 blocking_counter = new BlockingCounter(3); 5561 t.Start(); 5562 blocking_counter->Wait(); 5563 GLOB = 1; 5564 t.Join(); 5565 printf("\tGLOB=%d\n", GLOB); 5566 } 5567 REGISTER_TEST(Run, 126) 5568 } // namespace test126 5569 5570 5571 // test127. Bad code: unlocking a mutex locked by another thread. {{{1 5572 namespace test127 { 5573 Mutex mu; 5574 void Thread1() { 5575 mu.Lock(); 5576 usleep(1); // avoid tail call elimination 5577 } 5578 void Thread2() { 5579 usleep(100000); 5580 mu.Unlock(); 5581 usleep(1); // avoid tail call elimination 5582 } 5583 TEST(LockTests, UnlockingALockHeldByAnotherThread) { 5584 MyThreadArray t(Thread1, Thread2); 5585 t.Start(); 5586 t.Join(); 5587 } 5588 } // namespace test127 5589 5590 // test128. Suppressed code in concurrent accesses {{{1 5591 // Please use --suppressions=unittest.supp flag when running this test. 5592 namespace test128 { 5593 Mutex mu; 5594 int GLOB = 0; 5595 void Worker() { 5596 usleep(100000); 5597 mu.Lock(); 5598 GLOB++; 5599 mu.Unlock(); 5600 } 5601 void ThisFunctionShouldBeSuppressed() { 5602 GLOB++; 5603 } 5604 void Run() { 5605 printf("test128: Suppressed code in concurrent accesses.\n"); 5606 MyThreadArray t(Worker, ThisFunctionShouldBeSuppressed); 5607 t.Start(); 5608 t.Join(); 5609 } 5610 REGISTER_TEST2(Run, 128, FEATURE | EXCLUDE_FROM_ALL) 5611 } // namespace test128 5612 5613 // test129: TN. Synchronization via ReaderLockWhen(). {{{1 5614 namespace test129 { 5615 int GLOB = 0; 5616 Mutex MU; 5617 bool WeirdCondition(int* param) { 5618 *param = GLOB; // a write into Waiter's memory 5619 return GLOB > 0; 5620 } 5621 void Waiter() { 5622 int param = 0; 5623 MU.ReaderLockWhen(Condition(WeirdCondition, ¶m)); 5624 MU.ReaderUnlock(); 5625 CHECK(GLOB > 0); 5626 CHECK(param > 0); 5627 } 5628 void Waker() { 5629 usleep(100000); // Make sure the waiter blocks. 5630 MU.Lock(); 5631 GLOB++; 5632 MU.Unlock(); // calls ANNOTATE_CONDVAR_SIGNAL; 5633 } 5634 void Run() { 5635 printf("test129: Synchronization via ReaderLockWhen()\n"); 5636 MyThread mt(Waiter, NULL, "Waiter Thread"); 5637 mt.Start(); 5638 Waker(); 5639 mt.Join(); 5640 printf("\tGLOB=%d\n", GLOB); 5641 } 5642 REGISTER_TEST2(Run, 129, FEATURE); 5643 } // namespace test129 5644 5645 namespace NegativeTests_PerThreadTest { // {{{1 5646 #ifdef TLS 5647 // This test verifies that the race detector handles 5648 // thread-local storage (TLS) correctly. 5649 // As of 09-03-30 ThreadSanitizer has a bug: 5650 // - Thread1 starts 5651 // - Thread1 touches per_thread_global 5652 // - Thread1 ends 5653 // - Thread2 starts (and there is no happens-before relation between it and 5654 // Thread1) 5655 // - Thread2 touches per_thread_global 5656 // It may happen so that Thread2 will have per_thread_global in the same address 5657 // as Thread1. Since there is no happens-before relation between threads, 5658 // ThreadSanitizer reports a race. 5659 // 5660 // test131 does the same for stack. 5661 5662 static TLS int per_thread_global[10] = {0}; 5663 5664 void RealWorker() { // Touch per_thread_global. 5665 per_thread_global[1]++; 5666 per_thread_global[9]++; 5667 errno++; 5668 } 5669 5670 void Worker() { // Spawn few threads that touch per_thread_global. 5671 MyThreadArray t(RealWorker, RealWorker); 5672 t.Start(); 5673 t.Join(); 5674 } 5675 void Worker0() { usleep(0); Worker(); } 5676 void Worker1() { usleep(100000); Worker(); } 5677 void Worker2() { usleep(200000); Worker(); } 5678 void Worker3() { usleep(300000); Worker(); } 5679 5680 #ifdef WIN32 5681 TEST(NegativeTests, DISABLED_PerThreadTest) { // issue #23 5682 #else 5683 TEST(NegativeTests, PerThreadTest) { 5684 #endif 5685 MyThreadArray t1(Worker0, Worker1, Worker2, Worker3); 5686 t1.Start(); 5687 t1.Join(); 5688 } 5689 #endif // TLS 5690 } // namespace test130 5691 5692 5693 namespace NegativeTests_StackReuseTest { // {{{1 5694 // Same as PerThreadTest, but for stack. 5695 5696 void RealWorker() { // Touch stack. 5697 int stack_var = 0; 5698 stack_var++; 5699 } 5700 5701 void Worker() { // Spawn few threads that touch stack. 5702 MyThreadArray t(RealWorker, RealWorker); 5703 t.Start(); 5704 t.Join(); 5705 } 5706 void Worker0() { usleep(0); Worker(); } 5707 void Worker1() { usleep(100000); Worker(); } 5708 void Worker2() { usleep(200000); Worker(); } 5709 void Worker3() { usleep(300000); Worker(); } 5710 5711 TEST(NegativeTests, StackReuseTest) { 5712 MyThreadArray t(Worker0, Worker1, Worker2, Worker3); 5713 t.Start(); 5714 t.Join(); 5715 } 5716 5717 TEST(NegativeTests, StackReuseWithFlushTest) { 5718 MyThreadArray t1(Worker0, Worker1, Worker2, Worker3); 5719 MyThreadArray t2(Worker0, Worker1, Worker2, Worker3); 5720 t1.Start(); 5721 ANNOTATE_FLUSH_STATE(); 5722 usleep(400000); 5723 t2.Start(); 5724 t2.Join(); 5725 t1.Join(); 5726 } 5727 } // namespace test131 5728 5729 5730 // test132: TP. Simple race (write vs write). Works in fast-mode. {{{1 5731 namespace test132 { 5732 int GLOB = 0; 5733 void Worker() { GLOB = 1; } 5734 5735 void Run1() { 5736 ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test132"); 5737 printf("test132: positive; &GLOB=%p\n", &GLOB); 5738 ANNOTATE_TRACE_MEMORY(&GLOB); 5739 GLOB = 7; 5740 MyThreadArray t(Worker, Worker); 5741 t.Start(); 5742 t.Join(); 5743 } 5744 5745 void Run() { 5746 Run1(); 5747 } 5748 REGISTER_TEST(Run, 132); 5749 } // namespace test132 5750 5751 5752 // test133: TP. Simple race (write vs write). Works in fast mode. {{{1 5753 namespace test133 { 5754 // Same as test132, but everything is run from a separate thread spawned from 5755 // the main thread. 5756 int GLOB = 0; 5757 void Worker() { GLOB = 1; } 5758 5759 void Run1() { 5760 ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test133"); 5761 printf("test133: positive; &GLOB=%p\n", &GLOB); 5762 ANNOTATE_TRACE_MEMORY(&GLOB); 5763 GLOB = 7; 5764 MyThreadArray t(Worker, Worker); 5765 t.Start(); 5766 t.Join(); 5767 } 5768 void Run() { 5769 MyThread t(Run1); 5770 t.Start(); 5771 t.Join(); 5772 } 5773 REGISTER_TEST(Run, 133); 5774 } // namespace test133 5775 5776 5777 // test134 TN. Swap. Variant of test79. {{{1 5778 namespace test134 { 5779 #if 0 5780 typedef __gnu_cxx::hash_map<int, int> map_t; 5781 #else 5782 typedef std::map<int, int> map_t; 5783 #endif 5784 map_t map; 5785 Mutex mu; 5786 // Here we use swap to pass map between threads. 5787 // The synchronization is correct, but w/o the annotation 5788 // any hybrid detector will complain. 5789 5790 // Swap is very unfriendly to the lock-set (and hybrid) race detectors. 5791 // Since tmp is destructed outside the mutex, we need to have a happens-before 5792 // arc between any prior access to map and here. 5793 // Since the internals of tmp are created ouside the mutex and are passed to 5794 // other thread, we need to have a h-b arc between here and any future access. 5795 // These arcs can be created by HAPPENS_{BEFORE,AFTER} annotations, but it is 5796 // much simpler to apply pure-happens-before mode to the mutex mu. 5797 void Swapper() { 5798 map_t tmp; 5799 MutexLock lock(&mu); 5800 ANNOTATE_HAPPENS_AFTER(&map); 5801 // We swap the new empty map 'tmp' with 'map'. 5802 map.swap(tmp); 5803 ANNOTATE_HAPPENS_BEFORE(&map); 5804 // tmp (which is the old version of map) is destroyed here. 5805 } 5806 5807 void Worker() { 5808 MutexLock lock(&mu); 5809 ANNOTATE_HAPPENS_AFTER(&map); 5810 map[1]++; 5811 ANNOTATE_HAPPENS_BEFORE(&map); 5812 } 5813 5814 void Run() { 5815 printf("test134: negative (swap)\n"); 5816 // ********************** Shorter way: *********************** 5817 // ANNOTATE_PURE_HAPPENS_BEFORE_MUTEX(&mu); 5818 MyThreadArray t(Worker, Worker, Swapper, Worker, Worker); 5819 t.Start(); 5820 t.Join(); 5821 } 5822 REGISTER_TEST(Run, 134) 5823 } // namespace test134 5824 5825 // test137 TP. Races on stack variables. {{{1 5826 namespace test137 { 5827 int GLOB = 0; 5828 ProducerConsumerQueue q(10); 5829 5830 void Worker() { 5831 int stack; 5832 int *tmp = (int*)q.Get(); 5833 (*tmp)++; 5834 int *racey = &stack; 5835 q.Put(racey); 5836 (*racey)++; 5837 usleep(150000); 5838 // We may miss the races if we sleep less due to die_memory events... 5839 } 5840 5841 void Run() { 5842 int tmp = 0; 5843 printf("test137: TP. Races on stack variables.\n"); 5844 q.Put(&tmp); 5845 MyThreadArray t(Worker, Worker, Worker, Worker); 5846 t.Start(); 5847 t.Join(); 5848 q.Get(); 5849 } 5850 5851 REGISTER_TEST2(Run, 137, FEATURE | EXCLUDE_FROM_ALL) 5852 } // namespace test137 5853 5854 namespace ThreadPoolFNTests { // {{{1 5855 5856 // When using thread pools, two concurrent callbacks might be scheduled 5857 // onto the same executor thread. As a result, unnecessary happens-before 5858 // relation may be introduced between callbacks. 5859 // If we set the number of executor threads to 1, any known data 5860 // race detector will be silent. 5861 // However, the a similar situation may happen with any number of 5862 // executor threads (with some probability). 5863 5864 void Worker(int *var) { 5865 usleep(100000); 5866 *var = 42; 5867 } 5868 5869 TEST(ThreadPoolFNTests, OneProducerOneConsumer) { 5870 int RACEY = 0; 5871 printf("FN. Two closures hit the same thread in ThreadPool.\n"); 5872 5873 ThreadPool tp(1); 5874 tp.StartWorkers(); 5875 tp.Add(NewCallback(Worker, &RACEY)); 5876 tp.Add(NewCallback(Worker, &RACEY)); 5877 } 5878 5879 void PutWorkerOn(ThreadPool *tp, int *var) { 5880 usleep(100000); 5881 tp->Add(NewCallback(Worker, var)); 5882 usleep(100000); 5883 } 5884 5885 TEST(ThreadPoolFNTests, TwoProducersOneConsumer) { 5886 int RACEY = 0; 5887 printf("FN. Two closures hit the same thread in ThreadPool.\n"); 5888 5889 ThreadPool consumers_tp(1); 5890 consumers_tp.StartWorkers(); 5891 5892 ThreadPool producers_tp(2); 5893 producers_tp.StartWorkers(); 5894 producers_tp.Add(NewCallback(PutWorkerOn, &consumers_tp, &RACEY)); 5895 producers_tp.Add(NewCallback(PutWorkerOn, &consumers_tp, &RACEY)); 5896 } 5897 } // namespace ThreadPoolFNTests 5898 5899 // test139: FN. A true race hidden by reference counting annotation. {{{1 5900 namespace test139 { 5901 int GLOB = 0; 5902 RefCountedClass *obj; 5903 5904 void Worker1() { 5905 GLOB++; // First access. 5906 obj->Unref(); 5907 } 5908 5909 void Worker2() { 5910 usleep(100000); 5911 obj->Unref(); 5912 GLOB++; // Second access. 5913 } 5914 5915 void Run() { 5916 printf("test139: FN. A true race hidden by reference counting annotation.\n"); 5917 5918 obj = new RefCountedClass; 5919 obj->AnnotateUnref(); 5920 obj->Ref(); 5921 obj->Ref(); 5922 MyThreadArray mt(Worker1, Worker2); 5923 mt.Start(); 5924 mt.Join(); 5925 } 5926 5927 REGISTER_TEST2(Run, 139, FEATURE) 5928 } // namespace test139 5929 5930 // Simple FIFO queue annotated with PCQ annotations. {{{1 5931 class FifoMessageQueue { 5932 public: 5933 FifoMessageQueue() { ANNOTATE_PCQ_CREATE(this); } 5934 ~FifoMessageQueue() { ANNOTATE_PCQ_DESTROY(this); } 5935 // Send a message. 'message' should be positive. 5936 void Put(int message) { 5937 CHECK(message); 5938 MutexLock lock(&mu_); 5939 ANNOTATE_PCQ_PUT(this); 5940 q_.push(message); 5941 } 5942 // Return the message from the queue and pop it 5943 // or return 0 if there are no messages. 5944 int Get() { 5945 MutexLock lock(&mu_); 5946 if (q_.empty()) return 0; 5947 int res = q_.front(); 5948 q_.pop(); 5949 ANNOTATE_PCQ_GET(this); 5950 return res; 5951 } 5952 private: 5953 Mutex mu_; 5954 queue<int> q_; 5955 }; 5956 5957 5958 // test142: TN. Check PCQ_* annotations. {{{1 5959 namespace test142 { 5960 // Putter writes to array[i] and sends a message 'i'. 5961 // Getters receive messages and read array[message]. 5962 // PCQ_* annotations calm down the hybrid detectors. 5963 5964 const int N = 1000; 5965 int array[N+1]; 5966 5967 FifoMessageQueue q; 5968 5969 void Putter() { 5970 for (int i = 1; i <= N; i++) { 5971 array[i] = i*i; 5972 q.Put(i); 5973 usleep(1000); 5974 } 5975 } 5976 5977 void Getter() { 5978 int non_zero_received = 0; 5979 for (int i = 1; i <= N; i++) { 5980 int res = q.Get(); 5981 if (res > 0) { 5982 CHECK(array[res] = res * res); 5983 non_zero_received++; 5984 } 5985 usleep(1000); 5986 } 5987 #ifndef WIN32 5988 #ifdef OS_darwin 5989 printf("T=%p: non_zero_received=%d\n", 5990 (void*)pthread_self(), non_zero_received); 5991 #else 5992 printf("T=%d: non_zero_received=%d\n", 5993 (int)pthread_self(), non_zero_received); 5994 #endif 5995 #endif 5996 } 5997 5998 void Run() { 5999 printf("test142: tests PCQ annotations\n"); 6000 MyThreadArray t(Putter, Getter, Getter); 6001 t.Start(); 6002 t.Join(); 6003 } 6004 REGISTER_TEST(Run, 142) 6005 } // namespace test142 6006 6007 6008 // test143: TP. Check PCQ_* annotations. {{{1 6009 namespace test143 { 6010 // True positive. 6011 // We have a race on GLOB between Putter and one of the Getters. 6012 // Pure h-b will not see it. 6013 // If FifoMessageQueue was annotated using HAPPENS_BEFORE/AFTER, the race would 6014 // be missed too. 6015 // PCQ_* annotations do not hide this race. 6016 int GLOB = 0; 6017 StealthNotification n; 6018 6019 FifoMessageQueue q; 6020 6021 void Putter() { 6022 GLOB = 1; 6023 q.Put(1); 6024 n.signal(); 6025 } 6026 6027 void Getter() { 6028 n.wait(); 6029 q.Get(); 6030 CHECK(GLOB == 1); // Race here 6031 } 6032 6033 void Run() { 6034 q.Put(1); 6035 if (!Tsan_PureHappensBefore()) { 6036 ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "true races"); 6037 } 6038 printf("test143: tests PCQ annotations (true positive)\n"); 6039 MyThreadArray t(Putter, Getter, Getter); 6040 t.Start(); 6041 t.Join(); 6042 } 6043 REGISTER_TEST(Run, 143); 6044 } // namespace test143 6045 6046 // test144: Unit-test for a bug in fast-mode {{{1 6047 namespace test144 { 6048 struct Foo { 6049 int a, b; 6050 } ALIGNED(64); 6051 6052 struct Foo GLOB; 6053 int &RACEY = GLOB.a; 6054 6055 void Worker() { 6056 RACEY++; 6057 } 6058 6059 void Run() { 6060 printf("test144: fast-mode bug\n"); 6061 ANNOTATE_TRACE_MEMORY(&RACEY); 6062 ANNOTATE_EXPECT_RACE_FOR_TSAN(&RACEY, "Real race"); 6063 6064 // This line resets GLOB's creator_tid (bug). 6065 ANNOTATE_NEW_MEMORY(&GLOB.b, sizeof(GLOB.b)); 6066 6067 MyThreadArray t(Worker, Worker); 6068 t.Start(); 6069 t.Join(); 6070 } 6071 6072 REGISTER_TEST(Run, 144); 6073 } // namespace test144 6074 6075 // test145: Unit-test for a bug in fast-mode {{{1 6076 namespace test145 { 6077 // A variation of test144 for dynamic memory. 6078 6079 struct Foo { 6080 int a, b; 6081 } ALIGNED(64); 6082 6083 struct Foo *GLOB; 6084 int *RACEY = NULL; 6085 6086 void Worker() { 6087 (*RACEY)++; 6088 } 6089 6090 void Run() { 6091 printf("test145: fast-mode bug\n"); 6092 6093 GLOB = new Foo; 6094 RACEY = &(GLOB->a); 6095 ANNOTATE_TRACE_MEMORY(RACEY); 6096 ANNOTATE_EXPECT_RACE_FOR_TSAN(RACEY, "Real race"); 6097 6098 // This line resets GLOB's creator_tid (bug). 6099 ANNOTATE_NEW_MEMORY(&(GLOB->b), sizeof(GLOB->b)); 6100 6101 MyThreadArray t(Worker, Worker); 6102 t.Start(); 6103 t.Join(); 6104 delete GLOB; 6105 } 6106 6107 REGISTER_TEST(Run, 145); 6108 } // namespace test145 6109 6110 // test147: allocating 1.5G of mem in one chunk. {{{1 6111 namespace test147 { 6112 void Run() { 6113 printf("test147: malloc 1.5G\n"); 6114 free(malloc((1 << 30) + (1 << 29))); 6115 } 6116 REGISTER_TEST(Run, 147) 6117 } // namespace test147 6118 6119 // test148: FN. 3 threads, h-b hides race between T1 and T3. {{{1 6120 namespace test148 { 6121 int GLOB = 0; 6122 int COND = 0; 6123 Mutex mu; 6124 CondVar cv; 6125 6126 void Signaller() { 6127 usleep(1000000); 6128 GLOB = 1; 6129 mu.Lock(); 6130 COND = 1; 6131 cv.Signal(); 6132 mu.Unlock(); 6133 } 6134 6135 void Waiter() { 6136 mu.Lock(); 6137 while (COND == 0) 6138 cv.Wait(&mu); 6139 ANNOTATE_CONDVAR_LOCK_WAIT(&cv, &mu); 6140 GLOB = 2; 6141 mu.Unlock(); 6142 } 6143 6144 void Racer() { 6145 usleep(2000000); 6146 mu.Lock(); 6147 GLOB = 3; 6148 mu.Unlock(); 6149 } 6150 6151 void Run() { 6152 printf("test148: FN. 3 threads, h-b hides race between T1 and T3.\n"); 6153 MyThreadArray mta(Signaller, Waiter, Racer); 6154 mta.Start(); 6155 mta.Join(); 6156 } 6157 REGISTER_TEST(Run, 148) 6158 } // namespace test148 6159 6160 // test149: allocate and memset lots of of mem in several chunks. {{{1 6161 namespace test149 { 6162 void Run() { 6163 int kChunkSize = 1 << 26; 6164 printf("test149: malloc 8x%dM\n", kChunkSize / (1 << 20)); 6165 void *mem[8]; 6166 for (int i = 0; i < 8; i++) { 6167 mem[i] = malloc(kChunkSize); 6168 memset(mem[i], 0, kChunkSize); 6169 printf("+"); 6170 } 6171 for (int i = 0; i < 8; i++) { 6172 free(mem[i]); 6173 printf("-"); 6174 } 6175 printf(" Done\n"); 6176 } 6177 REGISTER_TEST2(Run, 149, EXCLUDE_FROM_ALL) // TODO(kcc): enable it back 6178 } // namespace test149 6179 6180 // test150: race which is detected after one of the thread has joined. {{{1 6181 namespace test150 { 6182 int GLOB = 0; 6183 StealthNotification n; 6184 void Writer1() { GLOB++; } 6185 void Writer2() { 6186 n.wait(); 6187 GLOB++; 6188 } 6189 TEST(PositiveTests, RaceDetectedAfterJoin) { 6190 ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "real race"); 6191 MyThread t1(Writer1); 6192 MyThread t2(Writer2); 6193 t1.Start(); 6194 t2.Start(); 6195 t1.Join(); 6196 n.signal(); 6197 t2.Join(); 6198 printf("\tGLOB=%d\n", GLOB); 6199 } 6200 } // namespace test150 6201 6202 6203 // test151: stress for the size of vector time clock. {{{1 6204 namespace test151 { 6205 int kNumThreads = 100; 6206 int kNumSegments = 5000000; 6207 void Void() { } 6208 void Run() { 6209 printf("test151: stress\n"); 6210 printf("Creating %d threads\n", kNumThreads); 6211 for (int i = 0; i < kNumThreads; i++) { 6212 MyThread t(Void); 6213 t.Start(); 6214 t.Join(); 6215 } 6216 printf("Creating %d segments\n", kNumSegments); 6217 for (int i = 0; i < kNumSegments; i++) { 6218 if (i % (kNumSegments / 50) == 0) 6219 printf("."); 6220 ANNOTATE_HAPPENS_BEFORE(NULL); 6221 } 6222 printf(" done\n"); 6223 } 6224 REGISTER_TEST2(Run, 151, PERFORMANCE | EXCLUDE_FROM_ALL) // TODO(kcc): enable 6225 } // namespace test151 6226 6227 // test152: atexit -> exit creates a h-b arc. {{{1 6228 namespace test152 { 6229 int GLOB = 0; 6230 MyThread *t; 6231 6232 void AtExitCallback() { 6233 GLOB++; 6234 } 6235 6236 void AtExitThread() { 6237 GLOB++; 6238 atexit(AtExitCallback); 6239 } 6240 6241 TEST(NegativeTests, AtExitTest) { 6242 t = new MyThread(AtExitThread); 6243 t->Start(); // We don't join it. 6244 } 6245 } // namespace test152 6246 6247 // test153: test for vanilla pthread_spinlock_t {{{1 6248 namespace test153 { 6249 #ifndef NO_SPINLOCK 6250 // pthread_spinlock_t is tricky because pthread_spin_unlock and 6251 // pthread_spin_init are the same symbol. 6252 int GLOB = 0; 6253 pthread_spinlock_t lock; 6254 6255 void Worker1() { 6256 pthread_spin_lock(&lock); 6257 GLOB++; 6258 pthread_spin_unlock(&lock); 6259 } 6260 6261 void Worker2() { 6262 while (pthread_spin_trylock(&lock) != 0) { } 6263 GLOB++; 6264 pthread_spin_unlock(&lock); 6265 } 6266 6267 6268 void Run() { 6269 printf("test153: pthread_spin_t\n"); 6270 for (int i = 0; i < 3; i++) { 6271 // test few times on the same lock to check how init/destroy are handled. 6272 pthread_spin_init(&lock, 0); 6273 MyThreadArray t(Worker1, Worker1, Worker2, Worker2); 6274 t.Start(); 6275 t.Join(); 6276 pthread_spin_destroy(&lock); 6277 } 6278 } 6279 REGISTER_TEST(Run, 153) 6280 #endif // NO_SPINLOCK 6281 } // namespace test153 6282 6283 // test154: long test with lots of races. {{{1 6284 namespace test154 { 6285 const int kNumIters = 100000; 6286 const int kArraySize = 100000; 6287 int *arr; 6288 6289 void RaceyAccess(int *a) { 6290 (*a)++; 6291 } 6292 6293 void RaceyLoop() { 6294 for (int j = 0; j < kArraySize; j++) { 6295 RaceyAccess(&arr[j]); 6296 } 6297 } 6298 6299 void Worker() { 6300 for (int i = 0; i < kNumIters; i++) { 6301 usleep(1); 6302 printf("."); 6303 if ((i % 40) == 39) 6304 printf("\n"); 6305 RaceyLoop(); 6306 } 6307 } 6308 6309 void Run() { 6310 arr = new int[kArraySize]; 6311 printf("test154: positive; long test with lots of races\n"); 6312 MyThreadArray t(Worker, Worker); 6313 t.Start(); 6314 t.Join(); 6315 delete arr; 6316 } 6317 REGISTER_TEST2(Run, 154, EXCLUDE_FROM_ALL) 6318 } // namespace test154 6319 6320 namespace PositiveTests_RaceInMemcpy { // {{{1 6321 char *GLOB; 6322 6323 void DoMemcpy() { 6324 memcpy(GLOB, GLOB + 1, 1); 6325 } 6326 6327 void DoMemmove() { 6328 memmove(GLOB, GLOB + 1, 1); 6329 } 6330 6331 void Write0() { 6332 GLOB[0] = 'z'; 6333 } 6334 6335 void DoStrlen() { 6336 CHECK(strlen(GLOB) == 3); 6337 } 6338 6339 void DoStrcpy() { 6340 CHECK(strcpy(GLOB, "zzz") == GLOB); 6341 } 6342 6343 void DoStrchr() { 6344 CHECK(strchr(GLOB, 'o') == (GLOB + 1)); 6345 } 6346 6347 void DoMemchr() { 6348 CHECK(memchr(GLOB, 'o', 4) == (GLOB + 1)); 6349 } 6350 6351 void DoStrrchr() { 6352 CHECK(strrchr(GLOB, '!') == NULL); 6353 } 6354 6355 void DoStrcmp() { 6356 CHECK(strcmp(GLOB, "xxx") != 0); 6357 } 6358 6359 void DoStrncmp() { 6360 CHECK(strncmp(GLOB, "xxx", 3) != 0); 6361 } 6362 6363 6364 void RunThreads(void (*f1)(void), void (*f2)(void), char *mem) { 6365 GLOB = mem; 6366 strcpy(GLOB, "foo"); 6367 ANNOTATE_EXPECT_RACE_FOR_TSAN(GLOB, "expected race"); 6368 MyThreadArray t(f1, f2); 6369 t.Start(); 6370 t.Join(); 6371 } 6372 6373 TEST(PositiveTests, RaceInMemcpy) { 6374 static char mem[4]; 6375 RunThreads(DoMemcpy, DoMemcpy, mem); 6376 } 6377 6378 TEST(PositiveTests, RaceInMemmove) { 6379 static char mem[4]; 6380 RunThreads(DoMemmove, DoMemmove, mem); 6381 } 6382 6383 TEST(PositiveTests, RaceInStrlen1) { 6384 static char mem[4]; 6385 RunThreads(DoStrlen, Write0, mem); 6386 } 6387 6388 TEST(PositiveTests, RaceInStrlen2) { 6389 static char mem[4]; 6390 RunThreads(Write0, DoStrlen, mem); 6391 } 6392 6393 TEST(PositiveTests, RaceInStrcpy) { 6394 static char mem[4]; 6395 RunThreads(Write0, DoStrcpy, mem); 6396 } 6397 6398 TEST(PositiveTests, RaceInStrchr) { 6399 static char mem[4]; 6400 RunThreads(Write0, DoStrchr, mem); 6401 } 6402 6403 TEST(PositiveTests, RaceInMemchr) { 6404 static char mem[4]; 6405 RunThreads(Write0, DoMemchr, mem); 6406 } 6407 6408 TEST(PositiveTests, RaceInStrrchr) { 6409 static char mem[4]; 6410 RunThreads(Write0, DoStrrchr, mem); 6411 } 6412 6413 TEST(PositiveTests, RaceInStrcmp) { 6414 static char mem[4]; 6415 RunThreads(Write0, DoStrcmp, mem); 6416 } 6417 6418 TEST(PositiveTests, RaceInStrncmp) { 6419 static char mem[4]; 6420 RunThreads(Write0, DoStrncmp, mem); 6421 } 6422 6423 } // namespace 6424 6425 // test157: TN. Test for stack traces (using ANNOTATE_NO_OP). {{{1 6426 namespace test157 { 6427 6428 void func3() { 6429 ANNOTATE_NO_OP((void*)__LINE__); 6430 } 6431 void func2() { 6432 func3(); 6433 } 6434 void func1() { 6435 func2(); 6436 } 6437 void Worker1() { 6438 func1(); 6439 ANNOTATE_NO_OP((void*)__LINE__); 6440 } 6441 void Worker2() { 6442 func2(); 6443 ANNOTATE_NO_OP((void*)__LINE__); 6444 } 6445 void Worker3() { 6446 func3(); 6447 ANNOTATE_NO_OP((void*)__LINE__); 6448 } 6449 void Run() { 6450 ANNOTATE_NO_OP((void*)__LINE__); 6451 printf("test157: negative\n"); 6452 ANNOTATE_NO_OP((void*)__LINE__); 6453 MyThreadArray t(Worker1, Worker2, Worker3); 6454 ANNOTATE_NO_OP((void*)__LINE__); 6455 t.Start(); 6456 ANNOTATE_NO_OP((void*)__LINE__); 6457 t.Join(); 6458 ANNOTATE_NO_OP((void*)__LINE__); 6459 } 6460 REGISTER_TEST(Run, 157); 6461 } // namespace test157 6462 6463 6464 namespace MemoryTypes { // {{{1 6465 void WriteChar(void *param) { 6466 *(char*)param = 1; 6467 usleep(500000); // let other threads hit this before exiting. 6468 } 6469 6470 void RaceOnMemory(void (*callback)(void *), char *mem) { 6471 ANNOTATE_FLUSH_EXPECTED_RACES(); 6472 ANNOTATE_EXPECT_RACE(mem, "race"); 6473 MyThread t1(callback, mem), 6474 t2(callback, mem); 6475 t1.Start(); 6476 t2.Start(); 6477 t1.Join(); 6478 t2.Join(); 6479 CHECK(*mem == 1); 6480 ANNOTATE_FLUSH_EXPECTED_RACES(); 6481 } 6482 6483 void RaceOnLocalStack(void (*callback)(void *)) { 6484 char object_on_stack = 0; 6485 // We may have had races on the main stack before -- forget about them. 6486 ANNOTATE_NEW_MEMORY(&object_on_stack, 1); 6487 RaceOnMemory(callback, &object_on_stack); 6488 } 6489 6490 // create a new function to make reports different. 6491 void WriteChar1(void *param) { WriteChar(param); } 6492 6493 TEST(MemoryTypes, RaceOnMainThreadStack) { 6494 RaceOnLocalStack(WriteChar1); 6495 } 6496 6497 void WriteChar2(void *param) { WriteChar(param); } 6498 6499 TEST(MemoryTypes, RaceOnNonMainThreadStack) { 6500 MyThread t((void (*)(void*))(RaceOnLocalStack), (void*)WriteChar2); 6501 t.Start(); 6502 t.Join(); 6503 } 6504 6505 void WriteChar3(void *param) { WriteChar(param); } 6506 6507 TEST(MemoryTypes, RaceOnMallocedMemory) { 6508 char *mem = (char*)malloc(100); 6509 RaceOnMemory(WriteChar3, mem+42); 6510 free(mem); 6511 } 6512 6513 void WriteChar4(void *param) { WriteChar(param); } 6514 6515 TEST(MemoryTypes, RaceOnCallocedMemory) { 6516 char *mem = (char*)calloc(30, 4); 6517 RaceOnMemory(WriteChar4, mem+42); 6518 free(mem); 6519 } 6520 6521 void WriteChar5(void *param) { WriteChar(param); } 6522 6523 TEST(MemoryTypes, RaceOnMemoryFromNew) { 6524 char *mem = new char; 6525 RaceOnMemory(WriteChar5, mem); 6526 delete mem; 6527 } 6528 6529 void WriteChar6(void *param) { WriteChar(param); } 6530 6531 TEST(MemoryTypes, RaceOnMemoryFromNewA) { 6532 char *mem = new char [100]; 6533 RaceOnMemory(WriteChar6, mem+42); 6534 delete [] mem; 6535 } 6536 6537 void WriteChar7(void *param) { WriteChar(param); } 6538 6539 TEST(MemoryTypes, RaceOnMemoryFromNewNoThrow) { 6540 char *mem = new (std::nothrow) char; 6541 RaceOnMemory(WriteChar7, mem); 6542 operator delete (mem, std::nothrow); 6543 } 6544 void WriteChar8(void *param) { WriteChar(param); } 6545 6546 TEST(MemoryTypes, RaceOnMemoryFromNewNoThrowA) { 6547 char *mem = new (std::nothrow) char [100]; 6548 RaceOnMemory(WriteChar8, mem+42); 6549 operator delete [] (mem, std::nothrow); 6550 } 6551 6552 void AllocateAndDeallocateUsingVariousAllocs() { 6553 for (int i = 0; i < 10000; i++) { 6554 char *p; 6555 switch (i % 5) { 6556 case 0: 6557 p = (char*)malloc(10); 6558 free(p); 6559 break; 6560 case 1: 6561 p = new char; 6562 delete p; 6563 break; 6564 case 2: 6565 p = new char [10]; 6566 delete [] p; 6567 case 3: 6568 p = new (std::nothrow) char; 6569 operator delete (p, std::nothrow); 6570 break; 6571 case 4: 6572 p = new (std::nothrow) char[10]; 6573 operator delete [](p, std::nothrow); 6574 break; 6575 } 6576 } 6577 } 6578 TEST(MemoryTypes, VariousAllocs) { 6579 void (*f)(void) = AllocateAndDeallocateUsingVariousAllocs; 6580 MyThreadArray t(f, f, f, f); 6581 t.Start(); 6582 t.Join(); 6583 } 6584 6585 void ReallocThread() { 6586 void *ptr = NULL; 6587 for (int i = 8; i < 128; i++) { 6588 int size = (1 << (i / 8)) - 1; 6589 ptr = realloc(ptr, size); 6590 ANNOTATE_TRACE_MEMORY(ptr); 6591 memset(ptr, 42, size); 6592 } 6593 free(ptr); 6594 } 6595 TEST(MemoryTypes, Reallocs) { 6596 MyThreadArray t(ReallocThread, ReallocThread, ReallocThread, ReallocThread); 6597 t.Start(); 6598 t.Join(); 6599 } 6600 } // namespace 6601 6602 6603 namespace StressTests_ThreadTree { //{{{1 6604 int GLOB = 0; 6605 6606 // Worker(N) will do 2^N increments of GLOB, each increment in a separate thread 6607 void Worker(int depth) { 6608 CHECK(depth >= 0); 6609 if (depth > 0) { 6610 MyThread t1((MyThread::worker_t)Worker, (void*)(intptr_t)(depth - 1)); 6611 MyThread t2((MyThread::worker_t)Worker, (void*)(intptr_t)(depth - 1)); 6612 t1.Start(); 6613 t2.Start(); 6614 t1.Join(); 6615 t2.Join(); 6616 } else { 6617 GLOB++; // Race here 6618 } 6619 } 6620 6621 TEST(StressTests, ThreadTree3) { 6622 ANNOTATE_EXPECT_RACE(&GLOB, "StressTests.ThreadTree3 race"); 6623 ANNOTATE_TRACE_MEMORY(&GLOB); 6624 Worker(3); 6625 } 6626 6627 TEST(StressTests, DISABLED_ThreadTree7) { 6628 ANNOTATE_EXPECT_RACE(&GLOB, "StressTests.ThreadTree7 race"); 6629 ANNOTATE_TRACE_MEMORY(&GLOB); 6630 Worker(7); 6631 } 6632 } // namespace test313 6633 6634 namespace StressTests_StartAndJoinManyThreads { //{{{1 6635 6636 void Worker() { 6637 } 6638 6639 // Too slow. Need to run it separately. 6640 TEST(StressTests, StartAndJoinManyThreads) { 6641 ANNOTATE_FLUSH_STATE(); 6642 for (int i = 0; i < 1100; i++) { 6643 if ((i % 100) == 0) 6644 printf("."); 6645 MyThread t1(Worker); 6646 MyThread t2(Worker); 6647 t1.Start(); 6648 t2.Start(); 6649 t1.Join(); 6650 t2.Join(); 6651 } 6652 printf("\n"); 6653 } 6654 } // namespace 6655 6656 namespace StressTests_ManyAccesses { // {{{1 6657 #ifndef NO_BARRIER 6658 const int kArrayLen = 128; // Small size, so that everything fits into cache. 6659 const int kNumIter = 1024 * 1024 * 2; 6660 int thread_id; 6661 int *array = NULL; 6662 Barrier *barrier; 6663 6664 void IncrementMe(int *x) { 6665 (*x)++; 6666 } 6667 6668 void NoRaceWorker() { 6669 int id = AtomicIncrement(&thread_id, 1); 6670 barrier->Block(); 6671 int *ptr = array + id * (kArrayLen + 64); // pad to avoid false sharing. 6672 for (int it = 0; it < kNumIter; it++) { 6673 for (int i = 0; i < kArrayLen; i++) { 6674 IncrementMe(ptr + i); 6675 } 6676 } 6677 } 6678 6679 void RunThreads(int n_threads, void (*f)(void)) { 6680 thread_id = -1; 6681 barrier = new Barrier(n_threads); 6682 // Allocate a lot so that operator new uses mmap, unless forced to use brk. 6683 array = new int[(kArrayLen + 64) * n_threads + (1 << 22)]; 6684 printf("ptr = %p\n", array); 6685 MyThread **t = new MyThread*[n_threads]; 6686 for (int i = 0; i < n_threads; i++) t[i] = new MyThread(NoRaceWorker); 6687 for (int i = 0; i < n_threads; i++) t[i]->Start(); 6688 for (int i = 0; i < n_threads; i++) t[i]->Join(); 6689 for (int i = 0; i < n_threads; i++) delete t[i]; 6690 delete [] t; 6691 delete [] array; 6692 } 6693 6694 // Just one thread. 6695 TEST(StressTests, DISABLED_ManyAccessesNoRace1Test) { 6696 RunThreads(1, NoRaceWorker); 6697 } 6698 6699 // 2 threads accessing different memory. 6700 TEST(StressTests, DISABLED_ManyAccessesNoRace2Test) { 6701 RunThreads(2, NoRaceWorker); 6702 } 6703 // 4 threads accessing different memory. 6704 TEST(StressTests, DISABLED_ManyAccessesNoRace4Test) { 6705 RunThreads(4, NoRaceWorker); 6706 } 6707 // 8 threads accessing different memory. 6708 TEST(StressTests, DISABLED_ManyAccessesNoRace8Test) { 6709 RunThreads(8, NoRaceWorker); 6710 } 6711 // 16 threads accessing different memory. 6712 TEST(StressTests, DISABLED_ManyAccessesNoRace16Test) { 6713 RunThreads(16, NoRaceWorker); 6714 } 6715 #endif // NO_BARRIER 6716 } // namespace 6717 6718 namespace NegativeTests_EnableRaceDetectionTest { // {{{1 6719 const size_t size = 10000; 6720 const size_t n_iter = 1000; 6721 int GLOB[size]; 6722 6723 void Worker() { 6724 for (size_t i = 0; i < n_iter; i++) { 6725 for (size_t j = 0; j < size; j++) { 6726 GLOB[j]++; 6727 } 6728 } 6729 } 6730 6731 TEST(NegativeTests, EnableRaceDetectionTest) { 6732 ANNOTATE_ENABLE_RACE_DETECTION(0); 6733 MyThreadArray t(Worker, Worker, Worker, Worker); 6734 t.Start(); 6735 t.Join(); 6736 ANNOTATE_ENABLE_RACE_DETECTION(1); 6737 } 6738 } 6739 6740 namespace PositiveTests_MopVsFree { // {{{1 6741 int *p; 6742 const int kIdx = 77; 6743 StealthNotification n; 6744 6745 void Read() { 6746 CHECK(p[kIdx] == 777); 6747 n.signal(); 6748 } 6749 void Free() { 6750 n.wait(); 6751 free(p); 6752 } 6753 6754 TEST(PositiveTests, ReadVsFree) { 6755 p = (int*)malloc(100 * sizeof(int)); 6756 p[kIdx] = 777; 6757 ANNOTATE_EXPECT_RACE(&p[kIdx], "race: read vs free"); 6758 MyThreadArray t(Read, Free); 6759 t.Start(); 6760 t.Join(); 6761 } 6762 6763 } // namespace 6764 6765 namespace ManySmallObjectsTest { // {{{1 6766 void Worker() { 6767 const int N = 1 << 21; 6768 struct T { 6769 int a, b, c, d; 6770 T() : a(1), b(2), c(3), d(4) { } 6771 }; 6772 T **a = new T*[N]; 6773 for (int i = 0; i < N; i++) { 6774 if ((i % (N / 16)) == 0) 6775 printf("+"); 6776 a[i] = new T; 6777 CHECK(a[i]->a == 1); 6778 } 6779 printf("\n"); 6780 for (int i = 0; i < N; i++) { 6781 if ((i % (N / 16)) == 0) 6782 printf("-"); 6783 delete a[i]; 6784 } 6785 printf("\n"); 6786 delete [] a; 6787 } 6788 6789 TEST(StressTests, DISABLED_ManySmallObjectsOneThreadTest) { 6790 Worker(); 6791 } 6792 6793 TEST(StressTests, DISABLED_ManySmallObjectsTwoThreadsTest) { 6794 MyThreadArray t(Worker, Worker); 6795 t.Start(); 6796 t.Join(); 6797 } 6798 } // namespace 6799 6800 namespace RepPrefixedInstructionsTest { //{{{1 6801 6802 #if defined (__GNUC__) && (defined(ARCH_x86) || defined(ARCH_amd64)) 6803 void rep_clr_1(uint8_t *s, long n) 6804 { 6805 intptr_t d0, d1; 6806 __asm__ __volatile__ ( 6807 "rep ; stosb" 6808 : "=&c" (d0), "=&D" (d1) 6809 : "a" (0), "1" (s), "0" (n) 6810 : "memory"); 6811 } 6812 6813 uint8_t mem1[1000]; 6814 6815 void Clr1_0_10() { rep_clr_1(mem1+ 0, 10); } 6816 void Clr1_10_10() { rep_clr_1(mem1+10, 10); } 6817 void Clr1_10_0() { rep_clr_1(mem1+10, 0); } 6818 6819 void Clr1_25_1() { rep_clr_1(mem1+25, 1); } 6820 void Clr1_25_0() { rep_clr_1(mem1+25, 0); } 6821 6822 void Clr1_50_30() { rep_clr_1(mem1+50, 30); } 6823 void Clr1_60_0() { rep_clr_1(mem1+60, 0); } 6824 void Clr1_60_1() { rep_clr_1(mem1+60, 1); } 6825 void Clr1_70_10() { rep_clr_1(mem1+70, 10); } 6826 6827 6828 void RunThreads(void (*f1)(void), void (*f2)(void)) { 6829 MyThreadArray t(f1, f2); 6830 t.Start(); 6831 t.Join(); 6832 } 6833 6834 TEST(NegativeTests, RepSanityTest) { 6835 memset(mem1, 0xff, sizeof(mem1)); 6836 rep_clr_1(mem1, 0); 6837 CHECK(mem1[0] != 0); 6838 rep_clr_1(mem1, 1); 6839 CHECK(mem1[0] == 0); 6840 CHECK(mem1[1] != 0); 6841 rep_clr_1(mem1, 5); 6842 CHECK(mem1[4] == 0); 6843 CHECK(mem1[5] != 0); 6844 } 6845 6846 TEST(NegativeTests, RepNegativeTest) { 6847 memset(mem1, 0xff, sizeof(mem1)); 6848 RunThreads(Clr1_0_10, Clr1_10_10); 6849 RunThreads(Clr1_10_0, Clr1_10_10); 6850 RunThreads(Clr1_25_0, Clr1_25_1); 6851 RunThreads(Clr1_50_30, Clr1_60_0); 6852 } 6853 6854 TEST(PositiveTests, RepPositive1Test) { 6855 memset(mem1, 0xff, sizeof(mem1)); 6856 ANNOTATE_EXPECT_RACE(mem1+10, "real race"); 6857 for (int i = 11; i < 20; i++) ANNOTATE_BENIGN_RACE(mem1 + i, ""); 6858 RunThreads(Clr1_10_10, Clr1_10_10); 6859 } 6860 TEST(PositiveTests, RepPositive2Test) { 6861 memset(mem1, 0xff, sizeof(mem1)); 6862 ANNOTATE_EXPECT_RACE(mem1+25, "real race"); 6863 RunThreads(Clr1_25_1, Clr1_25_1); 6864 } 6865 6866 TEST(PositiveTests, RepPositive3Test) { 6867 memset(mem1, 0xff, sizeof(mem1)); 6868 ANNOTATE_EXPECT_RACE(mem1+60, "real race"); 6869 RunThreads(Clr1_50_30, Clr1_60_1); 6870 } 6871 6872 TEST(PositiveTests, RepPositive4Test) { 6873 memset(mem1, 0xff, sizeof(mem1)); 6874 ANNOTATE_EXPECT_RACE(mem1+70, "real race"); 6875 for (int i = 71; i < 80; i++) ANNOTATE_BENIGN_RACE(mem1 + i, ""); 6876 RunThreads(Clr1_50_30, Clr1_70_10); 6877 } 6878 #endif // __GNUC__ ... 6879 } // namespace 6880 6881 // test400: Demo of a simple false positive. {{{1 6882 namespace test400 { 6883 static Mutex mu; 6884 static vector<int> *vec; // GUARDED_BY(mu); 6885 6886 void InitAllBeforeStartingThreads() { 6887 vec = new vector<int>; 6888 vec->push_back(1); 6889 vec->push_back(2); 6890 } 6891 6892 void Thread1() { 6893 MutexLock lock(&mu); 6894 vec->pop_back(); 6895 } 6896 6897 void Thread2() { 6898 MutexLock lock(&mu); 6899 vec->pop_back(); 6900 } 6901 6902 //---- Sub-optimal code --------- 6903 size_t NumberOfElementsLeft() { 6904 MutexLock lock(&mu); 6905 return vec->size(); 6906 } 6907 6908 void WaitForAllThreadsToFinish_InefficientAndTsanUnfriendly() { 6909 while(NumberOfElementsLeft()) { 6910 ; // sleep or print or do nothing. 6911 } 6912 // It is now safe to access vec w/o lock. 6913 // But a hybrid detector (like ThreadSanitizer) can't see it. 6914 // Solutions: 6915 // 1. Use pure happens-before detector (e.g. "tsan --pure-happens-before") 6916 // 2. Call ANNOTATE_PURE_HAPPENS_BEFORE_MUTEX(&mu) 6917 // in InitAllBeforeStartingThreads() 6918 // 3. (preferred) Use WaitForAllThreadsToFinish_Good() (see below). 6919 CHECK(vec->empty()); 6920 delete vec; 6921 } 6922 6923 //----- Better code ----------- 6924 6925 bool NoElementsLeft(vector<int> *v) { 6926 return v->empty(); 6927 } 6928 6929 void WaitForAllThreadsToFinish_Good() { 6930 mu.LockWhen(Condition(NoElementsLeft, vec)); 6931 mu.Unlock(); 6932 6933 // It is now safe to access vec w/o lock. 6934 CHECK(vec->empty()); 6935 delete vec; 6936 } 6937 6938 6939 void Run() { 6940 MyThreadArray t(Thread1, Thread2); 6941 InitAllBeforeStartingThreads(); 6942 t.Start(); 6943 WaitForAllThreadsToFinish_InefficientAndTsanUnfriendly(); 6944 // WaitForAllThreadsToFinish_Good(); 6945 t.Join(); 6946 } 6947 REGISTER_TEST2(Run, 400, RACE_DEMO) 6948 } // namespace test400 6949 6950 // test401: Demo of false positive caused by reference counting. {{{1 6951 namespace test401 { 6952 // A simplified example of reference counting. 6953 // DecRef() does ref count increment in a way unfriendly to race detectors. 6954 // DecRefAnnotated() does the same in a friendly way. 6955 6956 static vector<int> *vec; 6957 static int ref_count; 6958 6959 void InitAllBeforeStartingThreads(int number_of_threads) { 6960 vec = new vector<int>; 6961 vec->push_back(1); 6962 ref_count = number_of_threads; 6963 } 6964 6965 // Correct, but unfriendly to race detectors. 6966 int DecRef() { 6967 return AtomicIncrement(&ref_count, -1); 6968 } 6969 6970 // Correct and friendly to race detectors. 6971 int DecRefAnnotated() { 6972 ANNOTATE_HAPPENS_BEFORE(&ref_count); 6973 int res = AtomicIncrement(&ref_count, -1); 6974 if (res == 0) { 6975 ANNOTATE_HAPPENS_AFTER(&ref_count); 6976 } 6977 return res; 6978 } 6979 6980 void ThreadWorker() { 6981 CHECK(ref_count > 0); 6982 CHECK(vec->size() == 1); 6983 if (DecRef() == 0) { // Use DecRefAnnotated() instead! 6984 // No one uses vec now ==> delete it. 6985 delete vec; // A false race may be reported here. 6986 vec = NULL; 6987 } 6988 } 6989 6990 void Run() { 6991 MyThreadArray t(ThreadWorker, ThreadWorker, ThreadWorker); 6992 InitAllBeforeStartingThreads(3 /*number of threads*/); 6993 t.Start(); 6994 t.Join(); 6995 CHECK(vec == 0); 6996 } 6997 REGISTER_TEST2(Run, 401, RACE_DEMO) 6998 } // namespace test401 6999 7000 7001 // test502: produce lots of segments without cross-thread relations {{{1 7002 namespace test502 { 7003 7004 /* 7005 * This test produces ~1Gb of memory usage when run with the following options: 7006 * 7007 * --tool=helgrind 7008 * --trace-after-race=0 7009 * --num-callers=2 7010 * --more-context=no 7011 */ 7012 7013 Mutex MU; 7014 int GLOB = 0; 7015 7016 void TP() { 7017 for (int i = 0; i < 750000; i++) { 7018 MU.Lock(); 7019 GLOB++; 7020 MU.Unlock(); 7021 } 7022 } 7023 7024 void Run() { 7025 MyThreadArray t(TP, TP); 7026 printf("test502: produce lots of segments without cross-thread relations\n"); 7027 7028 t.Start(); 7029 t.Join(); 7030 } 7031 7032 REGISTER_TEST2(Run, 502, MEMORY_USAGE | PRINT_STATS | EXCLUDE_FROM_ALL 7033 | PERFORMANCE) 7034 } // namespace test502 7035 7036 // test503: produce lots of segments with simple HB-relations {{{1 7037 // HB cache-miss rate is ~55% 7038 namespace test503 { 7039 7040 // |- | | | | | 7041 // | \| | | | | 7042 // | |- | | | | 7043 // | | \| | | | 7044 // | | |- | | | 7045 // | | | \| | | 7046 // | | | |- | | 7047 // | | | | \| | 7048 // | | | | |- | 7049 // | | | | | \| 7050 // | | | | | |---- 7051 //->| | | | | | 7052 // |- | | | | | 7053 // | \| | | | | 7054 // ... 7055 7056 const int N_threads = 32; 7057 const int ARRAY_SIZE = 128; 7058 int GLOB[ARRAY_SIZE]; 7059 ProducerConsumerQueue *Q[N_threads]; 7060 int GLOB_limit = 100000; 7061 int count = -1; 7062 7063 void Worker(){ 7064 int myId = AtomicIncrement(&count, 1); 7065 7066 ProducerConsumerQueue &myQ = *Q[myId], &nextQ = *Q[(myId+1) % N_threads]; 7067 7068 // this code produces a new SS with each new segment 7069 while (myQ.Get() != NULL) { 7070 for (int i = 0; i < ARRAY_SIZE; i++) 7071 GLOB[i]++; 7072 7073 if (myId == 0 && GLOB[0] > GLOB_limit) { 7074 // Stop all threads 7075 for (int i = 0; i < N_threads; i++) 7076 Q[i]->Put(NULL); 7077 } else 7078 nextQ.Put(GLOB); 7079 } 7080 } 7081 7082 void Run() { 7083 printf("test503: produce lots of segments with simple HB-relations\n"); 7084 for (int i = 0; i < N_threads; i++) 7085 Q[i] = new ProducerConsumerQueue(1); 7086 Q[0]->Put(GLOB); 7087 7088 { 7089 ThreadPool pool(N_threads); 7090 pool.StartWorkers(); 7091 for (int i = 0; i < N_threads; i++) { 7092 pool.Add(NewCallback(Worker)); 7093 } 7094 } // all folks are joined here. 7095 7096 for (int i = 0; i < N_threads; i++) 7097 delete Q[i]; 7098 } 7099 7100 REGISTER_TEST2(Run, 503, MEMORY_USAGE | PRINT_STATS 7101 | PERFORMANCE | EXCLUDE_FROM_ALL) 7102 } // namespace test503 7103 7104 // test504: force massive cache fetch-wback (50% misses, mostly CacheLineZ) {{{1 7105 namespace test504 { 7106 #if !defined(WINE) and !defined(ANDROID) // Valgrind+wine hate large static objects 7107 const int N_THREADS = 2, 7108 HG_CACHELINE_COUNT = 1 << 16, 7109 HG_CACHELINE_SIZE = 1 << 6, 7110 HG_CACHE_SIZE = HG_CACHELINE_COUNT * HG_CACHELINE_SIZE; 7111 7112 // int gives us ~4x speed of the byte test 7113 // 4x array size gives us 7114 // total multiplier of 16x over the cachesize 7115 // so we can neglect the cached-at-the-end memory 7116 const int ARRAY_SIZE = 4 * HG_CACHE_SIZE, 7117 ITERATIONS = 30; 7118 int array[ARRAY_SIZE]; 7119 7120 int count = 0; 7121 Mutex count_mu; 7122 7123 void Worker() { 7124 count_mu.Lock(); 7125 int myId = ++count; 7126 count_mu.Unlock(); 7127 7128 // all threads write to different memory locations, 7129 // so no synchronization mechanisms are needed 7130 int lower_bound = ARRAY_SIZE * (myId-1) / N_THREADS, 7131 upper_bound = ARRAY_SIZE * ( myId ) / N_THREADS; 7132 for (int j = 0; j < ITERATIONS; j++) 7133 for (int i = lower_bound; i < upper_bound; 7134 i += HG_CACHELINE_SIZE / sizeof(array[0])) { 7135 array[i] = i; // each array-write generates a cache miss 7136 } 7137 } 7138 7139 void Run() { 7140 printf("test504: force massive CacheLineZ fetch-wback\n"); 7141 MyThreadArray t(Worker, Worker); 7142 t.Start(); 7143 t.Join(); 7144 } 7145 7146 REGISTER_TEST2(Run, 504, PERFORMANCE | PRINT_STATS | EXCLUDE_FROM_ALL) 7147 #endif // WINE 7148 } // namespace test504 7149 7150 // test505: force massive cache fetch-wback (60% misses) {{{1 7151 // modification of test504 - more threads, byte accesses and lots of mutexes 7152 // so it produces lots of CacheLineF misses (30-50% of CacheLineZ misses) 7153 namespace test505 { 7154 #if !defined(WINE) and !defined(ANDROID) // Valgrind+wine hate large static objects 7155 7156 const int N_THREADS = 2, 7157 HG_CACHELINE_COUNT = 1 << 16, 7158 HG_CACHELINE_SIZE = 1 << 6, 7159 HG_CACHE_SIZE = HG_CACHELINE_COUNT * HG_CACHELINE_SIZE; 7160 7161 const int ARRAY_SIZE = 4 * HG_CACHE_SIZE, 7162 ITERATIONS = 3; 7163 int64_t array[ARRAY_SIZE]; 7164 7165 int count = 0; 7166 Mutex count_mu; 7167 7168 void Worker() { 7169 const int N_MUTEXES = 5; 7170 Mutex mu[N_MUTEXES]; 7171 count_mu.Lock(); 7172 int myId = ++count; 7173 count_mu.Unlock(); 7174 7175 // all threads write to different memory locations, 7176 // so no synchronization mechanisms are needed 7177 int lower_bound = ARRAY_SIZE * (myId-1) / N_THREADS, 7178 upper_bound = ARRAY_SIZE * ( myId ) / N_THREADS; 7179 for (int j = 0; j < ITERATIONS; j++) 7180 for (int mutex_id = 0; mutex_id < N_MUTEXES; mutex_id++) { 7181 Mutex *m = & mu[mutex_id]; 7182 m->Lock(); 7183 for (int i = lower_bound + mutex_id, cnt = 0; 7184 i < upper_bound; 7185 i += HG_CACHELINE_SIZE / sizeof(array[0]), cnt++) { 7186 array[i] = i; // each array-write generates a cache miss 7187 } 7188 m->Unlock(); 7189 } 7190 } 7191 7192 void Run() { 7193 printf("test505: force massive CacheLineF fetch-wback\n"); 7194 MyThreadArray t(Worker, Worker); 7195 t.Start(); 7196 t.Join(); 7197 } 7198 7199 REGISTER_TEST2(Run, 505, PERFORMANCE | PRINT_STATS | EXCLUDE_FROM_ALL) 7200 #endif // WINE 7201 } // namespace test505 7202 7203 // test506: massive HB's using Barriers {{{1 7204 // HB cache miss is ~40% 7205 // segments consume 10x more memory than SSs 7206 // modification of test39 7207 namespace test506 { 7208 #ifndef NO_BARRIER 7209 // Same as test17 but uses Barrier class (pthread_barrier_t). 7210 int GLOB = 0; 7211 const int N_threads = 64, 7212 ITERATIONS = 1000; 7213 Barrier *barrier[ITERATIONS]; 7214 Mutex MU; 7215 7216 void Worker() { 7217 for (int i = 0; i < ITERATIONS; i++) { 7218 MU.Lock(); 7219 GLOB++; 7220 MU.Unlock(); 7221 barrier[i]->Block(); 7222 } 7223 } 7224 void Run() { 7225 printf("test506: massive HB's using Barriers\n"); 7226 for (int i = 0; i < ITERATIONS; i++) { 7227 barrier[i] = new Barrier(N_threads); 7228 } 7229 { 7230 ThreadPool pool(N_threads); 7231 pool.StartWorkers(); 7232 for (int i = 0; i < N_threads; i++) { 7233 pool.Add(NewCallback(Worker)); 7234 } 7235 } // all folks are joined here. 7236 CHECK(GLOB == N_threads * ITERATIONS); 7237 for (int i = 0; i < ITERATIONS; i++) { 7238 delete barrier[i]; 7239 } 7240 } 7241 REGISTER_TEST2(Run, 506, PERFORMANCE | PRINT_STATS | EXCLUDE_FROM_ALL); 7242 #endif // NO_BARRIER 7243 } // namespace test506 7244 7245 // test507: vgHelgrind_initIterAtFM/stackClear benchmark {{{1 7246 // vgHelgrind_initIterAtFM/stackClear consume ~8.5%/5.5% CPU 7247 namespace test507 { 7248 const int N_THREADS = 1, 7249 BUFFER_SIZE = 1, 7250 ITERATIONS = 1 << 20; 7251 7252 void Foo() { 7253 struct T { 7254 char temp; 7255 T() { 7256 ANNOTATE_RWLOCK_CREATE(&temp); 7257 } 7258 ~T() { 7259 ANNOTATE_RWLOCK_DESTROY(&temp); 7260 } 7261 } s[BUFFER_SIZE]; 7262 s->temp = '\0'; 7263 } 7264 7265 void Worker() { 7266 for (int j = 0; j < ITERATIONS; j++) { 7267 Foo(); 7268 } 7269 } 7270 7271 void Run() { 7272 printf("test507: vgHelgrind_initIterAtFM/stackClear benchmark\n"); 7273 { 7274 ThreadPool pool(N_THREADS); 7275 pool.StartWorkers(); 7276 for (int i = 0; i < N_THREADS; i++) { 7277 pool.Add(NewCallback(Worker)); 7278 } 7279 } // all folks are joined here. 7280 } 7281 REGISTER_TEST2(Run, 507, EXCLUDE_FROM_ALL); 7282 } // namespace test507 7283 7284 // test508: cmp_WordVecs_for_FM benchmark {{{1 7285 // 50+% of CPU consumption by cmp_WordVecs_for_FM 7286 namespace test508 { 7287 const int N_THREADS = 1, 7288 BUFFER_SIZE = 1 << 10, 7289 ITERATIONS = 1 << 9; 7290 7291 void Foo() { 7292 struct T { 7293 char temp; 7294 T() { 7295 ANNOTATE_RWLOCK_CREATE(&temp); 7296 } 7297 ~T() { 7298 ANNOTATE_RWLOCK_DESTROY(&temp); 7299 } 7300 } s[BUFFER_SIZE]; 7301 s->temp = '\0'; 7302 } 7303 7304 void Worker() { 7305 for (int j = 0; j < ITERATIONS; j++) { 7306 Foo(); 7307 } 7308 } 7309 7310 void Run() { 7311 printf("test508: cmp_WordVecs_for_FM benchmark\n"); 7312 { 7313 ThreadPool pool(N_THREADS); 7314 pool.StartWorkers(); 7315 for (int i = 0; i < N_THREADS; i++) { 7316 pool.Add(NewCallback(Worker)); 7317 } 7318 } // all folks are joined here. 7319 } 7320 REGISTER_TEST2(Run, 508, EXCLUDE_FROM_ALL); 7321 } // namespace test508 7322 7323 // test509: avl_find_node benchmark {{{1 7324 // 10+% of CPU consumption by avl_find_node 7325 namespace test509 { 7326 const int N_THREADS = 16, 7327 ITERATIONS = 1 << 8; 7328 7329 void Worker() { 7330 std::vector<Mutex*> mu_list; 7331 for (int i = 0; i < ITERATIONS; i++) { 7332 Mutex * mu = new Mutex(); 7333 mu_list.push_back(mu); 7334 mu->Lock(); 7335 } 7336 for (int i = ITERATIONS - 1; i >= 0; i--) { 7337 Mutex * mu = mu_list[i]; 7338 mu->Unlock(); 7339 delete mu; 7340 } 7341 } 7342 7343 void Run() { 7344 printf("test509: avl_find_node benchmark\n"); 7345 { 7346 ThreadPool pool(N_THREADS); 7347 pool.StartWorkers(); 7348 for (int i = 0; i < N_THREADS; i++) { 7349 pool.Add(NewCallback(Worker)); 7350 } 7351 } // all folks are joined here. 7352 } 7353 REGISTER_TEST2(Run, 509, EXCLUDE_FROM_ALL); 7354 } // namespace test509 7355 7356 // test510: SS-recycle test {{{1 7357 // this tests shows the case where only ~1% of SS are recycled 7358 namespace test510 { 7359 const int N_THREADS = 16, 7360 ITERATIONS = 1 << 10; 7361 int GLOB = 0; 7362 7363 void Worker() { 7364 usleep(100000); 7365 for (int i = 0; i < ITERATIONS; i++) { 7366 ANNOTATE_CONDVAR_SIGNAL((void*)0xDeadBeef); 7367 GLOB++; 7368 usleep(10); 7369 } 7370 } 7371 7372 void Run() { 7373 //ANNOTATE_BENIGN_RACE(&GLOB, "Test"); 7374 printf("test510: SS-recycle test\n"); 7375 { 7376 ThreadPool pool(N_THREADS); 7377 pool.StartWorkers(); 7378 for (int i = 0; i < N_THREADS; i++) { 7379 pool.Add(NewCallback(Worker)); 7380 } 7381 } // all folks are joined here. 7382 } 7383 REGISTER_TEST2(Run, 510, MEMORY_USAGE | PRINT_STATS | EXCLUDE_FROM_ALL); 7384 } // namespace test510 7385 7386 // test511: Segment refcounting test ('1' refcounting) {{{1 7387 namespace test511 { 7388 int GLOB = 0; 7389 7390 void Run () { 7391 for (int i = 0; i < 300; i++) { 7392 ANNOTATE_CONDVAR_SIGNAL(&GLOB); 7393 usleep(1000); 7394 GLOB++; 7395 ANNOTATE_CONDVAR_WAIT(&GLOB); 7396 } 7397 } 7398 REGISTER_TEST2(Run, 511, MEMORY_USAGE | PRINT_STATS | EXCLUDE_FROM_ALL); 7399 } // namespace test511 7400 7401 // test512: Access the same memory with big intersecting LockSets {{{1 7402 namespace test512 { 7403 const int N_MUTEXES = 128; 7404 const int DATA_SIZE = 1024; 7405 7406 Mutex mu[N_MUTEXES]; 7407 int GLOB[DATA_SIZE]; 7408 7409 void TP() { 7410 Mutex thread_mu; 7411 thread_mu.Lock(); 7412 for (int j = 0; j < 10; j++) { 7413 for (int m = 0; m < N_MUTEXES; m++) 7414 mu[m].Lock(); 7415 for (int i = 0; i < 3000; i++) { 7416 ANNOTATE_CONDVAR_SIGNAL(&GLOB); // Force new segment 7417 for (int k = 0; k < DATA_SIZE; k++) 7418 GLOB[k] = 42; 7419 } 7420 for (int m = 0; m < N_MUTEXES; m++) 7421 mu[m].Unlock(); 7422 } 7423 thread_mu.Unlock(); 7424 } 7425 7426 void Run() { 7427 MyThreadArray t(TP, TP); 7428 printf("test512: Access the same memory with big intersecting LockSets.\n"); 7429 7430 t.Start(); 7431 t.Join(); 7432 } 7433 7434 REGISTER_TEST2(Run, 512, EXCLUDE_FROM_ALL | PERFORMANCE) 7435 } // namespace test512 7436 7437 // test513: --fast-mode benchmark {{{1 7438 namespace test513 { 7439 7440 const int N_THREADS = 2, 7441 HG_CACHELINE_SIZE = 1 << 6, 7442 ARRAY_SIZE = HG_CACHELINE_SIZE * 512, 7443 MUTEX_ID_BITS = 8, 7444 MUTEX_ID_MASK = (1 << MUTEX_ID_BITS) - 1; 7445 7446 // Each thread has its own cacheline and tackles with it intensively 7447 const int ITERATIONS = 1024; 7448 int array[N_THREADS][ARRAY_SIZE]; 7449 7450 int count = 0; 7451 Mutex count_mu; 7452 Mutex mutex_arr[N_THREADS][MUTEX_ID_BITS]; 7453 7454 void Worker() { 7455 count_mu.Lock(); 7456 int myId = count++; 7457 count_mu.Unlock(); 7458 7459 // all threads write to different memory locations 7460 for (int j = 0; j < ITERATIONS; j++) { 7461 int mutex_mask = j & MUTEX_ID_BITS; 7462 for (int m = 0; m < MUTEX_ID_BITS; m++) 7463 if (mutex_mask & (1 << m)) 7464 mutex_arr[myId][m].Lock(); 7465 7466 for (int i = 0; i < ARRAY_SIZE; i++) { 7467 array[myId][i] = i; 7468 } 7469 7470 for (int m = 0; m < MUTEX_ID_BITS; m++) 7471 if (mutex_mask & (1 << m)) 7472 mutex_arr[myId][m].Unlock(); 7473 } 7474 } 7475 7476 void Run() { 7477 printf("test513: --fast-mode benchmark\n"); 7478 { 7479 ThreadPool pool(N_THREADS); 7480 pool.StartWorkers(); 7481 for (int i = 0; i < N_THREADS; i++) { 7482 pool.Add(NewCallback(Worker)); 7483 } 7484 } // all folks are joined here. 7485 } 7486 7487 REGISTER_TEST2(Run, 513, PERFORMANCE | PRINT_STATS | EXCLUDE_FROM_ALL) 7488 } // namespace test513 7489 7490 namespace ThreadChainTest { // {{{1 Reg test for thread creation 7491 void Thread1() { } 7492 void Thread2() { 7493 MyThread t(Thread1); 7494 t.Start(); 7495 t.Join(); 7496 } 7497 void Thread3() { 7498 MyThread t(Thread2); 7499 t.Start(); 7500 t.Join(); 7501 } 7502 void Thread4() { 7503 MyThread t(Thread3); 7504 t.Start(); 7505 t.Join(); 7506 } 7507 7508 TEST(RegTests, ThreadChainTest) { 7509 Thread4(); 7510 } 7511 7512 } // namespace 7513 7514 #ifndef ANDROID // GTest does not support ASSERT_DEBUG_DEATH. 7515 namespace SimpleDeathTest { // {{{1 Make sure that the tool handles death tests correctly 7516 #ifdef WIN32 7517 TEST(DeathTests, DISABLED_SimpleDeathTest) { 7518 #else 7519 TEST(DeathTests, SimpleDeathTest) { 7520 #endif 7521 ASSERT_DEBUG_DEATH(CHECK(false), ""); 7522 } 7523 } // namespace 7524 #endif 7525 7526 namespace IgnoreTests { // {{{1 Test how the tool works with indirect calls to fun_r functions 7527 int GLOB = 0; 7528 void (*f)() = NULL; 7529 7530 void NotIgnoredRacey() { 7531 GLOB++; 7532 } 7533 7534 void FunRFunction() { 7535 NotIgnoredRacey(); 7536 usleep(1); // avoid tail call elimination 7537 } 7538 7539 void DoDirectCall() { 7540 FunRFunction(); 7541 usleep(1); // avoid tail call elimination 7542 } 7543 7544 void DoIndirectCall() { 7545 (*f)(); 7546 usleep(1); // avoid tail call elimination 7547 } 7548 7549 TEST(IgnoreTests, DirectCallToFunR) { 7550 MyThreadArray mta(DoDirectCall, DoDirectCall); 7551 mta.Start(); 7552 mta.Join(); 7553 } 7554 7555 TEST(IgnoreTests, IndirectCallToFunR) { 7556 f = FunRFunction; 7557 MyThreadArray mta(DoIndirectCall, DoIndirectCall); 7558 mta.Start(); 7559 mta.Join(); 7560 } 7561 } // namespace 7562 7563 namespace MutexNotPhbTests { 7564 7565 int GLOB = 0; 7566 Mutex mu; 7567 StealthNotification n; 7568 7569 void SignalThread() { 7570 GLOB = 1; 7571 mu.Lock(); 7572 mu.Unlock(); 7573 n.signal(); 7574 } 7575 7576 void WaitThread() { 7577 n.wait(); 7578 mu.Lock(); 7579 mu.Unlock(); 7580 GLOB = 2; 7581 } 7582 7583 TEST(MutexNotPhbTests, MutexNotPhbTest) { 7584 ANNOTATE_NOT_HAPPENS_BEFORE_MUTEX(&mu); 7585 ANNOTATE_EXPECT_RACE(&GLOB, "MutexNotPhbTest. TP."); 7586 MyThreadArray mta(SignalThread, WaitThread); 7587 mta.Start(); 7588 mta.Join(); 7589 } 7590 } // namespace 7591 7592 namespace RaceVerifierTests_Simple { 7593 int GLOB = 0; 7594 7595 void Worker1() { 7596 GLOB = 1; 7597 } 7598 7599 void Worker2() { 7600 GLOB = 2; 7601 } 7602 7603 TEST(RaceVerifierTests, Simple) { 7604 ANNOTATE_EXPECT_RACE(&GLOB, "SimpleRace."); 7605 MyThreadArray t(Worker1, Worker2); 7606 t.Start(); 7607 t.Join(); 7608 } 7609 } // namespace 7610 7611 namespace RaceVerifierTests_Unverifiable { 7612 StealthNotification n; 7613 int GLOB = 0; 7614 7615 void Worker1() { 7616 if (!GLOB) 7617 GLOB = 1; 7618 n.signal(); 7619 } 7620 7621 void Worker2() { 7622 n.wait(); 7623 GLOB = 2; 7624 } 7625 7626 TEST(RaceVerifierTests, Unverifiable) { 7627 ANNOTATE_EXPECT_RACE(&GLOB, "SimpleRace. UNVERIFIABLE."); 7628 MyThreadArray t(Worker1, Worker2); 7629 t.Start(); 7630 t.Join(); 7631 } 7632 } // namespace 7633 7634 7635 namespace RaceVerifierTests_ManyRacesInOneTrace { 7636 StealthNotification n; 7637 int array[2]; 7638 7639 void Worker1() { 7640 array[0] = 1; 7641 array[1] = 2; 7642 } 7643 7644 void Worker2() { 7645 array[1] = array[0]; 7646 } 7647 7648 TEST(RaceVerifierTests, ManyRacesInOneTrace) { 7649 ANNOTATE_EXPECT_RACE(array + 0, "RaceVerifierTests_ManyRacesInOneTrace: race 1."); 7650 ANNOTATE_EXPECT_RACE(array + 1, "RaceVerifierTests_ManyRacesInOneTrace: race 2."); 7651 MyThreadArray t(Worker1, Worker2); 7652 t.Start(); 7653 t.Join(); 7654 } 7655 } // namespace 7656 7657 namespace PrintfTests_Simple { 7658 7659 void Worker1() { 7660 // This one is a printf() => vfprintf() 7661 fprintf(stderr, "Hello from a thread: %d\n", 2); 7662 // This one is a puts() 7663 fprintf(stderr, "Hello from a thread\n"); 7664 fprintf(stdout, "Hello from a thread: %d\n", 2); 7665 fprintf(stdout, "Hello from a thread\n"); 7666 } 7667 7668 TEST(PrintfTests, DISABLED_Simple) { 7669 MyThreadArray t(Worker1, Worker1); 7670 t.Start(); 7671 t.Join(); 7672 } 7673 } // namespace 7674 7675 namespace PrintfTests_RaceOnFwriteArgument { 7676 7677 char s[] = "abracadabra\n"; 7678 7679 void Worker1() { 7680 fwrite(s, 1, sizeof(s) - 1, stdout); 7681 } 7682 7683 void Worker2() { 7684 s[3] = 'z'; 7685 } 7686 7687 TEST(PrintfTests, RaceOnFwriteArgument) { 7688 ANNOTATE_TRACE_MEMORY(s + 3); 7689 ANNOTATE_EXPECT_RACE(s + 3, "PrintfTests_RaceOnFwriteArgument."); 7690 MyThreadArray t(Worker1, Worker2); 7691 t.Start(); 7692 t.Join(); 7693 } 7694 } // namespace 7695 7696 namespace PrintfTests_RaceOnPutsArgument { 7697 7698 char s[] = "abracadabra"; 7699 7700 void Worker1() { 7701 puts(s); 7702 } 7703 7704 void Worker2() { 7705 s[3] = 'z'; 7706 } 7707 7708 TEST(PrintfTests, RaceOnPutsArgument) { 7709 ANNOTATE_TRACE_MEMORY(s + 3); 7710 ANNOTATE_EXPECT_RACE(s + 3, "PrintfTests_RaceOnPutsArgument."); 7711 MyThreadArray t(Worker1, Worker2); 7712 t.Start(); 7713 t.Join(); 7714 } 7715 } // namespace 7716 7717 namespace PrintfTests_RaceOnPrintfArgument { 7718 7719 volatile char s[] = "abracadabra"; 7720 volatile char s2[] = "abracadabra"; 7721 7722 void Worker1() { 7723 fprintf(stdout, "printing a string: %s\n", s); 7724 fprintf(stderr, "printing a string: %s\n", s2); 7725 } 7726 7727 void Worker2() { 7728 s[3] = 'z'; 7729 s2[3] = 'z'; 7730 } 7731 7732 TEST(PrintfTests, DISABLED_RaceOnPrintfArgument) { 7733 ANNOTATE_EXPECT_RACE(s + 3, "PrintfTests_RaceOnPrintfArgument (stdout)."); 7734 ANNOTATE_EXPECT_RACE(s2 + 3, "PrintfTests_RaceOnPrintfArgument (stderr)."); 7735 MyThreadArray t(Worker1, Worker2); 7736 t.Start(); 7737 t.Join(); 7738 } 7739 } // namespace 7740 7741 // Apparently, %n is not supported in windows 7742 #ifndef WIN32 7743 namespace PrintfTests_RaceOnOutputArgument { 7744 7745 volatile char s[] = "abracadabra"; 7746 volatile int a = 0; 7747 7748 void Worker1() { 7749 fprintf(stdout, "printing a string: %s%n\n", s, &a); 7750 } 7751 7752 void Worker2() { 7753 fprintf(stdout, "the other thread have already printed %d characters\n", a); 7754 } 7755 7756 TEST(PrintfTests, DISABLED_RaceOnOutputArgument) { 7757 ANNOTATE_EXPECT_RACE(&a, "PrintfTests_RaceOnOutputArgument:int."); 7758 MyThreadArray t(Worker1, Worker2); 7759 t.Start(); 7760 t.Join(); 7761 } 7762 } // namespace 7763 #endif 7764 7765 namespace PrintfTests_Fflush { 7766 7767 volatile char s[] = "abracadabra"; 7768 volatile int a = 0; 7769 7770 void Worker1() { 7771 fflush(NULL); 7772 } 7773 7774 void Worker2() { 7775 fflush(NULL); 7776 } 7777 7778 TEST(PrintfTests, DISABLED_Fflush) { 7779 MyThreadArray t(Worker1, Worker2); 7780 t.Start(); 7781 t.Join(); 7782 } 7783 } // namespace 7784 7785 namespace BenignRaceTest { // {{{1 7786 const int kArrayLen = 97; 7787 char X[kArrayLen]; 7788 char *P; 7789 7790 int counter; 7791 7792 7793 void Worker() { 7794 (*P)++; 7795 ANNOTATE_HAPPENS_BEFORE(P); 7796 AtomicIncrement(&counter, -1); 7797 } 7798 7799 TEST(NegativeTests, BenignRaceTest) { 7800 ThreadPool pool1(1); 7801 ThreadPool pool2(1); 7802 ThreadPool pool3(1); 7803 pool1.StartWorkers(); 7804 pool2.StartWorkers(); 7805 pool3.StartWorkers(); 7806 7807 ANNOTATE_BENIGN_RACE(&counter, ""); 7808 const int kNIter = 1000; 7809 7810 for (int i = 0; i < kNIter; i++) { 7811 counter = 3; 7812 long len = (i % (kArrayLen / 3)) + 1; 7813 long beg = i % (kArrayLen - len); 7814 long end = beg + len; 7815 CHECK(beg < kArrayLen); 7816 CHECK(end <= kArrayLen); 7817 bool is_expected = i % 2; 7818 long pos = i % len; 7819 P = X + beg + pos; 7820 CHECK(P < X + kArrayLen); 7821 // printf("[%d] b=%ld e=%ld p=%ld is_expected=%d\n", 7822 // i, beg, end, pos, is_expected); 7823 ANNOTATE_NEW_MEMORY(X, kArrayLen); 7824 if (is_expected) { 7825 ANNOTATE_EXPECT_RACE(P, "expected race in BenignRaceTest"); 7826 } else { 7827 ANNOTATE_BENIGN_RACE_SIZED(X + beg, len, ""); 7828 } 7829 if ((i % (kNIter / 10)) == 0) { 7830 ANNOTATE_FLUSH_STATE(); 7831 } 7832 pool1.Add(NewCallback(Worker)); 7833 pool2.Add(NewCallback(Worker)); 7834 pool3.Add(NewCallback(Worker)); 7835 7836 while(AtomicIncrement(&counter, 0) != 0) 7837 usleep(1000); 7838 ANNOTATE_HAPPENS_AFTER(P); 7839 7840 ANNOTATE_FLUSH_EXPECTED_RACES(); 7841 } 7842 } 7843 } 7844 7845 namespace StressTests_FlushStateTest { // {{{1 7846 // Stress test for FlushState which happens in parallel with some work. 7847 const int N = 1000; 7848 int array[N]; 7849 7850 void Flusher() { 7851 for (int i = 0; i < 10; i++) { 7852 usleep(1000); 7853 ANNOTATE_FLUSH_STATE(); 7854 } 7855 } 7856 7857 void Write1(int i) { array[i]++; } 7858 void Write2(int i) { array[i]--; } 7859 int Read1(int i) { volatile int z = array[i]; return z; } 7860 int Read2(int i) { volatile int z = array[i]; return z; } 7861 7862 void Worker() { 7863 for (int iter = 0; iter < 10; iter++) { 7864 usleep(1000); 7865 for (int i = 0; i < N; i++) { 7866 Write1(i); 7867 Write2(i); 7868 Read1(i); 7869 Read2(i); 7870 } 7871 } 7872 } 7873 7874 TEST(StressTests, FlushStateTest) { 7875 MyThreadArray t(Flusher, Worker, Worker, Worker); 7876 t.Start(); 7877 t.Join(); 7878 } 7879 7880 } // namespace 7881 7882 // End {{{1 7883 // vim:shiftwidth=2:softtabstop=2:expandtab:foldmethod=marker 7884