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