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 Author: Timur Iskhodzhanov <opensource (at) google.com> 28 29 This file contains a set of demonstration tests for ThreadSanitizer. 30 */ 31 32 #include <gtest/gtest.h> 33 34 #include "test_utils.h" 35 36 int main(int argc, char** argv) { 37 testing::InitGoogleTest(&argc, argv); 38 return RUN_ALL_TESTS(); 39 } 40 41 namespace RaceReportDemoTest { // {{{1 42 Mutex mu1; // This Mutex guards var. 43 Mutex mu2; // This Mutex is not related to var. 44 int var; // GUARDED_BY(mu1) 45 46 void Thread1() { // Runs in thread named 'test-thread-1'. 47 MutexLock lock(&mu1); // Correct Mutex. 48 var = 1; 49 } 50 51 void Thread2() { // Runs in thread named 'test-thread-2'. 52 MutexLock lock(&mu2); // Wrong Mutex. 53 var = 2; 54 } 55 56 TEST(DemoTests, RaceReportDemoTest) { 57 ANNOTATE_TRACE_MEMORY(&var); 58 var = 0; 59 MyThread t1(Thread1, NULL, "test-thread-1"); 60 MyThread t2(Thread2, NULL, "test-thread-2"); 61 t1.Start(); 62 t2.Start(); 63 t1.Join(); 64 t2.Join(); 65 } 66 } // namespace RaceReportDemoTest 67 68 // test302: Complex race which happens at least twice. {{{1 69 namespace test302 { 70 // In this test we have many different accesses to GLOB and only one access 71 // is not synchronized properly. 72 int GLOB = 0; 73 74 Mutex MU1; 75 Mutex MU2; 76 void Worker() { 77 for(int i = 0; i < 100; i++) { 78 switch(i % 4) { 79 case 0: 80 // This read is protected correctly. 81 MU1.Lock(); CHECK(GLOB >= 0); MU1.Unlock(); 82 break; 83 case 1: 84 // Here we used the wrong lock! The reason of the race is here. 85 MU2.Lock(); CHECK(GLOB >= 0); MU2.Unlock(); 86 break; 87 case 2: 88 // This read is protected correctly. 89 MU1.Lock(); CHECK(GLOB >= 0); MU1.Unlock(); 90 break; 91 case 3: 92 // This write is protected correctly. 93 MU1.Lock(); GLOB++; MU1.Unlock(); 94 break; 95 } 96 // sleep a bit so that the threads interleave 97 // and the race happens at least twice. 98 usleep(100); 99 } 100 } 101 102 TEST(DemoTests, test302) { 103 printf("test302: Complex race that happens twice.\n"); 104 MyThread t1(Worker), t2(Worker); 105 t1.Start(); 106 t2.Start(); 107 t1.Join(); t2.Join(); 108 } 109 } // namespace test302 110 111 112 // test303: Need to trace the memory to understand the report. {{{1 113 namespace test303 { 114 int GLOB = 0; 115 116 Mutex MU; 117 void Worker1() { CHECK(GLOB >= 0); } 118 void Worker2() { MU.Lock(); GLOB=1; MU.Unlock();} 119 120 TEST(DemoTests, test303) { 121 printf("test303: a race that needs annotations.\n"); 122 ANNOTATE_TRACE_MEMORY(&GLOB); 123 MyThreadArray t(Worker1, Worker2); 124 t.Start(); 125 t.Join(); 126 } 127 } // namespace test303 128 129 130 131 // test304: Can not trace the memory, since it is a library object. {{{1 132 namespace test304 { 133 string *STR; 134 Mutex MU; 135 136 void Worker1() { 137 sleep(0); 138 ANNOTATE_CONDVAR_SIGNAL((void*)0xDEADBEAF); 139 MU.Lock(); CHECK(STR->length() >= 4); MU.Unlock(); 140 } 141 void Worker2() { 142 sleep(1); 143 ANNOTATE_CONDVAR_SIGNAL((void*)0xDEADBEAF); 144 CHECK(STR->length() >= 4); // Unprotected! 145 } 146 void Worker3() { 147 sleep(2); 148 ANNOTATE_CONDVAR_SIGNAL((void*)0xDEADBEAF); 149 MU.Lock(); CHECK(STR->length() >= 4); MU.Unlock(); 150 } 151 void Worker4() { 152 sleep(3); 153 ANNOTATE_CONDVAR_SIGNAL((void*)0xDEADBEAF); 154 MU.Lock(); *STR += " + a very very long string"; MU.Unlock(); 155 } 156 157 TEST(DemoTests, test304) { 158 STR = new string ("The String"); 159 printf("test304: a race where memory tracing does not work.\n"); 160 MyThreadArray t(Worker1, Worker2, Worker3, Worker4); 161 t.Start(); 162 t.Join(); 163 164 printf("%s\n", STR->c_str()); 165 delete STR; 166 } 167 } // namespace test304 168 169 170 171 // test305: A bit more tricky: two locks used inconsistenly. {{{1 172 namespace test305 { 173 int GLOB = 0; 174 175 // In this test GLOB is protected by MU1 and MU2, but inconsistently. 176 // The TRACES observed by helgrind are: 177 // TRACE[1]: Access{T2/S2 wr} -> new State{Mod; #LS=2; #SS=1; T2/S2} 178 // TRACE[2]: Access{T4/S9 wr} -> new State{Mod; #LS=1; #SS=2; T2/S2, T4/S9} 179 // TRACE[3]: Access{T5/S13 wr} -> new State{Mod; #LS=1; #SS=3; T2/S2, T4/S9, T5/S13} 180 // TRACE[4]: Access{T6/S19 wr} -> new State{Mod; #LS=0; #SS=4; T2/S2, T4/S9, T5/S13, T6/S19} 181 // 182 // The guilty access is either Worker2() or Worker4(), depending on 183 // which mutex is supposed to protect GLOB. 184 Mutex MU1; 185 Mutex MU2; 186 void Worker1() { MU1.Lock(); MU2.Lock(); GLOB=1; MU2.Unlock(); MU1.Unlock(); } 187 void Worker2() { MU1.Lock(); GLOB=2; MU1.Unlock(); } 188 void Worker3() { MU1.Lock(); MU2.Lock(); GLOB=3; MU2.Unlock(); MU1.Unlock(); } 189 void Worker4() { MU2.Lock(); GLOB=4; MU2.Unlock(); } 190 191 TEST(DemoTests, test305) { 192 ANNOTATE_TRACE_MEMORY(&GLOB); 193 printf("test305: simple race.\n"); 194 MyThread t1(Worker1), t2(Worker2), t3(Worker3), t4(Worker4); 195 t1.Start(); usleep(100); 196 t2.Start(); usleep(100); 197 t3.Start(); usleep(100); 198 t4.Start(); usleep(100); 199 t1.Join(); t2.Join(); t3.Join(); t4.Join(); 200 } 201 } // namespace test305 202 203 // test306: Two locks are used to protect a var. {{{1 204 namespace test306 { 205 int GLOB = 0; 206 // Thread1 and Thread2 access the var under two locks. 207 // Thread3 uses no locks. 208 209 Mutex MU1; 210 Mutex MU2; 211 void Worker1() { MU1.Lock(); MU2.Lock(); GLOB=1; MU2.Unlock(); MU1.Unlock(); } 212 void Worker2() { MU1.Lock(); MU2.Lock(); GLOB=3; MU2.Unlock(); MU1.Unlock(); } 213 void Worker3() { GLOB=4; } 214 215 TEST(DemoTests, test306) { 216 ANNOTATE_TRACE_MEMORY(&GLOB); 217 printf("test306: simple race.\n"); 218 MyThread t1(Worker1), t2(Worker2), t3(Worker3); 219 t1.Start(); usleep(100); 220 t2.Start(); usleep(100); 221 t3.Start(); usleep(100); 222 t1.Join(); t2.Join(); t3.Join(); 223 } 224 } // namespace test306 225 226 // test307: Simple race, code with control flow {{{1 227 namespace test307 { 228 int *GLOB = 0; 229 volatile /*to fake the compiler*/ bool some_condition = true; 230 231 232 void SomeFunc() { } 233 234 int FunctionWithControlFlow() { 235 int unrelated_stuff = 0; 236 unrelated_stuff++; 237 SomeFunc(); // "--keep-history=1" will point somewhere here. 238 if (some_condition) { // Or here 239 if (some_condition) { 240 unrelated_stuff++; // Or here. 241 unrelated_stuff++; 242 (*GLOB)++; // "--keep-history=2" will point here (experimental). 243 } 244 } 245 usleep(100000); 246 return unrelated_stuff; 247 } 248 249 void Worker1() { FunctionWithControlFlow(); } 250 void Worker2() { Worker1(); } 251 void Worker3() { Worker2(); } 252 void Worker4() { Worker3(); } 253 254 TEST(DemoTests, test307) { 255 GLOB = new int; 256 *GLOB = 1; 257 printf("test307: simple race, code with control flow\n"); 258 MyThreadArray t1(Worker1, Worker2, Worker3, Worker4); 259 t1.Start(); 260 t1.Join(); 261 } 262 } // namespace test307 263 264 // test308: Example of double-checked-locking {{{1 265 namespace test308 { 266 struct Foo { 267 int a; 268 }; 269 270 static int is_inited = 0; 271 static Mutex lock; 272 static Foo *foo; 273 274 void InitMe() { 275 if (!is_inited) { 276 lock.Lock(); 277 if (!is_inited) { 278 foo = new Foo; 279 foo->a = 42; 280 is_inited = 1; 281 } 282 lock.Unlock(); 283 } 284 } 285 286 void UseMe() { 287 InitMe(); 288 CHECK(foo && foo->a == 42); 289 } 290 291 void Worker1() { UseMe(); } 292 void Worker2() { UseMe(); } 293 void Worker3() { UseMe(); } 294 295 296 TEST(DemoTests, test308) { 297 ANNOTATE_TRACE_MEMORY(&is_inited); 298 printf("test308: Example of double-checked-locking\n"); 299 MyThreadArray t1(Worker1, Worker2, Worker3); 300 t1.Start(); 301 t1.Join(); 302 } 303 } // namespace test308 304 305 // test309: Simple race on an STL object. {{{1 306 namespace test309 { 307 string GLOB; 308 309 void Worker1() { 310 GLOB="Thread1"; 311 } 312 void Worker2() { 313 usleep(100000); 314 GLOB="Booooooooooo"; 315 } 316 317 TEST(DemoTests, test309) { 318 printf("test309: simple race on an STL object.\n"); 319 MyThread t1(Worker1), t2(Worker2); 320 t1.Start(); 321 t2.Start(); 322 t1.Join(); t2.Join(); 323 } 324 } // namespace test309 325 326 // test310: One more simple race. {{{1 327 namespace test310 { 328 int *PTR = NULL; // GUARDED_BY(mu1) 329 330 Mutex mu1; // Protects PTR. 331 Mutex mu2; // Unrelated to PTR. 332 Mutex mu3; // Unrelated to PTR. 333 334 void Writer1() { 335 MutexLock lock3(&mu3); // This lock is unrelated to PTR. 336 MutexLock lock1(&mu1); // Protect PTR. 337 *PTR = 1; 338 } 339 340 void Writer2() { 341 MutexLock lock2(&mu2); // This lock is unrelated to PTR. 342 MutexLock lock1(&mu1); // Protect PTR. 343 int some_unrelated_stuff = 0; 344 if (some_unrelated_stuff == 0) 345 some_unrelated_stuff++; 346 *PTR = 2; 347 } 348 349 350 void Reader() { 351 MutexLock lock2(&mu2); // Oh, gosh, this is a wrong mutex! 352 CHECK(*PTR <= 2); 353 } 354 355 // Some functions to make the stack trace non-trivial. 356 void DoWrite1() { Writer1(); } 357 void Thread1() { DoWrite1(); } 358 359 void DoWrite2() { Writer2(); } 360 void Thread2() { DoWrite2(); } 361 362 void DoRead() { Reader(); } 363 void Thread3() { DoRead(); } 364 365 TEST(DemoTests, test310) { 366 printf("test310: simple race.\n"); 367 PTR = new int; 368 ANNOTATE_TRACE_MEMORY(PTR); 369 *PTR = 0; 370 MyThread t1(Thread1, NULL, "writer1"), 371 t2(Thread2, NULL, "writer2"), 372 t3(Thread3, NULL, "buggy reader"); 373 t1.Start(); 374 t2.Start(); 375 usleep(100000); // Let the writers go first. 376 t3.Start(); 377 378 t1.Join(); 379 t2.Join(); 380 t3.Join(); 381 } 382 } // namespace test310 383 384 // test311: Yet another simple race. {{{1 385 namespace test311 { 386 int *PTR = NULL; // GUARDED_BY(mu1) 387 388 Mutex mu1; // Protects PTR. 389 Mutex mu2; // Unrelated to PTR. 390 Mutex mu3; // Unrelated to PTR. 391 392 void GoodWriter1() { // Runs in Thread1 393 MutexLock lock3(&mu3); // This lock is unrelated to PTR. 394 MutexLock lock1(&mu1); // Protect PTR. 395 *PTR = 1; 396 } 397 398 void GoodWriter2() { // Runs in Thread2 399 MutexLock lock2(&mu2); // This lock is unrelated to PTR. 400 MutexLock lock1(&mu1); // Protect PTR. 401 *PTR = 2; 402 } 403 404 void GoodReader() { // Runs in Thread3 405 MutexLock lock1(&mu1); // Protect PTR. 406 CHECK(*PTR >= 0); 407 } 408 409 void BuggyWriter() { // Runs in Thread4 410 MutexLock lock2(&mu2); // Wrong mutex! 411 *PTR = 3; 412 } 413 414 // Some functions to make the stack trace non-trivial. 415 void DoWrite1() { GoodWriter1(); } 416 void Thread1() { DoWrite1(); } 417 418 void DoWrite2() { GoodWriter2(); } 419 void Thread2() { DoWrite2(); } 420 421 void DoGoodRead() { GoodReader(); } 422 void Thread3() { DoGoodRead(); } 423 424 void DoBadWrite() { BuggyWriter(); } 425 void Thread4() { DoBadWrite(); } 426 427 TEST(DemoTests, test311) { 428 printf("test311: simple race.\n"); 429 PTR = new int; 430 ANNOTATE_TRACE_MEMORY(PTR); 431 *PTR = 0; 432 MyThread t1(Thread1, NULL, "good writer1"), 433 t2(Thread2, NULL, "good writer2"), 434 t3(Thread3, NULL, "good reader"), 435 t4(Thread4, NULL, "buggy writer"); 436 t1.Start(); 437 t3.Start(); 438 // t2 goes after t3. This way a pure happens-before detector has no chance. 439 usleep(10000); 440 t2.Start(); 441 usleep(100000); // Let the good folks go first. 442 t4.Start(); 443 444 t1.Join(); 445 t2.Join(); 446 t3.Join(); 447 t4.Join(); 448 } 449 } // namespace test311 450 451 // test312: A test with a very deep stack. {{{1 452 namespace test312 { 453 int GLOB = 0; 454 void RaceyWrite() { GLOB++; } 455 void Func1() { RaceyWrite(); } 456 void Func2() { Func1(); } 457 void Func3() { Func2(); } 458 void Func4() { Func3(); } 459 void Func5() { Func4(); } 460 void Func6() { Func5(); } 461 void Func7() { Func6(); } 462 void Func8() { Func7(); } 463 void Func9() { Func8(); } 464 void Func10() { Func9(); } 465 void Func11() { Func10(); } 466 void Func12() { Func11(); } 467 void Func13() { Func12(); } 468 void Func14() { Func13(); } 469 void Func15() { Func14(); } 470 void Func16() { Func15(); } 471 void Func17() { Func16(); } 472 void Func18() { Func17(); } 473 void Func19() { Func18(); } 474 void Worker() { Func19(); } 475 TEST(DemoTests, test312) { 476 printf("test312: simple race with deep stack.\n"); 477 MyThreadArray t(Worker, Worker, Worker); 478 t.Start(); 479 t.Join(); 480 } 481 } // namespace test312 482 483 // test313 TP: test for thread graph output {{{1 484 namespace test313 { 485 BlockingCounter *blocking_counter; 486 int GLOB = 0; 487 488 // Worker(N) will do 2^N increments of GLOB, each increment in a separate thread 489 void Worker(int depth) { 490 CHECK(depth >= 0); 491 if (depth > 0) { 492 ThreadPool pool(2); 493 pool.StartWorkers(); 494 pool.Add(NewCallback(Worker, depth-1)); 495 pool.Add(NewCallback(Worker, depth-1)); 496 } else { 497 GLOB++; // Race here 498 } 499 } 500 TEST(DemoTests, test313) { 501 printf("test313: positive\n"); 502 Worker(4); 503 printf("\tGLOB=%d\n", GLOB); 504 } 505 } // namespace test313 506 507 // test314: minimalistic test for race in vptr. {{{1 508 namespace test314 { 509 // Race on vptr. Will run A::F() or B::F() depending on the timing. 510 class A { 511 public: 512 A() : done_(false) { } 513 virtual void F() { 514 printf ("A::F()\n"); 515 } 516 void Done() { 517 MutexLock lock(&mu_); 518 done_ = true; 519 } 520 virtual ~A() { 521 while (true) { 522 MutexLock lock(&mu_); 523 if (done_) break; 524 } 525 } 526 private: 527 Mutex mu_; 528 bool done_; 529 }; 530 531 class B : public A { 532 public: 533 virtual void F() { 534 printf ("B::F()\n"); 535 } 536 }; 537 538 static A *a; 539 540 void Thread1() { 541 a->F(); 542 a->Done(); 543 }; 544 545 void Thread2() { 546 delete a; 547 } 548 TEST(DemoTests, test314) { 549 printf("test314: race on vptr; May print A::F() or B::F().\n"); 550 { // Will print B::F() 551 a = new B; 552 MyThreadArray t(Thread1, Thread2); 553 t.Start(); 554 t.Join(); 555 } 556 { // Will print A::F() 557 a = new B; 558 MyThreadArray t(Thread2, Thread1); 559 t.Start(); 560 t.Join(); 561 } 562 } 563 } // namespace test314 564 565 // test315: demo for hybrid's false positive. {{{1 566 namespace test315 { 567 int GLOB; 568 Mutex mu; 569 int flag; 570 571 void Thread1() { 572 sleep(1); 573 mu.Lock(); 574 bool f = flag; 575 mu.Unlock(); 576 if (f) { 577 GLOB++; 578 } 579 } 580 581 void Thread2() { 582 GLOB++; 583 mu.Lock(); 584 flag = true; 585 mu.Unlock(); 586 } 587 588 TEST(DemoTests, test315) { 589 GLOB = 0; 590 printf("test315: false positive of the hybrid state machine\n"); 591 MyThreadArray t(Thread1, Thread2); 592 t.Start(); 593 t.Join(); 594 } 595 } // namespace test315 596