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#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 55static CondVar CV; 56static 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// 70namespace test11 { 71int GLOB = 0; 72Mutex MU; 73void Worker() { 74 usleep(200000); 75 CHECK(GLOB != 777); 76 77 MU.Lock(); 78 COND++; 79 CV.Signal(); 80 MU.Unlock(); 81} 82 83void 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 100TEST(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 110namespace test75 { 111int GLOB = 0; 112sem_t sem[2]; 113 114void Poster() { 115 GLOB = 1; 116 sem_post(&sem[0]); 117 sem_post(&sem[1]); 118} 119 120void Waiter() { 121 sem_wait(&sem[0]); 122 CHECK(GLOB==1); 123} 124void TryWaiter() { 125 usleep(500000); 126 sem_trywait(&sem[1]); 127 CHECK(GLOB==1); 128} 129 130TEST(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 157namespace 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// 168int GLOB = 0; 169int fd_out = -1; 170int fd_in = -1; 171 172void 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 180void 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. 191TEST(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 218namespace NegativeTests_PthreadOnce { // {{{1 219int *GLOB = NULL; 220static pthread_once_t once = PTHREAD_ONCE_INIT; 221void Init() { 222 GLOB = new int; 223 ANNOTATE_TRACE_MEMORY(GLOB); 224 *GLOB = 777; 225} 226 227void Worker0() { 228 pthread_once(&once, Init); 229} 230void Worker1() { 231 usleep(100000); 232 pthread_once(&once, Init); 233 CHECK(*GLOB == 777); 234} 235 236 237TEST(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 247namespace test110 { 248int GLOB = 0; 249static int STATIC; 250 251char *STACK = 0; 252 253int *MALLOC; 254int *CALLOC; 255int *REALLOC; 256int *VALLOC; 257int *PVALLOC; 258int *MEMALIGN; 259int *POSIX_MEMALIGN; 260int *MMAP; 261 262int *NEW; 263int *NEW_ARR; 264 265void 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} 283TEST(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 340namespace test115 { 341int tid = 0; 342Mutex mu; 343const char *kSemName = "drt-test-sem"; 344 345int GLOB = 0; 346 347sem_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 356void 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. */ 381TEST(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 403namespace test122 { 404int VAR1 = 0; 405int VAR2 = 0; 406RWLock mu; 407 408void WriteWhileHoldingReaderLock(int *p) { 409 usleep(100000); 410 ReaderLockScoped lock(&mu); // Reader lock for writing. -- bug. 411 (*p)++; 412} 413 414void CorrectWrite(int *p) { 415 WriterLockScoped lock(&mu); 416 (*p)++; 417} 418 419void Thread1() { WriteWhileHoldingReaderLock(&VAR1); } 420void Thread2() { CorrectWrite(&VAR1); } 421void Thread3() { CorrectWrite(&VAR2); } 422void Thread4() { WriteWhileHoldingReaderLock(&VAR2); } 423 424 425TEST(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 443namespace 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 454const int n_threads = 3; 455RWLock mu; 456int GLOB[n_threads]; 457 458int adder_num; // updated atomically. 459 460void 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 469void 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 480TEST(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 505namespace MmapTest { // {{{1 506 507const int kMmapSize = 65536; 508 509void 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 518void Worker1() { 519 MyThreadArray t(SubWorker, SubWorker, SubWorker, SubWorker); 520 t.Start(); 521 t.Join(); 522} 523void Worker() { 524 MyThreadArray t(Worker1, Worker1, Worker1, Worker1); 525 t.Start(); 526 t.Join(); 527} 528 529TEST(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. 540namespace MmapRegressionTest { // {{{1 541 542const int kMmapSize = 65536; 543const uintptr_t kStartAddress = 0x10000; 544 545StealthNotification n1; 546 547void 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 555TEST(NegativeTests, MmapRegressionTest) { 556 MyThreadArray t(Worker, Worker); 557 t.Start(); 558 t.Join(); 559} 560 561} // namespace 562 563// test136. Unlock twice. {{{1 564namespace test136 { 565TEST(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 583namespace test141 { 584int GLOB1 = 0, 585 GLOB2 = 0; 586char *dir_name = NULL, 587 *filename = NULL; 588 589void 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 598void 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 608void 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 617void 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 627TEST(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 655namespace 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. 659int GLOB1 = 0; 660char padding1[64]; 661int GLOB2 = 0; 662char padding2[64]; 663int GLOB3 = 0; 664char padding3[64]; 665int GLOB4 = 0; 666RWLock MU; 667StealthNotification n1, n2, n3, n4, n5; 668 669void 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 682void 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 697void 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 713TEST(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 731namespace 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. 737pthread_barrier_t B; 738int L; 739 740// A1/A2: write L, then wait for barrier, then sleep 741void a1() { 742 L = 1; 743 pthread_barrier_wait(&B); 744 sleep(1); 745} 746void a2() { 747 pthread_barrier_wait(&B); 748 sleep(1); 749} 750 751// B1/B2: sleep, wait for barrier, then write L 752void b1() { 753 sleep(1); 754 pthread_barrier_wait(&B); 755 L = 1; 756} 757void b2() { 758 sleep(1); 759 pthread_barrier_wait(&B); 760} 761 762TEST(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 775int *G = NULL; 776 777void Worker() { 778 pthread_barrier_wait(&B); 779 (*G) = 1; 780 pthread_barrier_wait(&B); 781} 782 783TEST(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 801TEST(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 817namespace NegativeTests_PthreadCreateFailureTest { // {{{1 818#ifdef OS_linux 819void* ThreadRoutine(void *) { 820 return NULL; 821} 822 823TEST(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 834namespace Signals { // {{{1 835 836typedef void (*Sigaction)(int, siginfo_t *, void *); 837 838int GLOB = 0; 839 840static 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 859static 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 880void 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__ 893Mutex mu; 894 895void SignalHandlerWithMutex(int, siginfo_t*, void*) { 896 mu.Lock(); 897 GLOB++; 898 mu.Unlock(); 899} 900 901TEST(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. 914SpinLock sl; 915 916void SignalHandlerWithSpinlock(int, siginfo_t*, void*) { 917 sl.Lock(); 918 GLOB++; 919 sl.Unlock(); 920} 921 922TEST(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. 933static void WaitTestSignalHandler(int, siginfo_t*, void*) { 934 ANNOTATE_HAPPENS_AFTER((void*)0x1234); 935} 936 937void WaitTestWorker() { 938 for (int i = 0; i < 1000000; i++) { 939 ANNOTATE_HAPPENS_AFTER((void*)0x1234); 940 } 941} 942 943TEST(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 954pid_t child_pid = 0; 955 956void child_handler(int signum) { 957 if (signum == SIGCHLD && child_pid == 0) { 958 printf("Whoops, PID shouldn't be 0!\n"); 959 } 960} 961 962TEST(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 978TEST(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 985namespace NegativeTests_epoll { // {{{1 986#ifdef OS_linux 987int GLOB; 988 989// Currently, ThreadSanitizer should create hb arcs between 990// epoll_ctl and epoll_wait regardless of the parameters. Check that. 991 992void Worker1() { 993 GLOB++; 994 struct epoll_event event; 995 epoll_ctl(0, 0, 0, &event); 996} 997void Worker2() { 998 struct epoll_event event; 999 epoll_wait(0, &event, 0, 0); 1000 GLOB++; 1001} 1002 1003TEST(NegativeTests,epollTest) { 1004 MyThreadArray mta(Worker1, Worker2); 1005 mta.Start(); 1006 mta.Join(); 1007} 1008#endif // OS_linux 1009} 1010namespace NegativeTests_LockfTest { // {{{1 1011 1012class 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 1043int GLOB; 1044 1045void Worker() { 1046 mu.Lock(); 1047 GLOB++; 1048 mu.Unlock(); 1049} 1050 1051TEST(NegativeTests,DISABLED_LockfTest) { 1052 mu.set_fd(1 /* stdout */); 1053 MyThreadArray mta(Worker, Worker); 1054 mta.Start(); 1055 mta.Join(); 1056} 1057 1058} 1059namespace PositiveTests_LockThenNoLock { // {{{1 1060// Regression test for a bug fixed by r2312 1061int GLOB; 1062pthread_mutex_t mu; 1063StealthNotification n1, n2; 1064 1065void 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 1074void 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 1083TEST(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__ 1096namespace NegativeTests_PthreadCondWaitRelativeNp { // {{{1 1097int GLOB = 0; 1098pthread_mutex_t mu; 1099pthread_cond_t cv; 1100 1101void 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 1109void Waker() { 1110 pthread_mutex_lock(&mu); 1111 GLOB = 1; 1112 pthread_cond_signal(&cv); 1113 pthread_mutex_unlock(&mu); 1114} 1115 1116TEST(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 1128namespace PositiveTests_RWLockVsRWLockTest { // {{{1 1129// Test that reader lock/unlock do not create a hb-arc. 1130RWLock mu; 1131int GLOB; 1132StealthNotification n; 1133 1134void Thread1() { 1135 GLOB = 1; 1136 mu.ReaderLock(); 1137 mu.ReaderUnlock(); 1138 n.signal(); 1139} 1140 1141void Thread2() { 1142 n.wait(); 1143 mu.ReaderLock(); 1144 mu.ReaderUnlock(); 1145 GLOB = 1; 1146} 1147 1148TEST(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 1158namespace TSDTests { 1159// Test the support for libpthread TSD destructors. 1160pthread_key_t key; 1161const int kInitialValue = 0xfeedface; 1162int tsd_array[2]; 1163 1164void Destructor(void *ptr) { 1165 int *write = (int*) ptr; 1166 *write = kInitialValue; 1167} 1168 1169void 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 1177void Worker0() { DoWork(0); } 1178void Worker1() { DoWork(1); } 1179 1180TEST(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