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