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