1 /* 2 This file is part of Valgrind, a dynamic binary instrumentation 3 framework. 4 5 Copyright (C) 2008-2008 Google Inc 6 opensource (at) google.com 7 8 This program is free software; you can redistribute it and/or 9 modify it under the terms of the GNU General Public License as 10 published by the Free Software Foundation; either version 2 of the 11 License, or (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, but 14 WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program; if not, write to the Free Software 20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 21 02111-1307, USA. 22 23 The GNU General Public License is contained in the file COPYING. 24 */ 25 26 /* Author: Konstantin Serebryany <opensource (at) google.com> 27 28 This file contains a set of unit tests for a data race detection tool. 29 30 These tests can be compiled with pthreads (default) or 31 with any other library that supports threads, locks, cond vars, etc. 32 33 */ 34 #ifdef WIN32 35 #error "Don't build this file on Windows!" 36 #endif 37 38 #include <fcntl.h> 39 #include <fenv.h> 40 #include <queue> 41 #include <signal.h> 42 #include <stdlib.h> 43 #include <string> 44 #include <vector> 45 #include <unistd.h> 46 47 #ifdef OS_linux 48 # include <sys/epoll.h> 49 #endif // OS_linux 50 51 #include "test_utils.h" 52 #include <gtest/gtest.h> 53 #include "gtest_fixture_injection.h" 54 55 static CondVar CV; 56 static int COND = 0; 57 58 // test11: FP. Synchronization via CondVar, 2 workers. {{{1 59 // This test is properly synchronized, but currently (Dec 2007) 60 // helgrind reports a false positive. 61 // 62 // Parent: Worker1, Worker2: 63 // 1. Start(workers) a. read(GLOB) 64 // 2. MU.Lock() b. MU.Lock() 65 // 3. while(COND != 2) /-------- c. CV.Signal() 66 // CV.Wait(&MU) <-------/ d. MU.Unlock() 67 // 4. MU.Unlock() 68 // 5. write(GLOB) 69 // 70 namespace test11 { 71 int GLOB = 0; 72 Mutex MU; 73 void Worker() { 74 usleep(200000); 75 CHECK(GLOB != 777); 76 77 MU.Lock(); 78 COND++; 79 CV.Signal(); 80 MU.Unlock(); 81 } 82 83 void Parent() { 84 COND = 0; 85 86 MyThreadArray t(Worker, Worker); 87 t.Start(); 88 89 MU.Lock(); 90 while(COND != 2) { 91 CV.Wait(&MU); 92 } 93 MU.Unlock(); 94 95 GLOB = 2; 96 97 t.Join(); 98 } 99 100 TEST(NegativeTests, test11) { 101 // ANNOTATE_EXPECT_RACE(&GLOB, "test11. FP. Fixed by MSMProp1."); 102 printf("test11: negative\n"); 103 Parent(); 104 printf("\tGLOB=%d\n", GLOB); 105 } 106 } // namespace test11 107 108 109 // test75: TN. Test for sem_post, sem_wait, sem_trywait. {{{1 110 namespace test75 { 111 int GLOB = 0; 112 sem_t sem[2]; 113 114 void Poster() { 115 GLOB = 1; 116 sem_post(&sem[0]); 117 sem_post(&sem[1]); 118 } 119 120 void Waiter() { 121 sem_wait(&sem[0]); 122 CHECK(GLOB==1); 123 } 124 void TryWaiter() { 125 usleep(500000); 126 sem_trywait(&sem[1]); 127 CHECK(GLOB==1); 128 } 129 130 TEST(NegativeTests, test75) { 131 #ifndef NO_UNNAMED_SEM 132 sem_init(&sem[0], 0, 0); 133 sem_init(&sem[1], 0, 0); 134 135 printf("test75: negative\n"); 136 { 137 MyThreadArray t(Poster, Waiter); 138 t.Start(); 139 t.Join(); 140 } 141 GLOB = 2; 142 { 143 MyThreadArray t(Poster, TryWaiter); 144 t.Start(); 145 t.Join(); 146 } 147 printf("\tGLOB=%d\n", GLOB); 148 149 sem_destroy(&sem[0]); 150 sem_destroy(&sem[1]); 151 #endif // NO_UNNAMED_SEM 152 } 153 } // namespace test75 154 155 156 // test98: Synchronization via read/write (or send/recv). {{{1 157 namespace test98 { 158 // The synchronization here is done by a pair of read/write calls 159 // that create a happens-before arc. Same may be done with send/recv. 160 // Such synchronization is quite unusual in real programs 161 // (why would one synchronizae via a file or socket?), but 162 // quite possible in unittests where one threads runs for producer 163 // and one for consumer. 164 // 165 // A race detector has to create a happens-before arcs for 166 // {read,send}->{write,recv} even if the file descriptors are different. 167 // 168 int GLOB = 0; 169 int fd_out = -1; 170 int fd_in = -1; 171 172 void Writer() { 173 usleep(1000); 174 GLOB = 1; 175 const char *str = "Hey there!\n"; 176 const int size = strlen(str) + 1; 177 CHECK(size == write(fd_out, str, size)); 178 } 179 180 void Reader() { 181 char buff[100]; 182 while (read(fd_in, buff, 100) == 0) 183 sleep(1); 184 printf("read: %s\n", buff); 185 GLOB = 2; 186 } 187 188 #ifndef __APPLE__ 189 // Tsan for Mac OS is missing the unlink() syscall handler. 190 // TODO(glider): add the syscall handler to Valgrind. 191 TEST(NegativeTests, test98) { 192 printf("test98: negative, synchronization via I/O\n"); 193 char in_name[100]; 194 char out_name[100]; 195 // we open two files, on for reading and one for writing, 196 // but the files are actually the same (symlinked). 197 sprintf(in_name, "/tmp/racecheck_unittest_in.%d", getpid()); 198 sprintf(out_name, "/tmp/racecheck_unittest_out.%d", getpid()); 199 fd_out = creat(out_name, O_WRONLY | S_IRWXU); 200 CHECK(0 == symlink(out_name, in_name)); 201 fd_in = open(in_name, 0, O_RDONLY); 202 CHECK(fd_out >= 0); 203 CHECK(fd_in >= 0); 204 MyThreadArray t(Writer, Reader); 205 t.Start(); 206 t.Join(); 207 printf("\tGLOB=%d\n", GLOB); 208 // cleanup 209 close(fd_in); 210 close(fd_out); 211 unlink(in_name); 212 unlink(out_name); 213 } 214 #endif // __APPLE__ 215 } // namespace test98 216 217 218 namespace NegativeTests_PthreadOnce { // {{{1 219 int *GLOB = NULL; 220 static pthread_once_t once = PTHREAD_ONCE_INIT; 221 void Init() { 222 GLOB = new int; 223 ANNOTATE_TRACE_MEMORY(GLOB); 224 *GLOB = 777; 225 } 226 227 void Worker0() { 228 pthread_once(&once, Init); 229 } 230 void Worker1() { 231 usleep(100000); 232 pthread_once(&once, Init); 233 CHECK(*GLOB == 777); 234 } 235 236 237 TEST(NegativeTests, PthreadOnceTest) { 238 MyThreadArray t(Worker0, Worker1, Worker1, Worker1); 239 t.Start(); 240 t.Join(); 241 printf("\tGLOB=%d\n", *GLOB); 242 } 243 } // namespace 244 245 246 // test110: TP. Simple races with stack, global and heap objects. {{{1 247 namespace test110 { 248 int GLOB = 0; 249 static int STATIC; 250 251 char *STACK = 0; 252 253 int *MALLOC; 254 int *CALLOC; 255 int *REALLOC; 256 int *VALLOC; 257 int *PVALLOC; 258 int *MEMALIGN; 259 int *POSIX_MEMALIGN; 260 int *MMAP; 261 262 int *NEW; 263 int *NEW_ARR; 264 265 void Worker() { 266 GLOB++; 267 STATIC++; 268 269 (*STACK)++; 270 271 (*MALLOC)++; 272 (*CALLOC)++; 273 (*REALLOC)++; 274 (*VALLOC)++; 275 (*PVALLOC)++; 276 (*MEMALIGN)++; 277 (*POSIX_MEMALIGN)++; 278 (*MMAP)++; 279 280 (*NEW)++; 281 (*NEW_ARR)++; 282 } 283 TEST(PositiveTests, test110) { 284 printf("test110: positive (race on a stack object)\n"); 285 286 char x = 0; 287 STACK = &x; 288 289 MALLOC = (int*)malloc(sizeof(int)); 290 CALLOC = (int*)calloc(1, sizeof(int)); 291 REALLOC = (int*)realloc(NULL, sizeof(int)); 292 VALLOC = (int*)valloc(sizeof(int)); 293 PVALLOC = (int*)valloc(sizeof(int)); // TODO: pvalloc breaks helgrind. 294 MEMALIGN = (int*)memalign(64, sizeof(int)); 295 CHECK(0 == posix_memalign((void**)&POSIX_MEMALIGN, 64, sizeof(int))); 296 MMAP = (int*)mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE, 297 MAP_PRIVATE | MAP_ANON, -1, 0); 298 299 NEW = new int; 300 NEW_ARR = new int[10]; 301 302 303 ANNOTATE_EXPECT_RACE(STACK, "real race on stack object"); 304 ANNOTATE_EXPECT_RACE(&GLOB, "real race on global object"); 305 ANNOTATE_EXPECT_RACE(&STATIC, "real race on a static global object"); 306 ANNOTATE_EXPECT_RACE(MALLOC, "real race on a malloc-ed object"); 307 ANNOTATE_EXPECT_RACE(CALLOC, "real race on a calloc-ed object"); 308 ANNOTATE_EXPECT_RACE(REALLOC, "real race on a realloc-ed object"); 309 ANNOTATE_EXPECT_RACE(VALLOC, "real race on a valloc-ed object"); 310 ANNOTATE_EXPECT_RACE(PVALLOC, "real race on a pvalloc-ed object"); 311 ANNOTATE_EXPECT_RACE(MEMALIGN, "real race on a memalign-ed object"); 312 ANNOTATE_EXPECT_RACE(POSIX_MEMALIGN, "real race on a posix_memalign-ed object"); 313 ANNOTATE_EXPECT_RACE(MMAP, "real race on a mmap-ed object"); 314 315 ANNOTATE_EXPECT_RACE(NEW, "real race on a new-ed object"); 316 ANNOTATE_EXPECT_RACE(NEW_ARR, "real race on a new[]-ed object"); 317 318 MyThreadArray t(Worker, Worker, Worker); 319 t.Start(); 320 t.Join(); 321 printf("\tSTACK=%d\n", *STACK); 322 CHECK(GLOB <= 3); 323 CHECK(STATIC <= 3); 324 325 free(MALLOC); 326 free(CALLOC); 327 free(REALLOC); 328 free(VALLOC); 329 free(PVALLOC); 330 free(MEMALIGN); 331 free(POSIX_MEMALIGN); 332 munmap(MMAP, sizeof(int)); 333 delete NEW; 334 delete [] NEW_ARR; 335 } 336 } // namespace test110 337 338 339 // test115: TN. sem_open. {{{1 340 namespace test115 { 341 int tid = 0; 342 Mutex mu; 343 const char *kSemName = "drt-test-sem"; 344 345 int GLOB = 0; 346 347 sem_t *DoSemOpen() { 348 // TODO: there is some race report inside sem_open 349 // for which suppressions do not work... (???) 350 ANNOTATE_IGNORE_WRITES_BEGIN(); 351 sem_t *sem = sem_open(kSemName, O_CREAT, 0600, 3); 352 ANNOTATE_IGNORE_WRITES_END(); 353 return sem; 354 } 355 356 void Worker() { 357 mu.Lock(); 358 int my_tid = tid++; 359 mu.Unlock(); 360 361 if (my_tid == 0) { 362 GLOB = 1; 363 } 364 365 // if the detector observes a happens-before arc between 366 // sem_open and sem_wait, it will be silent. 367 sem_t *sem = DoSemOpen(); 368 usleep(100000); 369 CHECK(sem != SEM_FAILED); 370 CHECK(sem_wait(sem) == 0); 371 372 if (my_tid > 0) { 373 CHECK(GLOB == 1); 374 } 375 } 376 377 #ifndef __APPLE__ 378 /* This test is disabled for Darwin because of the tricky implementation of 379 * sem_open on that platform: subsequent attempts to open an existing semafore 380 * create new ones. */ 381 TEST(NegativeTests, test115) { 382 printf("test115: stab (sem_open())\n"); 383 384 // just check that sem_open is not completely broken 385 sem_unlink(kSemName); 386 sem_t* sem = DoSemOpen(); 387 CHECK(sem != SEM_FAILED); 388 CHECK(sem_wait(sem) == 0); 389 sem_unlink(kSemName); 390 391 // check that sem_open and sem_wait create a happens-before arc. 392 MyThreadArray t(Worker, Worker, Worker); 393 t.Start(); 394 t.Join(); 395 // clean up 396 sem_unlink(kSemName); 397 } 398 #endif // __APPLE__ 399 } // namespace test115 400 401 402 // test122 TP: Simple test with RWLock {{{1 403 namespace test122 { 404 int VAR1 = 0; 405 int VAR2 = 0; 406 RWLock mu; 407 408 void WriteWhileHoldingReaderLock(int *p) { 409 usleep(100000); 410 ReaderLockScoped lock(&mu); // Reader lock for writing. -- bug. 411 (*p)++; 412 } 413 414 void CorrectWrite(int *p) { 415 WriterLockScoped lock(&mu); 416 (*p)++; 417 } 418 419 void Thread1() { WriteWhileHoldingReaderLock(&VAR1); } 420 void Thread2() { CorrectWrite(&VAR1); } 421 void Thread3() { CorrectWrite(&VAR2); } 422 void Thread4() { WriteWhileHoldingReaderLock(&VAR2); } 423 424 425 TEST(PositiveTests, test122) { 426 printf("test122: positive (rw-lock)\n"); 427 VAR1 = 0; 428 VAR2 = 0; 429 ANNOTATE_TRACE_MEMORY(&VAR1); 430 ANNOTATE_TRACE_MEMORY(&VAR2); 431 if (!Tsan_PureHappensBefore()) { 432 ANNOTATE_EXPECT_RACE_FOR_TSAN(&VAR1, "test122. TP. ReaderLock-ed while writing"); 433 ANNOTATE_EXPECT_RACE_FOR_TSAN(&VAR2, "test122. TP. ReaderLock-ed while writing"); 434 } 435 MyThreadArray t(Thread1, Thread2, Thread3, Thread4); 436 t.Start(); 437 t.Join(); 438 } 439 } // namespace test122 440 441 442 // test125 TN: Backwards lock (annotated). {{{1 443 namespace test125 { 444 // This test uses "Backwards mutex" locking protocol. 445 // We take a *reader* lock when writing to a per-thread data 446 // (GLOB[thread_num]) and we take a *writer* lock when we 447 // are reading from the entire array at once. 448 // 449 // Such locking protocol is not understood by ThreadSanitizer's 450 // hybrid state machine. So, you either have to use a pure-happens-before 451 // detector ("tsan --pure-happens-before") or apply pure happens-before mode 452 // to this particular lock by using ANNOTATE_PURE_HAPPENS_BEFORE_MUTEX(&mu). 453 454 const int n_threads = 3; 455 RWLock mu; 456 int GLOB[n_threads]; 457 458 int adder_num; // updated atomically. 459 460 void Adder() { 461 int my_num = AtomicIncrement(&adder_num, 1) - 1; 462 CHECK(my_num >= 0); 463 CHECK(my_num < n_threads); 464 465 ReaderLockScoped lock(&mu); 466 GLOB[my_num]++; 467 } 468 469 void Aggregator() { 470 int sum = 0; 471 { 472 WriterLockScoped lock(&mu); 473 for (int i = 0; i < n_threads; i++) { 474 sum += GLOB[i]; 475 } 476 } 477 printf("sum=%d\n", sum); 478 } 479 480 TEST(NegativeTests, test125) { 481 printf("test125: negative\n"); 482 483 ANNOTATE_PURE_HAPPENS_BEFORE_MUTEX(&mu); 484 485 // run Adders, then Aggregator 486 adder_num = 0; 487 { 488 MyThreadArray t(Adder, Adder, Adder, Aggregator); 489 t.Start(); 490 t.Join(); 491 } 492 493 // Run Aggregator first. 494 adder_num = 0; 495 { 496 MyThreadArray t(Aggregator, Adder, Adder, Adder); 497 t.Start(); 498 t.Join(); 499 } 500 501 } 502 } // namespace test125 503 504 505 namespace MmapTest { // {{{1 506 507 const int kMmapSize = 65536; 508 509 void SubWorker() { 510 for (int i = 0; i < 500; i++) { 511 int *ptr = (int*)mmap(NULL, kMmapSize, PROT_READ | PROT_WRITE, 512 MAP_PRIVATE | MAP_ANON, -1, 0); 513 *ptr = 42; 514 munmap(ptr, kMmapSize); 515 } 516 } 517 518 void Worker1() { 519 MyThreadArray t(SubWorker, SubWorker, SubWorker, SubWorker); 520 t.Start(); 521 t.Join(); 522 } 523 void Worker() { 524 MyThreadArray t(Worker1, Worker1, Worker1, Worker1); 525 t.Start(); 526 t.Join(); 527 } 528 529 TEST(NegativeTests, MmapTest) { 530 MyThreadArray t(Worker, Worker, Worker, Worker); 531 t.Start(); 532 t.Join(); 533 } 534 } // namespace 535 536 537 // A regression test for mmap/munmap handling in Pin. 538 // If the tool misses munmap() calls it may report a false positive if two 539 // threads map the same memory region. 540 namespace MmapRegressionTest { // {{{1 541 542 const int kMmapSize = 65536; 543 const uintptr_t kStartAddress = 0x10000; 544 545 StealthNotification n1; 546 547 void Worker() { 548 int *ptr = (int*)mmap((void*)kStartAddress, kMmapSize, 549 PROT_READ | PROT_WRITE, 550 MAP_PRIVATE | MAP_ANON, -1, 0); 551 *ptr = 42; 552 munmap(ptr, kMmapSize); 553 } 554 555 TEST(NegativeTests, MmapRegressionTest) { 556 MyThreadArray t(Worker, Worker); 557 t.Start(); 558 t.Join(); 559 } 560 561 } // namespace 562 563 // test136. Unlock twice. {{{1 564 namespace test136 { 565 TEST(LockTests, UnlockTwice) { 566 pthread_mutexattr_t attr; 567 CHECK(0 == pthread_mutexattr_init(&attr)); 568 CHECK(0 == pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK)); 569 570 pthread_mutex_t mu; 571 CHECK(0 == pthread_mutex_init(&mu, &attr)); 572 CHECK(0 == pthread_mutex_lock(&mu)); 573 CHECK(0 == pthread_mutex_unlock(&mu)); 574 int ret_unlock = pthread_mutex_unlock(&mu); // unlocking twice. 575 int ret_destroy = pthread_mutex_destroy(&mu); 576 printf(" pthread_mutex_unlock returned %d\n", ret_unlock); 577 printf(" pthread_mutex_destroy returned %d\n", ret_destroy); 578 } 579 } // namespace test136 580 581 582 // test141 FP. unlink/fopen, rmdir/opendir. {{{1 583 namespace test141 { 584 int GLOB1 = 0, 585 GLOB2 = 0; 586 char *dir_name = NULL, 587 *filename = NULL; 588 589 void Waker1() { 590 usleep(100000); 591 GLOB1 = 1; // Write 592 // unlink deletes a file 'filename' 593 // which exits spin-loop in Waiter1(). 594 printf(" Deleting file...\n"); 595 CHECK(unlink(filename) == 0); 596 } 597 598 void Waiter1() { 599 FILE *tmp; 600 while ((tmp = fopen(filename, "r")) != NULL) { 601 fclose(tmp); 602 usleep(10000); 603 } 604 printf(" ...file has been deleted\n"); 605 GLOB1 = 2; // Write 606 } 607 608 void Waker2() { 609 usleep(100000); 610 GLOB2 = 1; // Write 611 // rmdir deletes a directory 'dir_name' 612 // which exit spin-loop in Waker(). 613 printf(" Deleting directory...\n"); 614 CHECK(rmdir(dir_name) == 0); 615 } 616 617 void Waiter2() { 618 DIR *tmp; 619 while ((tmp = opendir(dir_name)) != NULL) { 620 closedir(tmp); 621 usleep(10000); 622 } 623 printf(" ...directory has been deleted\n"); 624 GLOB2 = 2; 625 } 626 627 TEST(NegativeTests, test141) { 628 printf("test141: FP. unlink/fopen, rmdir/opendir.\n"); 629 630 dir_name = strdup("/tmp/tsan-XXXXXX"); 631 CHECK(mkdtemp(dir_name) != 0); 632 633 filename = strdup((std::string() + dir_name + "/XXXXXX").c_str()); 634 const int fd = mkstemp(filename); 635 CHECK(fd >= 0); 636 close(fd); 637 638 MyThreadArray mta1(Waker1, Waiter1); 639 mta1.Start(); 640 mta1.Join(); 641 642 MyThreadArray mta2(Waker2, Waiter2); 643 mta2.Start(); 644 mta2.Join(); 645 646 free(filename); 647 filename = 0; 648 free(dir_name); 649 dir_name = 0; 650 } 651 } // namespace test141 652 653 654 // test146: TP. Unit test for RWLock::TryLock and RWLock::ReaderTryLock. {{{1 655 namespace test146 { 656 // Worker1 locks the globals for writing for a long time. 657 // Worker2 tries to write to globals twice: without a writer lock and with it. 658 // Worker3 tries to read from globals twice: without a reader lock and with it. 659 int GLOB1 = 0; 660 char padding1[64]; 661 int GLOB2 = 0; 662 char padding2[64]; 663 int GLOB3 = 0; 664 char padding3[64]; 665 int GLOB4 = 0; 666 RWLock MU; 667 StealthNotification n1, n2, n3, n4, n5; 668 669 void Worker1() { 670 MU.Lock(); 671 GLOB1 = 1; 672 GLOB2 = 1; 673 GLOB3 = 1; 674 GLOB4 = 1; 675 n1.signal(); 676 n2.wait(); 677 n3.wait(); 678 MU.Unlock(); 679 n4.signal(); 680 } 681 682 void Worker2() { 683 n1.wait(); 684 if (MU.TryLock()) CHECK(0); 685 else 686 GLOB1 = 2; 687 n2.signal(); 688 n5.wait(); 689 if (MU.TryLock()) { 690 GLOB2 = 2; 691 MU.Unlock(); 692 } else { 693 CHECK(0); 694 } 695 } 696 697 void Worker3() { 698 n1.wait(); 699 if (MU.ReaderTryLock()) CHECK(0); 700 else 701 printf("\treading GLOB3: %d\n", GLOB3); 702 n3.signal(); 703 n4.wait(); 704 if (MU.ReaderTryLock()) { 705 printf("\treading GLOB4: %d\n", GLOB4); 706 MU.ReaderUnlock(); 707 } else { 708 CHECK(0); 709 } 710 n5.signal(); 711 } 712 713 TEST(PositiveTests, test146) { 714 ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB1, "test146. TP: a data race on GLOB1."); 715 ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB3, "test146. TP: a data race on GLOB3."); 716 ANNOTATE_TRACE_MEMORY(&GLOB1); 717 ANNOTATE_TRACE_MEMORY(&GLOB2); 718 ANNOTATE_TRACE_MEMORY(&GLOB3); 719 ANNOTATE_TRACE_MEMORY(&GLOB4); 720 printf("test146: positive\n"); 721 MyThreadArray t(Worker1, Worker2, Worker3); 722 t.Start(); 723 t.Join(); 724 printf("\tGLOB1=%d\n", GLOB1); 725 printf("\tGLOB2=%d\n", GLOB2); 726 printf("\tGLOB3=%d\n", GLOB3); 727 printf("\tGLOB4=%d\n", GLOB4); 728 } 729 } // namespace test146 730 731 namespace PositiveTests_CyclicBarrierTest { // {{{1 732 #ifndef NO_BARRIER 733 // regression test for correct support of cyclic barrier. 734 // This test was suggested by Julian Seward. 735 // There is a race on L here between a1 and b1, 736 // but a naive support of barrier makes us miss this race. 737 pthread_barrier_t B; 738 int L; 739 740 // A1/A2: write L, then wait for barrier, then sleep 741 void a1() { 742 L = 1; 743 pthread_barrier_wait(&B); 744 sleep(1); 745 } 746 void a2() { 747 pthread_barrier_wait(&B); 748 sleep(1); 749 } 750 751 // B1/B2: sleep, wait for barrier, then write L 752 void b1() { 753 sleep(1); 754 pthread_barrier_wait(&B); 755 L = 1; 756 } 757 void b2() { 758 sleep(1); 759 pthread_barrier_wait(&B); 760 } 761 762 TEST(PositiveTests, CyclicBarrierTest) { 763 ANNOTATE_EXPECT_RACE_FOR_TSAN(&L, "real race, may be hidden" 764 " by incorrect implementation of barrier"); 765 pthread_barrier_init(&B, NULL, 3); 766 MyThreadArray t1(a1, a2, a2), 767 t2(b1, b2, b2); 768 t1.Start(); 769 t2.Start(); 770 t1.Join(); 771 t2.Join(); 772 } 773 774 775 int *G = NULL; 776 777 void Worker() { 778 pthread_barrier_wait(&B); 779 (*G) = 1; 780 pthread_barrier_wait(&B); 781 } 782 783 TEST(PositiveTests, CyclicBarrierTwoCallsTest) { 784 pthread_barrier_init(&B, NULL, 2); 785 G = new int(0); 786 ANNOTATE_TRACE_MEMORY(G); 787 ANNOTATE_EXPECT_RACE_FOR_TSAN(G, "real race, may be hidden" 788 " by incorrect implementation of barrier"); 789 MyThreadArray t1(Worker, Worker); 790 t1.Start(); 791 t1.Join(); 792 CHECK(*G == 1); 793 delete G; 794 } 795 796 797 798 #endif // NO_BARRIER 799 } // namespace 800 801 TEST(NegativeTests, Mmap84GTest) { // {{{1 802 #ifdef ARCH_amd64 803 #ifdef OS_linux 804 // test that we can mmap 84G and can do it fast. 805 size_t size = (1ULL << 32) * 21; // 21 * 4G 806 void *mem_ptr = mmap((void *) 0, 807 size, 808 PROT_EXEC | PROT_READ | PROT_WRITE, 809 MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE, 810 -1, 811 (off_t) 0); 812 printf("res=%p\n", mem_ptr); 813 #endif 814 #endif 815 } 816 817 namespace NegativeTests_PthreadCreateFailureTest { // {{{1 818 #ifdef OS_linux 819 void* ThreadRoutine(void *) { 820 return NULL; 821 } 822 823 TEST(NegativeTests, PthreadCreateFailureTest) { 824 pthread_attr_t attributes; 825 pthread_attr_init(&attributes); 826 pthread_attr_setstacksize(&attributes, -1); 827 pthread_t handle; 828 CHECK(pthread_create(&handle, &attributes, ThreadRoutine, NULL) != 0); 829 pthread_attr_destroy(&attributes); 830 } 831 #endif // OS_linux 832 } // namespace NegativeTests_PthreadCreateFailureTest 833 834 namespace Signals { // {{{1 835 836 typedef void (*Sigaction)(int, siginfo_t *, void *); 837 838 int GLOB = 0; 839 840 static void EnableSigprof(Sigaction SignalHandler) { 841 struct sigaction sa; 842 sa.sa_sigaction = SignalHandler; 843 sa.sa_flags = SA_RESTART | SA_SIGINFO; 844 sigemptyset(&sa.sa_mask); 845 if (sigaction(SIGPROF, &sa, NULL) != 0) { 846 perror("sigaction"); 847 abort(); 848 } 849 struct itimerval timer; 850 timer.it_interval.tv_sec = 0; 851 timer.it_interval.tv_usec = 1000000 / 10000; 852 timer.it_value = timer.it_interval; 853 if (setitimer(ITIMER_PROF, &timer, 0) != 0) { 854 perror("setitimer"); 855 abort(); 856 } 857 } 858 859 static void DisableSigprof() { 860 // Disable the profiling timer. 861 struct itimerval timer; 862 timer.it_interval.tv_sec = 0; 863 timer.it_interval.tv_usec = 0; 864 timer.it_value = timer.it_interval; 865 if (setitimer(ITIMER_PROF, &timer, 0) != 0) { 866 perror("setitimer"); 867 abort(); 868 } 869 // Ignore SIGPROFs from now on. 870 struct sigaction sa; 871 sa.sa_handler = SIG_IGN; 872 sa.sa_flags = SA_RESTART | SA_SIGINFO; 873 sigemptyset(&sa.sa_mask); 874 if (sigaction(SIGPROF, &sa, NULL) != 0) { 875 perror("sigaction"); 876 abort(); 877 } 878 } 879 880 void MallocTestWorker() { 881 for (int i = 0; i < 100000; i++) { 882 void *x = malloc((i % 64) + 1); 883 free (x); 884 } 885 } 886 887 // Regression test for 888 // http://code.google.com/p/data-race-test/issues/detail?id=13 . 889 // Make sure that locking events are handled in signal handlers. 890 // 891 // For some reason, invoking the signal handlers causes deadlocks on Mac OS. 892 #ifndef __APPLE__ 893 Mutex mu; 894 895 void SignalHandlerWithMutex(int, siginfo_t*, void*) { 896 mu.Lock(); 897 GLOB++; 898 mu.Unlock(); 899 } 900 901 TEST(Signals, SignalsAndMallocTestWithMutex) { 902 EnableSigprof(SignalHandlerWithMutex); 903 MyThreadArray t(MallocTestWorker, MallocTestWorker, MallocTestWorker); 904 t.Start(); 905 t.Join(); 906 printf("\tGLOB=%d\n", GLOB); 907 DisableSigprof(); 908 } 909 #endif 910 911 // Another regression test for 912 // http://code.google.com/p/data-race-test/issues/detail?id=13 . 913 // Make sure that locking events are handled in signal handlers. 914 SpinLock sl; 915 916 void SignalHandlerWithSpinlock(int, siginfo_t*, void*) { 917 sl.Lock(); 918 GLOB++; 919 sl.Unlock(); 920 } 921 922 TEST(Signals, DISABLED_SignalsAndMallocTestWithSpinlock) { 923 EnableSigprof(SignalHandlerWithSpinlock); 924 MyThreadArray t(MallocTestWorker, MallocTestWorker, MallocTestWorker); 925 t.Start(); 926 t.Join(); 927 printf("\tGLOB=%d\n", GLOB); 928 DisableSigprof(); 929 } 930 931 // Regression test for 932 // http://code.google.com/p/data-race-test/issues/detail?id=14. 933 static void WaitTestSignalHandler(int, siginfo_t*, void*) { 934 ANNOTATE_HAPPENS_AFTER((void*)0x1234); 935 } 936 937 void WaitTestWorker() { 938 for (int i = 0; i < 1000000; i++) { 939 ANNOTATE_HAPPENS_AFTER((void*)0x1234); 940 } 941 } 942 943 TEST(Signals, SignalsAndWaitTest) { 944 EnableSigprof(WaitTestSignalHandler); 945 MyThreadArray t(WaitTestWorker, WaitTestWorker, WaitTestWorker); 946 t.Start(); 947 t.Join(); 948 DisableSigprof(); 949 } 950 951 #ifndef __APPLE__ 952 // this test crashes on Mac in debug TSan build, see 953 // http://code.google.com/p/data-race-test/issues/detail?id=47 954 pid_t child_pid = 0; 955 956 void child_handler(int signum) { 957 if (signum == SIGCHLD && child_pid == 0) { 958 printf("Whoops, PID shouldn't be 0!\n"); 959 } 960 } 961 962 TEST(Signals, PositiveTests_RaceInSignal) { 963 // Currently the data race on child_pid can't be found, 964 // see http://code.google.com/p/data-race-test/issues/detail?id=46 965 //ANNOTATE_EXPECT_RACE(&child_pid, "Race on pid: fork vs signal handler"); 966 signal(SIGCHLD, child_handler); 967 child_pid = fork(); 968 if (child_pid == 0) { 969 // in child 970 exit(0); 971 } 972 wait(NULL); 973 } 974 #endif // __APPLE__ 975 976 } // namespace; 977 978 TEST(WeirdSizesTests, FegetenvTest) { 979 // http://code.google.com/p/data-race-test/issues/detail?id=36 980 fenv_t tmp; 981 if (fegetenv(&tmp) != 0) 982 FAIL() << "fegetenv failed"; 983 } 984 985 namespace NegativeTests_epoll { // {{{1 986 #ifdef OS_linux 987 int GLOB; 988 989 // Currently, ThreadSanitizer should create hb arcs between 990 // epoll_ctl and epoll_wait regardless of the parameters. Check that. 991 992 void Worker1() { 993 GLOB++; 994 struct epoll_event event; 995 epoll_ctl(0, 0, 0, &event); 996 } 997 void Worker2() { 998 struct epoll_event event; 999 epoll_wait(0, &event, 0, 0); 1000 GLOB++; 1001 } 1002 1003 TEST(NegativeTests,epollTest) { 1004 MyThreadArray mta(Worker1, Worker2); 1005 mta.Start(); 1006 mta.Join(); 1007 } 1008 #endif // OS_linux 1009 } 1010 namespace NegativeTests_LockfTest { // {{{1 1011 1012 class ShmMutex { 1013 public: 1014 ShmMutex() : fd_(-1) { } 1015 void set_fd(int fd) { 1016 CHECK(fd_ == -1); 1017 fd_ = fd; 1018 } 1019 void Lock() { 1020 LockOrUnlockInternal(true); 1021 } 1022 void Unlock() { 1023 LockOrUnlockInternal(false); 1024 } 1025 private: 1026 void LockOrUnlockInternal(bool lock) { 1027 CHECK(fd_ >= 0); 1028 while (lockf(fd_, lock ? F_LOCK : F_ULOCK, 0) < 0) { 1029 if (errno == EINTR) { 1030 continue; 1031 } else if (errno == ENOLCK) { 1032 usleep(5000); 1033 continue; 1034 } 1035 CHECK(0); 1036 } 1037 1038 } 1039 1040 int fd_; 1041 } mu; 1042 1043 int GLOB; 1044 1045 void Worker() { 1046 mu.Lock(); 1047 GLOB++; 1048 mu.Unlock(); 1049 } 1050 1051 TEST(NegativeTests,DISABLED_LockfTest) { 1052 mu.set_fd(1 /* stdout */); 1053 MyThreadArray mta(Worker, Worker); 1054 mta.Start(); 1055 mta.Join(); 1056 } 1057 1058 } 1059 namespace PositiveTests_LockThenNoLock { // {{{1 1060 // Regression test for a bug fixed by r2312 1061 int GLOB; 1062 pthread_mutex_t mu; 1063 StealthNotification n1, n2; 1064 1065 void Worker1() { 1066 pthread_mutex_lock(&mu); 1067 GLOB = 1; 1068 pthread_mutex_unlock(&mu); 1069 n1.signal(); 1070 n2.wait(); 1071 GLOB = 2; 1072 } 1073 1074 void Worker2() { 1075 pthread_mutex_lock(&mu); 1076 GLOB = 3; 1077 pthread_mutex_unlock(&mu); 1078 n2.signal(); 1079 n1.wait(); 1080 GLOB = 4; 1081 } 1082 1083 TEST(PositiveTests, LockThenNoLock) { 1084 pthread_mutex_init(&mu, NULL); 1085 ANNOTATE_TRACE_MEMORY(&GLOB); 1086 ANNOTATE_EXPECT_RACE(&GLOB, "race"); 1087 ANNOTATE_NOT_HAPPENS_BEFORE_MUTEX(&mu); 1088 MyThreadArray t(Worker1, Worker2); 1089 t.Start(); 1090 t.Join(); 1091 pthread_mutex_destroy(&mu); 1092 } 1093 } // namespace 1094 1095 #ifdef __APPLE__ 1096 namespace NegativeTests_PthreadCondWaitRelativeNp { // {{{1 1097 int GLOB = 0; 1098 pthread_mutex_t mu; 1099 pthread_cond_t cv; 1100 1101 void Waiter() { 1102 struct timespec tv = {1000, 1000}; 1103 pthread_mutex_lock(&mu); 1104 pthread_cond_timedwait_relative_np(&cv, &mu, &tv); 1105 GLOB = 2; 1106 pthread_mutex_unlock(&mu); 1107 } 1108 1109 void Waker() { 1110 pthread_mutex_lock(&mu); 1111 GLOB = 1; 1112 pthread_cond_signal(&cv); 1113 pthread_mutex_unlock(&mu); 1114 } 1115 1116 TEST(NegativeTests, PthreadCondWaitRelativeNpTest) { 1117 pthread_mutex_init(&mu, NULL); 1118 pthread_cond_init(&cv, NULL); 1119 MyThreadArray t(Waiter, Waker); 1120 t.Start(); 1121 t.Join(); 1122 pthread_mutex_destroy(&mu); 1123 pthread_cond_destroy(&cv); 1124 } 1125 } // namespace 1126 #endif // __APPLE__ 1127 1128 namespace PositiveTests_RWLockVsRWLockTest { // {{{1 1129 // Test that reader lock/unlock do not create a hb-arc. 1130 RWLock mu; 1131 int GLOB; 1132 StealthNotification n; 1133 1134 void Thread1() { 1135 GLOB = 1; 1136 mu.ReaderLock(); 1137 mu.ReaderUnlock(); 1138 n.signal(); 1139 } 1140 1141 void Thread2() { 1142 n.wait(); 1143 mu.ReaderLock(); 1144 mu.ReaderUnlock(); 1145 GLOB = 1; 1146 } 1147 1148 TEST(PositiveTests, RWLockVsRWLockTest) { 1149 ANNOTATE_PURE_HAPPENS_BEFORE_MUTEX(&mu); 1150 ANNOTATE_EXPECT_RACE(&GLOB, "rwunlock/rwlock is not a hb-arc"); 1151 MyThreadArray t(Thread1, Thread2); 1152 t.Start(); 1153 t.Join(); 1154 } 1155 1156 } // namespace 1157 1158 namespace TSDTests { 1159 // Test the support for libpthread TSD destructors. 1160 pthread_key_t key; 1161 const int kInitialValue = 0xfeedface; 1162 int tsd_array[2]; 1163 1164 void Destructor(void *ptr) { 1165 int *write = (int*) ptr; 1166 *write = kInitialValue; 1167 } 1168 1169 void DoWork(int index) { 1170 int *value = &(tsd_array[index]); 1171 *value = 42; 1172 pthread_setspecific(key, value); 1173 int *read = (int*) pthread_getspecific(key); 1174 CHECK(read == value); 1175 } 1176 1177 void Worker0() { DoWork(0); } 1178 void Worker1() { DoWork(1); } 1179 1180 TEST(TSDTests, TSDDestructorTest) { 1181 pthread_key_create(&key, Destructor); 1182 MyThreadArray t(Worker0, Worker1); 1183 t.Start(); 1184 t.Join(); 1185 for (int i = 0; i < 2; ++i) { 1186 CHECK(tsd_array[i] == kInitialValue); 1187 } 1188 } 1189 1190 } 1191 1192 // End {{{1 1193 // vim:shiftwidth=2:softtabstop=2:expandtab:foldmethod=marker 1194