1610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov/* 2610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov This file is part of Valgrind, a dynamic binary instrumentation 3610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov framework. 4610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 5610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov Copyright (C) 2008-2008 Google Inc 6610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov opensource@google.com 7610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 8610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov This program is free software; you can redistribute it and/or 9610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov modify it under the terms of the GNU General Public License as 10610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov published by the Free Software Foundation; either version 2 of the 11610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov License, or (at your option) any later version. 12610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 13610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov This program is distributed in the hope that it will be useful, but 14610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov WITHOUT ANY WARRANTY; without even the implied warranty of 15610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov General Public License for more details. 17610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 18610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov You should have received a copy of the GNU General Public License 19610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov along with this program; if not, write to the Free Software 20610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 21610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 02111-1307, USA. 22610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 23610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov The GNU General Public License is contained in the file COPYING. 24610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov*/ 25610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 26610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov/* Author: Konstantin Serebryany <opensource@google.com> 27610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov Author: Timur Iskhodzhanov <opensource@google.com> 28610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 29610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov This file contains a set of demonstration tests for ThreadSanitizer. 30610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov*/ 31610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 32610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#include <gtest/gtest.h> 33610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 34610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#include "test_utils.h" 35610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 36610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint main(int argc, char** argv) { 37610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov testing::InitGoogleTest(&argc, argv); 38610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov return RUN_ALL_TESTS(); 39610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov} 40610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 41610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace RaceReportDemoTest { // {{{1 42610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex mu1; // This Mutex guards var. 43610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex mu2; // This Mutex is not related to var. 44610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint var; // GUARDED_BY(mu1) 45610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 46610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Thread1() { // Runs in thread named 'test-thread-1'. 47610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov MutexLock lock(&mu1); // Correct Mutex. 48610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov var = 1; 49610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov} 50610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 51610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Thread2() { // Runs in thread named 'test-thread-2'. 52610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov MutexLock lock(&mu2); // Wrong Mutex. 53610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov var = 2; 54610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov} 55610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 56610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(DemoTests, RaceReportDemoTest) { 57610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov ANNOTATE_TRACE_MEMORY(&var); 58610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov var = 0; 59610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov MyThread t1(Thread1, NULL, "test-thread-1"); 60610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov MyThread t2(Thread2, NULL, "test-thread-2"); 61610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov t1.Start(); 62610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov t2.Start(); 63610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov t1.Join(); 64610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov t2.Join(); 65610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov} 66610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov} // namespace RaceReportDemoTest 67610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 68610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test302: Complex race which happens at least twice. {{{1 69610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test302 { 70610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// In this test we have many different accesses to GLOB and only one access 71610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// is not synchronized properly. 72610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint GLOB = 0; 73610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 74610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex MU1; 75610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex MU2; 76610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker() { 77610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov for(int i = 0; i < 100; i++) { 78610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov switch(i % 4) { 79610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov case 0: 80610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov // This read is protected correctly. 81610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov MU1.Lock(); CHECK(GLOB >= 0); MU1.Unlock(); 82610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov break; 83610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov case 1: 84610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov // Here we used the wrong lock! The reason of the race is here. 85610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov MU2.Lock(); CHECK(GLOB >= 0); MU2.Unlock(); 86610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov break; 87610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov case 2: 88610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov // This read is protected correctly. 89610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov MU1.Lock(); CHECK(GLOB >= 0); MU1.Unlock(); 90610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov break; 91610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov case 3: 92610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov // This write is protected correctly. 93610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov MU1.Lock(); GLOB++; MU1.Unlock(); 94610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov break; 95610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov } 96610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov // sleep a bit so that the threads interleave 97610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov // and the race happens at least twice. 98610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov usleep(100); 99610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov } 100610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov} 101610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 102610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(DemoTests, test302) { 103610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov printf("test302: Complex race that happens twice.\n"); 104610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov MyThread t1(Worker), t2(Worker); 105610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov t1.Start(); 106610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov t2.Start(); 107610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov t1.Join(); t2.Join(); 108610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov} 109610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov} // namespace test302 110610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 111610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 112610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test303: Need to trace the memory to understand the report. {{{1 113610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test303 { 114610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint GLOB = 0; 115610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 116610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex MU; 117610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker1() { CHECK(GLOB >= 0); } 118610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker2() { MU.Lock(); GLOB=1; MU.Unlock();} 119610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 120610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(DemoTests, test303) { 121610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov printf("test303: a race that needs annotations.\n"); 122610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov ANNOTATE_TRACE_MEMORY(&GLOB); 123610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov MyThreadArray t(Worker1, Worker2); 124610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov t.Start(); 125610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov t.Join(); 126610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov} 127610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov} // namespace test303 128610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 129610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 130610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 131610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test304: Can not trace the memory, since it is a library object. {{{1 132610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test304 { 133610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovstring *STR; 134610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex MU; 135610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 136610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker1() { 137610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov sleep(0); 138610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov ANNOTATE_CONDVAR_SIGNAL((void*)0xDEADBEAF); 139610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov MU.Lock(); CHECK(STR->length() >= 4); MU.Unlock(); 140610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov} 141610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker2() { 142610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov sleep(1); 143610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov ANNOTATE_CONDVAR_SIGNAL((void*)0xDEADBEAF); 144610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov CHECK(STR->length() >= 4); // Unprotected! 145610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov} 146610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker3() { 147610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov sleep(2); 148610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov ANNOTATE_CONDVAR_SIGNAL((void*)0xDEADBEAF); 149610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov MU.Lock(); CHECK(STR->length() >= 4); MU.Unlock(); 150610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov} 151610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker4() { 152610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov sleep(3); 153610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov ANNOTATE_CONDVAR_SIGNAL((void*)0xDEADBEAF); 154610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov MU.Lock(); *STR += " + a very very long string"; MU.Unlock(); 155610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov} 156610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 157610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(DemoTests, test304) { 158610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov STR = new string ("The String"); 159610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov printf("test304: a race where memory tracing does not work.\n"); 160610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov MyThreadArray t(Worker1, Worker2, Worker3, Worker4); 161610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov t.Start(); 162610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov t.Join(); 163610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 164610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov printf("%s\n", STR->c_str()); 165610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov delete STR; 166610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov} 167610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov} // namespace test304 168610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 169610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 170610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 171610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test305: A bit more tricky: two locks used inconsistenly. {{{1 172610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test305 { 173610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint GLOB = 0; 174610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 175610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// In this test GLOB is protected by MU1 and MU2, but inconsistently. 176610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// The TRACES observed by helgrind are: 177610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// TRACE[1]: Access{T2/S2 wr} -> new State{Mod; #LS=2; #SS=1; T2/S2} 178610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// TRACE[2]: Access{T4/S9 wr} -> new State{Mod; #LS=1; #SS=2; T2/S2, T4/S9} 179610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// TRACE[3]: Access{T5/S13 wr} -> new State{Mod; #LS=1; #SS=3; T2/S2, T4/S9, T5/S13} 180610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// TRACE[4]: Access{T6/S19 wr} -> new State{Mod; #LS=0; #SS=4; T2/S2, T4/S9, T5/S13, T6/S19} 181610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 182610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// The guilty access is either Worker2() or Worker4(), depending on 183610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// which mutex is supposed to protect GLOB. 184610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex MU1; 185610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex MU2; 186610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker1() { MU1.Lock(); MU2.Lock(); GLOB=1; MU2.Unlock(); MU1.Unlock(); } 187610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker2() { MU1.Lock(); GLOB=2; MU1.Unlock(); } 188610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker3() { MU1.Lock(); MU2.Lock(); GLOB=3; MU2.Unlock(); MU1.Unlock(); } 189610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker4() { MU2.Lock(); GLOB=4; MU2.Unlock(); } 190610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 191610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(DemoTests, test305) { 192610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov ANNOTATE_TRACE_MEMORY(&GLOB); 193610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov printf("test305: simple race.\n"); 194610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov MyThread t1(Worker1), t2(Worker2), t3(Worker3), t4(Worker4); 195610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov t1.Start(); usleep(100); 196610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov t2.Start(); usleep(100); 197610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov t3.Start(); usleep(100); 198610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov t4.Start(); usleep(100); 199610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov t1.Join(); t2.Join(); t3.Join(); t4.Join(); 200610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov} 201610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov} // namespace test305 202610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 203610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test306: Two locks are used to protect a var. {{{1 204610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test306 { 205610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint GLOB = 0; 206610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Thread1 and Thread2 access the var under two locks. 207610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Thread3 uses no locks. 208610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 209610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex MU1; 210610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex MU2; 211610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker1() { MU1.Lock(); MU2.Lock(); GLOB=1; MU2.Unlock(); MU1.Unlock(); } 212610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker2() { MU1.Lock(); MU2.Lock(); GLOB=3; MU2.Unlock(); MU1.Unlock(); } 213610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker3() { GLOB=4; } 214610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 215610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(DemoTests, test306) { 216610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov ANNOTATE_TRACE_MEMORY(&GLOB); 217610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov printf("test306: simple race.\n"); 218610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov MyThread t1(Worker1), t2(Worker2), t3(Worker3); 219610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov t1.Start(); usleep(100); 220610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov t2.Start(); usleep(100); 221610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov t3.Start(); usleep(100); 222610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov t1.Join(); t2.Join(); t3.Join(); 223610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov} 224610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov} // namespace test306 225610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 226610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test307: Simple race, code with control flow {{{1 227610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test307 { 228610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint *GLOB = 0; 229610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvolatile /*to fake the compiler*/ bool some_condition = true; 230610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 231610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 232610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid SomeFunc() { } 233610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 234610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint FunctionWithControlFlow() { 235610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov int unrelated_stuff = 0; 236610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov unrelated_stuff++; 237610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov SomeFunc(); // "--keep-history=1" will point somewhere here. 238610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov if (some_condition) { // Or here 239610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov if (some_condition) { 240610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov unrelated_stuff++; // Or here. 241610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov unrelated_stuff++; 242610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov (*GLOB)++; // "--keep-history=2" will point here (experimental). 243610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov } 244610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov } 245610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov usleep(100000); 246610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov return unrelated_stuff; 247610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov} 248610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 249610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker1() { FunctionWithControlFlow(); } 250610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker2() { Worker1(); } 251610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker3() { Worker2(); } 252610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker4() { Worker3(); } 253610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 254610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(DemoTests, test307) { 255610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov GLOB = new int; 256610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov *GLOB = 1; 257610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov printf("test307: simple race, code with control flow\n"); 258610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov MyThreadArray t1(Worker1, Worker2, Worker3, Worker4); 259610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov t1.Start(); 260610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov t1.Join(); 261610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov} 262610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov} // namespace test307 263610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 264610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test308: Example of double-checked-locking {{{1 265610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test308 { 266610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovstruct Foo { 267610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov int a; 268610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}; 269610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 270610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovstatic int is_inited = 0; 271610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovstatic Mutex lock; 272610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovstatic Foo *foo; 273610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 274610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid InitMe() { 275610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov if (!is_inited) { 276610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov lock.Lock(); 277610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov if (!is_inited) { 278610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov foo = new Foo; 279610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov foo->a = 42; 280610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov is_inited = 1; 281610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov } 282610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov lock.Unlock(); 283610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov } 284610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov} 285610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 286610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid UseMe() { 287610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov InitMe(); 288610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov CHECK(foo && foo->a == 42); 289610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov} 290610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 291610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker1() { UseMe(); } 292610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker2() { UseMe(); } 293610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker3() { UseMe(); } 294610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 295610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 296610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(DemoTests, test308) { 297610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov ANNOTATE_TRACE_MEMORY(&is_inited); 298610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov printf("test308: Example of double-checked-locking\n"); 299610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov MyThreadArray t1(Worker1, Worker2, Worker3); 300610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov t1.Start(); 301610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov t1.Join(); 302610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov} 303610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov} // namespace test308 304610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 305610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test309: Simple race on an STL object. {{{1 306610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test309 { 307610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovstring GLOB; 308610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 309610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker1() { 310610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov GLOB="Thread1"; 311610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov} 312610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker2() { 313610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov usleep(100000); 314610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov GLOB="Booooooooooo"; 315610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov} 316610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 317610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(DemoTests, test309) { 318610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov printf("test309: simple race on an STL object.\n"); 319610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov MyThread t1(Worker1), t2(Worker2); 320610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov t1.Start(); 321610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov t2.Start(); 322610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov t1.Join(); t2.Join(); 323610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov} 324610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov} // namespace test309 325610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 326610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test310: One more simple race. {{{1 327610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test310 { 328610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint *PTR = NULL; // GUARDED_BY(mu1) 329610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 330610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex mu1; // Protects PTR. 331610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex mu2; // Unrelated to PTR. 332610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex mu3; // Unrelated to PTR. 333610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 334610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Writer1() { 335610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov MutexLock lock3(&mu3); // This lock is unrelated to PTR. 336610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov MutexLock lock1(&mu1); // Protect PTR. 337610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov *PTR = 1; 338610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov} 339610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 340610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Writer2() { 341610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov MutexLock lock2(&mu2); // This lock is unrelated to PTR. 342610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov MutexLock lock1(&mu1); // Protect PTR. 343610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov int some_unrelated_stuff = 0; 344610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov if (some_unrelated_stuff == 0) 345610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov some_unrelated_stuff++; 346610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov *PTR = 2; 347610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov} 348610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 349610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 350610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Reader() { 351610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov MutexLock lock2(&mu2); // Oh, gosh, this is a wrong mutex! 352610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov CHECK(*PTR <= 2); 353610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov} 354610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 355610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Some functions to make the stack trace non-trivial. 356610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid DoWrite1() { Writer1(); } 357610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Thread1() { DoWrite1(); } 358610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 359610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid DoWrite2() { Writer2(); } 360610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Thread2() { DoWrite2(); } 361610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 362610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid DoRead() { Reader(); } 363610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Thread3() { DoRead(); } 364610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 365610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(DemoTests, test310) { 366610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov printf("test310: simple race.\n"); 367610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov PTR = new int; 368610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov ANNOTATE_TRACE_MEMORY(PTR); 369610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov *PTR = 0; 370610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov MyThread t1(Thread1, NULL, "writer1"), 371610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov t2(Thread2, NULL, "writer2"), 372610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov t3(Thread3, NULL, "buggy reader"); 373610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov t1.Start(); 374610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov t2.Start(); 375610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov usleep(100000); // Let the writers go first. 376610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov t3.Start(); 377610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 378610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov t1.Join(); 379610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov t2.Join(); 380610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov t3.Join(); 381610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov} 382610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov} // namespace test310 383610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 384610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test311: Yet another simple race. {{{1 385610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test311 { 386610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint *PTR = NULL; // GUARDED_BY(mu1) 387610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 388610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex mu1; // Protects PTR. 389610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex mu2; // Unrelated to PTR. 390610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex mu3; // Unrelated to PTR. 391610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 392610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid GoodWriter1() { // Runs in Thread1 393610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov MutexLock lock3(&mu3); // This lock is unrelated to PTR. 394610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov MutexLock lock1(&mu1); // Protect PTR. 395610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov *PTR = 1; 396610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov} 397610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 398610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid GoodWriter2() { // Runs in Thread2 399610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov MutexLock lock2(&mu2); // This lock is unrelated to PTR. 400610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov MutexLock lock1(&mu1); // Protect PTR. 401610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov *PTR = 2; 402610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov} 403610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 404610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid GoodReader() { // Runs in Thread3 405610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov MutexLock lock1(&mu1); // Protect PTR. 406610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov CHECK(*PTR >= 0); 407610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov} 408610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 409610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid BuggyWriter() { // Runs in Thread4 410610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov MutexLock lock2(&mu2); // Wrong mutex! 411610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov *PTR = 3; 412610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov} 413610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 414610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Some functions to make the stack trace non-trivial. 415610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid DoWrite1() { GoodWriter1(); } 416610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Thread1() { DoWrite1(); } 417610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 418610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid DoWrite2() { GoodWriter2(); } 419610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Thread2() { DoWrite2(); } 420610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 421610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid DoGoodRead() { GoodReader(); } 422610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Thread3() { DoGoodRead(); } 423610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 424610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid DoBadWrite() { BuggyWriter(); } 425610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Thread4() { DoBadWrite(); } 426610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 427610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(DemoTests, test311) { 428610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov printf("test311: simple race.\n"); 429610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov PTR = new int; 430610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov ANNOTATE_TRACE_MEMORY(PTR); 431610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov *PTR = 0; 432610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov MyThread t1(Thread1, NULL, "good writer1"), 433610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov t2(Thread2, NULL, "good writer2"), 434610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov t3(Thread3, NULL, "good reader"), 435610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov t4(Thread4, NULL, "buggy writer"); 436610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov t1.Start(); 437610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov t3.Start(); 438610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov // t2 goes after t3. This way a pure happens-before detector has no chance. 439610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov usleep(10000); 440610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov t2.Start(); 441610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov usleep(100000); // Let the good folks go first. 442610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov t4.Start(); 443610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 444610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov t1.Join(); 445610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov t2.Join(); 446610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov t3.Join(); 447610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov t4.Join(); 448610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov} 449610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov} // namespace test311 450610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 451610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test312: A test with a very deep stack. {{{1 452610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test312 { 453610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint GLOB = 0; 454610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid RaceyWrite() { GLOB++; } 455610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Func1() { RaceyWrite(); } 456610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Func2() { Func1(); } 457610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Func3() { Func2(); } 458610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Func4() { Func3(); } 459610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Func5() { Func4(); } 460610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Func6() { Func5(); } 461610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Func7() { Func6(); } 462610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Func8() { Func7(); } 463610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Func9() { Func8(); } 464610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Func10() { Func9(); } 465610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Func11() { Func10(); } 466610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Func12() { Func11(); } 467610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Func13() { Func12(); } 468610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Func14() { Func13(); } 469610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Func15() { Func14(); } 470610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Func16() { Func15(); } 471610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Func17() { Func16(); } 472610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Func18() { Func17(); } 473610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Func19() { Func18(); } 474610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker() { Func19(); } 475610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(DemoTests, test312) { 476610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov printf("test312: simple race with deep stack.\n"); 477610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov MyThreadArray t(Worker, Worker, Worker); 478610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov t.Start(); 479610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov t.Join(); 480610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov} 481610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov} // namespace test312 482610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 483610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test313 TP: test for thread graph output {{{1 484610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test313 { 485610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovBlockingCounter *blocking_counter; 486610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint GLOB = 0; 487610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 488610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Worker(N) will do 2^N increments of GLOB, each increment in a separate thread 489610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker(int depth) { 490610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov CHECK(depth >= 0); 491610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov if (depth > 0) { 492610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov ThreadPool pool(2); 493610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov pool.StartWorkers(); 494610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov pool.Add(NewCallback(Worker, depth-1)); 495610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov pool.Add(NewCallback(Worker, depth-1)); 496610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov } else { 497610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov GLOB++; // Race here 498610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov } 499610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov} 500610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(DemoTests, test313) { 501610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov printf("test313: positive\n"); 502610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov Worker(4); 503610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov printf("\tGLOB=%d\n", GLOB); 504610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov} 505610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov} // namespace test313 506610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 507610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test314: minimalistic test for race in vptr. {{{1 508610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test314 { 509610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Race on vptr. Will run A::F() or B::F() depending on the timing. 510610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovclass A { 511610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov public: 512610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov A() : done_(false) { } 513610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov virtual void F() { 514610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov printf ("A::F()\n"); 515610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov } 516610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov void Done() { 517610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov MutexLock lock(&mu_); 518610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov done_ = true; 519610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov } 520610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov virtual ~A() { 521610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov while (true) { 522610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov MutexLock lock(&mu_); 523610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov if (done_) break; 524610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov } 525610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov } 526610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov private: 527610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov Mutex mu_; 528610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov bool done_; 529610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}; 530610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 531610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovclass B : public A { 532610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov public: 533610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov virtual void F() { 534610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov printf ("B::F()\n"); 535610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov } 536610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}; 537610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 538610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovstatic A *a; 539610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 540610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Thread1() { 541610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov a->F(); 542610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov a->Done(); 543610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}; 544610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 545610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Thread2() { 546610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov delete a; 547610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov} 548610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(DemoTests, test314) { 549610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov printf("test314: race on vptr; May print A::F() or B::F().\n"); 550610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov { // Will print B::F() 551610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov a = new B; 552610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov MyThreadArray t(Thread1, Thread2); 553610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov t.Start(); 554610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov t.Join(); 555610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov } 556610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov { // Will print A::F() 557610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov a = new B; 558610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov MyThreadArray t(Thread2, Thread1); 559610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov t.Start(); 560610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov t.Join(); 561610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov } 562610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov} 563610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov} // namespace test314 564610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 565610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test315: demo for hybrid's false positive. {{{1 566610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test315 { 567610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint GLOB; 568610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex mu; 569610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint flag; 570610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 571610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Thread1() { 572610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov sleep(1); 573610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov mu.Lock(); 574610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov bool f = flag; 575610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov mu.Unlock(); 576610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov if (f) { 577610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov GLOB++; 578610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov } 579610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov} 580610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 581610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Thread2() { 582610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov GLOB++; 583610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov mu.Lock(); 584610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov flag = true; 585610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov mu.Unlock(); 586610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov} 587610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 588610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(DemoTests, test315) { 589610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov GLOB = 0; 590610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov printf("test315: false positive of the hybrid state machine\n"); 591610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov MyThreadArray t(Thread1, Thread2); 592610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov t.Start(); 593610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov t.Join(); 594610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov} 595610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov} // namespace test315 596