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