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
28610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov This file contains a set of unit tests for a data race detection tool.
29610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
30610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov These tests can be compiled with pthreads (default) or
31610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov with any other library that supports threads, locks, cond vars, etc.
32610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
33610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov*/
34610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
35610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#include <fcntl.h>
36610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#include <signal.h>
37610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#include <stdlib.h>
38610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#include <string.h>
39610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
40610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#include <string>
41610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#include <queue>
42610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#include <vector>
43610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
44610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#include "old_test_suite.h"
45610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#include "test_utils.h"
46610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
47610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#include <gtest/gtest.h>
48610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#include "gtest_fixture_injection.h"
49610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
50610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// The tests are
51610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// - Stability tests (marked STAB)
52610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// - Performance tests (marked PERF)
53610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// - Feature tests
54610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//   - TN (true negative) : no race exists and the tool is silent.
55610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//   - TP (true positive) : a race exists and reported.
56610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//   - FN (false negative): a race exists but not reported.
57610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//   - FP (false positive): no race exists but the tool reports it.
58610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
59610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// The feature tests are marked according to the behavior of ThreadSanitizer.
60610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
61610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// TP and FP tests are annotated with ANNOTATE_EXPECT_RACE,
62610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// so, no error reports should be seen when running under ThreadSanitizer.
63610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
64610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// When some of the FP cases are fixed in helgrind we'll need
65610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// to update these tests.
66610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
67610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Each test resides in its own namespace.
68610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Namespaces are named test01, test02, ...
69610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Please, *DO NOT* change the logic of existing tests nor rename them.
70610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Create a new test instead.
71610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
72610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Some tests use sleep()/usleep().
73610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// This is not a synchronization, but a simple way to trigger
74610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// some specific behaviour of the race detector's scheduler.
75610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
76610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Globals and utilities used by several tests. {{{1
77610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovstatic CondVar CV;
78610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovstatic int     COND = 0;
79610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
80610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test00: {{{1
81610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test00 {
82610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
83610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
84610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test00: negative\n");
85610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB=%d\n", GLOB);
86610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
87610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST(Run, 00)
88610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test00
89610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
90610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
91610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test01: TP. Simple race (write vs write). {{{1
92610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test01 {
93610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
94610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
95610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker1() {
96610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 1;
97610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
98610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
99610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker2() {
100610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 2;
101610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
102610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
103610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
104610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test01. TP.");
105610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_TRACE_MEMORY(&GLOB);
106610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test01: positive\n");
107610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Worker1, Worker2);
108610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
109610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
110610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB=%d\n", GLOB);
111610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
112610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST(Run, 1);
113610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test01
114610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
115610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
116610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test02: TN. Synchronization via CondVar. {{{1
117610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test02 {
118610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
119610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Two write accesses to GLOB are synchronized because
120610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// the pair of CV.Signal() and CV.Wait() establish happens-before relation.
121610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
122610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Waiter:                      Waker:
123610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 1. COND = 0
124610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 2. Start(Waker)
125610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 3. MU.Lock()                 a. write(GLOB)
126610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                              b. MU.Lock()
127610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                              c. COND = 1
128610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                         /--- d. CV.Signal()
129610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//  4. while(COND)        /     e. MU.Unlock()
130610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//       CV.Wait(MU) <---/
131610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//  5. MU.Unlock()
132610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//  6. write(GLOB)
133610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex   MU;
134610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
135610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Waker() {
136610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(200000);  // Make sure the waiter blocks.
137610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 1;
138610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
139610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
140610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  COND = 1;
141610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CV.Signal();
142610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
143610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
144610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
145610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Waiter() {
146610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ThreadPool pool(1);
147610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  pool.StartWorkers();
148610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  COND = 0;
149610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  pool.Add(NewCallback(Waker));
150610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
151610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  while(COND != 1)
152610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    CV.Wait(&MU);
153610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
154610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 2;
155610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
156610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
157610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test02: negative\n");
158610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  Waiter();
159610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB=%d\n", GLOB);
160610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
161610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST(Run, 2);
162610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test02
163610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
164610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
165610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test03: TN. Synchronization via LockWhen, signaller gets there first. {{{1
166610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test03 {
167610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
168610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Two write accesses to GLOB are synchronized via conditional critical section.
169610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Note that LockWhen() happens first (we use sleep(1) to make sure)!
170610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
171610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Waiter:                           Waker:
172610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 1. COND = 0
173610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 2. Start(Waker)
174610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                                   a. write(GLOB)
175610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                                   b. MU.Lock()
176610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                                   c. COND = 1
177610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                              /--- d. MU.Unlock()
178610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 3. MU.LockWhen(COND==1) <---/
179610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 4. MU.Unlock()
180610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 5. write(GLOB)
181610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex   MU;
182610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
183610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Waker() {
184610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(100000);  // Make sure the waiter blocks.
185610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 1;
186610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
187610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
188610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  COND = 1; // We are done! Tell the Waiter.
189610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock(); // calls ANNOTATE_CONDVAR_SIGNAL;
190610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
191610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Waiter() {
192610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ThreadPool pool(1);
193610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  pool.StartWorkers();
194610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  COND = 0;
195610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  pool.Add(NewCallback(Waker));
196610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.LockWhen(Condition(&ArgIsOne, &COND));  // calls ANNOTATE_CONDVAR_WAIT
197610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();  // Waker is done!
198610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
199610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 2;
200610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
201610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
202610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test03: negative\n");
203610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  Waiter();
204610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB=%d\n", GLOB);
205610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
206610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST2(Run, 3, FEATURE|NEEDS_ANNOTATIONS);
207610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test03
208610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
209610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test04: TN. Synchronization via PCQ. {{{1
210610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test04 {
211610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
212610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovProducerConsumerQueue Q(INT_MAX);
213610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Two write accesses to GLOB are separated by PCQ Put/Get.
214610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
215610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Putter:                        Getter:
216610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 1. write(GLOB)
217610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 2. Q.Put() ---------\          .
218610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                      \-------> a. Q.Get()
219610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                                b. write(GLOB)
220610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
221610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
222610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Putter() {
223610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 1;
224610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  Q.Put(NULL);
225610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
226610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
227610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Getter() {
228610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  Q.Get();
229610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 2;
230610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
231610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
232610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
233610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test04: negative\n");
234610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Putter, Getter);
235610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
236610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
237610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB=%d\n", GLOB);
238610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
239610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST(Run, 4);
240610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test04
241610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
242610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
243610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test05: FP. Synchronization via CondVar, but waiter does not block. {{{1
244610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Since CondVar::Wait() is not called, we get a false positive.
245610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test05 {
246610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
247610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Two write accesses to GLOB are synchronized via CondVar.
248610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// But race detector can not see it.
249610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// See this for details:
250610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// http://www.valgrind.org/docs/manual/hg-manual.html#hg-manual.effective-use.
251610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
252610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Waiter:                                  Waker:
253610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 1. COND = 0
254610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 2. Start(Waker)
255610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 3. MU.Lock()                             a. write(GLOB)
256610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                                          b. MU.Lock()
257610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                                          c. COND = 1
258610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                                          d. CV.Signal()
259610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//  4. while(COND)                          e. MU.Unlock()
260610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//       CV.Wait(MU) <<< not called
261610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//  5. MU.Unlock()
262610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//  6. write(GLOB)
263610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex   MU;
264610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
265610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Waker() {
266610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 1;
267610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
268610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  COND = 1;
269610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CV.Signal();
270610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
271610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
272610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
273610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Waiter() {
274610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(100000);  // Make sure the signaller gets first.
275610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
276610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  while(COND != 1)
277610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    CV.Wait(&MU);
278610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
279610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 2;
280610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
281610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
282610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test05: unavoidable false positive\n");
283610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  COND = 0;
284610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  if (!Tsan_PureHappensBefore())
285610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test05. FP. Unavoidable in hybrid scheme.");
286610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Waker, Waiter);
287610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
288610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
289610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB=%d\n", GLOB);
290610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
291610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST(Run, 5);
292610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test05
293610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
294610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
295610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test06: TN. Synchronization via CondVar, but Waker gets there first.  {{{1
296610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test06 {
297610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
298610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Same as test05 but we annotated the Wait() loop.
299610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
300610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Waiter:                                            Waker:
301610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 1. COND = 0
302610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 2. Start(Waker)
303610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 3. MU.Lock()                                       a. write(GLOB)
304610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                                                    b. MU.Lock()
305610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                                                    c. COND = 1
306610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                                           /------- d. CV.Signal()
307610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//  4. while(COND)                          /         e. MU.Unlock()
308610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//       CV.Wait(MU) <<< not called        /
309610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//  6. ANNOTATE_CONDVAR_WAIT(CV, MU) <----/
310610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//  5. MU.Unlock()
311610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//  6. write(GLOB)
312610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
313610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex   MU;
314610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
315610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Waker() {
316610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 1;
317610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
318610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  COND = 1;
319610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CV.Signal();
320610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
321610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
322610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
323610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Waiter() {
324610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ThreadPool pool(1);
325610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  pool.StartWorkers();
326610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  COND = 0;
327610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  pool.Add(NewCallback(Waker));
328610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(500000);  // Make sure the signaller gets first.
329610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
330610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  while(COND != 1)
331610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    CV.Wait(&MU);
332610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_CONDVAR_LOCK_WAIT(&CV, &MU);
333610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
334610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
335610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 2;
336610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
337610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
338610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test06: negative\n");
339610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  Waiter();
340610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB=%d\n", GLOB);
341610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
342610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST2(Run, 6, FEATURE|NEEDS_ANNOTATIONS);
343610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test06
344610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
345610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
346610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test07: TN. Synchronization via LockWhen(), Signaller is observed first. {{{1
347610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test07 {
348610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
349610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovbool    COND = 0;
350610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Two write accesses to GLOB are synchronized via conditional critical section.
351610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// LockWhen() is observed after COND has been set (due to sleep).
352610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Unlock() calls ANNOTATE_CONDVAR_SIGNAL().
353610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
354610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Waiter:                           Signaller:
355610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 1. COND = 0
356610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 2. Start(Signaller)
357610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                                   a. write(GLOB)
358610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                                   b. MU.Lock()
359610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                                   c. COND = 1
360610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                              /--- d. MU.Unlock calls ANNOTATE_CONDVAR_SIGNAL
361610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 3. MU.LockWhen(COND==1) <---/
362610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 4. MU.Unlock()
363610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 5. write(GLOB)
364610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
365610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex   MU;
366610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Signaller() {
367610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 1;
368610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
369610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  COND = true; // We are done! Tell the Waiter.
370610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock(); // calls ANNOTATE_CONDVAR_SIGNAL;
371610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
372610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Waiter() {
373610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  COND = false;
374610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThread t(Signaller);
375610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
376610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(100000);  // Make sure the signaller gets there first.
377610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
378610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.LockWhen(Condition(&ArgIsTrue, &COND));  // calls ANNOTATE_CONDVAR_WAIT
379610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();  // Signaller is done!
380610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
381610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 2; // If LockWhen didn't catch the signal, a race may be reported here.
382610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
383610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
384610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
385610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test07: negative\n");
386610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  Waiter();
387610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB=%d\n", GLOB);
388610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
389610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST2(Run, 7, FEATURE|NEEDS_ANNOTATIONS);
390610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test07
391610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
392610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test08: TN. Synchronization via thread start/join. {{{1
393610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test08 {
394610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
395610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Three accesses to GLOB are separated by thread start/join.
396610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
397610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Parent:                        Worker:
398610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 1. write(GLOB)
399610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 2. Start(Worker) ------------>
400610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                                a. write(GLOB)
401610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 3. Join(Worker) <------------
402610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 4. write(GLOB)
403610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker() {
404610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 2;
405610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
406610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
407610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Parent() {
408610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThread t(Worker);
409610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 1;
410610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
411610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
412610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 3;
413610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
414610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
415610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test08: negative\n");
416610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  Parent();
417610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB=%d\n", GLOB);
418610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
419610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST(Run, 8);
420610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test08
421610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
422610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
423610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test09: TP. Simple race (read vs write). {{{1
424610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test09 {
425610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
426610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// A simple data race between writer and reader.
427610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Write happens after read (enforced by sleep).
428610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Usually, easily detectable by a race detector.
429610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Writer() {
430610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(100000);
431610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 3;
432610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
433610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Reader() {
434610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(GLOB != -777);
435610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
436610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
437610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
438610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_TRACE_MEMORY(&GLOB);
439610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test09. TP.");
440610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test09: positive\n");
441610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Writer, Reader);
442610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
443610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
444610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB=%d\n", GLOB);
445610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
446610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST(Run, 9);
447610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test09
448610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
449610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
450610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test10: FN. Simple race (write vs read). {{{1
451610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test10 {
452610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
453610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// A simple data race between writer and reader.
454610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Write happens before Read (enforced by sleep),
455610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// otherwise this test is the same as test09.
456610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
457610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Writer:                    Reader:
458610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 1. write(GLOB)             a. sleep(long enough so that GLOB
459610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                                is most likely initialized by Writer)
460610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                            b. read(GLOB)
461610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
462610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
463610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Eraser algorithm does not detect the race here,
464610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// see Section 2.2 of http://citeseer.ist.psu.edu/savage97eraser.html.
465610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
466610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Writer() {
467610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 3;
468610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
469610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Reader() {
470610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(100000);
471610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(GLOB != -777);
472610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
473610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
474610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
475610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test10. TP. FN in MSMHelgrind.");
476610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test10: positive\n");
477610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Writer, Reader);
478610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
479610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
480610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB=%d\n", GLOB);
481610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
482610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST(Run, 10);
483610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test10
484610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
485610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
486610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test12: FP. Synchronization via Mutex, then via PCQ. {{{1
487610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test12 {
488610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
489610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// This test is properly synchronized, but currently (Dec 2007)
490610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// helgrind reports a false positive.
491610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
492610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// First, we write to GLOB under MU, then we synchronize via PCQ,
493610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// which is essentially a semaphore.
494610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
495610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Putter:                       Getter:
496610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 1. MU.Lock()                  a. MU.Lock()
497610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 2. write(GLOB) <---- MU ----> b. write(GLOB)
498610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 3. MU.Unlock()                c. MU.Unlock()
499610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 4. Q.Put()   ---------------> d. Q.Get()
500610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                               e. write(GLOB)
501610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
502610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovProducerConsumerQueue Q(INT_MAX);
503610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex   MU;
504610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
505610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Putter() {
506610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
507610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB++;
508610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
509610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
510610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  Q.Put(NULL);
511610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
512610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
513610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Getter() {
514610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
515610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB++;
516610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
517610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
518610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  Q.Get();
519610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB++;
520610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
521610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
522610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
523610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//  ANNOTATE_EXPECT_RACE(&GLOB, "test12. FP. Fixed by MSMProp1.");
524610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test12: negative\n");
525610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Putter, Getter);
526610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
527610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
528610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB=%d\n", GLOB);
529610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
530610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST(Run, 12);
531610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test12
532610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
533610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
534610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test13: FP. Synchronization via Mutex, then via LockWhen. {{{1
535610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test13 {
536610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
537610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// This test is essentially the same as test12, but uses LockWhen
538610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// instead of PCQ.
539610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
540610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Waker:                                     Waiter:
541610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 1. MU.Lock()                               a. MU.Lock()
542610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 2. write(GLOB) <---------- MU ---------->  b. write(GLOB)
543610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 3. MU.Unlock()                             c. MU.Unlock()
544610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 4. MU.Lock()                               .
545610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 5. COND = 1                                .
546610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 6. ANNOTATE_CONDVAR_SIGNAL -------\        .
547610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 7. MU.Unlock()                     \       .
548610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                                     \----> d. MU.LockWhen(COND == 1)
549610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                                            e. MU.Unlock()
550610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                                            f. write(GLOB)
551610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex   MU;
552610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
553610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Waker() {
554610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
555610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB++;
556610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
557610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
558610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
559610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  COND = 1;
560610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_CONDVAR_SIGNAL(&MU);
561610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
562610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
563610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
564610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Waiter() {
565610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
566610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB++;
567610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
568610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
569610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.LockWhen(Condition(&ArgIsOne, &COND));
570610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
571610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB++;
572610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
573610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
574610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
575610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//  ANNOTATE_EXPECT_RACE(&GLOB, "test13. FP. Fixed by MSMProp1.");
576610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test13: negative\n");
577610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  COND = 0;
578610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
579610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Waker, Waiter);
580610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
581610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
582610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
583610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB=%d\n", GLOB);
584610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
585610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST2(Run, 13, FEATURE|NEEDS_ANNOTATIONS);
586610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test13
587610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
588610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
589610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test14: FP. Synchronization via PCQ, reads, 2 workers. {{{1
590610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test14 {
591610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
592610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// This test is properly synchronized, but currently (Dec 2007)
593610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// helgrind reports a false positive.
594610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
595610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// This test is similar to test11, but uses PCQ (semaphore).
596610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
597610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Putter2:                  Putter1:                     Getter:
598610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 1. read(GLOB)             a. read(GLOB)
599610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 2. Q2.Put() ----\         b. Q1.Put() -----\           .
600610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                  \                          \--------> A. Q1.Get()
601610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                   \----------------------------------> B. Q2.Get()
602610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                                                        C. write(GLOB)
603610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovProducerConsumerQueue Q1(INT_MAX), Q2(INT_MAX);
604610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
605610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Putter1() {
606610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(GLOB != 777);
607610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  Q1.Put(NULL);
608610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
609610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Putter2() {
610610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(GLOB != 777);
611610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  Q2.Put(NULL);
612610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
613610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Getter() {
614610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  Q1.Get();
615610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  Q2.Get();
616610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB++;
617610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
618610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
619610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//  ANNOTATE_EXPECT_RACE(&GLOB, "test14. FP. Fixed by MSMProp1.");
620610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test14: negative\n");
621610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Getter, Putter1, Putter2);
622610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
623610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
624610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB=%d\n", GLOB);
625610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
626610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST(Run, 14);
627610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test14
628610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
629610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
630610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test15: TN. Synchronization via LockWhen. One waker and 2 waiters. {{{1
631610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test15 {
632610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Waker:                                   Waiter1, Waiter2:
633610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 1. write(GLOB)
634610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 2. MU.Lock()
635610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 3. COND = 1
636610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 4. ANNOTATE_CONDVAR_SIGNAL ------------> a. MU.LockWhen(COND == 1)
637610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 5. MU.Unlock()                           b. MU.Unlock()
638610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                                          c. read(GLOB)
639610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
640610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
641610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex   MU;
642610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
643610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Waker() {
644610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 2;
645610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
646610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
647610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  COND = 1;
648610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_CONDVAR_SIGNAL(&MU);
649610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
650610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov};
651610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
652610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Waiter() {
653610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.LockWhen(Condition(&ArgIsOne, &COND));
654610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
655610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(GLOB != 777);
656610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
657610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
658610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
659610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
660610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  COND = 0;
661610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test15: negative\n");
662610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Waker, Waiter, Waiter);
663610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
664610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
665610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB=%d\n", GLOB);
666610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
667610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST(Run, 15);
668610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test15
669610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
670610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
671610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test16: FP. Barrier (emulated by CV), 2 threads. {{{1
672610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test16 {
673610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Worker1:                                     Worker2:
674610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 1. MU.Lock()                                 a. MU.Lock()
675610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 2. write(GLOB) <------------ MU ---------->  b. write(GLOB)
676610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 3. MU.Unlock()                               c. MU.Unlock()
677610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 4. MU2.Lock()                                d. MU2.Lock()
678610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 5. COND--                                    e. COND--
679610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 6. ANNOTATE_CONDVAR_SIGNAL(MU2) ---->V       .
680610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 7. MU2.Await(COND == 0) <------------+------ f. ANNOTATE_CONDVAR_SIGNAL(MU2)
681610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 8. MU2.Unlock()                      V-----> g. MU2.Await(COND == 0)
682610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 9. read(GLOB)                                h. MU2.Unlock()
683610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                                              i. read(GLOB)
684610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
685610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
686610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// TODO: This way we may create too many edges in happens-before graph.
687610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Arndt Mühlenfeld in his PhD (TODO: link) suggests creating special nodes in
688610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// happens-before graph to reduce the total number of edges.
689610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// See figure 3.14.
690610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
691610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
692610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
693610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex   MU;
694610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex MU2;
695610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
696610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker() {
697610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
698610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB++;
699610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
700610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
701610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU2.Lock();
702610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  COND--;
703610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_CONDVAR_SIGNAL(&MU2);
704610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU2.Await(Condition(&ArgIsZero, &COND));
705610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU2.Unlock();
706610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
707610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(GLOB == 2);
708610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
709610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
710610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
711610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//  ANNOTATE_EXPECT_RACE(&GLOB, "test16. FP. Fixed by MSMProp1 + Barrier support.");
712610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  COND = 2;
713610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test16: negative\n");
714610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Worker, Worker);
715610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
716610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
717610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB=%d\n", GLOB);
718610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
719610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST2(Run, 16, FEATURE|NEEDS_ANNOTATIONS);
720610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test16
721610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
722610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
723610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test17: FP. Barrier (emulated by CV), 3 threads. {{{1
724610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test17 {
725610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Same as test16, but with 3 threads.
726610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
727610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex   MU;
728610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex MU2;
729610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
730610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker() {
731610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
732610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB++;
733610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
734610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
735610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU2.Lock();
736610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  COND--;
737610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_CONDVAR_SIGNAL(&MU2);
738610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU2.Await(Condition(&ArgIsZero, &COND));
739610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU2.Unlock();
740610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
741610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(GLOB == 3);
742610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
743610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
744610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
745610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  COND = 3;
746610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test17: negative\n");
747610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Worker, Worker, Worker);
748610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
749610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
750610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB=%d\n", GLOB);
751610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
752610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST2(Run, 17, FEATURE|NEEDS_ANNOTATIONS);
753610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test17
754610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
755610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
756610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test18: TN. Synchronization via Await(), signaller gets there first. {{{1
757610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test18 {
758610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
759610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex   MU;
760610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Same as test03, but uses Mutex::Await() instead of Mutex::LockWhen().
761610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
762610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Waker() {
763610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(100000);  // Make sure the waiter blocks.
764610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 1;
765610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
766610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
767610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  COND = 1; // We are done! Tell the Waiter.
768610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock(); // calls ANNOTATE_CONDVAR_SIGNAL;
769610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
770610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Waiter() {
771610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ThreadPool pool(1);
772610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  pool.StartWorkers();
773610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  COND = 0;
774610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  pool.Add(NewCallback(Waker));
775610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
776610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
777610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Await(Condition(&ArgIsOne, &COND));  // calls ANNOTATE_CONDVAR_WAIT
778610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();  // Waker is done!
779610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
780610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 2;
781610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
782610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
783610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test18: negative\n");
784610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  Waiter();
785610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB=%d\n", GLOB);
786610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
787610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST2(Run, 18, FEATURE|NEEDS_ANNOTATIONS);
788610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test18
789610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
790610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test19: TN. Synchronization via AwaitWithTimeout(). {{{1
791610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test19 {
792610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
793610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Same as test18, but with AwaitWithTimeout. Do not timeout.
794610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex   MU;
795610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Waker() {
796610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(100000);  // Make sure the waiter blocks.
797610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 1;
798610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
799610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
800610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  COND = 1; // We are done! Tell the Waiter.
801610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock(); // calls ANNOTATE_CONDVAR_SIGNAL;
802610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
803610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Waiter() {
804610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ThreadPool pool(1);
805610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  pool.StartWorkers();
806610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  COND = 0;
807610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  pool.Add(NewCallback(Waker));
808610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
809610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
810610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(MU.AwaitWithTimeout(Condition(&ArgIsOne, &COND), INT_MAX));
811610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
812610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
813610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 2;
814610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
815610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
816610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test19: negative\n");
817610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  Waiter();
818610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB=%d\n", GLOB);
819610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
820610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST2(Run, 19, FEATURE|NEEDS_ANNOTATIONS);
821610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test19
822610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
823610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test20: TP. Incorrect synchronization via AwaitWhen(), timeout. {{{1
824610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test20 {
825610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
826610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex   MU;
827610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// True race. We timeout in AwaitWhen.
828610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Waker() {
829610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 1;
830610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(100 * 1000);
831610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
832610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Waiter() {
833610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
834610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(!MU.AwaitWithTimeout(Condition(&ArgIsOne, &COND), 100));
835610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
836610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
837610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 2;
838610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
839610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
840610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test20: positive\n");
841610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  COND = 0;
842610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test20. TP.");
843610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Waker, Waiter);
844610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
845610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
846610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB=%d\n", GLOB);
847610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
848610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST2(Run, 20, FEATURE|NEEDS_ANNOTATIONS);
849610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test20
850610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
851610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test21: TP. Incorrect synchronization via LockWhenWithTimeout(). {{{1
852610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test21 {
853610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
854610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// True race. We timeout in LockWhenWithTimeout().
855610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex   MU;
856610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Waker() {
857610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 1;
858610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(100 * 1000);
859610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
860610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Waiter() {
861610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(!MU.LockWhenWithTimeout(Condition(&ArgIsOne, &COND), 100));
862610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
863610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
864610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 2;
865610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
866610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
867610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test21: positive\n");
868610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  COND = 0;
869610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test21. TP.");
870610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Waker, Waiter);
871610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
872610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
873610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB=%d\n", GLOB);
874610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
875610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST2(Run, 21, FEATURE|NEEDS_ANNOTATIONS);
876610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test21
877610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
878610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test22: TP. Incorrect synchronization via CondVar::WaitWithTimeout(). {{{1
879610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test22 {
880610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
881610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex   MU;
882610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// True race. We timeout in CondVar::WaitWithTimeout().
883610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Waker() {
884610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 1;
885610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(100 * 1000);
886610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
887610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Waiter() {
888610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  int ms_left_to_wait = 100;
889610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  int deadline_ms = GetTimeInMs() + ms_left_to_wait;
890610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
891610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  while(COND != 1 && ms_left_to_wait > 0) {
892610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    CV.WaitWithTimeout(&MU, ms_left_to_wait);
893610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    ms_left_to_wait = deadline_ms - GetTimeInMs();
894610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
895610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
896610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
897610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 2;
898610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
899610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
900610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test22: positive\n");
901610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  COND = 0;
902610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test22. TP.");
903610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Waker, Waiter);
904610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
905610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
906610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB=%d\n", GLOB);
907610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
908610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST(Run, 22);
909610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test22
910610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
911610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test23: TN. TryLock, ReaderLock, ReaderTryLock. {{{1
912610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test23 {
913610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Correct synchronization with TryLock, Lock, ReaderTryLock, ReaderLock.
914610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
915610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex   MU;
916610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker_TryLock() {
917610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int i = 0; i < 20; i++) {
918610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    while (true) {
919610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      if (MU.TryLock()) {
920610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov        GLOB++;
921610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov        MU.Unlock();
922610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov        break;
923610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      }
924610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      usleep(1000);
925610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    }
926610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
927610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
928610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
929610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker_ReaderTryLock() {
930610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int i = 0; i < 20; i++) {
931610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    while (true) {
932610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      if (MU.ReaderTryLock()) {
933610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov        CHECK(GLOB != 777);
934610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov        MU.ReaderUnlock();
935610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov        break;
936610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      }
937610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      usleep(1000);
938610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    }
939610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
940610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
941610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
942610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker_ReaderLock() {
943610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int i = 0; i < 20; i++) {
944610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    MU.ReaderLock();
945610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    CHECK(GLOB != 777);
946610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    MU.ReaderUnlock();
947610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    usleep(1000);
948610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
949610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
950610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
951610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker_Lock() {
952610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int i = 0; i < 20; i++) {
953610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    MU.Lock();
954610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    GLOB++;
955610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    MU.Unlock();
956610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    usleep(1000);
957610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
958610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
959610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
960610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
961610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test23: negative\n");
962610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Worker_TryLock,
963610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov                  Worker_ReaderTryLock,
964610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov                  Worker_ReaderLock,
965610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov                  Worker_Lock
966610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov                  );
967610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
968610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
969610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB=%d\n", GLOB);
970610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
971610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST(Run, 23);
972610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test23
973610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
974610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test24: TN. Synchronization via ReaderLockWhen(). {{{1
975610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test24 {
976610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
977610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex   MU;
978610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Same as test03, but uses ReaderLockWhen().
979610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
980610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Waker() {
981610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(100000);  // Make sure the waiter blocks.
982610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 1;
983610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
984610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
985610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  COND = 1; // We are done! Tell the Waiter.
986610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock(); // calls ANNOTATE_CONDVAR_SIGNAL;
987610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
988610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Waiter() {
989610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ThreadPool pool(1);
990610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  pool.StartWorkers();
991610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  COND = 0;
992610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  pool.Add(NewCallback(Waker));
993610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.ReaderLockWhen(Condition(&ArgIsOne, &COND));
994610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.ReaderUnlock();
995610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
996610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 2;
997610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
998610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
999610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test24: negative\n");
1000610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  Waiter();
1001610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB=%d\n", GLOB);
1002610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
1003610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST2(Run, 24, FEATURE|NEEDS_ANNOTATIONS);
1004610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test24
1005610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1006610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test25: TN. Synchronization via ReaderLockWhenWithTimeout(). {{{1
1007610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test25 {
1008610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
1009610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex   MU;
1010610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Same as test24, but uses ReaderLockWhenWithTimeout().
1011610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// We do not timeout.
1012610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1013610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Waker() {
1014610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(100000);  // Make sure the waiter blocks.
1015610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 1;
1016610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1017610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
1018610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  COND = 1; // We are done! Tell the Waiter.
1019610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock(); // calls ANNOTATE_CONDVAR_SIGNAL;
1020610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
1021610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Waiter() {
1022610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ThreadPool pool(1);
1023610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  pool.StartWorkers();
1024610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  COND = 0;
1025610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  pool.Add(NewCallback(Waker));
1026610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(MU.ReaderLockWhenWithTimeout(Condition(&ArgIsOne, &COND), INT_MAX));
1027610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.ReaderUnlock();
1028610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1029610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 2;
1030610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
1031610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
1032610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test25: negative\n");
1033610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  Waiter();
1034610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB=%d\n", GLOB);
1035610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
1036610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST2(Run, 25, FEATURE|NEEDS_ANNOTATIONS);
1037610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test25
1038610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1039610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test26: TP. Incorrect synchronization via ReaderLockWhenWithTimeout(). {{{1
1040610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test26 {
1041610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
1042610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex   MU;
1043610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Same as test25, but we timeout and incorrectly assume happens-before.
1044610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1045610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Waker() {
1046610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 1;
1047610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(10000);
1048610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
1049610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Waiter() {
1050610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(!MU.ReaderLockWhenWithTimeout(Condition(&ArgIsOne, &COND), 100));
1051610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.ReaderUnlock();
1052610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1053610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 2;
1054610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
1055610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
1056610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test26: positive\n");
1057610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  COND = 0;
1058610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test26. TP");
1059610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Waker, Waiter);
1060610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
1061610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
1062610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB=%d\n", GLOB);
1063610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
1064610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST2(Run, 26, FEATURE|NEEDS_ANNOTATIONS);
1065610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test26
1066610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1067610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1068610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test27: TN. Simple synchronization via SpinLock. {{{1
1069610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test27 {
1070610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#ifndef NO_SPINLOCK
1071610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
1072610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovSpinLock MU;
1073610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker() {
1074610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
1075610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB++;
1076610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
1077610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(10000);
1078610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
1079610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1080610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
1081610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test27: negative\n");
1082610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Worker, Worker, Worker, Worker);
1083610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
1084610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
1085610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB=%d\n", GLOB);
1086610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
1087610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST2(Run, 27, FEATURE|NEEDS_ANNOTATIONS);
1088610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#endif
1089610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test27
1090610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1091610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1092610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test28: TN. Synchronization via Mutex, then PCQ. 3 threads {{{1
1093610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test28 {
1094610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Putter1:                       Getter:                         Putter2:
1095610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 1. MU.Lock()                                                   A. MU.Lock()
1096610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 2. write(GLOB)                                                 B. write(GLOB)
1097610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 3. MU.Unlock()                                                 C. MU.Unlock()
1098610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 4. Q.Put() ---------\                                 /------- D. Q.Put()
1099610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 5. MU.Lock()         \-------> a. Q.Get()            /         E. MU.Lock()
1100610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 6. read(GLOB)                  b. Q.Get() <---------/          F. read(GLOB)
1101610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 7. MU.Unlock()                   (sleep)                       G. MU.Unlock()
1102610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                                c. read(GLOB)
1103610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovProducerConsumerQueue Q(INT_MAX);
1104610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
1105610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex   MU;
1106610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1107610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Putter() {
1108610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
1109610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB++;
1110610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
1111610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1112610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  Q.Put(NULL);
1113610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1114610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
1115610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(GLOB != 777);
1116610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
1117610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
1118610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1119610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Getter() {
1120610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  Q.Get();
1121610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  Q.Get();
1122610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(100000);
1123610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(GLOB == 2);
1124610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
1125610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1126610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
1127610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test28: negative\n");
1128610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Getter, Putter, Putter);
1129610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
1130610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
1131610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB=%d\n", GLOB);
1132610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
1133610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST(Run, 28);
1134610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test28
1135610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1136610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1137610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test29: TN. Synchronization via Mutex, then PCQ. 4 threads. {{{1
1138610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test29 {
1139610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Similar to test28, but has two Getters and two PCQs.
1140610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovProducerConsumerQueue *Q1, *Q2;
1141610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex   MU;
1142610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
1143610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1144610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Putter(ProducerConsumerQueue *q) {
1145610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
1146610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB++;
1147610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
1148610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1149610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  q->Put(NULL);
1150610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  q->Put(NULL);
1151610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1152610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
1153610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(GLOB != 777);
1154610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
1155610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1156610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
1157610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1158610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Putter1() { Putter(Q1); }
1159610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Putter2() { Putter(Q2); }
1160610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1161610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Getter() {
1162610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  Q1->Get();
1163610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  Q2->Get();
1164610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(100000);
1165610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(GLOB == 2);
1166610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(48000); //  TODO: remove this when FP in test32 is fixed.
1167610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
1168610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1169610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
1170610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test29: negative\n");
1171610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  Q1 = new ProducerConsumerQueue(INT_MAX);
1172610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  Q2 = new ProducerConsumerQueue(INT_MAX);
1173610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Getter, Getter, Putter1, Putter2);
1174610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
1175610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
1176610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB=%d\n", GLOB);
1177610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  delete Q1;
1178610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  delete Q2;
1179610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
1180610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST(Run, 29);
1181610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test29
1182610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1183610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1184610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test30: TN. Synchronization via 'safe' race. Writer vs multiple Readers. {{{1
1185610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test30 {
1186610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// This test shows a very risky kind of synchronization which is very easy
1187610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// to get wrong. Actually, I am not sure I've got it right.
1188610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
1189610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Writer:                                 Reader1, Reader2, ..., ReaderN:
1190610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 1. write(GLOB[i]: i >= BOUNDARY)        a. n = BOUNDARY
1191610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 2. HAPPENS_BEFORE(BOUNDARY+1)  -------> b. HAPPENS_AFTER(n)
1192610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 3. BOUNDARY++;                          c. read(GLOB[i]: i < n)
1193610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
1194610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Here we have a 'safe' race on accesses to BOUNDARY and
1195610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// no actual races on accesses to GLOB[]:
1196610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Writer writes to GLOB[i] where i>=BOUNDARY and then increments BOUNDARY.
1197610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Readers read BOUNDARY and read GLOB[i] where i<BOUNDARY.
1198610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
1199610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// I am not completely sure that this scheme guaranties no race between
1200610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// accesses to GLOB since compilers and CPUs
1201610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// are free to rearrange memory operations.
1202610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// I am actually sure that this scheme is wrong unless we use
1203610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// some smart memory fencing...
1204610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1205610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1206610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovconst int N = 48;
1207610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovstatic int GLOB[N];
1208610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvolatile int BOUNDARY = 0;
1209610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1210610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Writer() {
1211610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int i = 0; i < N; i++) {
1212610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    CHECK(BOUNDARY == i);
1213610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    for (int j = i; j < N; j++) {
1214610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      GLOB[j] = j;
1215610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    }
1216610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    ANNOTATE_HAPPENS_BEFORE(reinterpret_cast<void*>(BOUNDARY+1));
1217610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    BOUNDARY++;
1218610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    usleep(1000);
1219610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
1220610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
1221610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1222610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Reader() {
1223610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  int n;
1224610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  do {
1225610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    n = BOUNDARY;
1226610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    if (n == 0) continue;
1227610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    ANNOTATE_HAPPENS_AFTER(reinterpret_cast<void*>(n));
1228610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    for (int i = 0; i < n; i++) {
1229610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      CHECK(GLOB[i] == i);
1230610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    }
1231610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    usleep(100);
1232610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  } while(n < N);
1233610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
1234610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1235610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
1236610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_EXPECT_RACE((void*)(&BOUNDARY), "test30. Sync via 'safe' race.");
1237610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test30: negative\n");
1238610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Writer, Reader, Reader, Reader);
1239610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
1240610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
1241610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB=%d\n", GLOB[N-1]);
1242610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
1243610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST2(Run, 30, FEATURE|NEEDS_ANNOTATIONS);
1244610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test30
1245610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1246610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1247610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test31: TN. Synchronization via 'safe' race. Writer vs Writer. {{{1
1248610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test31 {
1249610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// This test is similar to test30, but
1250610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// it has one Writer instead of mulitple Readers.
1251610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
1252610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Writer1:                                Writer2
1253610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 1. write(GLOB[i]: i >= BOUNDARY)        a. n = BOUNDARY
1254610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 2. HAPPENS_BEFORE(BOUNDARY+1)  -------> b. HAPPENS_AFTER(n)
1255610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 3. BOUNDARY++;                          c. write(GLOB[i]: i < n)
1256610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
1257610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1258610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovconst int N = 48;
1259610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovstatic int GLOB[N];
1260610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvolatile int BOUNDARY = 0;
1261610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1262610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Writer1() {
1263610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int i = 0; i < N; i++) {
1264610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    CHECK(BOUNDARY == i);
1265610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    for (int j = i; j < N; j++) {
1266610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      GLOB[j] = j;
1267610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    }
1268610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    ANNOTATE_HAPPENS_BEFORE(reinterpret_cast<void*>(BOUNDARY+1));
1269610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    BOUNDARY++;
1270610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    usleep(1000);
1271610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
1272610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
1273610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1274610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Writer2() {
1275610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  int n;
1276610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  do {
1277610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    n = BOUNDARY;
1278610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    if (n == 0) continue;
1279610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    ANNOTATE_HAPPENS_AFTER(reinterpret_cast<void*>(n));
1280610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    for (int i = 0; i < n; i++) {
1281610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      if(GLOB[i] == i) {
1282610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov        GLOB[i]++;
1283610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      }
1284610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    }
1285610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    usleep(100);
1286610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  } while(n < N);
1287610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
1288610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1289610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
1290610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_EXPECT_RACE((void*)(&BOUNDARY), "test31. Sync via 'safe' race.");
1291610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test31: negative\n");
1292610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Writer1, Writer2);
1293610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
1294610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
1295610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB=%d\n", GLOB[N-1]);
1296610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
1297610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST2(Run, 31, FEATURE|NEEDS_ANNOTATIONS);
1298610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test31
1299610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1300610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1301610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test32: FP. Synchronization via thread create/join. W/R. {{{1
1302610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test32 {
1303610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// This test is well synchronized but helgrind 3.3.0 reports a race.
1304610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
1305610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Parent:                   Writer:               Reader:
1306610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 1. Start(Reader) -----------------------\       .
1307610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                                          \      .
1308610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 2. Start(Writer) ---\                     \     .
1309610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                      \---> a. MU.Lock()    \--> A. sleep(long enough)
1310610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                            b. write(GLOB)
1311610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                      /---- c. MU.Unlock()
1312610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 3. Join(Writer) <---/
1313610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                                                 B. MU.Lock()
1314610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                                                 C. read(GLOB)
1315610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                                   /------------ D. MU.Unlock()
1316610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 4. Join(Reader) <----------------/
1317610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 5. write(GLOB)
1318610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
1319610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
1320610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// The call to sleep() in Reader is not part of synchronization,
1321610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// it is required to trigger the false positive in helgrind 3.3.0.
1322610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
1323610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
1324610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex   MU;
1325610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1326610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Writer() {
1327610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
1328610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 1;
1329610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
1330610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
1331610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1332610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Reader() {
1333610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(480000);
1334610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
1335610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(GLOB != 777);
1336610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
1337610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
1338610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1339610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Parent() {
1340610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThread r(Reader);
1341610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThread w(Writer);
1342610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  r.Start();
1343610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  w.Start();
1344610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1345610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  w.Join();  // 'w' joins first.
1346610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  r.Join();
1347610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1348610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 2;
1349610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
1350610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1351610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
1352610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//  ANNOTATE_EXPECT_RACE(&GLOB, "test32. FP. Fixed by MSMProp1.");
1353610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test32: negative\n");
1354610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  Parent();
1355610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB=%d\n", GLOB);
1356610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
1357610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1358610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST(Run, 32);
1359610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test32
1360610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1361610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1362610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test33: STAB. Stress test for the number of thread sets (TSETs). {{{1
1363610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test33 {
1364610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
1365610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Here we access N memory locations from within log(N) threads.
1366610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// We do it in such a way that helgrind creates nearly all possible TSETs.
1367610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Then we join all threads and start again (N_iter times).
1368610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovconst int N_iter = 48;
1369610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovconst int Nlog  = 15;
1370610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovconst int N     = 1 << Nlog;
1371610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovstatic int ARR[N];
1372610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex   MU;
1373610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1374610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker() {
1375610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
1376610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  int n = ++GLOB;
1377610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
1378610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1379610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  n %= Nlog;
1380610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int i = 0; i < N; i++) {
1381610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    // ARR[i] is accessed by threads from i-th subset
1382610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    if (i & (1 << n)) {
1383610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov        CHECK(ARR[i] == 0);
1384610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    }
1385610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
1386610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
1387610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1388610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
1389610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test33:\n");
1390610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1391610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  std::vector<MyThread*> vec(Nlog);
1392610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1393610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int j = 0; j < N_iter; j++) {
1394610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    // Create and start Nlog threads
1395610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    for (int i = 0; i < Nlog; i++) {
1396610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      vec[i] = new MyThread(Worker);
1397610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    }
1398610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    for (int i = 0; i < Nlog; i++) {
1399610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      vec[i]->Start();
1400610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    }
1401610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    // Join all threads.
1402610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    for (int i = 0; i < Nlog; i++) {
1403610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      vec[i]->Join();
1404610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      delete vec[i];
1405610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    }
1406610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    printf("------------------\n");
1407610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
1408610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1409610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB=%d; ARR[1]=%d; ARR[7]=%d; ARR[N-1]=%d\n",
1410610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov         GLOB, ARR[1], ARR[7], ARR[N-1]);
1411610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
1412610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST2(Run, 33, STABILITY|EXCLUDE_FROM_ALL);
1413610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test33
1414610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1415610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1416610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test34: STAB. Stress test for the number of locks sets (LSETs). {{{1
1417610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test34 {
1418610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Similar to test33, but for lock sets.
1419610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
1420610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovconst int N_iter = 48;
1421610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovconst int Nlog = 10;
1422610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovconst int N    = 1 << Nlog;
1423610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovstatic int ARR[N];
1424610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovstatic Mutex *MUs[Nlog];
1425610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1426610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker() {
1427610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    for (int i = 0; i < N; i++) {
1428610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      // ARR[i] is protected by MUs from i-th subset of all MUs
1429610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      for (int j = 0; j < Nlog; j++)  if (i & (1 << j)) MUs[j]->Lock();
1430610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      CHECK(ARR[i] == 0);
1431610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      for (int j = 0; j < Nlog; j++)  if (i & (1 << j)) MUs[j]->Unlock();
1432610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    }
1433610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
1434610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1435610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
1436610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test34:\n");
1437610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int iter = 0; iter < N_iter; iter++) {
1438610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    for (int i = 0; i < Nlog; i++) {
1439610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      MUs[i] = new Mutex;
1440610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    }
1441610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    MyThreadArray t(Worker, Worker);
1442610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    t.Start();
1443610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    t.Join();
1444610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    for (int i = 0; i < Nlog; i++) {
1445610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      delete MUs[i];
1446610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    }
1447610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    printf("------------------\n");
1448610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
1449610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB=%d\n", GLOB);
1450610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
1451610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST2(Run, 34, STABILITY|EXCLUDE_FROM_ALL);
1452610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test34
1453610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1454610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1455610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test35: PERF. Lots of mutexes and lots of call to free().  {{{1
1456610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test35 {
1457610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Helgrind 3.3.0 has very slow in shadow_mem_make_NoAccess(). Fixed locally.
1458610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// With the fix helgrind runs this test about a minute.
1459610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Without the fix -- about 5 minutes. (on c2d 2.4GHz).
1460610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
1461610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// TODO: need to figure out the best way for performance testing.
1462610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint **ARR;
1463610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovconst int N_mu   = 25000;
1464610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovconst int N_free = 48000;
1465610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1466610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker() {
1467610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int i = 0; i < N_free; i++)
1468610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    CHECK(777 == *ARR[i]);
1469610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
1470610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1471610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
1472610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test35:\n");
1473610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  std::vector<Mutex*> mus;
1474610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1475610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ARR = new int *[N_free];
1476610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int i = 0; i < N_free; i++) {
1477610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    const int c = N_free / N_mu;
1478610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    if ((i % c) == 0) {
1479610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      mus.push_back(new Mutex);
1480610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      mus.back()->Lock();
1481610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      mus.back()->Unlock();
1482610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    }
1483610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    ARR[i] = new int(777);
1484610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
1485610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1486610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // Need to put all ARR[i] into shared state in order
1487610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // to trigger the performance bug.
1488610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Worker, Worker);
1489610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
1490610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
1491610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1492610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int i = 0; i < N_free; i++) delete ARR[i];
1493610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  delete [] ARR;
1494610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1495610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (size_t i = 0; i < mus.size(); i++) {
1496610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    delete mus[i];
1497610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
1498610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
1499610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST2(Run, 35, PERFORMANCE|EXCLUDE_FROM_ALL);
1500610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test35
1501610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1502610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1503610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test36: TN. Synchronization via Mutex, then PCQ. 3 threads. W/W {{{1
1504610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test36 {
1505610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// variation of test28 (W/W instead of W/R)
1506610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1507610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Putter1:                       Getter:                         Putter2:
1508610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 1. MU.Lock();                                                  A. MU.Lock()
1509610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 2. write(GLOB)                                                 B. write(GLOB)
1510610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 3. MU.Unlock()                                                 C. MU.Unlock()
1511610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 4. Q.Put() ---------\                                 /------- D. Q.Put()
1512610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 5. MU1.Lock()        \-------> a. Q.Get()            /         E. MU1.Lock()
1513610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 6. MU.Lock()                   b. Q.Get() <---------/          F. MU.Lock()
1514610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 7. write(GLOB)                                                 G. write(GLOB)
1515610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 8. MU.Unlock()                                                 H. MU.Unlock()
1516610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 9. MU1.Unlock()                  (sleep)                       I. MU1.Unlock()
1517610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                                c. MU1.Lock()
1518610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                                d. write(GLOB)
1519610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                                e. MU1.Unlock()
1520610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovProducerConsumerQueue Q(INT_MAX);
1521610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
1522610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex   MU, MU1;
1523610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1524610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Putter() {
1525610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
1526610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB++;
1527610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
1528610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1529610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  Q.Put(NULL);
1530610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1531610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU1.Lock();
1532610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
1533610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB++;
1534610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
1535610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU1.Unlock();
1536610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
1537610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1538610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Getter() {
1539610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  Q.Get();
1540610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  Q.Get();
1541610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(100000);
1542610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU1.Lock();
1543610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB++;
1544610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU1.Unlock();
1545610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
1546610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1547610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
1548610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test36: negative \n");
1549610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Getter, Putter, Putter);
1550610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
1551610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
1552610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB=%d\n", GLOB);
1553610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
1554610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST(Run, 36);
1555610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test36
1556610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1557610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1558610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test37: TN. Simple synchronization (write vs read). {{{1
1559610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test37 {
1560610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
1561610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex   MU;
1562610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Similar to test10, but properly locked.
1563610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Writer:             Reader:
1564610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 1. MU.Lock()
1565610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 2. write
1566610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 3. MU.Unlock()
1567610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                    a. MU.Lock()
1568610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                    b. read
1569610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                    c. MU.Unlock();
1570610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1571610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Writer() {
1572610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
1573610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 3;
1574610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
1575610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
1576610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Reader() {
1577610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(100000);
1578610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
1579610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(GLOB != -777);
1580610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
1581610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
1582610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1583610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
1584610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test37: negative\n");
1585610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Writer, Reader);
1586610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
1587610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
1588610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB=%d\n", GLOB);
1589610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
1590610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST(Run, 37);
1591610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test37
1592610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1593610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1594610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test38: TN. Synchronization via Mutexes and PCQ. 4 threads. W/W {{{1
1595610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test38 {
1596610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Fusion of test29 and test36.
1597610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1598610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Putter1:            Putter2:           Getter1:       Getter2:
1599610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//    MU1.Lock()          MU1.Lock()
1600610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//    write(GLOB)         write(GLOB)
1601610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//    MU1.Unlock()        MU1.Unlock()
1602610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//    Q1.Put()            Q2.Put()
1603610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//    Q1.Put()            Q2.Put()
1604610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//    MU1.Lock()          MU1.Lock()
1605610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//    MU2.Lock()          MU2.Lock()
1606610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//    write(GLOB)         write(GLOB)
1607610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//    MU2.Unlock()        MU2.Unlock()
1608610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//    MU1.Unlock()        MU1.Unlock()     sleep          sleep
1609610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                                         Q1.Get()       Q1.Get()
1610610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                                         Q2.Get()       Q2.Get()
1611610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                                         MU2.Lock()     MU2.Lock()
1612610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                                         write(GLOB)    write(GLOB)
1613610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                                         MU2.Unlock()   MU2.Unlock()
1614610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
1615610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1616610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1617610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovProducerConsumerQueue *Q1, *Q2;
1618610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
1619610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex   MU, MU1, MU2;
1620610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1621610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Putter(ProducerConsumerQueue *q) {
1622610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU1.Lock();
1623610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB++;
1624610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU1.Unlock();
1625610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1626610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  q->Put(NULL);
1627610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  q->Put(NULL);
1628610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1629610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU1.Lock();
1630610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU2.Lock();
1631610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB++;
1632610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU2.Unlock();
1633610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU1.Unlock();
1634610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1635610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
1636610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1637610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Putter1() { Putter(Q1); }
1638610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Putter2() { Putter(Q2); }
1639610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1640610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Getter() {
1641610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(100000);
1642610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  Q1->Get();
1643610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  Q2->Get();
1644610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1645610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU2.Lock();
1646610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB++;
1647610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU2.Unlock();
1648610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1649610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(48000); //  TODO: remove this when FP in test32 is fixed.
1650610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
1651610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1652610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
1653610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test38: negative\n");
1654610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  Q1 = new ProducerConsumerQueue(INT_MAX);
1655610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  Q2 = new ProducerConsumerQueue(INT_MAX);
1656610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Getter, Getter, Putter1, Putter2);
1657610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
1658610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
1659610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB=%d\n", GLOB);
1660610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  delete Q1;
1661610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  delete Q2;
1662610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
1663610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST(Run, 38);
1664610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test38
1665610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1666610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace NegativeTests_Barrier {  // {{{1
1667610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#ifndef NO_BARRIER
1668610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Same as test17 but uses Barrier class (pthread_barrier_t).
1669610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
1670610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovconst int N_threads = 3;
1671610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovBarrier barrier(N_threads);
1672610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex   MU;
1673610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1674610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker() {
1675610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
1676610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB++;
1677610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
1678610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  barrier.Block();
1679610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(GLOB == N_threads);
1680610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
1681610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1682610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(NegativeTests, Barrier) {
1683610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_TRACE_MEMORY(&GLOB);
1684610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  {
1685610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    ThreadPool pool(N_threads);
1686610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    pool.StartWorkers();
1687610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    for (int i = 0; i < N_threads; i++) {
1688610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      pool.Add(NewCallback(Worker));
1689610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    }
1690610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  } // all folks are joined here.
1691610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(GLOB == 3);
1692610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
1693610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#endif // NO_BARRIER
1694610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test39
1695610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1696610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1697610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test40: FP. Synchronization via Mutexes and PCQ. 4 threads. W/W {{{1
1698610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test40 {
1699610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Similar to test38 but with different order of events (due to sleep).
1700610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1701610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Putter1:            Putter2:           Getter1:       Getter2:
1702610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//    MU1.Lock()          MU1.Lock()
1703610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//    write(GLOB)         write(GLOB)
1704610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//    MU1.Unlock()        MU1.Unlock()
1705610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//    Q1.Put()            Q2.Put()
1706610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//    Q1.Put()            Q2.Put()
1707610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                                        Q1.Get()       Q1.Get()
1708610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                                        Q2.Get()       Q2.Get()
1709610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                                        MU2.Lock()     MU2.Lock()
1710610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                                        write(GLOB)    write(GLOB)
1711610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                                        MU2.Unlock()   MU2.Unlock()
1712610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
1713610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//    MU1.Lock()          MU1.Lock()
1714610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//    MU2.Lock()          MU2.Lock()
1715610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//    write(GLOB)         write(GLOB)
1716610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//    MU2.Unlock()        MU2.Unlock()
1717610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//    MU1.Unlock()        MU1.Unlock()
1718610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1719610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1720610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovProducerConsumerQueue *Q1, *Q2;
1721610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
1722610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex   MU, MU1, MU2;
1723610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1724610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Putter(ProducerConsumerQueue *q) {
1725610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU1.Lock();
1726610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB++;
1727610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU1.Unlock();
1728610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1729610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  q->Put(NULL);
1730610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  q->Put(NULL);
1731610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(100000);
1732610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1733610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU1.Lock();
1734610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU2.Lock();
1735610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB++;
1736610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU2.Unlock();
1737610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU1.Unlock();
1738610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1739610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
1740610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1741610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Putter1() { Putter(Q1); }
1742610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Putter2() { Putter(Q2); }
1743610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1744610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Getter() {
1745610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  Q1->Get();
1746610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  Q2->Get();
1747610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1748610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU2.Lock();
1749610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB++;
1750610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU2.Unlock();
1751610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1752610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(48000); //  TODO: remove this when FP in test32 is fixed.
1753610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
1754610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1755610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
1756610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//  ANNOTATE_EXPECT_RACE(&GLOB, "test40. FP. Fixed by MSMProp1. Complex Stuff.");
1757610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test40: negative\n");
1758610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  Q1 = new ProducerConsumerQueue(INT_MAX);
1759610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  Q2 = new ProducerConsumerQueue(INT_MAX);
1760610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Getter, Getter, Putter1, Putter2);
1761610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
1762610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
1763610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB=%d\n", GLOB);
1764610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  delete Q1;
1765610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  delete Q2;
1766610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
1767610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST(Run, 40);
1768610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test40
1769610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1770610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test41: TN. Test for race that appears when loading a dynamic symbol. {{{1
1771610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test41 {
1772610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker() {
1773610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_NO_OP(NULL); // An empty function, loaded from dll.
1774610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
1775610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
1776610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test41: negative\n");
1777610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Worker, Worker, Worker);
1778610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
1779610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
1780610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
1781610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST2(Run, 41, FEATURE|NEEDS_ANNOTATIONS);
1782610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test41
1783610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1784610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1785610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test42: TN. Using the same cond var several times. {{{1
1786610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test42 {
1787610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint GLOB = 0;
1788610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint COND = 0;
1789610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint N_threads = 3;
1790610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex   MU;
1791610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1792610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker1() {
1793610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB=1;
1794610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1795610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
1796610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  COND = 1;
1797610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CV.Signal();
1798610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
1799610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1800610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
1801610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  while (COND != 0)
1802610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    CV.Wait(&MU);
1803610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_CONDVAR_LOCK_WAIT(&CV, &MU);
1804610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
1805610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1806610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB=3;
1807610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1808610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
1809610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1810610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker2() {
1811610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1812610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
1813610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  while (COND != 1)
1814610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    CV.Wait(&MU);
1815610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_CONDVAR_LOCK_WAIT(&CV, &MU);
1816610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
1817610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1818610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB=2;
1819610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1820610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
1821610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  COND = 0;
1822610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CV.Signal();
1823610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
1824610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1825610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
1826610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1827610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
1828610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//  ANNOTATE_EXPECT_RACE(&GLOB, "test42. TN. debugging.");
1829610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test42: negative\n");
1830610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Worker1, Worker2);
1831610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
1832610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
1833610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB=%d\n", GLOB);
1834610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
1835610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST2(Run, 42, FEATURE|NEEDS_ANNOTATIONS);
1836610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test42
1837610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1838610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1839610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1840610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test43: TN. {{{1
1841610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test43 {
1842610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
1843610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Putter:            Getter:
1844610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 1. write
1845610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 2. Q.Put() --\     .
1846610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 3. read       \--> a. Q.Get()
1847610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                    b. read
1848610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
1849610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovProducerConsumerQueue Q(INT_MAX);
1850610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Putter() {
1851610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 1;
1852610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  Q.Put(NULL);
1853610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(GLOB == 1);
1854610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
1855610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Getter() {
1856610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  Q.Get();
1857610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(100000);
1858610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(GLOB == 1);
1859610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
1860610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
1861610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test43: negative\n");
1862610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Putter, Getter);
1863610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
1864610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
1865610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB=%d\n", GLOB);
1866610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
1867610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST(Run, 43)
1868610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test43
1869610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1870610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1871610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test44: FP. {{{1
1872610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test44 {
1873610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
1874610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Putter:            Getter:
1875610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 1. read
1876610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 2. Q.Put() --\     .
1877610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 3. MU.Lock()  \--> a. Q.Get()
1878610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 4. write
1879610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 5. MU.Unlock()
1880610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                    b. MU.Lock()
1881610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                    c. write
1882610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                    d. MU.Unlock();
1883610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
1884610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex   MU;
1885610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovProducerConsumerQueue Q(INT_MAX);
1886610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Putter() {
1887610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(GLOB == 0);
1888610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  Q.Put(NULL);
1889610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
1890610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 1;
1891610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
1892610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
1893610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Getter() {
1894610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  Q.Get();
1895610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(100000);
1896610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
1897610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 1;
1898610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
1899610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
1900610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
1901610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//  ANNOTATE_EXPECT_RACE(&GLOB, "test44. FP. Fixed by MSMProp1.");
1902610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test44: negative\n");
1903610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Putter, Getter);
1904610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
1905610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
1906610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB=%d\n", GLOB);
1907610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
1908610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST(Run, 44)
1909610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test44
1910610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1911610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1912610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test45: TN. {{{1
1913610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test45 {
1914610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
1915610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Putter:            Getter:
1916610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 1. read
1917610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 2. Q.Put() --\     .
1918610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 3. MU.Lock()  \--> a. Q.Get()
1919610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 4. write
1920610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 5. MU.Unlock()
1921610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                    b. MU.Lock()
1922610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                    c. read
1923610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                    d. MU.Unlock();
1924610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
1925610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex   MU;
1926610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovProducerConsumerQueue Q(INT_MAX);
1927610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Putter() {
1928610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(GLOB == 0);
1929610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  Q.Put(NULL);
1930610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
1931610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB++;
1932610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
1933610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
1934610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Getter() {
1935610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  Q.Get();
1936610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(100000);
1937610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
1938610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(GLOB <= 1);
1939610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
1940610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
1941610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
1942610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test45: negative\n");
1943610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Putter, Getter);
1944610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
1945610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
1946610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB=%d\n", GLOB);
1947610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
1948610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST(Run, 45)
1949610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test45
1950610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1951610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1952610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test46: FN. {{{1
1953610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test46 {
1954610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
1955610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// First:                             Second:
1956610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 1. write
1957610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 2. MU.Lock()
1958610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 3. write
1959610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 4. MU.Unlock()                      (sleep)
1960610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                                    a. MU.Lock()
1961610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                                    b. write
1962610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                                    c. MU.Unlock();
1963610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
1964610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex   MU;
1965610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid First() {
1966610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB++;
1967610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
1968610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB++;
1969610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
1970610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
1971610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Second() {
1972610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(480000);
1973610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
1974610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB++;
1975610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
1976610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1977610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // just a print.
1978610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // If we move it to Run()  we will get report in MSMHelgrind
1979610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // due to its false positive (test32).
1980610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
1981610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB=%d\n", GLOB);
1982610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
1983610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
1984610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
1985610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_TRACE_MEMORY(&GLOB);
1986610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(First, Second);
1987610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
1988610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
1989610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
1990610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST(Run, 46)
1991610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test46
1992610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1993610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
1994610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test47: TP. Not detected by pure happens-before detectors. {{{1
1995610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test47 {
1996610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// A true race that can not be detected by a pure happens-before
1997610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// race detector.
1998610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
1999610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// First:                             Second:
2000610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 1. write
2001610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 2. MU.Lock()
2002610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 3. MU.Unlock()                      (sleep)
2003610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                                    a. MU.Lock()
2004610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                                    b. MU.Unlock();
2005610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                                    c. write
2006610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
2007610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex   MU;
2008610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid First() {
2009610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB=1;
2010610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
2011610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
2012610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
2013610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Second() {
2014610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(480000);
2015610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
2016610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
2017610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB++;
2018610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
2019610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
2020610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  if (!Tsan_PureHappensBefore())
2021610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test47. TP. Not detected by pure HB.");
2022610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test47: positive\n");
2023610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(First, Second);
2024610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
2025610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
2026610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB=%d\n", GLOB);
2027610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
2028610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST(Run, 47)
2029610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test47
2030610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2031610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2032610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test48: FN. Simple race (single write vs multiple reads). {{{1
2033610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test48 {
2034610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
2035610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// same as test10 but with single writer and  multiple readers
2036610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// A simple data race between single writer and  multiple readers.
2037610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Write happens before Reads (enforced by sleep(1)),
2038610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2039610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
2040610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Writer:                    Readers:
2041610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 1. write(GLOB)             a. sleep(long enough so that GLOB
2042610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                                is most likely initialized by Writer)
2043610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                            b. read(GLOB)
2044610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
2045610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
2046610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Eraser algorithm does not detect the race here,
2047610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// see Section 2.2 of http://citeseer.ist.psu.edu/savage97eraser.html.
2048610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
2049610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Writer() {
2050610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 3;
2051610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
2052610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Reader() {
2053610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(100000);
2054610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(GLOB != -777);
2055610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
2056610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2057610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
2058610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test48. TP. FN in MSMHelgrind.");
2059610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test48: positive\n");
2060610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Writer, Reader,Reader,Reader);
2061610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
2062610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
2063610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB=%d\n", GLOB);
2064610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
2065610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST(Run, 48)
2066610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test48
2067610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2068610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2069610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test49: FN. Simple race (single write vs multiple reads). {{{1
2070610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test49 {
2071610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
2072610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// same as test10 but with multiple read operations done by a single reader
2073610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// A simple data race between writer and readers.
2074610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Write happens before Read (enforced by sleep(1)),
2075610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
2076610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Writer:                    Reader:
2077610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 1. write(GLOB)             a. sleep(long enough so that GLOB
2078610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                                is most likely initialized by Writer)
2079610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                            b. read(GLOB)
2080610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                            c. read(GLOB)
2081610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                            d. read(GLOB)
2082610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                            e. read(GLOB)
2083610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
2084610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
2085610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Eraser algorithm does not detect the race here,
2086610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// see Section 2.2 of http://citeseer.ist.psu.edu/savage97eraser.html.
2087610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
2088610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Writer() {
2089610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 3;
2090610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
2091610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Reader() {
2092610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(100000);
2093610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(GLOB != -777);
2094610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(GLOB != -777);
2095610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(GLOB != -777);
2096610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(GLOB != -777);
2097610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
2098610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2099610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
2100610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test49. TP. FN in MSMHelgrind.");
2101610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test49: positive\n");
2102610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Writer, Reader);
2103610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
2104610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
2105610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB=%d\n", GLOB);
2106610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
2107610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST(Run, 49);
2108610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test49
2109610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2110610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2111610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test50: TP. Synchronization via CondVar. {{{1
2112610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test50 {
2113610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
2114610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex   MU;
2115610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Two last write accesses to GLOB are not synchronized
2116610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
2117610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Waiter:                      Waker:
2118610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 1. COND = 0
2119610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 2. Start(Waker)
2120610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 3. MU.Lock()                 a. write(GLOB)
2121610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                              b. MU.Lock()
2122610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                              c. COND = 1
2123610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                         /--- d. CV.Signal()
2124610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//  4. while(COND != 1)   /     e. MU.Unlock()
2125610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//       CV.Wait(MU) <---/
2126610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//  5. MU.Unlock()
2127610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//  6. write(GLOB)              f. MU.Lock()
2128610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                              g. write(GLOB)
2129610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                              h. MU.Unlock()
2130610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2131610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2132610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Waker() {
2133610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(100000);  // Make sure the waiter blocks.
2134610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2135610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 1;
2136610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2137610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
2138610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  COND = 1;
2139610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CV.Signal();
2140610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
2141610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2142610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(100000);
2143610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
2144610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 3;
2145610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
2146610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
2147610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2148610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Waiter() {
2149610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
2150610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  while(COND != 1)
2151610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    CV.Wait(&MU);
2152610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_CONDVAR_LOCK_WAIT(&CV, &MU);
2153610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
2154610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2155610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 2;
2156610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
2157610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
2158610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test50: positive\n");
2159610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  COND = 0;
2160610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test50. TP.");
2161610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Waker, Waiter);
2162610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
2163610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
2164610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB=%d\n", GLOB);
2165610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
2166610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST2(Run, 50, FEATURE|NEEDS_ANNOTATIONS);
2167610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test50
2168610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2169610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2170610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test51: TP. Synchronization via CondVar: problem with several signals. {{{1
2171610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test51 {
2172610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
2173610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     COND = 0;
2174610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex   MU;
2175610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovStealthNotification n1, n2;
2176610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2177610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// scheduler dependent results because of several signals
2178610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// second signal will be lost
2179610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
2180610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Waiter:                      Waker:
2181610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 1. Start(Waker)
2182610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 2. MU.Lock()
2183610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 3. while(COND)
2184610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//       CV.Wait(MU)<-\         .
2185610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 4. MU.Unlock()      \        .
2186610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 5. write(GLOB)       \       a. write(GLOB)
2187610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                       \      b. MU.Lock()
2188610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                        \     c. COND = 1
2189610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                         \--- d. CV.Signal()
2190610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                              e. MU.Unlock()
2191610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
2192610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                              f. write(GLOB)
2193610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
2194610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                              g. MU.Lock()
2195610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                              h. COND = 1
2196610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                    LOST<---- i. CV.Signal()
2197610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                              j. MU.Unlock()
2198610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2199610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Waker() {
2200610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  n1.wait();  // Make sure the waiter blocks.
2201610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2202610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 1;
2203610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2204610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
2205610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  COND = 1;
2206610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CV.Signal();
2207610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
2208610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2209610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  n2.wait();  // Make sure the waiter continued.
2210610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2211610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 2;
2212610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2213610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
2214610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  COND = 1;
2215610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CV.Signal();   //Lost Signal
2216610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
2217610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
2218610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2219610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Waiter() {
2220610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
2221610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  n1.signal();  // Ready to get the first signal.
2222610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  while(COND != 1)
2223610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    CV.Wait(&MU);
2224610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
2225610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2226610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 3;
2227610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  n2.signal(); // Ready to miss the second signal.
2228610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
2229610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
2230610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_EXPECT_RACE(&GLOB, "test51. TP.");
2231610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test51: positive\n");
2232610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Waiter, Waker);
2233610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
2234610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
2235610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB=%d\n", GLOB);
2236610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
2237610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST(Run, 51);
2238610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test51
2239610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2240610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2241610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test52: TP. Synchronization via CondVar: problem with several signals. {{{1
2242610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test52 {
2243610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
2244610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     COND = 0;
2245610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex   MU;
2246610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovStealthNotification n1, n2;
2247610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2248610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// same as test51 but the first signal will be lost
2249610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// scheduler dependent results because of several signals
2250610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
2251610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Waiter:                      Waker:
2252610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 1. Start(Waker)
2253610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                              a. write(GLOB)
2254610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                              b. MU.Lock()
2255610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                              c. COND = 1
2256610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                    LOST<---- d. CV.Signal()
2257610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                              e. MU.Unlock()
2258610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
2259610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 2. MU.Lock()
2260610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 3. while(COND)
2261610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//       CV.Wait(MU)<-\         .
2262610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 4. MU.Unlock()      \        f. write(GLOB)
2263610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 5. write(GLOB)       \       .
2264610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                       \      g. MU.Lock()
2265610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                        \     h. COND = 1
2266610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                         \--- i. CV.Signal()
2267610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                              j. MU.Unlock()
2268610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2269610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Waker() {
2270610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2271610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 1;
2272610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2273610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
2274610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  COND = 1;
2275610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CV.Signal();    //lost signal
2276610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
2277610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2278610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  n1.signal();  // Ok, now we may block.
2279610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  n2.wait();    // We blocked.
2280610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2281610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 2;
2282610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2283610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
2284610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  COND = 1;
2285610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CV.Signal();
2286610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
2287610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
2288610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2289610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Waiter() {
2290610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  n1.wait();  // The first signal is lost.
2291610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2292610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
2293610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  n2.signal(); // The 2-nd signal may go.
2294610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  while(COND != 1)
2295610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    CV.Wait(&MU);
2296610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
2297610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2298610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 3;
2299610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
2300610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
2301610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test52: positive\n");
2302610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_EXPECT_RACE(&GLOB, "test52. TP.");
2303610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Waker, Waiter);
2304610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
2305610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
2306610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB=%d\n", GLOB);
2307610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
2308610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST(Run, 52);
2309610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test52
2310610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2311610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2312610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test53: FP. Synchronization via implicit semaphore. {{{1
2313610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test53 {
2314610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Correctly synchronized test, but the common lockset is empty.
2315610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// The variable FLAG works as an implicit semaphore.
2316610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// MSMHelgrind still does not complain since it does not maintain the lockset
2317610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// at the exclusive state. But MSMProp1 does complain.
2318610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// See also test54.
2319610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
2320610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
2321610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Initializer:                  Users
2322610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 1. MU1.Lock()
2323610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 2. write(GLOB)
2324610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 3. FLAG = true
2325610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 4. MU1.Unlock()
2326610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                               a. MU1.Lock()
2327610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                               b. f = FLAG;
2328610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                               c. MU1.Unlock()
2329610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                               d. if (!f) goto a.
2330610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                               e. MU2.Lock()
2331610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                               f. write(GLOB)
2332610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                               g. MU2.Unlock()
2333610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
2334610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2335610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
2336610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovbool    FLAG = false;
2337610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex   MU1, MU2;
2338610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2339610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Initializer() {
2340610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU1.Lock();
2341610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 1000;
2342610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  FLAG = true;
2343610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU1.Unlock();
2344610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(100000); // just in case
2345610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
2346610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2347610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid User() {
2348610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  bool f = false;
2349610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  while(!f) {
2350610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    MU1.Lock();
2351610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    f = FLAG;
2352610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    MU1.Unlock();
2353610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    usleep(10000);
2354610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
2355610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // at this point Initializer will not access GLOB again
2356610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU2.Lock();
2357610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(GLOB >= 1000);
2358610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB++;
2359610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU2.Unlock();
2360610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
2361610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2362610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
2363610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  if (!Tsan_PureHappensBefore())
2364610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test53. FP. Implicit semaphore");
2365610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test53: FP. false positive, Implicit semaphore\n");
2366610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Initializer, User, User);
2367610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
2368610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
2369610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB=%d\n", GLOB);
2370610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
2371610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST(Run, 53)
2372610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test53
2373610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2374610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2375610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test54: TN. Synchronization via implicit semaphore. Annotated {{{1
2376610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test54 {
2377610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Same as test53, but annotated.
2378610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
2379610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovbool    FLAG = false;
2380610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex   MU1, MU2;
2381610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2382610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Initializer() {
2383610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU1.Lock();
2384610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 1000;
2385610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  FLAG = true;
2386610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_CONDVAR_SIGNAL(&GLOB);
2387610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU1.Unlock();
2388610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(100000); // just in case
2389610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
2390610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2391610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid User() {
2392610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  bool f = false;
2393610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  while(!f) {
2394610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    MU1.Lock();
2395610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    f = FLAG;
2396610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    MU1.Unlock();
2397610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    usleep(10000);
2398610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
2399610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // at this point Initializer will not access GLOB again
2400610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_CONDVAR_WAIT(&GLOB);
2401610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU2.Lock();
2402610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(GLOB >= 1000);
2403610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB++;
2404610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU2.Unlock();
2405610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
2406610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2407610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
2408610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test54: negative\n");
2409610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Initializer, User, User);
2410610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
2411610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
2412610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB=%d\n", GLOB);
2413610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
2414610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST2(Run, 54, FEATURE|NEEDS_ANNOTATIONS)
2415610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test54
2416610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2417610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2418610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test55: FP. Synchronization with TryLock. Not easy for race detectors {{{1
2419610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test55 {
2420610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// "Correct" synchronization with TryLock and Lock.
2421610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
2422610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// This scheme is actually very risky.
2423610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// It is covered in detail in this video:
2424610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// http://youtube.com/watch?v=mrvAqvtWYb4 (slide 36, near 50-th minute).
2425610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
2426610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex   MU;
2427610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2428610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker_Lock() {
2429610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 1;
2430610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
2431610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
2432610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2433610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker_TryLock() {
2434610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  while (true) {
2435610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    if (!MU.TryLock()) {
2436610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      MU.Unlock();
2437610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      break;
2438610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    }
2439610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    else
2440610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      MU.Unlock();
2441610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    usleep(100);
2442610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
2443610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 2;
2444610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
2445610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2446610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
2447610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test55:\n");
2448610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Worker_Lock, Worker_TryLock);
2449610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
2450610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
2451610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB=%d\n", GLOB);
2452610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
2453610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST2(Run, 55, FEATURE|EXCLUDE_FROM_ALL);
2454610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test55
2455610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2456610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2457610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2458610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test56: TP. Use of ANNOTATE_BENIGN_RACE. {{{1
2459610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test56 {
2460610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// For whatever reason the user wants to treat
2461610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// a race on GLOB as a benign race.
2462610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
2463610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB2 = 0;
2464610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2465610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker() {
2466610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB++;
2467610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
2468610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2469610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
2470610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_BENIGN_RACE(&GLOB, "test56. Use of ANNOTATE_BENIGN_RACE.");
2471610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_BENIGN_RACE(&GLOB2, "No race. The tool should be silent");
2472610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test56: positive\n");
2473610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Worker, Worker, Worker, Worker);
2474610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
2475610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
2476610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB=%d\n", GLOB);
2477610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
2478610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST2(Run, 56, FEATURE|NEEDS_ANNOTATIONS)
2479610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test56
2480610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2481610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2482610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test57: TN: Correct use of atomics. {{{1
2483610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test57 {
2484610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
2485610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Writer() {
2486610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int i = 0; i < 10; i++) {
2487610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    AtomicIncrement(&GLOB, 1);
2488610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    usleep(1000);
2489610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
2490610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
2491610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Reader() {
2492610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  while (GLOB < 20) usleep(1000);
2493610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
2494610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
2495610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test57: negative\n");
2496610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Writer, Writer, Reader, Reader);
2497610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
2498610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
2499610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(GLOB == 20);
2500610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB=%d\n", GLOB);
2501610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
2502610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST(Run, 57)
2503610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test57
2504610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2505610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2506610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test58: TN. User defined synchronization. {{{1
2507610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test58 {
2508610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB1 = 1;
2509610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB2 = 2;
2510610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     FLAG1 = 0;
2511610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     FLAG2 = 0;
2512610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2513610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Correctly synchronized test, but the common lockset is empty.
2514610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// The variables FLAG1 and FLAG2 used for synchronization and as
2515610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// temporary variables for swapping two global values.
2516610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Such kind of synchronization is rarely used (Excluded from all tests??).
2517610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2518610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker2() {
2519610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  FLAG1=GLOB2;
2520610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2521610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  while(!FLAG2)
2522610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    ;
2523610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB2=FLAG2;
2524610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
2525610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2526610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker1() {
2527610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  FLAG2=GLOB1;
2528610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2529610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  while(!FLAG1)
2530610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    ;
2531610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB1=FLAG1;
2532610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
2533610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2534610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
2535610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test58:\n");
2536610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Worker1, Worker2);
2537610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
2538610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
2539610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB1=%d\n", GLOB1);
2540610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB2=%d\n", GLOB2);
2541610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
2542610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST2(Run, 58, FEATURE|EXCLUDE_FROM_ALL)
2543610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test58
2544610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2545610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2546610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2547610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test59: TN. User defined synchronization. Annotated {{{1
2548610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test59 {
2549610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     COND1 = 0;
2550610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     COND2 = 0;
2551610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB1 = 1;
2552610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB2 = 2;
2553610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     FLAG1 = 0;
2554610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     FLAG2 = 0;
2555610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// same as test 58 but annotated
2556610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2557610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker2() {
2558610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  FLAG1=GLOB2;
2559610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_CONDVAR_SIGNAL(&COND2);
2560610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  while(!FLAG2) usleep(1);
2561610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_CONDVAR_WAIT(&COND1);
2562610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB2=FLAG2;
2563610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
2564610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2565610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker1() {
2566610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  FLAG2=GLOB1;
2567610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_CONDVAR_SIGNAL(&COND1);
2568610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  while(!FLAG1) usleep(1);
2569610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_CONDVAR_WAIT(&COND2);
2570610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB1=FLAG1;
2571610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
2572610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2573610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
2574610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test59: negative\n");
2575610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_BENIGN_RACE(&FLAG1, "synchronization via 'safe' race");
2576610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_BENIGN_RACE(&FLAG2, "synchronization via 'safe' race");
2577610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Worker1, Worker2);
2578610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
2579610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
2580610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB1=%d\n", GLOB1);
2581610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB2=%d\n", GLOB2);
2582610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
2583610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST2(Run, 59, FEATURE|NEEDS_ANNOTATIONS)
2584610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test59
2585610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2586610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2587610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test60: TN. Correct synchronization using signal-wait {{{1
2588610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test60 {
2589610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     COND1 = 0;
2590610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     COND2 = 0;
2591610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB1 = 1;
2592610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB2 = 2;
2593610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     FLAG2 = 0;
2594610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     FLAG1 = 0;
2595610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex   MU;
2596610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// same as test 59 but synchronized with signal-wait.
2597610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2598610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker2() {
2599610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  FLAG1=GLOB2;
2600610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2601610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
2602610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  COND1 = 1;
2603610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CV.Signal();
2604610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
2605610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2606610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
2607610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  while(COND2 != 1)
2608610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    CV.Wait(&MU);
2609610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_CONDVAR_LOCK_WAIT(&CV, &MU);
2610610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
2611610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2612610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB2=FLAG2;
2613610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
2614610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2615610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker1() {
2616610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  FLAG2=GLOB1;
2617610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2618610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
2619610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  COND2 = 1;
2620610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CV.Signal();
2621610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
2622610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2623610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
2624610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  while(COND1 != 1)
2625610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    CV.Wait(&MU);
2626610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_CONDVAR_LOCK_WAIT(&CV, &MU);
2627610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
2628610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2629610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB1=FLAG1;
2630610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
2631610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2632610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
2633610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test60: negative\n");
2634610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Worker1, Worker2);
2635610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
2636610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
2637610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB1=%d\n", GLOB1);
2638610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB2=%d\n", GLOB2);
2639610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
2640610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST2(Run, 60, FEATURE|NEEDS_ANNOTATIONS)
2641610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test60
2642610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2643610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2644610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test61: TN. Synchronization via Mutex as in happens-before, annotated. {{{1
2645610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test61 {
2646610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex MU;
2647610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
2648610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     *P1 = NULL, *P2 = NULL;
2649610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2650610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// In this test Mutex lock/unlock operations introduce happens-before relation.
2651610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// We annotate the code so that MU is treated as in pure happens-before detector.
2652610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2653610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2654610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Putter() {
2655610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_PURE_HAPPENS_BEFORE_MUTEX(&MU);
2656610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
2657610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  if (P1 == NULL) {
2658610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    P1 = &GLOB;
2659610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    *P1 = 1;
2660610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
2661610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
2662610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
2663610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2664610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Getter() {
2665610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  bool done  = false;
2666610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  while (!done) {
2667610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    MU.Lock();
2668610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    if (P1) {
2669610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      done = true;
2670610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      P2 = P1;
2671610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      P1 = NULL;
2672610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    }
2673610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    MU.Unlock();
2674610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
2675610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  *P2 = 2;
2676610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
2677610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2678610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2679610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
2680610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test61: negative\n");
2681610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Putter, Getter);
2682610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
2683610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
2684610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB=%d\n", GLOB);
2685610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
2686610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST2(Run, 61, FEATURE|NEEDS_ANNOTATIONS)
2687610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test61
2688610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2689610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2690610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test62: STAB. Create as many segments as possible. {{{1
2691610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test62 {
2692610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Helgrind 3.3.0 will fail as it has a hard limit of < 2^24 segments.
2693610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// A better scheme is to implement garbage collection for segments.
2694610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovProducerConsumerQueue Q(INT_MAX);
2695610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovconst int N = 1 << 22;
2696610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2697610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Putter() {
2698610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int i = 0; i < N; i++){
2699610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    if ((i % (N / 8)) == 0) {
2700610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      printf("i=%d\n", i);
2701610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    }
2702610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    Q.Put(NULL);
2703610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
2704610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
2705610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2706610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Getter() {
2707610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int i = 0; i < N; i++)
2708610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    Q.Get();
2709610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
2710610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2711610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
2712610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test62:\n");
2713610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Putter, Getter);
2714610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
2715610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
2716610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
2717610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST2(Run, 62, STABILITY|EXCLUDE_FROM_ALL)
2718610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test62
2719610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2720610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2721610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test63: STAB. Create as many segments as possible and do it fast. {{{1
2722610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test63 {
2723610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Helgrind 3.3.0 will fail as it has a hard limit of < 2^24 segments.
2724610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// A better scheme is to implement garbage collection for segments.
2725610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovconst int N = 1 << 24;
2726610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint C = 0;
2727610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2728610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Putter() {
2729610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int i = 0; i < N; i++){
2730610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    if ((i % (N / 8)) == 0) {
2731610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      printf("i=%d\n", i);
2732610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    }
2733610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    ANNOTATE_CONDVAR_SIGNAL(&C);
2734610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
2735610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
2736610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2737610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Getter() {
2738610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
2739610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2740610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
2741610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test63:\n");
2742610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Putter, Getter);
2743610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
2744610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
2745610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
2746610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST2(Run, 63, STABILITY|EXCLUDE_FROM_ALL)
2747610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test63
2748610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2749610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2750610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test64: TP. T2 happens-before T3, but T1 is independent. Reads in T1/T2. {{{1
2751610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test64 {
2752610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// True race between T1 and T3:
2753610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
2754610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// T1:                   T2:                   T3:
2755610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 1. read(GLOB)         (sleep)
2756610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                       a. read(GLOB)
2757610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                       b. Q.Put() ----->    A. Q.Get()
2758610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                                            B. write(GLOB)
2759610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
2760610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
2761610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2762610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
2763610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovProducerConsumerQueue Q(INT_MAX);
2764610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2765610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid T1() {
2766610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(GLOB == 0);
2767610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
2768610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2769610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid T2() {
2770610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(100000);
2771610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(GLOB == 0);
2772610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  Q.Put(NULL);
2773610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
2774610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2775610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid T3() {
2776610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  Q.Get();
2777610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 1;
2778610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
2779610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2780610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2781610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
2782610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test64: TP.");
2783610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test64: positive\n");
2784610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(T1, T2, T3);
2785610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
2786610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
2787610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB=%d\n", GLOB);
2788610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
2789610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST(Run, 64)
2790610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test64
2791610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2792610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2793610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test65: TP. T2 happens-before T3, but T1 is independent. Writes in T1/T2. {{{1
2794610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test65 {
2795610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Similar to test64.
2796610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// True race between T1 and T3:
2797610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
2798610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// T1:                   T2:                   T3:
2799610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 1. MU.Lock()
2800610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 2. write(GLOB)
2801610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 3. MU.Unlock()         (sleep)
2802610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                       a. MU.Lock()
2803610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                       b. write(GLOB)
2804610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                       c. MU.Unlock()
2805610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                       d. Q.Put() ----->    A. Q.Get()
2806610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                                            B. write(GLOB)
2807610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
2808610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
2809610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2810610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
2811610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex   MU;
2812610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovProducerConsumerQueue Q(INT_MAX);
2813610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2814610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid T1() {
2815610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
2816610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB++;
2817610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
2818610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
2819610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2820610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid T2() {
2821610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(100000);
2822610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
2823610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB++;
2824610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
2825610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  Q.Put(NULL);
2826610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
2827610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2828610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid T3() {
2829610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  Q.Get();
2830610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 1;
2831610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
2832610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2833610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2834610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
2835610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  if (!Tsan_PureHappensBefore())
2836610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test65. TP.");
2837610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test65: positive\n");
2838610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(T1, T2, T3);
2839610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
2840610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
2841610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB=%d\n", GLOB);
2842610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
2843610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST(Run, 65)
2844610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test65
2845610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2846610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2847610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test66: TN. Two separate pairs of signaller/waiter using the same CV. {{{1
2848610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test66 {
2849610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB1 = 0;
2850610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB2 = 0;
2851610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     C1 = 0;
2852610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     C2 = 0;
2853610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex   MU;
2854610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2855610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Signaller1() {
2856610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB1 = 1;
2857610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
2858610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  C1 = 1;
2859610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CV.Signal();
2860610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
2861610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
2862610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2863610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Signaller2() {
2864610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB2 = 1;
2865610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(100000);
2866610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
2867610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  C2 = 1;
2868610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CV.Signal();
2869610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
2870610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
2871610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2872610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Waiter1() {
2873610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
2874610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  while (C1 != 1) CV.Wait(&MU);
2875610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_CONDVAR_WAIT(&CV);
2876610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
2877610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB1 = 2;
2878610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
2879610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2880610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Waiter2() {
2881610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
2882610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  while (C2 != 1) CV.Wait(&MU);
2883610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_CONDVAR_WAIT(&CV);
2884610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
2885610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB2 = 2;
2886610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
2887610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2888610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
2889610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test66: negative\n");
2890610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Signaller1, Signaller2, Waiter1, Waiter2);
2891610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
2892610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
2893610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB=%d/%d\n", GLOB1, GLOB2);
2894610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
2895610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST2(Run, 66, FEATURE|NEEDS_ANNOTATIONS)
2896610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test66
2897610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2898610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2899610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test67: FN. Race between Signaller1 and Waiter2 {{{1
2900610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test67 {
2901610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Similar to test66, but there is a real race here.
2902610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
2903610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Here we create a happens-before arc between Signaller1 and Waiter2
2904610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// even though there should be no such arc.
2905610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// However, it's probably improssible (or just very hard) to avoid it.
2906610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
2907610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     C1 = 0;
2908610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     C2 = 0;
2909610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex   MU;
2910610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2911610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Signaller1() {
2912610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 1;
2913610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
2914610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  C1 = 1;
2915610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CV.Signal();
2916610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
2917610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
2918610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2919610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Signaller2() {
2920610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(100000);
2921610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
2922610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  C2 = 1;
2923610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CV.Signal();
2924610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
2925610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
2926610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2927610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Waiter1() {
2928610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
2929610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  while (C1 != 1) CV.Wait(&MU);
2930610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_CONDVAR_WAIT(&CV);
2931610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
2932610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
2933610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2934610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Waiter2() {
2935610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
2936610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  while (C2 != 1) CV.Wait(&MU);
2937610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_CONDVAR_WAIT(&CV);
2938610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
2939610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 2;
2940610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
2941610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2942610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
2943610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_EXPECT_RACE(&GLOB, "test67. FN. Race between Signaller1 and Waiter2");
2944610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test67: positive\n");
2945610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Signaller1, Signaller2, Waiter1, Waiter2);
2946610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
2947610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
2948610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB=%d\n", GLOB);
2949610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
2950610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST2(Run, 67, FEATURE|NEEDS_ANNOTATIONS|EXCLUDE_FROM_ALL)
2951610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test67
2952610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2953610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2954610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test68: TP. Writes are protected by MU, reads are not. {{{1
2955610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test68 {
2956610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// In this test, all writes to GLOB are protected by a mutex
2957610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// but some reads go unprotected.
2958610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// This is certainly a race, but in some cases such code could occur in
2959610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// a correct program. For example, the unprotected reads may be used
2960610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// for showing statistics and are not required to be precise.
2961610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
2962610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     COND = 0;
2963610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovconst int N_writers = 3;
2964610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex MU, MU1;
2965610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2966610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Writer() {
2967610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int i = 0; i < 100; i++) {
2968610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    MU.Lock();
2969610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    GLOB++;
2970610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    MU.Unlock();
2971610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
2972610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2973610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // we are done
2974610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU1.Lock();
2975610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  COND++;
2976610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU1.Unlock();
2977610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
2978610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2979610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Reader() {
2980610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  bool cont = true;
2981610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  while (cont) {
2982610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    CHECK(GLOB >= 0);
2983610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2984610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    // are we done?
2985610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    MU1.Lock();
2986610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    if (COND == N_writers)
2987610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      cont = false;
2988610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    MU1.Unlock();
2989610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    usleep(100);
2990610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
2991610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
2992610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
2993610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
2994610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_EXPECT_RACE(&GLOB, "TP. Writes are protected, reads are not.");
2995610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test68: positive\n");
2996610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Reader, Writer, Writer, Writer);
2997610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
2998610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
2999610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB=%d\n", GLOB);
3000610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
3001610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST(Run, 68)
3002610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test68
3003610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3004610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3005610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test69:  {{{1
3006610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test69 {
3007610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// This is the same as test68, but annotated.
3008610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// We do not want to annotate GLOB as a benign race
3009610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// because we want to allow racy reads only in certain places.
3010610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
3011610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// TODO:
3012610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
3013610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     COND = 0;
3014610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovconst int N_writers = 3;
3015610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     FAKE_MU = 0;
3016610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex MU, MU1;
3017610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3018610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Writer() {
3019610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int i = 0; i < 10; i++) {
3020610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    MU.Lock();
3021610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    GLOB++;
3022610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    MU.Unlock();
3023610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
3024610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3025610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // we are done
3026610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU1.Lock();
3027610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  COND++;
3028610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU1.Unlock();
3029610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
3030610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3031610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Reader() {
3032610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  bool cont = true;
3033610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  while (cont) {
3034610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    ANNOTATE_IGNORE_READS_BEGIN();
3035610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    CHECK(GLOB >= 0);
3036610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    ANNOTATE_IGNORE_READS_END();
3037610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3038610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    // are we done?
3039610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    MU1.Lock();
3040610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    if (COND == N_writers)
3041610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      cont = false;
3042610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    MU1.Unlock();
3043610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    usleep(100);
3044610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
3045610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
3046610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3047610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
3048610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test69: negative\n");
3049610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Reader, Writer, Writer, Writer);
3050610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
3051610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
3052610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB=%d\n", GLOB);
3053610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
3054610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST(Run, 69)
3055610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test69
3056610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3057610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test70: STAB. Check that TRACE_MEMORY works. {{{1
3058610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test70 {
3059610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
3060610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
3061610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test70: negative\n");
3062610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_TRACE_MEMORY(&GLOB);
3063610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 1;
3064610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB=%d\n", GLOB);
3065610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
3066610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST(Run, 70)
3067610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test70
3068610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3069610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3070610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3071610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace NegativeTests_Strlen {  // {{{1
3072610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// This test is a reproducer for a benign race in strlen (as well as index, etc).
3073610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Some implementations of strlen may read up to 7 bytes past the end of the string
3074610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// thus touching memory which may not belong to this string.
3075610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Such race is benign because the data read past the end of the string is not used.
3076610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
3077610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Here, we allocate a 8-byte aligned string str and initialize first 5 bytes.
3078610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Then one thread calls strlen(str) (as well as index & rindex)
3079610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// and another thread initializes str[5]..str[7].
3080610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
3081610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// This can be fixed in Helgrind by intercepting strlen and replacing it
3082610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// with a simpler implementation.
3083610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3084610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovchar    *str;
3085610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovchar    *tmp2;
3086610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid WorkerX() {
3087610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(100000);
3088610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ASSERT_TRUE(strlen(str) == 4);
3089610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#ifndef WIN32
3090610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  EXPECT_TRUE(index(str, 'X') == str);
3091610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  EXPECT_TRUE(index(str, 'x') == str+1);
3092610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  EXPECT_TRUE(index(str, 'Y') == NULL);
3093610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#ifndef ANDROID
3094610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  EXPECT_TRUE(rindex(str, 'X') == str+2);
3095610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  EXPECT_TRUE(rindex(str, 'x') == str+3);
3096610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  EXPECT_TRUE(rindex(str, 'Y') == NULL);
3097610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#endif
3098610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#else
3099610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  EXPECT_TRUE(lstrlenA(NULL) == 0);
3100610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  EXPECT_TRUE(lstrlenW(NULL) == 0);
3101610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#endif
3102610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  EXPECT_TRUE(strchr(str, 'X') == str);
3103610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  EXPECT_TRUE(strchr(str, 'x') == str+1);
3104610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  EXPECT_TRUE(strchr(str, 'Y') == NULL);
3105610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  EXPECT_TRUE(memchr(str, 'X', 8) == str);
3106610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  EXPECT_TRUE(memchr(str, 'x', 8) == str+1);
3107610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  char tmp[100] = "Zzz";
3108610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  EXPECT_TRUE(memmove(tmp, str, strlen(str) + 1) == tmp);
3109610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  EXPECT_TRUE(strcmp(tmp,str) == 0);
3110610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  EXPECT_TRUE(strncmp(tmp,str, 4) == 0);
3111610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  EXPECT_TRUE(memmove(str, tmp, strlen(tmp) + 1) == str);
3112610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#ifndef WIN32
3113610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#ifndef ANDROID
3114610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  EXPECT_TRUE(stpcpy(tmp2, str) == tmp2+4);
3115610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#endif
3116610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  EXPECT_TRUE(strcpy(tmp2, str) == tmp2);
3117610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  EXPECT_TRUE(strncpy(tmp, str, 4) == tmp);
3118610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // These may not be properly intercepted since gcc -O1 may inline
3119610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // strcpy/stpcpy in presence of a statically sized array. Damn.
3120610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // EXPECT_TRUE(stpcpy(tmp, str) == tmp+4);
3121610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // EXPECT_TRUE(strcpy(tmp, str) == tmp);
3122610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#endif
3123610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  EXPECT_TRUE(strrchr(str, 'X') == str+2);
3124610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  EXPECT_TRUE(strrchr(str, 'x') == str+3);
3125610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  EXPECT_TRUE(strrchr(str, 'Y') == NULL);
3126610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
3127610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid WorkerY() {
3128610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  str[5] = 'Y';
3129610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  str[6] = 'Y';
3130610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  str[7] = '\0';
3131610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
3132610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3133610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(NegativeTests, StrlenAndFriends) {
3134610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  str = new char[8];
3135610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  tmp2 = new char[8];
3136610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  str[0] = 'X';
3137610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  str[1] = 'x';
3138610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  str[2] = 'X';
3139610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  str[3] = 'x';
3140610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  str[4] = '\0';
3141610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThread t1(WorkerY);
3142610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThread t2(WorkerX);
3143610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t1.Start();
3144610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t2.Start();
3145610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t1.Join();
3146610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t2.Join();
3147610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ASSERT_STREQ("XxXx", str);
3148610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ASSERT_STREQ("YY", str+5);
3149610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3150610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  char foo[8] = {10, 20, 127, (char)128, (char)250, -50, 0};
3151610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  EXPECT_TRUE(strchr(foo, 10) != 0);
3152610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  EXPECT_TRUE(strchr(foo, 127) != 0);
3153610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  EXPECT_TRUE(strchr(foo, 128) != 0);
3154610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  EXPECT_TRUE(strchr(foo, 250) != 0);
3155610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  EXPECT_TRUE(strchr(foo, -50) != 0);
3156610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  EXPECT_TRUE(strchr(foo, -60) == 0);
3157610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  EXPECT_TRUE(strchr(foo, 0) != 0);
3158610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  EXPECT_TRUE(strchr(foo, 0) == foo + strlen(foo));
3159610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  EXPECT_TRUE(strrchr(foo, 10) != 0);
3160610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  EXPECT_TRUE(strrchr(foo, 0) != 0);
3161610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  EXPECT_TRUE(strrchr(foo, 0) == foo + strlen(foo));
3162610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  EXPECT_TRUE(strrchr(foo, 250) != 0);
3163610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  EXPECT_TRUE(strrchr(foo, -60) == 0);
3164610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  delete [] str;
3165610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  delete [] tmp2;
3166610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // TODO(kcc): add more tests to check that interceptors are correct.
3167610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
3168610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test71
3169610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3170610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace NegativeTests_EmptyRep {  // {{{1
3171610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker() {
3172610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  string s;
3173610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  s.erase();
3174610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
3175610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3176610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(NegativeTests, DISABLED_EmptyRepTest) {
3177610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // This is a test for the reports on an internal race in std::string implementation.
3178610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=40518
3179610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // ThreadSanitizer should be silent on this, but currently it is silent
3180610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // only on Valgrind/Linux.
3181610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray mta(Worker, Worker);
3182610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  mta.Start();
3183610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  mta.Join();
3184610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
3185610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  //namespace NegativeTests_EmptyRep
3186610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3187610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace NegativeTests_StdStringDtor {  // {{{1
3188610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Some implementations of std::string (including the one on Linux)
3189610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// are unfriendly to race detectors since they use atomic reference counting
3190610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// in a way that race detectors can not understand.
3191610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
3192610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// See http://code.google.com/p/data-race-test/issues/detail?id=40
3193610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovstring *s = NULL;
3194610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovBlockingCounter *counter = NULL;
3195610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3196610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid DestroyWorker() {
3197610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  string x = *s;  // force string copy (increments ref count).
3198610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  counter->DecrementCount();
3199610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // x is destructed, ref count is decremented.
3200610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
3201610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3202610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid AssignWorker() {
3203610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  string x = *s;  // force string copy (increments ref count).
3204610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  counter->DecrementCount();
3205610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // x is assigned, the ref count is decremented.
3206610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(100000);
3207610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  x = "ZZZ";
3208610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
3209610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3210610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(NegativeTests, StdStringDtorVsDtor) {
3211610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray mta(DestroyWorker, DestroyWorker, DestroyWorker);
3212610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  counter = new BlockingCounter(3);
3213610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  s = new string ("foo");
3214610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  mta.Start();
3215610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3216610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  counter->Wait();
3217610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3218610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  delete s;  // ref count becomes zero and the object is destroyed.
3219610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  mta.Join();
3220610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  delete counter;
3221610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
3222610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3223610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(NegativeTests, DISABLED_StdStringDtorVsAssign) {
3224610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray mta(AssignWorker, AssignWorker, AssignWorker);
3225610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  counter = new BlockingCounter(3);
3226610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  s = new string ("foo");
3227610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  mta.Start();
3228610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3229610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  counter->Wait();
3230610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3231610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  delete s;  // ref count becomes zero and the object is destroyed.
3232610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  mta.Join();
3233610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  delete counter;
3234610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
3235610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  //namespace NegativeTests_EmptyRep
3236610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3237610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace PositiveTests_MutexDtorNoSync {
3238610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Check that Mutex::~Mutex() doesn't introduce h-b arcs.
3239610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint *GLOB = NULL;
3240610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3241610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid WriteThenScopedLocalMutex() {
3242610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  *GLOB = 1;
3243610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  {
3244610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    Mutex l;
3245610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
3246610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
3247610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3248610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid ScopedLocalMutexThenWrite() {
3249610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  {
3250610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    Mutex l;
3251610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
3252610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  *GLOB = 2;
3253610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
3254610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3255610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(PositiveTests, MutexDtorNoSyncTest) {
3256610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = new int(0);
3257610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_EXPECT_RACE(GLOB, "TP: PositiveTests.MutexDtorNoSyncTest");
3258610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(WriteThenScopedLocalMutex,
3259610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov                  ScopedLocalMutexThenWrite);
3260610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
3261610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
3262610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  delete GLOB;
3263610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
3264610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3265610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid WriteThenScopedLocalMutexLockUnlock() {
3266610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  *GLOB = 1;
3267610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  {
3268610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    Mutex l;
3269610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    l.Lock();
3270610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    l.Unlock();
3271610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
3272610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
3273610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3274610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid ScopedLocalMutexLockUnlockThenWrite() {
3275610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  {
3276610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    Mutex l;
3277610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    l.Lock();
3278610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    l.Unlock();
3279610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
3280610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  *GLOB = 2;
3281610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
3282610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3283610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(PositiveTests, MutexDtorNoSyncTest2) {
3284610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = new int(0);
3285610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_EXPECT_RACE(GLOB, "TP: PositiveTests.MutexDtorNoSyncTest2");
3286610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(WriteThenScopedLocalMutexLockUnlock,
3287610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov                  ScopedLocalMutexLockUnlockThenWrite);
3288610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
3289610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
3290610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  delete GLOB;
3291610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
3292610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3293610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace PositiveTests_MutexDtorSync
3294610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3295610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace PositiveTests_FprintfThreadCreateTest {
3296610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Check that fprintf doesn't introduce h-b with the start of the
3297610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// following thread
3298610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint *GLOB;
3299610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovStealthNotification *n;
3300610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3301610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker1() {
3302610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  *GLOB = 1;
3303610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  fprintf(stdout, "Hello, world!\n");
3304610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  n->signal();
3305610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
3306610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3307610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker2() {
3308610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  *GLOB = 2;
3309610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
3310610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3311610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#if !defined(_MSC_VER)
3312610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// TODO(timurrrr): investigate Windows FN and un-#if
3313610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(PositiveTests, FprintfThreadCreateTest) {
3314610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = new int;
3315610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_EXPECT_RACE(GLOB, "TP: PositiveTests.FprintfThreadCreateTest");
3316610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  n = new StealthNotification;
3317610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThread t1(Worker1);
3318610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t1.Start();
3319610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  n->wait();
3320610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThread t2(Worker2);
3321610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t2.Start();
3322610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t2.Join();
3323610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t1.Join();
3324610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  delete n;
3325610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  delete GLOB;
3326610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
3327610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#endif
3328610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3329610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov} // namespace PositiveTests_FprintfThreadCreateTest
3330610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3331610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test72: STAB. Stress test for the number of segment sets (SSETs). {{{1
3332610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test72 {
3333610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#ifndef NO_BARRIER
3334610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Variation of test33.
3335610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Instead of creating Nlog*N_iter threads,
3336610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// we create Nlog threads and do N_iter barriers.
3337610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
3338610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovconst int N_iter = 30;
3339610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovconst int Nlog  = 16;
3340610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovconst int N     = 1 << Nlog;
3341610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovstatic int64_t ARR1[N];
3342610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovstatic int64_t ARR2[N];
3343610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovBarrier *barriers[N_iter];
3344610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex   MU;
3345610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3346610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker() {
3347610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
3348610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  int n = ++GLOB;
3349610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
3350610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3351610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  n %= Nlog;
3352610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3353610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int it = 0; it < N_iter; it++) {
3354610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    // Iterate N_iter times, block on barrier after each iteration.
3355610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    // This way Helgrind will create new segments after each barrier.
3356610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3357610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    for (int x = 0; x < 2; x++) {
3358610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      // run the inner loop twice.
3359610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      // When a memory location is accessed second time it is likely
3360610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      // that the state (SVal) will be unchanged.
3361610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      // The memory machine may optimize this case.
3362610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      for (int i = 0; i < N; i++) {
3363610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov        // ARR1[i] and ARR2[N-1-i] are accessed by threads from i-th subset
3364610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov        if (i & (1 << n)) {
3365610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov          CHECK(ARR1[i] == 0);
3366610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov          CHECK(ARR2[N-1-i] == 0);
3367610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov        }
3368610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      }
3369610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    }
3370610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    barriers[it]->Block();
3371610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
3372610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
3373610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3374610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3375610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
3376610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test72:\n");
3377610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3378610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  std::vector<MyThread*> vec(Nlog);
3379610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3380610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int i = 0; i < N_iter; i++)
3381610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    barriers[i] = new Barrier(Nlog);
3382610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3383610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // Create and start Nlog threads
3384610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int i = 0; i < Nlog; i++) {
3385610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    vec[i] = new MyThread(Worker);
3386610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    vec[i]->Start();
3387610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
3388610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3389610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // Join all threads.
3390610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int i = 0; i < Nlog; i++) {
3391610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    vec[i]->Join();
3392610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    delete vec[i];
3393610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
3394610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int i = 0; i < N_iter; i++)
3395610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    delete barriers[i];
3396610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3397610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  /*printf("\tGLOB=%d; ARR[1]=%d; ARR[7]=%d; ARR[N-1]=%d\n",
3398610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov         GLOB, (int)ARR1[1], (int)ARR1[7], (int)ARR1[N-1]);*/
3399610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
3400610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST2(Run, 72, STABILITY|PERFORMANCE|EXCLUDE_FROM_ALL);
3401610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#endif // NO_BARRIER
3402610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test72
3403610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3404610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3405610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test73: STAB. Stress test for the number of (SSETs), different access sizes. {{{1
3406610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test73 {
3407610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#ifndef NO_BARRIER
3408610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Variation of test72.
3409610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// We perform accesses of different sizes to the same location.
3410610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
3411610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovconst int N_iter = 2;
3412610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovconst int Nlog  = 16;
3413610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovconst int N     = 1 << Nlog;
3414610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovstatic int64_t ARR1[N];
3415610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovstatic int ARR2[N];
3416610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovBarrier *barriers[N_iter];
3417610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex   MU;
3418610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3419610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker() {
3420610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
3421610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  int n = ++GLOB;
3422610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
3423610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3424610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  n %= Nlog;
3425610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3426610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int it = 0; it < N_iter; it++) {
3427610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    // Iterate N_iter times, block on barrier after each iteration.
3428610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    // This way Helgrind will create new segments after each barrier.
3429610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3430610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    for (int x = 0; x < 4; x++) {
3431610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      for (int i = 0; i < N; i++) {
3432610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov        // ARR1[i] are accessed by threads from i-th subset
3433610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov        if (i & (1 << n)) {
3434610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov          for (int off = 0; off < (1 << x); off++) {
3435610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov            switch(x) {
3436610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov              case 0: CHECK(          ARR1  [i * (1<<x) + off] == 0); break;
3437610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov              case 1: CHECK(((int*)  (ARR1))[i * (1<<x) + off] == 0); break;
3438610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov              case 2: CHECK(((short*)(ARR1))[i * (1<<x) + off] == 0); break;
3439610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov              case 3: CHECK(((char*) (ARR1))[i * (1<<x) + off] == 0); break;
3440610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov            }
3441610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov            switch(x) {
3442610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov              case 1: CHECK(((int*)  (ARR2))[i * (1<<x) + off] == 0); break;
3443610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov              case 2: CHECK(((short*)(ARR2))[i * (1<<x) + off] == 0); break;
3444610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov              case 3: CHECK(((char*) (ARR2))[i * (1<<x) + off] == 0); break;
3445610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov            }
3446610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov          }
3447610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov        }
3448610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      }
3449610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    }
3450610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    barriers[it]->Block();
3451610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
3452610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
3453610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3454610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3455610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3456610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
3457610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test73:\n");
3458610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3459610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  std::vector<MyThread*> vec(Nlog);
3460610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3461610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int i = 0; i < N_iter; i++)
3462610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    barriers[i] = new Barrier(Nlog);
3463610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3464610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // Create and start Nlog threads
3465610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int i = 0; i < Nlog; i++) {
3466610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    vec[i] = new MyThread(Worker);
3467610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    vec[i]->Start();
3468610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
3469610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3470610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // Join all threads.
3471610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int i = 0; i < Nlog; i++) {
3472610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    vec[i]->Join();
3473610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    delete vec[i];
3474610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
3475610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int i = 0; i < N_iter; i++)
3476610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    delete barriers[i];
3477610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3478610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  /*printf("\tGLOB=%d; ARR[1]=%d; ARR[7]=%d; ARR[N-1]=%d\n",
3479610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov         GLOB, (int)ARR1[1], (int)ARR1[7], (int)ARR1[N-1]);*/
3480610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
3481610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST2(Run, 73, STABILITY|PERFORMANCE|EXCLUDE_FROM_ALL);
3482610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#endif // NO_BARRIER
3483610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test73
3484610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3485610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3486610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test74: PERF. A lot of lock/unlock calls. {{{1
3487610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace    test74 {
3488610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovconst int N = 100000;
3489610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex   MU;
3490610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(StressTests, ManyLocksUnlocks) {
3491610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int i = 0; i < N; i++ ) {
3492610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    MU.Lock();
3493610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    MU.Unlock();
3494610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
3495610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
3496610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test74
3497610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3498610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// RefCountedClass {{{1
3499610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovstruct RefCountedClass {
3500610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov public:
3501610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  RefCountedClass() {
3502610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    annotate_unref_ = false;
3503610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    ref_ = 0;
3504610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    data_ = 0;
3505610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
3506610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3507610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ~RefCountedClass() {
3508610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    CHECK(ref_ == 0);     // race may be reported here
3509610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    int data_val = data_; // and here
3510610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov                          // if MU is not annotated
3511610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    data_ = 0;
3512610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    ref_ = -1;
3513610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    printf("\tRefCountedClass::data_ = %d\n", data_val);
3514610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
3515610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3516610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  void AccessData() {
3517610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    this->mu_.Lock();
3518610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    this->data_++;
3519610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    this->mu_.Unlock();
3520610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
3521610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3522610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  void Ref() {
3523610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    MU.Lock();
3524610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    CHECK(ref_ >= 0);
3525610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    ref_++;
3526610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    MU.Unlock();
3527610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
3528610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3529610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  void Unref() {
3530610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    MU.Lock();
3531610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    CHECK(ref_ > 0);
3532610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    ref_--;
3533610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    bool do_delete = ref_ == 0;
3534610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    if (annotate_unref_) {
3535610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      ANNOTATE_HAPPENS_BEFORE(this);
3536610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    }
3537610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    MU.Unlock();
3538610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    if (do_delete) {
3539610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      if (annotate_unref_) {
3540610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov        ANNOTATE_HAPPENS_AFTER(this);
3541610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      }
3542610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      delete this;
3543610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    }
3544610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
3545610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3546610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  static void Annotate_MU() {
3547610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    ANNOTATE_PURE_HAPPENS_BEFORE_MUTEX(&MU);
3548610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
3549610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  void AnnotateUnref() {
3550610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    annotate_unref_ = true;
3551610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
3552610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  void Annotate_Race() {
3553610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    ANNOTATE_BENIGN_RACE_SIZED(this, sizeof(*this), "needs annotation");
3554610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
3555610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov private:
3556610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  bool annotate_unref_;
3557610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3558610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  int data_;
3559610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  Mutex mu_; // protects data_
3560610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3561610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  int ref_;
3562610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  static Mutex MU; // protects ref_
3563610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov};
3564610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3565610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex RefCountedClass::MU;
3566610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3567610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test76: FP. Ref counting, no annotations. {{{1
3568610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test76 {
3569610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#ifndef NO_BARRIER
3570610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
3571610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovBarrier barrier(4);
3572610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovRefCountedClass *object = NULL;
3573610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker() {
3574610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  object->Ref();
3575610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  barrier.Block();
3576610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  object->AccessData();
3577610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  object->Unref();
3578610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
3579610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
3580610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test76: false positive (ref counting)\n");
3581610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  object = new RefCountedClass;
3582610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  object->Annotate_Race();
3583610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Worker, Worker, Worker, Worker);
3584610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
3585610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
3586610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
3587610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST2(Run, 76, FEATURE)
3588610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#endif // NO_BARRIER
3589610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test76
3590610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3591610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3592610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3593610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test77: TN. Ref counting, MU is annotated. {{{1
3594610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test77 {
3595610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#ifndef NO_BARRIER
3596610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// same as test76, but RefCountedClass::MU is annotated.
3597610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
3598610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovBarrier barrier(4);
3599610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovRefCountedClass *object = NULL;
3600610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker() {
3601610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  object->Ref();
3602610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  barrier.Block();
3603610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  object->AccessData();
3604610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  object->Unref();
3605610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
3606610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
3607610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test77: true negative (ref counting), mutex is annotated\n");
3608610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  RefCountedClass::Annotate_MU();
3609610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  object = new RefCountedClass;
3610610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Worker, Worker, Worker, Worker);
3611610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
3612610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
3613610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
3614610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST(Run, 77)
3615610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#endif // NO_BARRIER
3616610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test77
3617610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3618610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3619610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3620610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test78: TN. Ref counting, Unref is annotated. {{{1
3621610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test78 {
3622610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#ifndef NO_BARRIER
3623610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// same as test76, but RefCountedClass::Unref is annotated.
3624610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
3625610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovBarrier barrier(4);
3626610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovRefCountedClass *object = NULL;
3627610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker() {
3628610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  object->Ref();
3629610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  barrier.Block();
3630610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  object->AccessData();
3631610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  object->Unref();
3632610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
3633610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
3634610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test78: true negative (ref counting), Unref is annotated\n");
3635610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  RefCountedClass::Annotate_MU();
3636610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  object = new RefCountedClass;
3637610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Worker, Worker, Worker, Worker);
3638610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
3639610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
3640610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
3641610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST(Run, 78)
3642610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#endif // NO_BARRIER
3643610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test78
3644610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3645610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3646610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3647610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test79 TN. Swap. {{{1
3648610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test79 {
3649610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#if 0
3650610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovtypedef __gnu_cxx::hash_map<int, int> map_t;
3651610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#else
3652610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovtypedef std::map<int, int> map_t;
3653610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#endif
3654610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovmap_t   MAP;
3655610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex   MU;
3656610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3657610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Here we use swap to pass MAP between threads.
3658610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// The synchronization is correct, but w/o ANNOTATE_PURE_HAPPENS_BEFORE_MUTEX
3659610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Helgrind will complain.
3660610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3661610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker1() {
3662610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  map_t tmp;
3663610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
3664610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // We swap the new empty map 'tmp' with 'MAP'.
3665610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MAP.swap(tmp);
3666610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
3667610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // tmp (which is the old version of MAP) is destroyed here.
3668610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
3669610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3670610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker2() {
3671610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
3672610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MAP[1]++;  // Just update MAP under MU.
3673610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
3674610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
3675610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3676610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker3() { Worker1(); }
3677610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker4() { Worker2(); }
3678610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3679610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
3680610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_PURE_HAPPENS_BEFORE_MUTEX(&MU);
3681610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test79: negative\n");
3682610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Worker1, Worker2, Worker3, Worker4);
3683610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
3684610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
3685610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
3686610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST(Run, 79)
3687610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test79
3688610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3689610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3690610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// AtomicRefCountedClass. {{{1
3691610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Same as RefCountedClass, but using atomic ops instead of mutex.
3692610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovstruct AtomicRefCountedClass {
3693610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov public:
3694610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  AtomicRefCountedClass() {
3695610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    annotate_unref_ = false;
3696610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    ref_ = 0;
3697610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    data_ = 0;
3698610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
3699610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3700610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ~AtomicRefCountedClass() {
3701610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    CHECK(ref_ == 0);     // race may be reported here
3702610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    int data_val = data_; // and here
3703610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    data_ = 0;
3704610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    ref_ = -1;
3705610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    printf("\tRefCountedClass::data_ = %d\n", data_val);
3706610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
3707610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3708610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  void AccessData() {
3709610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    this->mu_.Lock();
3710610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    this->data_++;
3711610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    this->mu_.Unlock();
3712610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
3713610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3714610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  void Ref() {
3715610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    AtomicIncrement(&ref_, 1);
3716610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
3717610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3718610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  void Unref() {
3719610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    // DISCLAIMER: I am not sure I've implemented this correctly
3720610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    // (might require some memory barrier, etc).
3721610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    // But this implementation of reference counting is enough for
3722610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    // the purpose of Helgrind demonstration.
3723610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    AtomicIncrement(&ref_, -1);
3724610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    if (annotate_unref_) { ANNOTATE_HAPPENS_BEFORE(this); }
3725610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    if (ref_ == 0) {
3726610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      if (annotate_unref_) { ANNOTATE_HAPPENS_AFTER(this); }
3727610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      delete this;
3728610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    }
3729610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
3730610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3731610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  void AnnotateUnref() {
3732610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    annotate_unref_ = true;
3733610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
3734610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  void Annotate_Race() {
3735610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    ANNOTATE_BENIGN_RACE(&this->data_, "needs annotation");
3736610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
3737610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov private:
3738610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  bool annotate_unref_;
3739610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3740610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  Mutex mu_;
3741610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  int data_; // under mu_
3742610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3743610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  int ref_;  // used in atomic ops.
3744610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov};
3745610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3746610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test80: FP. Ref counting with atomics, no annotations. {{{1
3747610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test80 {
3748610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#ifndef NO_BARRIER
3749610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
3750610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovBarrier barrier(4);
3751610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovAtomicRefCountedClass *object = NULL;
3752610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker() {
3753610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  object->Ref();
3754610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  barrier.Block();
3755610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  object->AccessData();
3756610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  object->Unref(); // All the tricky stuff is here.
3757610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
3758610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
3759610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test80: false positive (ref counting)\n");
3760610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  object = new AtomicRefCountedClass;
3761610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  object->Annotate_Race();
3762610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Worker, Worker, Worker, Worker);
3763610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
3764610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
3765610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
3766610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST2(Run, 80, FEATURE|EXCLUDE_FROM_ALL)
3767610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#endif // NO_BARRIER
3768610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test80
3769610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3770610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3771610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test81: TN. Ref counting with atomics, Unref is annotated. {{{1
3772610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test81 {
3773610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#ifndef NO_BARRIER
3774610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// same as test80, but Unref is annotated.
3775610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
3776610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovBarrier barrier(4);
3777610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovAtomicRefCountedClass *object = NULL;
3778610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker() {
3779610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  object->Ref();
3780610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  barrier.Block();
3781610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  object->AccessData();
3782610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  object->Unref(); // All the tricky stuff is here.
3783610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
3784610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
3785610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test81: negative (annotated ref counting)\n");
3786610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  object = new AtomicRefCountedClass;
3787610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  object->AnnotateUnref();
3788610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Worker, Worker, Worker, Worker);
3789610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
3790610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
3791610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
3792610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST2(Run, 81, FEATURE|EXCLUDE_FROM_ALL)
3793610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#endif // NO_BARRIER
3794610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test81
3795610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3796610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3797610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test82: Object published w/o synchronization. {{{1
3798610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test82 {
3799610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3800610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Writer creates a new object and makes the pointer visible to the Reader.
3801610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Reader waits until the object pointer is non-null and reads the object.
3802610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
3803610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// On Core 2 Duo this test will sometimes (quite rarely) fail in
3804610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// the CHECK below, at least if compiled with -O2.
3805610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
3806610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// The sequence of events::
3807610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Thread1:                  Thread2:
3808610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//   a. arr_[...] = ...
3809610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//   b. foo[i]    = ...
3810610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                           A. ... = foo[i]; // non NULL
3811610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                           B. ... = arr_[...];
3812610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
3813610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//  Since there is no proper synchronization, during the even (B)
3814610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//  Thread2 may not see the result of the event (a).
3815610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//  On x86 and x86_64 this happens due to compiler reordering instructions.
3816610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//  On other arcitectures it may also happen due to cashe inconsistency.
3817610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3818610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovclass FOO {
3819610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov public:
3820610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  FOO() {
3821610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    idx_ = rand() % 1024;
3822610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    arr_[idx_] = 77777;
3823610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  //   __asm__ __volatile__("" : : : "memory"); // this fixes!
3824610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
3825610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  static void check(volatile FOO *foo) {
3826610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    CHECK(foo->arr_[foo->idx_] == 77777);
3827610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
3828610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov private:
3829610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  int idx_;
3830610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  int arr_[1024];
3831610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov};
3832610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3833610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovconst int N = 100000;
3834610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovstatic volatile FOO *foo[N];
3835610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex   MU;
3836610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3837610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Writer() {
3838610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int i = 0; i < N; i++) {
3839610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    foo[i] = new FOO;
3840610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    usleep(100);
3841610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
3842610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
3843610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3844610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Reader() {
3845610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int i = 0; i < N; i++) {
3846610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    while (!foo[i]) {
3847610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      MU.Lock();   // this is NOT a synchronization,
3848610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      MU.Unlock(); // it just helps foo[i] to become visible in Reader.
3849610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    }
3850610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    if ((i % 100) == 0) {
3851610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      printf("rd %d\n", i);
3852610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    }
3853610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    // At this point Reader() sees the new value of foo[i]
3854610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    // but in very rare cases will not see the new value of foo[i]->arr_.
3855610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    // Thus this CHECK will sometimes fail.
3856610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    FOO::check(foo[i]);
3857610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
3858610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
3859610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3860610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
3861610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test82: positive\n");
3862610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Writer, Reader);
3863610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
3864610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
3865610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
3866610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST2(Run, 82, FEATURE|EXCLUDE_FROM_ALL)
3867610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test82
3868610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3869610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3870610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test83: Object published w/o synchronization (simple version){{{1
3871610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test83 {
3872610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// A simplified version of test83 (example of a wrong code).
3873610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// This test, though incorrect, will almost never fail.
3874610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvolatile static int *ptr = NULL;
3875610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex   MU;
3876610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3877610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Writer() {
3878610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(100);
3879610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ptr = new int(777);
3880610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
3881610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3882610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Reader() {
3883610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  while(!ptr) {
3884610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    MU.Lock(); // Not a synchronization!
3885610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    MU.Unlock();
3886610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
3887610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(*ptr == 777);
3888610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
3889610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3890610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
3891610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//  printf("test83: positive\n");
3892610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Writer, Reader);
3893610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
3894610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
3895610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
3896610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST2(Run, 83, FEATURE|EXCLUDE_FROM_ALL)
3897610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test83
3898610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3899610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3900610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test84: TP. True race (regression test for a bug related to atomics){{{1
3901610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test84 {
3902610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Helgrind should not create HB arcs for the bus lock even when
3903610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// --pure-happens-before=yes is used.
3904610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Bug found in by Bart Van Assche, the test is taken from
3905610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// valgrind file drd/tests/atomic_var.c.
3906610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovstatic int s_x = 0;
3907610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov/* s_dummy[] ensures that s_x and s_y are not in the same cache line. */
3908610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovstatic char s_dummy[512] = {0};
3909610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovstatic int s_y;
3910610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3911610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid thread_func_1()
3912610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov{
3913610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  s_y = 1;
3914610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  AtomicIncrement(&s_x, 1);
3915610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
3916610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3917610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid thread_func_2()
3918610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov{
3919610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  while (AtomicIncrement(&s_x, 0) == 0)
3920610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    ;
3921610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("y = %d\n", s_y);
3922610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
3923610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3924610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3925610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
3926610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(s_dummy[0] == 0);  // Avoid compiler warning about 's_dummy unused'.
3927610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test84: positive\n");
3928610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_EXPECT_RACE_FOR_TSAN(&s_y, "test84: TP. true race.");
3929610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(thread_func_1, thread_func_2);
3930610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
3931610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
3932610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
3933610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST(Run, 84)
3934610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test84
3935610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3936610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3937610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Test for RunningOnValgrind(). {{{1
3938610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(NegativeTests, RunningOnValgrindTest) {
3939610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("RunningOnValgrind() = %d\n", RunningOnValgrind());
3940610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
3941610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3942610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace NegativeTests_BenignRaceInDtor {  // {{{
3943610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Test for race inside DTOR: racey write to vptr. Benign.
3944610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// This test shows a racey access to vptr (the pointer to vtbl).
3945610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// We have class A and class B derived from A.
3946610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Both classes have a virtual function f() and a virtual DTOR.
3947610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// We create an object 'A *a = new B'
3948610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// and pass this object from Thread1 to Thread2.
3949610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Thread2 calls a->f(). This call reads a->vtpr.
3950610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Thread1 deletes the object. B::~B waits untill the object can be destroyed
3951610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// (flag_stopped == true) but at the very beginning of B::~B
3952610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// a->vptr is written to.
3953610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// So, we have a race on a->vptr.
3954610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// On this particular test this race is benign, but HarmfulRaceInDtor shows
3955610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// how such race could harm.
3956610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
3957610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
3958610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
3959610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Threa1:                                            Thread2:
3960610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 1. A a* = new B;
3961610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 2. Q.Put(a); ------------\                         .
3962610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                           \-------------------->   a. a = Q.Get();
3963610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                                                    b. a->f();
3964610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                                       /---------   c. flag_stopped = true;
3965610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 3. delete a;                         /
3966610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//    waits untill flag_stopped <------/
3967610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//    inside the dtor
3968610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
3969610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3970610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovbool flag_stopped = false;
3971610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex mu;
3972610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3973610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovProducerConsumerQueue Q(INT_MAX);  // Used to pass A* between threads.
3974610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3975610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovstruct A {
3976610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  A()  { printf("A::A()\n"); }
3977610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  virtual ~A() { printf("A::~A()\n"); }
3978610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  virtual void f() { }
3979610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3980610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  uintptr_t padding[15];
3981610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov} ALIGNED(64);
3982610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3983610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovstruct B: A {
3984610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  B()  { printf("B::B()\n"); }
3985610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  virtual ~B() {
3986610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    // The race is here.    <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
3987610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    printf("B::~B()\n");
3988610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    // wait until flag_stopped is true.
3989610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    mu.LockWhen(Condition(&ArgIsTrue, &flag_stopped));
3990610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    mu.Unlock();
3991610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    printf("B::~B() done\n");
3992610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
3993610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  virtual void f() { }
3994610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov};
3995610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
3996610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Waiter() {
3997610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  A *a = new B;
3998610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("Waiter: B created\n");
3999610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  Q.Put(a);
4000610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(100000); // so that Worker calls a->f() first.
4001610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("Waiter: deleting B\n");
4002610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  delete a;
4003610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("Waiter: B deleted\n");
4004610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(100000);
4005610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("Waiter: done\n");
4006610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
4007610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4008610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker() {
4009610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  A *a = reinterpret_cast<A*>(Q.Get());
4010610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("Worker: got A\n");
4011610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  a->f();
4012610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4013610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  mu.Lock();
4014610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  flag_stopped = true;
4015610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  mu.Unlock();
4016610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(200000);
4017610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("Worker: done\n");
4018610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
4019610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4020610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(NegativeTests, BenignRaceInDtor) {
4021610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Waiter, Worker);
4022610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
4023610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
4024610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
4025610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace
4026610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4027610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4028610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace PositiveTests_HarmfulRaceInDtor {  // {{{
4029610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// A variation of BenignRaceInDtor where the race is harmful.
4030610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Race on vptr. Will run A::F() or B::F() depending on the timing.
4031610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovclass A {
4032610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov public:
4033610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  A() : done_(false) {
4034610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    // W/o this annotation tsan may produce additional warnings in hybrid mode.
4035610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    ANNOTATE_PURE_HAPPENS_BEFORE_MUTEX(&mu_);
4036610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
4037610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  virtual void F() {
4038610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    printf ("A::F()\n");
4039610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
4040610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  void Done() {
4041610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    MutexLock lock(&mu_);
4042610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    done_ = true;
4043610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
4044610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  virtual ~A() {
4045610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    while (true) {
4046610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      {
4047610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov        MutexLock lock(&mu_);
4048610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov        if (done_) break;
4049610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      }
4050610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      usleep(10);  // yield.
4051610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    }
4052610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
4053610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov private:
4054610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  Mutex mu_;
4055610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  bool  done_;
4056610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov};
4057610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4058610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovclass B : public A {
4059610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov public:
4060610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  virtual void F() {
4061610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    // TODO(kcc): enable this printf back once issue 57 is fixed.
4062610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    // printf ("B::F()\n");
4063610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
4064610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov};
4065610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4066610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovstatic A *a;
4067610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4068610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Thread1() {
4069610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  a->F();
4070610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  a->Done();
4071610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  sleep(1);
4072610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov};
4073610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4074610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Thread2() {
4075610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  delete a;
4076610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
4077610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(PositiveTests, HarmfulRaceInDtorB) {
4078610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_FLUSH_EXPECTED_RACES();
4079610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // Will print B::F()
4080610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  a = new B;
4081610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_EXPECT_RACE(a, "HarmfulRaceInDtor #1: expected race on a->vptr");
4082610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_TRACE_MEMORY(a);
4083610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Thread1, Thread2);
4084610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
4085610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
4086610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_FLUSH_EXPECTED_RACES();
4087610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
4088610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4089610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(PositiveTests, HarmfulRaceInDtorA) {
4090610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_FLUSH_EXPECTED_RACES();
4091610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // Will print A::F()
4092610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  a = new B;
4093610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_EXPECT_RACE(a, "HarmfulRaceInDtor #2: expected race on a->vptr");
4094610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_TRACE_MEMORY(a);
4095610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Thread2, Thread1);
4096610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
4097610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
4098610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_FLUSH_EXPECTED_RACES();
4099610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
4100610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4101610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace
4102610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4103610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4104610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace AnnotateIgnoreTests {  // {{{1
4105610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4106610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint racey_write = 0;
4107610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4108610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid RaceyWriter() {
4109610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_IGNORE_WRITES_BEGIN();
4110610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  racey_write = 1;
4111610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_IGNORE_WRITES_END();
4112610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
4113610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4114610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(NegativeTests, AnnotateIgnoreWritesTest) {
4115610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThread t(RaceyWriter);
4116610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
4117610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  racey_write = 1;
4118610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
4119610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
4120610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4121610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint racey_read = 0;
4122610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4123610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid RaceyReader1() {
4124610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_IGNORE_READS_BEGIN();
4125610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(racey_read != 777);
4126610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_IGNORE_READS_END();
4127610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
4128610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4129610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid RaceyReader2() {
4130610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(ANNOTATE_UNPROTECTED_READ(racey_read) != 777);
4131610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
4132610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4133610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(NegativeTests, AnnotateIgnoreReadsTest) {
4134610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(RaceyReader1, RaceyReader2);
4135610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
4136610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  racey_read = 1;
4137610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
4138610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
4139610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4140610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint incorrectly_annotated_racey_write = 0;
4141610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4142610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid IncorrectlyAnnotatedRaceyWriter() {
4143610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_IGNORE_READS_BEGIN();
4144610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  incorrectly_annotated_racey_write = 1;
4145610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_IGNORE_READS_END();
4146610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
4147610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4148610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(PositiveTests, AnnotateIgnoreReadsOnWriteTest) {
4149610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_EXPECT_RACE(&incorrectly_annotated_racey_write, "expected race");
4150610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThread t(IncorrectlyAnnotatedRaceyWriter);
4151610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
4152610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  incorrectly_annotated_racey_write = 1;
4153610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
4154610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_FLUSH_EXPECTED_RACES();
4155610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
4156610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4157610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint incorrectly_annotated_racey_read = 0;
4158610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4159610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid IncorrectlyAnnotatedRaceyReader() {
4160610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_IGNORE_WRITES_BEGIN();
4161610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(incorrectly_annotated_racey_read != 777);
4162610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_IGNORE_WRITES_END();
4163610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
4164610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4165610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(PositiveTests, AnnotateIgnoreWritesOnReadTest) {
4166610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_EXPECT_RACE(&incorrectly_annotated_racey_read, "expected race");
4167610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThread t(IncorrectlyAnnotatedRaceyReader);
4168610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
4169610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  incorrectly_annotated_racey_read = 1;
4170610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
4171610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_FLUSH_EXPECTED_RACES();
4172610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
4173610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4174610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace
4175610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4176610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4177610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test89: Test for debug info. {{{1
4178610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test89 {
4179610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Simlpe races with different objects (stack, heap globals; scalars, structs).
4180610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Also, if run with --trace-level=2 this test will show a sequence of
4181610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// CTOR and DTOR calls.
4182610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovstruct STRUCT {
4183610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  int a, b, c;
4184610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov};
4185610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4186610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovstruct A {
4187610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  int a;
4188610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  A() {
4189610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    ANNOTATE_TRACE_MEMORY(&a);
4190610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    a = 1;
4191610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
4192610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  virtual ~A() {
4193610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    a = 4;
4194610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
4195610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov};
4196610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4197610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovstruct B : A {
4198610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  B()  { CHECK(a == 1); }
4199610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  virtual ~B() { CHECK(a == 3); }
4200610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov};
4201610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovstruct C : B {
4202610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  C()  { a = 2; }
4203610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  virtual ~C() { a = 3; }
4204610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov};
4205610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4206610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint            GLOBAL = 0;
4207610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint           *STACK  = 0;
4208610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovSTRUCT         GLOB_STRUCT;
4209610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovSTRUCT        *STACK_STRUCT;
4210610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovSTRUCT        *HEAP_STRUCT;
4211610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4212610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker() {
4213610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOBAL = 1;
4214610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  *STACK = 1;
4215610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB_STRUCT.b   = 1;
4216610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  STACK_STRUCT->b = 1;
4217610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  HEAP_STRUCT->b  = 1;
4218610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
4219610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4220610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
4221610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  int stack_var = 0;
4222610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  STACK = &stack_var;
4223610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4224610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  STRUCT stack_struct;
4225610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  STACK_STRUCT = &stack_struct;
4226610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4227610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  HEAP_STRUCT = new STRUCT;
4228610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4229610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test89: negative\n");
4230610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Worker, Worker);
4231610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
4232610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
4233610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4234610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  delete HEAP_STRUCT;
4235610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4236610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  A *a = new C;
4237610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("Using 'a->a':  %d\n", a->a);
4238610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  delete a;
4239610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
4240610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST2(Run, 89, FEATURE|EXCLUDE_FROM_ALL)
4241610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test89
4242610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4243610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4244610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test90: FP. Test for a safely-published pointer (read-only). {{{1
4245610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test90 {
4246610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// The Publisher creates an object and safely publishes it under a mutex.
4247610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Readers access the object read-only.
4248610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// See also test91.
4249610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
4250610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Without annotations Helgrind will issue a false positive in Reader().
4251610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
4252610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Choices for annotations:
4253610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//   -- ANNOTATE_CONDVAR_SIGNAL/ANNOTATE_CONDVAR_WAIT
4254610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//   -- ANNOTATE_PURE_HAPPENS_BEFORE_MUTEX
4255610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//   -- ANNOTATE_PUBLISH_MEMORY_RANGE.
4256610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4257610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     *GLOB = 0;
4258610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex   MU;
4259610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4260610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovStealthNotification n1;
4261610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4262610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Publisher() {
4263610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
4264610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = (int*)malloc(128 * sizeof(int));
4265610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_TRACE_MEMORY(&GLOB[42]);
4266610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB[42] = 777;
4267610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  if (!Tsan_PureHappensBefore())
4268610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB[42], "test90. FP. This is a false positve");
4269610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
4270610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  n1.signal();
4271610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(200000);
4272610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
4273610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4274610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Reader() {
4275610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  n1.wait();
4276610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  while (true) {
4277610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    MU.Lock();
4278610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    int *p = &GLOB[42];
4279610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    MU.Unlock();
4280610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    if (p) {
4281610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      CHECK(*p == 777);  // Race is reported here.
4282610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      break;
4283610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    }
4284610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
4285610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
4286610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4287610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
4288610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test90: false positive (safely published pointer).\n");
4289610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Publisher, Reader, Reader, Reader);
4290610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
4291610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
4292610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  free(GLOB);
4293610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
4294610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST(Run, 90)
4295610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test90
4296610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4297610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4298610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test91: FP. Test for a safely-published pointer (read-write). {{{1
4299610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test91 {
4300610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Similar to test90.
4301610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// The Publisher creates an object and safely publishes it under a mutex MU1.
4302610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Accessors get the object under MU1 and access it (read/write) under MU2.
4303610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
4304610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Without annotations Helgrind will issue a false positive in Accessor().
4305610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
4306610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4307610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     *GLOB = 0;
4308610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex   MU, MU1, MU2;
4309610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4310610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Publisher() {
4311610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU1.Lock();
4312610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = (int*)malloc(128 * sizeof(int));
4313610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB[42] = 777;
4314610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  if (!Tsan_PureHappensBefore())
4315610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB[42], "test91. FP. This is a false positve");
4316610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU1.Unlock();
4317610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
4318610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4319610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Accessor() {
4320610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(10000);
4321610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  while (true) {
4322610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    MU1.Lock();
4323610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    int *p = &GLOB[42];
4324610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    MU1.Unlock();
4325610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    if (p) {
4326610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      MU2.Lock();
4327610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      (*p)++;  // Race is reported here.
4328610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      CHECK(*p >  777);
4329610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      MU2.Unlock();
4330610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      break;
4331610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    }
4332610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
4333610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
4334610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4335610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
4336610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test91: false positive (safely published pointer, read/write).\n");
4337610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Publisher, Accessor, Accessor, Accessor);
4338610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
4339610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
4340610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  free(GLOB);
4341610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
4342610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST(Run, 91)
4343610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test91
4344610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4345610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4346610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test92: TN. Test for a safely-published pointer (read-write), annotated. {{{1
4347610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test92 {
4348610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Similar to test91, but annotated with ANNOTATE_PUBLISH_MEMORY_RANGE.
4349610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
4350610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
4351610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Publisher:                                       Accessors:
4352610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
4353610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 1. MU1.Lock()
4354610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 2. Create GLOB.
4355610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 3. ANNOTATE_PUBLISH_...(GLOB) -------\            .
4356610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 4. MU1.Unlock()                       \           .
4357610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                                        \          a. MU1.Lock()
4358610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                                         \         b. Get GLOB
4359610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                                          \        c. MU1.Unlock()
4360610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//                                           \-->    d. Access GLOB
4361610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
4362610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//  A happens-before arc is created between ANNOTATE_PUBLISH_MEMORY_RANGE and
4363610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//  accesses to GLOB.
4364610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4365610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovstruct ObjType {
4366610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  int arr[10];
4367610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov};
4368610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4369610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovObjType *GLOB = 0;
4370610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex   MU, MU1, MU2;
4371610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4372610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Publisher() {
4373610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU1.Lock();
4374610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = new ObjType;
4375610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int i = 0; i < 10; i++) {
4376610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    GLOB->arr[i] = 777;
4377610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
4378610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // This annotation should go right before the object is published.
4379610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_PUBLISH_MEMORY_RANGE(GLOB, sizeof(*GLOB));
4380610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU1.Unlock();
4381610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
4382610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4383610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Accessor(int index) {
4384610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  while (true) {
4385610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    MU1.Lock();
4386610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    ObjType *p = GLOB;
4387610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    MU1.Unlock();
4388610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    if (p) {
4389610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      MU2.Lock();
4390610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      p->arr[index]++;  // W/o the annotations the race will be reported here.
4391610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      CHECK(p->arr[index] ==  778);
4392610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      MU2.Unlock();
4393610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      break;
4394610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    }
4395610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
4396610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
4397610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4398610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Accessor0() { Accessor(0); }
4399610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Accessor5() { Accessor(5); }
4400610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Accessor9() { Accessor(9); }
4401610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4402610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
4403610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test92: safely published pointer, read/write, annotated.\n");
4404610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Publisher, Accessor0, Accessor5, Accessor9);
4405610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
4406610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
4407610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\t*GLOB=%d\n", GLOB->arr[0]);
4408610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
4409610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST(Run, 92)
4410610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test92
4411610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4412610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4413610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test93: TP. Test for incorrect usage of ANNOTATE_PUBLISH_MEMORY_RANGE. {{{1
4414610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test93 {
4415610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
4416610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4417610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Reader() {
4418610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(GLOB == 0);
4419610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
4420610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4421610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Publisher() {
4422610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(10000);
4423610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // Incorrect, used after the memory has been accessed in another thread.
4424610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_PUBLISH_MEMORY_RANGE(&GLOB, sizeof(GLOB));
4425610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
4426610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4427610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
4428610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test93: positive, misuse of ANNOTATE_PUBLISH_MEMORY_RANGE\n");
4429610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Reader, Publisher);
4430610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
4431610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
4432610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB=%d\n", GLOB);
4433610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
4434610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST2(Run, 93, FEATURE|EXCLUDE_FROM_ALL)
4435610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test93
4436610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4437610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4438610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test94: TP. Check do_cv_signal/fake segment logic {{{1
4439610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test94 {
4440610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB;
4441610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4442610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint COND  = 0;
4443610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint COND2 = 0;
4444610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex MU, MU2;
4445610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovCondVar CV, CV2;
4446610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4447610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovStealthNotification n1, n2, n3;
4448610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4449610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Thr1() {
4450610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4451610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  n2.wait();  // Make sure the waiter blocks.
4452610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 1; // WRITE
4453610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4454610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
4455610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  COND = 1;
4456610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CV.Signal();
4457610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
4458610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  n1.signal();
4459610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
4460610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Thr2() {
4461610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // Make sure CV2.Signal() "happens after" CV.Signal()
4462610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  n1.wait();
4463610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // Make sure the waiter blocks.
4464610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  n3.wait();
4465610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4466610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU2.Lock();
4467610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  COND2 = 1;
4468610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CV2.Signal();
4469610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU2.Unlock();
4470610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
4471610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Thr3() {
4472610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
4473610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  n2.signal();
4474610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  while(COND != 1)
4475610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    CV.Wait(&MU);
4476610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
4477610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
4478610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Thr4() {
4479610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU2.Lock();
4480610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  n3.signal();
4481610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  while(COND2 != 1)
4482610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    CV2.Wait(&MU2);
4483610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU2.Unlock();
4484610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 2; // READ: no HB-relation between CV.Signal and CV2.Wait !
4485610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
4486610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
4487610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test94: TP.");
4488610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test94: TP. Check do_cv_signal/fake segment logic\n");
4489610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray mta(Thr1, Thr2, Thr3, Thr4);
4490610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  mta.Start();
4491610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  mta.Join();
4492610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB=%d\n", GLOB);
4493610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
4494610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST(Run, 94);
4495610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test94
4496610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4497610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test95: TP. Check do_cv_signal/fake segment logic {{{1
4498610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test95 {
4499610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
4500610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4501610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint COND  = 0;
4502610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint COND2 = 0;
4503610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex MU, MU2;
4504610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovCondVar CV, CV2;
4505610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4506610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Thr1() {
4507610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(1000*1000); // Make sure CV2.Signal() "happens before" CV.Signal()
4508610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(10000);  // Make sure the waiter blocks.
4509610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4510610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 1; // WRITE
4511610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4512610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
4513610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  COND = 1;
4514610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CV.Signal();
4515610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
4516610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
4517610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Thr2() {
4518610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(10000);  // Make sure the waiter blocks.
4519610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4520610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU2.Lock();
4521610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  COND2 = 1;
4522610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CV2.Signal();
4523610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU2.Unlock();
4524610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
4525610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Thr3() {
4526610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
4527610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  while(COND != 1)
4528610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    CV.Wait(&MU);
4529610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
4530610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
4531610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Thr4() {
4532610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU2.Lock();
4533610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  while(COND2 != 1)
4534610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    CV2.Wait(&MU2);
4535610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU2.Unlock();
4536610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 2; // READ: no HB-relation between CV.Signal and CV2.Wait !
4537610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
4538610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
4539610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test95: TP.");
4540610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test95: TP. Check do_cv_signal/fake segment logic\n");
4541610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray mta(Thr1, Thr2, Thr3, Thr4);
4542610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  mta.Start();
4543610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  mta.Join();
4544610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB=%d\n", GLOB);
4545610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
4546610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST(Run, 95);
4547610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test95
4548610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4549610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test96: TN. tricky LockSet behaviour {{{1
4550610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 3 threads access the same memory with three different
4551610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// locksets: {A, B}, {B, C}, {C, A}.
4552610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// These locksets have empty intersection
4553610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test96 {
4554610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
4555610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4556610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex A, B, C;
4557610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4558610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Thread1() {
4559610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MutexLock a(&A);
4560610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MutexLock b(&B);
4561610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB++;
4562610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
4563610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4564610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Thread2() {
4565610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MutexLock b(&B);
4566610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MutexLock c(&C);
4567610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB++;
4568610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
4569610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4570610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Thread3() {
4571610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MutexLock a(&A);
4572610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MutexLock c(&C);
4573610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB++;
4574610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
4575610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4576610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
4577610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test96: FP. tricky LockSet behaviour\n");
4578610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_TRACE_MEMORY(&GLOB);
4579610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray mta(Thread1, Thread2, Thread3);
4580610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  mta.Start();
4581610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  mta.Join();
4582610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(GLOB == 3);
4583610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB=%d\n", GLOB);
4584610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
4585610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST(Run, 96);
4586610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test96
4587610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4588610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace FalseNegativeOfFastModeTest {  // {{{1
4589610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// This test shows false negative with --fast-mode=yes.
4590610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovconst int HG_CACHELINE_SIZE = 64;
4591610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4592610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovStealthNotification n1, n2;
4593610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4594610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovconst int ARRAY_SIZE = HG_CACHELINE_SIZE * 4 / sizeof(int);
4595610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint array[ARRAY_SIZE];
4596610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint * GLOB = &array[ARRAY_SIZE/2];
4597610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov/*
4598610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  We use sizeof(array) == 4 * HG_CACHELINE_SIZE to be sure that GLOB points
4599610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  to a memory inside a CacheLineZ which is inside array's memory range
4600610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov */
4601610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4602610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Reader() {
4603610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  n1.wait();
4604610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(0 != *GLOB);
4605610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  n2.signal();
4606610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
4607610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4608610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(PositiveTests, FalseNegativeOfFastModeTest) {
4609610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Reader);
4610610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_TRACE_MEMORY(GLOB);
4611610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_EXPECT_RACE_FOR_TSAN(GLOB, __FUNCTION__);
4612610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4613610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
4614610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  *GLOB = 0x12345;
4615610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  n1.signal();
4616610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  n2.wait();
4617610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
4618610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
4619610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace
4620610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4621610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test99: TP. Unit test for a bug in LockWhen*. {{{1
4622610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test99 {
4623610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4624610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4625610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovbool GLOB = false;
4626610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex mu;
4627610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4628610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovstatic void Thread1() {
4629610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int i = 0; i < 100; i++) {
4630610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    mu.LockWhenWithTimeout(Condition(&ArgIsTrue, &GLOB), 5);
4631610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    GLOB = false;
4632610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    mu.Unlock();
4633610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    usleep(10000);
4634610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
4635610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
4636610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4637610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovstatic void Thread2() {
4638610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int i = 0; i < 100; i++) {
4639610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    mu.Lock();
4640610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    mu.Unlock();
4641610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    usleep(10000);
4642610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
4643610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
4644610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4645610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
4646610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test99: regression test for LockWhen*\n");
4647610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Thread1, Thread2);
4648610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
4649610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
4650610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
4651610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST(Run, 99);
4652610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test99
4653610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4654610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4655610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test100: Test for initialization bit. {{{1
4656610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test100 {
4657610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     G1 = 0;
4658610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     G2 = 0;
4659610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     G3 = 0;
4660610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     G4 = 0;
4661610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4662610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Creator() {
4663610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  G1 = 1; CHECK(G1);
4664610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  G2 = 1;
4665610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  G3 = 1; CHECK(G3);
4666610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  G4 = 1;
4667610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
4668610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4669610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker1() {
4670610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(100000);
4671610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(G1);
4672610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(G2);
4673610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  G3 = 3;
4674610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  G4 = 3;
4675610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
4676610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4677610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker2() {
4678610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4679610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
4680610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4681610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4682610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
4683610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test100: test for initialization bit. \n");
4684610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Creator, Worker1, Worker2);
4685610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_TRACE_MEMORY(&G1);
4686610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_TRACE_MEMORY(&G2);
4687610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_TRACE_MEMORY(&G3);
4688610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_TRACE_MEMORY(&G4);
4689610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
4690610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
4691610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
4692610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST2(Run, 100, FEATURE|EXCLUDE_FROM_ALL)
4693610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test100
4694610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4695610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4696610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test101: TN. Two signals and two waits. {{{1
4697610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test101 {
4698610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex MU;
4699610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovCondVar CV;
4700610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
4701610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4702610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint C1 = 0, C2 = 0;
4703610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4704610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Signaller() {
4705610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(100000);
4706610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
4707610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  C1 = 1;
4708610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CV.Signal();
4709610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("signal\n");
4710610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
4711610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4712610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 1;
4713610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4714610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(500000);
4715610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
4716610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  C2 = 1;
4717610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CV.Signal();
4718610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("signal\n");
4719610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
4720610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
4721610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4722610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Waiter() {
4723610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
4724610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  while(!C1)
4725610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    CV.Wait(&MU);
4726610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("wait\n");
4727610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
4728610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4729610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
4730610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  while(!C2)
4731610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    CV.Wait(&MU);
4732610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("wait\n");
4733610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();
4734610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4735610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 2;
4736610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4737610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
4738610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4739610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
4740610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test101: negative\n");
4741610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Waiter, Signaller);
4742610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
4743610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
4744610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB=%d\n", GLOB);
4745610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
4746610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST(Run, 101)
4747610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test101
4748610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4749610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test102: --fast-mode=yes vs. --initialization-bit=yes {{{1
4750610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test102 {
4751610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovconst int HG_CACHELINE_SIZE = 64;
4752610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4753610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex MU;
4754610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4755610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovconst int ARRAY_SIZE = HG_CACHELINE_SIZE * 4 / sizeof(int);
4756610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint array[ARRAY_SIZE + 1];
4757610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint * GLOB = &array[ARRAY_SIZE/2];
4758610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov/*
4759610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  We use sizeof(array) == 4 * HG_CACHELINE_SIZE to be sure that GLOB points
4760610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  to a memory inside a CacheLineZ which is inside array's memory range
4761610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov*/
4762610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4763610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovStealthNotification n1, n2, n3;
4764610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4765610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Reader() {
4766610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  n1.wait();
4767610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(777 == GLOB[0]);
4768610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  n2.signal();
4769610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  n3.wait();
4770610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(777 == GLOB[1]);
4771610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
4772610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4773610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
4774610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Reader);
4775610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_EXPECT_RACE_FOR_TSAN(GLOB+0, "test102: TP. FN with --fast-mode=yes");
4776610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_EXPECT_RACE_FOR_TSAN(GLOB+1, "test102: TP");
4777610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test102: --fast-mode=yes vs. --initialization-bit=yes\n");
4778610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4779610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
4780610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB[0] = 777;
4781610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  n1.signal();
4782610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  n2.wait();
4783610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB[1] = 777;
4784610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  n3.signal();
4785610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
4786610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
4787610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4788610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST2(Run, 102, FEATURE)
4789610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test102
4790610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4791610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test103: Access different memory locations with different LockSets {{{1
4792610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test103 {
4793610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovconst int N_MUTEXES = 6;
4794610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovconst int LOCKSET_INTERSECTION_SIZE = 3;
4795610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4796610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint data[1 << LOCKSET_INTERSECTION_SIZE] = {0};
4797610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex MU[N_MUTEXES];
4798610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4799610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovinline int LS_to_idx (int ls) {
4800610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  return (ls >> (N_MUTEXES - LOCKSET_INTERSECTION_SIZE))
4801610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      & ((1 << LOCKSET_INTERSECTION_SIZE) - 1);
4802610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
4803610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4804610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker() {
4805610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int ls = 0; ls < (1 << N_MUTEXES); ls++) {
4806610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    if (LS_to_idx(ls) == 0)
4807610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      continue;
4808610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    for (int m = 0; m < N_MUTEXES; m++)
4809610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      if (ls & (1 << m))
4810610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov        MU[m].Lock();
4811610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4812610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    data[LS_to_idx(ls)]++;
4813610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4814610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    for (int m = N_MUTEXES - 1; m >= 0; m--)
4815610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      if (ls & (1 << m))
4816610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov        MU[m].Unlock();
4817610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
4818610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
4819610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4820610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
4821610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test103: Access different memory locations with different LockSets\n");
4822610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Worker, Worker, Worker, Worker);
4823610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
4824610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
4825610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
4826610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST2(Run, 103, FEATURE)
4827610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test103
4828610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4829610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test104: TP. Simple race (write vs write). Heap mem. {{{1
4830610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test104 {
4831610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     *GLOB = NULL;
4832610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker() {
4833610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB[42] = 1;
4834610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
4835610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4836610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Parent() {
4837610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThread t(Worker);
4838610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
4839610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(100000);
4840610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB[42] = 2;
4841610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
4842610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
4843610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
4844610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = (int*)malloc(128 * sizeof(int));
4845610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB[42] = 0;
4846610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_EXPECT_RACE(&GLOB[42], "test104. TP.");
4847610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_TRACE_MEMORY(&GLOB[42]);
4848610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test104: positive\n");
4849610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  Parent();
4850610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB=%d\n", GLOB[42]);
4851610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  free(GLOB);
4852610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
4853610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST(Run, 104);
4854610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test104
4855610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4856610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4857610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test105: Checks how stack grows. {{{1
4858610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test105 {
4859610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
4860610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4861610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid F1() {
4862610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  int ar[32];
4863610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//  ANNOTATE_TRACE_MEMORY(&ar[0]);
4864610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//  ANNOTATE_TRACE_MEMORY(&ar[31]);
4865610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ar[0] = 1;
4866610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ar[31] = 1;
4867610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(ar[0] == 1);
4868610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
4869610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4870610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker() {
4871610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  int ar[32];
4872610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//  ANNOTATE_TRACE_MEMORY(&ar[0]);
4873610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//  ANNOTATE_TRACE_MEMORY(&ar[31]);
4874610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ar[0] = 1;
4875610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ar[31] = 1;
4876610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(ar[0] == 1);
4877610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  F1();
4878610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
4879610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4880610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
4881610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test105: negative\n");
4882610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  Worker();
4883610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThread t(Worker);
4884610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
4885610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
4886610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB=%d\n", GLOB);
4887610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
4888610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST(Run, 105)
4889610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test105
4890610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4891610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4892610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test107: Test for ANNOTATE_EXPECT_RACE {{{1
4893610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test107 {
4894610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
4895610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
4896610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test107: negative\n");
4897610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_EXPECT_RACE(&GLOB, "No race in fact. Just checking the tool.");
4898610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB=%d\n", GLOB);
4899610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
4900610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST2(Run, 107, FEATURE|EXCLUDE_FROM_ALL)
4901610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test107
4902610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4903610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4904610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test108: TN. initialization of static object. {{{1
4905610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test108 {
4906610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Here we have a function-level static object.
4907610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Starting from gcc 4 this is therad safe,
4908610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// but is is not thread safe with many other compilers.
4909610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
4910610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Helgrind/ThreadSanitizer supports this kind of initialization by
4911610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// intercepting __cxa_guard_acquire/__cxa_guard_release
4912610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// and ignoring all accesses between them.
4913610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// pthread_once is supported in the same manner.
4914610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovclass Foo {
4915610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov public:
4916610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  Foo() {
4917610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    ANNOTATE_TRACE_MEMORY(&a_);
4918610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    a_ = 42;
4919610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
4920610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  void Check() const { CHECK(a_ == 42); }
4921610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov private:
4922610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  int a_;
4923610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov};
4924610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4925610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovconst Foo *GetFoo() {
4926610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  static const Foo *foo = new Foo();
4927610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  return foo;
4928610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
4929610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker0() {
4930610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GetFoo();
4931610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
4932610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4933610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker() {
4934610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(200000);
4935610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  const Foo *foo = GetFoo();
4936610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  foo->Check();
4937610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
4938610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4939610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4940610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
4941610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test108: negative, initialization of static object\n");
4942610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Worker0, Worker, Worker);
4943610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
4944610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
4945610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
4946610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#ifdef __GNUC__
4947610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST2(Run, 108, FEATURE)
4948610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#endif
4949610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test108
4950610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4951610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4952610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test109: TN. Checking happens before between parent and child threads. {{{1
4953610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test109 {
4954610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Check that the detector correctly connects
4955610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//   pthread_create with the new thread
4956610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// and
4957610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//   thread exit with pthread_join
4958610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovconst int N = 32;
4959610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovstatic int GLOB[N];
4960610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4961610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker(void *a) {
4962610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(10000);
4963610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//  printf("--Worker : %ld %p\n", (int*)a - GLOB, (void*)pthread_self());
4964610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  int *arg = (int*)a;
4965610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  (*arg)++;
4966610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
4967610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4968610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
4969610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test109: negative\n");
4970610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThread *t[N];
4971610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int i  = 0; i < N; i++) {
4972610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    t[i] = new MyThread(Worker, &GLOB[i]);
4973610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
4974610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int i  = 0; i < N; i++) {
4975610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    ANNOTATE_TRACE_MEMORY(&GLOB[i]);
4976610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    GLOB[i] = 1;
4977610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    t[i]->Start();
4978610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//    printf("--Started: %p\n", (void*)t[i]->tid());
4979610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
4980610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int i  = 0; i < N; i++) {
4981610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//    printf("--Joining: %p\n", (void*)t[i]->tid());
4982610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    t[i]->Join();
4983610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//    printf("--Joined : %p\n", (void*)t[i]->tid());
4984610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    GLOB[i]++;
4985610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
4986610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int i  = 0; i < N; i++) delete t[i];
4987610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4988610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB=%d\n", GLOB[13]);
4989610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
4990610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST(Run, 109)
4991610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test109
4992610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4993610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
4994610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test111: TN. Unit test for a bug related to stack handling. {{{1
4995610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test111 {
4996610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovchar     *GLOB = 0;
4997610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovbool COND = false;
4998610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex mu;
4999610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovconst int N = 3000;
5000610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5001610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid write_to_p(char *p, int val) {
5002610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int i = 0; i < N; i++)
5003610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    p[i] = val;
5004610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
5005610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5006610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid f1() {
5007610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  char some_stack[N];
5008610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  write_to_p(some_stack, 1);
5009610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  mu.LockWhen(Condition(&ArgIsTrue, &COND));
5010610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  mu.Unlock();
5011610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
5012610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5013610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid f2() {
5014610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  char some_stack[N];
5015610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  char some_more_stack[N];
5016610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  write_to_p(some_stack, 2);
5017610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  write_to_p(some_more_stack, 2);
5018610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
5019610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5020610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid f0() { f2(); }
5021610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5022610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker1() {
5023610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  f0();
5024610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  f1();
5025610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  f2();
5026610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
5027610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5028610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker2() {
5029610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(100000);
5030610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  mu.Lock();
5031610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  COND = true;
5032610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  mu.Unlock();
5033610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
5034610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5035610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
5036610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test111: regression test\n");
5037610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Worker1, Worker1, Worker2);
5038610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
5039610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
5040610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
5041610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST2(Run, 111, FEATURE)
5042610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test111
5043610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5044610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test112: STAB. Test for ANNOTATE_PUBLISH_MEMORY_RANGE{{{1
5045610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test112 {
5046610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovchar     *GLOB = 0;
5047610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovconst int N = 64 * 5;
5048610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex mu;
5049610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovbool ready = false; // under mu
5050610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint beg, end; // under mu
5051610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5052610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex mu1;
5053610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5054610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker() {
5055610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5056610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  bool is_ready = false;
5057610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  int b, e;
5058610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  while (!is_ready) {
5059610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    mu.Lock();
5060610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    is_ready = ready;
5061610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    b = beg;
5062610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    e = end;
5063610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    mu.Unlock();
5064610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    usleep(1000);
5065610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
5066610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5067610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  mu1.Lock();
5068610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int i = b; i < e; i++) {
5069610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    GLOB[i]++;
5070610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
5071610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  mu1.Unlock();
5072610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
5073610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5074610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid PublishRange(int b, int e) {
5075610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Worker, Worker);
5076610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ready = false; // runs before other threads
5077610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
5078610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5079610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_NEW_MEMORY(GLOB + b, e - b);
5080610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_TRACE_MEMORY(GLOB + b);
5081610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int j = b; j < e; j++) {
5082610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    GLOB[j] = 0;
5083610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
5084610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_PUBLISH_MEMORY_RANGE(GLOB + b, e - b);
5085610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5086610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // hand off
5087610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  mu.Lock();
5088610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ready = true;
5089610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  beg = b;
5090610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  end = e;
5091610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  mu.Unlock();
5092610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5093610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
5094610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
5095610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5096610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
5097610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test112: stability (ANNOTATE_PUBLISH_MEMORY_RANGE)\n");
5098610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = new char [N];
5099610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5100610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  PublishRange(0, 10);
5101610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  PublishRange(3, 5);
5102610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5103610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  PublishRange(12, 13);
5104610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  PublishRange(10, 14);
5105610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5106610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  PublishRange(15, 17);
5107610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  PublishRange(16, 18);
5108610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5109610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // do few more random publishes.
5110610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int i = 0; i < 20; i++) {
5111610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    const int begin = rand() % N;
5112610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    const int size = (rand() % (N - begin)) + 1;
5113610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    CHECK(size > 0);
5114610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    CHECK(begin + size <= N);
5115610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    PublishRange(begin, begin + size);
5116610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
5117610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5118610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("GLOB = %d\n", (int)GLOB[0]);
5119610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
5120610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST2(Run, 112, STABILITY)
5121610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test112
5122610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5123610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5124610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test113: PERF. A lot of lock/unlock calls. Many locks {{{1
5125610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace    test113 {
5126610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovconst int kNumIter = 100000;
5127610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovconst int kNumLocks = 7;
5128610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex   MU[kNumLocks];
5129610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST (StressTests, ManyLocksUnlocks2) {
5130610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test113: perf\n");
5131610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int i = 0; i < kNumIter; i++ ) {
5132610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    for (int j = 0; j < kNumLocks; j++) {
5133610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      if (i & (1 << j)) MU[j].Lock();
5134610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    }
5135610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    for (int j = kNumLocks - 1; j >= 0; j--) {
5136610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      if (i & (1 << j)) MU[j].Unlock();
5137610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    }
5138610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
5139610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
5140610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test113
5141610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5142610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5143610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test114: STAB. Recursive static initialization. {{{1
5144610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace    test114 {
5145610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint Bar() {
5146610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  static int bar = 1;
5147610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  return bar;
5148610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
5149610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint Foo() {
5150610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  static int foo = Bar();
5151610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  return foo;
5152610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
5153610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker() {
5154610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  static int x = Foo();
5155610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(x == 1);
5156610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
5157610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
5158610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test114: stab\n");
5159610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Worker, Worker);
5160610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
5161610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
5162610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
5163610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#ifdef __GNUC__
5164610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST(Run, 114)
5165610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#endif
5166610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test114
5167610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5168610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test116: TN. some operations with string<> objects. {{{1
5169610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test116 {
5170610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5171610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker() {
5172610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  string A[10], B[10], C[10];
5173610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int i = 0; i < 1000; i++) {
5174610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    for (int j = 0; j < 10; j++) {
5175610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      string &a = A[j];
5176610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      string &b = B[j];
5177610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      string &c = C[j];
5178610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      a = "sdl;fkjhasdflksj df";
5179610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      b = "sdf sdf;ljsd ";
5180610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      c = "'sfdf df";
5181610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      c = b;
5182610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      a = c;
5183610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      b = a;
5184610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      swap(a,b);
5185610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      swap(b,c);
5186610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    }
5187610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    for (int j = 0; j < 10; j++) {
5188610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      string &a = A[j];
5189610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      string &b = B[j];
5190610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      string &c = C[j];
5191610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      a.clear();
5192610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      b.clear();
5193610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      c.clear();
5194610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    }
5195610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
5196610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
5197610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5198610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
5199610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test116: negative (strings)\n");
5200610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Worker, Worker, Worker);
5201610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
5202610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
5203610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
5204610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST2(Run, 116, FEATURE|EXCLUDE_FROM_ALL)
5205610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test116
5206610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5207610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test117: TN. Many calls to function-scope static init. {{{1
5208610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test117 {
5209610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovconst int N = 50;
5210610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5211610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint Foo() {
5212610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(20000);
5213610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  return 1;
5214610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
5215610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5216610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker(void *a) {
5217610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  static int foo = Foo();
5218610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(foo == 1);
5219610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
5220610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5221610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
5222610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test117: negative\n");
5223610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThread *t[N];
5224610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int i  = 0; i < N; i++) {
5225610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    t[i] = new MyThread(Worker);
5226610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
5227610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int i  = 0; i < N; i++) {
5228610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    t[i]->Start();
5229610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
5230610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int i  = 0; i < N; i++) {
5231610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    t[i]->Join();
5232610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
5233610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int i  = 0; i < N; i++) delete t[i];
5234610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
5235610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#ifndef WIN32
5236610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// This is racey on Windows!
5237610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST(Run, 117)
5238610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#endif
5239610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test117
5240610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5241610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5242610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5243610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test118 PERF: One signal, multiple waits. {{{1
5244610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace   test118 {
5245610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
5246610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovconst int kNumIter = 2000000;
5247610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Signaller() {
5248610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(50000);
5249610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_CONDVAR_SIGNAL(&GLOB);
5250610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
5251610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Waiter() {
5252610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int i = 0; i < kNumIter; i++) {
5253610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    ANNOTATE_CONDVAR_WAIT(&GLOB);
5254610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    if (i == kNumIter / 2)
5255610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      usleep(100000);
5256610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
5257610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
5258610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(StressTests, OneSignalManyWaits) {
5259610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test118: perf\n");
5260610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Signaller, Waiter, Signaller, Waiter);
5261610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
5262610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
5263610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB=%d\n", GLOB);
5264610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
5265610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test118
5266610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5267610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5268610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test119: TP. Testing that malloc does not introduce any HB arc. {{{1
5269610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test119 {
5270610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
5271610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker1() {
5272610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 1;
5273610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  free(malloc(123));
5274610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
5275610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker2() {
5276610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(100000);
5277610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  free(malloc(345));
5278610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 2;
5279610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
5280610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
5281610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test119: positive (checking if malloc creates HB arcs)\n");
5282610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  if (!(Tsan_PureHappensBefore() && kMallocUsesMutex))
5283610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "true race");
5284610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Worker1, Worker2);
5285610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
5286610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
5287610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB=%d\n", GLOB);
5288610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
5289610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST(Run, 119)
5290610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test119
5291610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5292610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5293610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test120: TP. Thread1: write then read. Thread2: read. {{{1
5294610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test120 {
5295610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
5296610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5297610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Thread1() {
5298610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 1;           // write
5299610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(GLOB);        // read
5300610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
5301610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5302610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Thread2() {
5303610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(100000);
5304610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(GLOB >= 0);   // read
5305610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
5306610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5307610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
5308610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "TP (T1: write then read, T2: read)");
5309610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test120: positive\n");
5310610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Thread1, Thread2);
5311610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 1;
5312610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
5313610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
5314610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB=%d\n", GLOB);
5315610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
5316610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST(Run, 120)
5317610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test120
5318610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5319610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5320610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace DoubleCheckedLocking {  // {{{1
5321610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovstruct Foo {
5322610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  uintptr_t padding1[16];
5323610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  uintptr_t a;
5324610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  uintptr_t padding2[16];
5325610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov};
5326610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5327610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovstatic Mutex mu;
5328610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovstatic Foo  *foo;
5329610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5330610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid InitMe() {
5331610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  if (!foo) {
5332610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    MutexLock lock(&mu);
5333610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    if (!foo) {
5334610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      ANNOTATE_EXPECT_RACE_FOR_TSAN(&foo, "Double-checked locking (ptr)");
5335610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      foo = new Foo;
5336610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      if (Tsan_PureHappensBefore()) {
5337610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov        // A pure h-b detector may or may not detect this.
5338610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov        ANNOTATE_BENIGN_RACE(&foo->a, "real race");
5339610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      } else {
5340610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov        // ThreadSanitizer in full hybrid mode must detect it.
5341610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov        ANNOTATE_EXPECT_RACE_FOR_TSAN(&foo->a, "Double-checked locking (obj)");
5342610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      }
5343610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      foo->a = 42;
5344610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    }
5345610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
5346610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
5347610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5348610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid UseMe() {
5349610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  InitMe();
5350610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(foo);
5351610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  if (foo->a != 42) {
5352610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    printf("foo->a = %d (should be 42)\n", (int)foo->a);
5353610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
5354610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
5355610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5356610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker1() { UseMe(); }
5357610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker2() { UseMe(); }
5358610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker3() { UseMe(); }
5359610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5360610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5361610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(PositiveTests, DoubleCheckedLocking1) {
5362610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  foo = NULL;
5363610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t1(Worker1, Worker2, Worker3);
5364610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t1.Start();
5365610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t1.Join();
5366610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  delete foo;
5367610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
5368610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace DoubleCheckedLocking
5369610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5370610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace DoubleCheckedLocking2 {  // {{{1
5371610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovstruct Foo {
5372610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  uintptr_t padding1[16];
5373610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  uintptr_t a;
5374610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  uintptr_t padding2[16];
5375610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov};
5376610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5377610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovFoo *foo;
5378610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex mu;
5379610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5380610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid InitMe() {
5381610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  if (foo) return;
5382610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  Foo *x = new Foo;
5383610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_BENIGN_RACE(&x->a, "may or may not detect this race");
5384610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  x->a = 42;
5385610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  {
5386610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    MutexLock lock(&mu);
5387610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    if (!foo) {
5388610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      foo = x;
5389610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      x = NULL;
5390610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    }
5391610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
5392610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  if (x) delete x;
5393610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
5394610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5395610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker() {
5396610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  InitMe();
5397610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(foo);
5398610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(foo->a == 42);
5399610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
5400610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5401610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(PositiveTests, DoubleCheckedLocking2) {
5402610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  foo = NULL;
5403610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_EXPECT_RACE(&foo, "real race");
5404610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t1(Worker, Worker, Worker, Worker);
5405610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t1.Start();
5406610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t1.Join();
5407610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  delete foo;
5408610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
5409610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5410610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace DoubleCheckedLocking2
5411610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5412610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace PositiveTests_DifferentSizeAccessTest {  // {{{1
5413610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5414610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovuint64_t arr[1000];
5415610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovsize_t    arr_index = 0;
5416610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovuint64_t *MEM;
5417610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovsize_t size[3];
5418610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovsize_t offset[3];
5419610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5420610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid GenericWrite(size_t s, size_t off) {
5421610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  switch(s) {
5422610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    case 8:
5423610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      CHECK(off == 0);
5424610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      ((uint64_t*)MEM)[off] = 1;
5425610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      break;
5426610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    case 4:
5427610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      CHECK(off < 2);
5428610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      ((uint32_t*)MEM)[off] = 1;
5429610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      break;
5430610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    case 2:
5431610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      CHECK(off < 4);
5432610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      ((uint16_t*)MEM)[off] = 1;
5433610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      break;
5434610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    case 1:
5435610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      CHECK(off < 8);
5436610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      ((uint8_t*)MEM)[off] = 1;
5437610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      break;
5438610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    default: CHECK(0); break;
5439610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
5440610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
5441610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5442610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Thread1() { GenericWrite(size[0], offset[0]); }
5443610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Thread2() { GenericWrite(size[1], offset[1]); }
5444610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5445610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovbool TwoRangesIntersect(size_t beg1, size_t end1, size_t beg2, size_t end2) {
5446610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  if (beg1 <= beg2 && end1 > beg2) return true;
5447610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  if (beg2 <= beg1 && end2 > beg1) return true;
5448610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  return false;
5449610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
5450610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5451610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid RunTwoThreads(size_t size1, size_t offset1, size_t size2, size_t offset2) {
5452610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  size[0] = size1;
5453610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  size[1] = size2;
5454610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  offset[0] = offset1;
5455610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  offset[1] = offset2;
5456610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  long beg1 = offset1 * size1;
5457610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  long end1 = beg1 + size1;
5458610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  long beg2 = offset2 * size2;
5459610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  long end2 = beg2 + size2;
5460610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  bool have_intersection = TwoRangesIntersect(beg1, end1, beg2, end2);
5461610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  char descr[1024];
5462610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MEM = &arr[arr_index++];
5463610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  sprintf(descr, "Testing: [%ld, %ld) vs [%ld, %ld] (%s intersection); p=%p",
5464610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov          beg1, end1, beg2, end2, have_intersection ? "have" : "no", MEM);
5465610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  fprintf(stderr, "%s\n", descr);
5466610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  char *racey_addr_beg = (char*)MEM + max(beg1, beg2);
5467610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  char *racey_addr_end = (char*)MEM + min(end1, end2);
5468610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  if (have_intersection) {
5469610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    ANNOTATE_EXPECT_RACE(racey_addr_beg, descr);
5470610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    if (racey_addr_end - racey_addr_beg >= 2) {
5471610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      // We expect a race on the first racey byte, but we may also see some
5472610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      // races in other bytes (e.g. if a 8-byte store is implemented via two
5473610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      // 4-byte stores on a 32-bit arch). Ignore these extra races.
5474610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      ANNOTATE_BENIGN_RACE_SIZED(racey_addr_beg+1, racey_addr_end - racey_addr_beg - 1,
5475610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov                           "race");
5476610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    }
5477610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
5478610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t1(Thread1, Thread2);
5479610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t1.Start();
5480610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t1.Join();
5481610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
5482610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5483610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid TestTwoSizes(size_t size1, size_t offset1, size_t size2, size_t offset2) {
5484610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  RunTwoThreads(size1, offset1, size2, offset2);
5485610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  RunTwoThreads(size2, offset2, size1, offset1);
5486610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
5487610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5488610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(PositiveTests, DifferentSizeAccessTest) {
5489610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for(int size1_log = 3; size1_log >= 0; size1_log--) {
5490610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    for (int size2_log = size1_log; size2_log >= 0; size2_log--) {
5491610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      for (int off1 = 0; off1 < (1 << (3-size1_log)); off1++) {
5492610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov        for (int off2 = 0; off2 < (1 << (3-size2_log)); off2++) {
5493610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov          RunTwoThreads(1 << size1_log, off1, 1 << size2_log, off2);
5494610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov        }
5495610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      }
5496610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    }
5497610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
5498610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
5499610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5500610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5501610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovconst int kStressArrSize = 100;
5502610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovchar stress_arr[kStressArrSize];
5503610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5504610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid StressWorker() {
5505610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  const int n = 100000;
5506610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  char foo[kStressArrSize];
5507610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  memset(foo, 0, sizeof(foo));
5508610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int i = 0; i < n; i++) {
5509610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    memcpy(stress_arr + i % (kStressArrSize / 2), foo, i % (kStressArrSize / 3));
5510610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
5511610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
5512610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5513610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(StressTests, DifferentSizeAccessStressTest) {
5514610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_BENIGN_RACE_SIZED(stress_arr, sizeof(stress_arr), "race");
5515610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(StressWorker, StressWorker, StressWorker);
5516610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
5517610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
5518610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
5519610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace
5520610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5521610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test124: What happens if we delete an unlocked lock? {{{1
5522610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test124 {
5523610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// This test does not worg with pthreads (you can't call
5524610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// pthread_mutex_destroy on a locked lock).
5525610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
5526610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovconst int N = 1000;
5527610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker() {
5528610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  Mutex *a_large_local_array_of_mutexes;
5529610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  a_large_local_array_of_mutexes = new Mutex[N];
5530610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int i = 0; i < N; i++) {
5531610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    a_large_local_array_of_mutexes[i].Lock();
5532610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
5533610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  delete []a_large_local_array_of_mutexes;
5534610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 1;
5535610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
5536610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5537610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
5538610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test124: negative\n");
5539610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Worker, Worker, Worker);
5540610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
5541610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
5542610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB=%d\n", GLOB);
5543610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
5544610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST2(Run, 124, FEATURE|EXCLUDE_FROM_ALL)
5545610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test124
5546610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5547610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5548610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test126 TN: test for BlockingCounter {{{1
5549610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace  test126 {
5550610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovBlockingCounter *blocking_counter;
5551610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
5552610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker() {
5553610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(blocking_counter);
5554610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(GLOB == 0);
5555610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  blocking_counter->DecrementCount();
5556610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
5557610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
5558610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test126: negative\n");
5559610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Worker, Worker, Worker);
5560610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  blocking_counter = new BlockingCounter(3);
5561610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
5562610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  blocking_counter->Wait();
5563610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 1;
5564610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
5565610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB=%d\n", GLOB);
5566610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
5567610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST(Run, 126)
5568610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test126
5569610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5570610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5571610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test127. Bad code: unlocking a mutex locked by another thread. {{{1
5572610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test127 {
5573610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex mu;
5574610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Thread1() {
5575610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  mu.Lock();
5576610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(1); // avoid tail call elimination
5577610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
5578610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Thread2() {
5579610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(100000);
5580610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  mu.Unlock();
5581610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(1); // avoid tail call elimination
5582610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
5583610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(LockTests, UnlockingALockHeldByAnotherThread) {
5584610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Thread1, Thread2);
5585610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
5586610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
5587610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
5588610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test127
5589610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5590610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test128. Suppressed code in concurrent accesses {{{1
5591610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Please use --suppressions=unittest.supp flag when running this test.
5592610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test128 {
5593610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex mu;
5594610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint GLOB = 0;
5595610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker() {
5596610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(100000);
5597610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  mu.Lock();
5598610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB++;
5599610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  mu.Unlock();
5600610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
5601610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid ThisFunctionShouldBeSuppressed() {
5602610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB++;
5603610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
5604610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
5605610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test128: Suppressed code in concurrent accesses.\n");
5606610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Worker, ThisFunctionShouldBeSuppressed);
5607610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
5608610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
5609610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
5610610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST2(Run, 128, FEATURE | EXCLUDE_FROM_ALL)
5611610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test128
5612610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5613610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test129: TN. Synchronization via ReaderLockWhen(). {{{1
5614610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test129 {
5615610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
5616610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex   MU;
5617610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovbool WeirdCondition(int* param) {
5618610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  *param = GLOB;  // a write into Waiter's memory
5619610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  return GLOB > 0;
5620610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
5621610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Waiter() {
5622610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  int param = 0;
5623610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.ReaderLockWhen(Condition(WeirdCondition, &param));
5624610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.ReaderUnlock();
5625610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(GLOB > 0);
5626610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(param > 0);
5627610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
5628610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Waker() {
5629610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(100000);  // Make sure the waiter blocks.
5630610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Lock();
5631610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB++;
5632610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MU.Unlock();     // calls ANNOTATE_CONDVAR_SIGNAL;
5633610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
5634610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
5635610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test129: Synchronization via ReaderLockWhen()\n");
5636610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThread mt(Waiter, NULL, "Waiter Thread");
5637610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  mt.Start();
5638610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  Waker();
5639610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  mt.Join();
5640610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB=%d\n", GLOB);
5641610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
5642610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST2(Run, 129, FEATURE);
5643610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test129
5644610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5645610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace NegativeTests_PerThreadTest {  // {{{1
5646610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#ifdef TLS
5647610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// This test verifies that the race detector handles
5648610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// thread-local storage (TLS) correctly.
5649610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// As of 09-03-30 ThreadSanitizer has a bug:
5650610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//   - Thread1 starts
5651610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//   - Thread1 touches per_thread_global
5652610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//   - Thread1 ends
5653610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//   - Thread2 starts (and there is no happens-before relation between it and
5654610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//   Thread1)
5655610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//   - Thread2 touches per_thread_global
5656610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// It may happen so that Thread2 will have per_thread_global in the same address
5657610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// as Thread1. Since there is no happens-before relation between threads,
5658610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// ThreadSanitizer reports a race.
5659610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//
5660610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test131 does the same for stack.
5661610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5662610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovstatic TLS int per_thread_global[10] = {0};
5663610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5664610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid RealWorker() {  // Touch per_thread_global.
5665610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  per_thread_global[1]++;
5666610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  per_thread_global[9]++;
5667610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  errno++;
5668610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
5669610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5670610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker() {  // Spawn few threads that touch per_thread_global.
5671610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(RealWorker, RealWorker);
5672610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
5673610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
5674610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
5675610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker0() { usleep(0);      Worker(); }
5676610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker1() { usleep(100000); Worker(); }
5677610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker2() { usleep(200000); Worker(); }
5678610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker3() { usleep(300000); Worker(); }
5679610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5680610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#ifdef WIN32
5681610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(NegativeTests, DISABLED_PerThreadTest) {  // issue #23
5682610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#else
5683610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(NegativeTests, PerThreadTest) {
5684610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#endif
5685610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t1(Worker0, Worker1, Worker2, Worker3);
5686610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t1.Start();
5687610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t1.Join();
5688610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
5689610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#endif // TLS
5690610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test130
5691610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5692610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5693610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace NegativeTests_StackReuseTest {  // {{{1
5694610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Same as PerThreadTest, but for stack.
5695610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5696610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid RealWorker() {  // Touch stack.
5697610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  int stack_var = 0;
5698610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  stack_var++;
5699610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
5700610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5701610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker() {  // Spawn few threads that touch stack.
5702610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(RealWorker, RealWorker);
5703610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
5704610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
5705610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
5706610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker0() { usleep(0);      Worker(); }
5707610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker1() { usleep(100000); Worker(); }
5708610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker2() { usleep(200000); Worker(); }
5709610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker3() { usleep(300000); Worker(); }
5710610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5711610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(NegativeTests, StackReuseTest) {
5712610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Worker0, Worker1, Worker2, Worker3);
5713610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
5714610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
5715610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
5716610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5717610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(NegativeTests, StackReuseWithFlushTest) {
5718610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t1(Worker0, Worker1, Worker2, Worker3);
5719610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t2(Worker0, Worker1, Worker2, Worker3);
5720610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t1.Start();
5721610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_FLUSH_STATE();
5722610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(400000);
5723610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t2.Start();
5724610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t2.Join();
5725610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t1.Join();
5726610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
5727610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test131
5728610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5729610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5730610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test132: TP. Simple race (write vs write). Works in fast-mode. {{{1
5731610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test132 {
5732610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
5733610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker() { GLOB = 1; }
5734610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5735610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run1() {
5736610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test132");
5737610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test132: positive; &GLOB=%p\n", &GLOB);
5738610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_TRACE_MEMORY(&GLOB);
5739610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 7;
5740610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Worker, Worker);
5741610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
5742610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
5743610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
5744610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5745610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
5746610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  Run1();
5747610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
5748610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST(Run, 132);
5749610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test132
5750610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5751610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5752610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test133: TP. Simple race (write vs write). Works in fast mode. {{{1
5753610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test133 {
5754610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Same as test132, but everything is run from a separate thread spawned from
5755610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// the main thread.
5756610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
5757610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker() { GLOB = 1; }
5758610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5759610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run1() {
5760610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test133");
5761610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test133: positive; &GLOB=%p\n", &GLOB);
5762610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_TRACE_MEMORY(&GLOB);
5763610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 7;
5764610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Worker, Worker);
5765610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
5766610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
5767610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
5768610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
5769610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThread t(Run1);
5770610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
5771610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
5772610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
5773610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST(Run, 133);
5774610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test133
5775610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5776610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5777610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test134 TN. Swap. Variant of test79. {{{1
5778610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test134 {
5779610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#if 0
5780610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovtypedef __gnu_cxx::hash_map<int, int> map_t;
5781610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#else
5782610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovtypedef std::map<int, int> map_t;
5783610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#endif
5784610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovmap_t   map;
5785610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex   mu;
5786610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Here we use swap to pass map between threads.
5787610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// The synchronization is correct, but w/o the annotation
5788610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// any hybrid detector will complain.
5789610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5790610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Swap is very unfriendly to the lock-set (and hybrid) race detectors.
5791610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Since tmp is destructed outside the mutex, we need to have a happens-before
5792610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// arc between any prior access to map and here.
5793610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Since the internals of tmp are created ouside the mutex and are passed to
5794610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// other thread, we need to have a h-b arc between here and any future access.
5795610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// These arcs can be created by HAPPENS_{BEFORE,AFTER} annotations, but it is
5796610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// much simpler to apply pure-happens-before mode to the mutex mu.
5797610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Swapper() {
5798610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  map_t tmp;
5799610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MutexLock lock(&mu);
5800610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_HAPPENS_AFTER(&map);
5801610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // We swap the new empty map 'tmp' with 'map'.
5802610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  map.swap(tmp);
5803610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_HAPPENS_BEFORE(&map);
5804610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // tmp (which is the old version of map) is destroyed here.
5805610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
5806610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5807610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker() {
5808610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MutexLock lock(&mu);
5809610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_HAPPENS_AFTER(&map);
5810610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  map[1]++;
5811610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_HAPPENS_BEFORE(&map);
5812610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
5813610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5814610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
5815610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test134: negative (swap)\n");
5816610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // ********************** Shorter way: ***********************
5817610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // ANNOTATE_PURE_HAPPENS_BEFORE_MUTEX(&mu);
5818610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Worker, Worker, Swapper, Worker, Worker);
5819610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
5820610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
5821610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
5822610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST(Run, 134)
5823610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test134
5824610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5825610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test137 TP. Races on stack variables. {{{1
5826610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test137 {
5827610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint GLOB = 0;
5828610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovProducerConsumerQueue q(10);
5829610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5830610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker() {
5831610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  int stack;
5832610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  int *tmp = (int*)q.Get();
5833610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  (*tmp)++;
5834610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  int *racey = &stack;
5835610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  q.Put(racey);
5836610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  (*racey)++;
5837610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(150000);
5838610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // We may miss the races if we sleep less due to die_memory events...
5839610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
5840610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5841610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
5842610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  int tmp = 0;
5843610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test137: TP. Races on stack variables.\n");
5844610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  q.Put(&tmp);
5845610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Worker, Worker, Worker, Worker);
5846610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
5847610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
5848610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  q.Get();
5849610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
5850610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5851610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST2(Run, 137, FEATURE | EXCLUDE_FROM_ALL)
5852610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test137
5853610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5854610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace ThreadPoolFNTests {  // {{{1
5855610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5856610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// When using thread pools, two concurrent callbacks might be scheduled
5857610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// onto the same executor thread. As a result, unnecessary happens-before
5858610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// relation may be introduced between callbacks.
5859610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// If we set the number of executor threads to 1, any known data
5860610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// race detector will be silent.
5861610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// However, the a similar situation may happen with any number of
5862610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// executor threads (with some probability).
5863610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5864610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker(int *var) {
5865610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(100000);
5866610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  *var = 42;
5867610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
5868610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5869610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(ThreadPoolFNTests, OneProducerOneConsumer) {
5870610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  int RACEY = 0;
5871610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("FN. Two closures hit the same thread in ThreadPool.\n");
5872610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5873610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ThreadPool tp(1);
5874610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  tp.StartWorkers();
5875610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  tp.Add(NewCallback(Worker, &RACEY));
5876610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  tp.Add(NewCallback(Worker, &RACEY));
5877610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
5878610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5879610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid PutWorkerOn(ThreadPool *tp, int *var) {
5880610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(100000);
5881610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  tp->Add(NewCallback(Worker, var));
5882610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(100000);
5883610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
5884610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5885610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(ThreadPoolFNTests, TwoProducersOneConsumer) {
5886610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  int RACEY = 0;
5887610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("FN. Two closures hit the same thread in ThreadPool.\n");
5888610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5889610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ThreadPool consumers_tp(1);
5890610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  consumers_tp.StartWorkers();
5891610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5892610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ThreadPool producers_tp(2);
5893610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  producers_tp.StartWorkers();
5894610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  producers_tp.Add(NewCallback(PutWorkerOn, &consumers_tp, &RACEY));
5895610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  producers_tp.Add(NewCallback(PutWorkerOn, &consumers_tp, &RACEY));
5896610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
5897610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace ThreadPoolFNTests
5898610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5899610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test139: FN. A true race hidden by reference counting annotation. {{{1
5900610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test139 {
5901610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint GLOB = 0;
5902610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovRefCountedClass *obj;
5903610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5904610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker1() {
5905610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB++;  // First access.
5906610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  obj->Unref();
5907610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
5908610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5909610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker2() {
5910610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(100000);
5911610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  obj->Unref();
5912610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB++;  // Second access.
5913610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
5914610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5915610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
5916610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test139: FN. A true race hidden by reference counting annotation.\n");
5917610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5918610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  obj = new RefCountedClass;
5919610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  obj->AnnotateUnref();
5920610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  obj->Ref();
5921610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  obj->Ref();
5922610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray mt(Worker1, Worker2);
5923610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  mt.Start();
5924610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  mt.Join();
5925610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
5926610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5927610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST2(Run, 139, FEATURE)
5928610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test139
5929610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5930610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Simple FIFO queue annotated with PCQ annotations. {{{1
5931610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovclass FifoMessageQueue {
5932610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov public:
5933610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  FifoMessageQueue() { ANNOTATE_PCQ_CREATE(this); }
5934610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ~FifoMessageQueue() { ANNOTATE_PCQ_DESTROY(this); }
5935610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // Send a message. 'message' should be positive.
5936610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  void Put(int message) {
5937610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    CHECK(message);
5938610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    MutexLock lock(&mu_);
5939610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    ANNOTATE_PCQ_PUT(this);
5940610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    q_.push(message);
5941610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
5942610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // Return the message from the queue and pop it
5943610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // or return 0 if there are no messages.
5944610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  int Get() {
5945610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    MutexLock lock(&mu_);
5946610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    if (q_.empty()) return 0;
5947610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    int res = q_.front();
5948610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    q_.pop();
5949610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    ANNOTATE_PCQ_GET(this);
5950610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    return res;
5951610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
5952610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov private:
5953610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  Mutex mu_;
5954610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  queue<int> q_;
5955610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov};
5956610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5957610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5958610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test142: TN. Check PCQ_* annotations. {{{1
5959610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test142 {
5960610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Putter writes to array[i] and sends a message 'i'.
5961610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Getters receive messages and read array[message].
5962610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// PCQ_* annotations calm down the hybrid detectors.
5963610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5964610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovconst int N = 1000;
5965610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint array[N+1];
5966610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5967610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovFifoMessageQueue q;
5968610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5969610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Putter() {
5970610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int i = 1; i <= N; i++) {
5971610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    array[i] = i*i;
5972610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    q.Put(i);
5973610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    usleep(1000);
5974610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
5975610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
5976610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5977610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Getter() {
5978610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  int non_zero_received  = 0;
5979610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int i = 1; i <= N; i++) {
5980610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    int res = q.Get();
5981610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    if (res > 0) {
5982610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      CHECK(array[res] = res * res);
5983610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      non_zero_received++;
5984610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    }
5985610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    usleep(1000);
5986610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
5987610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#ifndef WIN32
5988610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#ifdef OS_darwin
5989610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("T=%p: non_zero_received=%d\n",
5990610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov         (void*)pthread_self(), non_zero_received);
5991610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#else
5992610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("T=%d: non_zero_received=%d\n",
5993610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov         (int)pthread_self(), non_zero_received);
5994610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#endif
5995610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#endif
5996610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
5997610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
5998610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
5999610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test142: tests PCQ annotations\n");
6000610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Putter, Getter, Getter);
6001610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
6002610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
6003610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6004610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST(Run, 142)
6005610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test142
6006610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6007610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6008610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test143: TP. Check PCQ_* annotations. {{{1
6009610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test143 {
6010610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// True positive.
6011610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// We have a race on GLOB between Putter and one of the Getters.
6012610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Pure h-b will not see it.
6013610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// If FifoMessageQueue was annotated using HAPPENS_BEFORE/AFTER, the race would
6014610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// be missed too.
6015610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// PCQ_* annotations do not hide this race.
6016610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
6017610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovStealthNotification n;
6018610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6019610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovFifoMessageQueue q;
6020610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6021610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Putter() {
6022610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 1;
6023610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  q.Put(1);
6024610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  n.signal();
6025610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6026610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6027610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Getter() {
6028610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  n.wait();
6029610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  q.Get();
6030610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(GLOB == 1);  // Race here
6031610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6032610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6033610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
6034610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  q.Put(1);
6035610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  if (!Tsan_PureHappensBefore()) {
6036610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "true races");
6037610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
6038610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test143: tests PCQ annotations (true positive)\n");
6039610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Putter, Getter, Getter);
6040610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
6041610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
6042610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6043610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST(Run, 143);
6044610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test143
6045610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6046610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test144: Unit-test for a bug in fast-mode {{{1
6047610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test144 {
6048610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovstruct Foo {
6049610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  int a, b;
6050610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov} ALIGNED(64);
6051610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6052610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovstruct Foo GLOB;
6053610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint &RACEY = GLOB.a;
6054610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6055610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker() {
6056610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  RACEY++;
6057610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6058610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6059610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
6060610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test144: fast-mode bug\n");
6061610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_TRACE_MEMORY(&RACEY);
6062610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_EXPECT_RACE_FOR_TSAN(&RACEY, "Real race");
6063610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6064610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // This line resets GLOB's creator_tid (bug).
6065610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_NEW_MEMORY(&GLOB.b, sizeof(GLOB.b));
6066610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6067610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Worker, Worker);
6068610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
6069610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
6070610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6071610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6072610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST(Run, 144);
6073610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test144
6074610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6075610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test145: Unit-test for a bug in fast-mode {{{1
6076610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test145 {
6077610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// A variation of test144 for dynamic memory.
6078610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6079610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovstruct Foo {
6080610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  int a, b;
6081610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov} ALIGNED(64);
6082610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6083610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovstruct Foo *GLOB;
6084610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint *RACEY = NULL;
6085610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6086610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker() {
6087610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  (*RACEY)++;
6088610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6089610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6090610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
6091610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test145: fast-mode bug\n");
6092610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6093610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = new Foo;
6094610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  RACEY = &(GLOB->a);
6095610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_TRACE_MEMORY(RACEY);
6096610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_EXPECT_RACE_FOR_TSAN(RACEY, "Real race");
6097610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6098610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // This line resets GLOB's creator_tid (bug).
6099610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_NEW_MEMORY(&(GLOB->b), sizeof(GLOB->b));
6100610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6101610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Worker, Worker);
6102610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
6103610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
6104610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  delete GLOB;
6105610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6106610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6107610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST(Run, 145);
6108610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test145
6109610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6110610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test147: allocating 1.5G of mem in one chunk. {{{1
6111610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test147 {
6112610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
6113610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test147: malloc 1.5G\n");
6114610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  free(malloc((1 << 30) + (1 << 29)));
6115610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6116610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST(Run, 147)
6117610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test147
6118610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6119610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test148: FN. 3 threads, h-b hides race between T1 and T3. {{{1
6120610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test148 {
6121610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint GLOB = 0;
6122610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint COND = 0;
6123610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex mu;
6124610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovCondVar cv;
6125610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6126610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Signaller() {
6127610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(1000000);
6128610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 1;
6129610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  mu.Lock();
6130610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  COND = 1;
6131610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  cv.Signal();
6132610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  mu.Unlock();
6133610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6134610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6135610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Waiter() {
6136610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  mu.Lock();
6137610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  while (COND == 0)
6138610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    cv.Wait(&mu);
6139610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_CONDVAR_LOCK_WAIT(&cv, &mu);
6140610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 2;
6141610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  mu.Unlock();
6142610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6143610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6144610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Racer() {
6145610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(2000000);
6146610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  mu.Lock();
6147610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 3;
6148610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  mu.Unlock();
6149610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6150610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6151610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
6152610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test148: FN. 3 threads, h-b hides race between T1 and T3.\n");
6153610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray mta(Signaller, Waiter, Racer);
6154610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  mta.Start();
6155610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  mta.Join();
6156610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6157610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST(Run, 148)
6158610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test148
6159610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6160610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test149: allocate and memset lots of of mem in several chunks. {{{1
6161610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test149 {
6162610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
6163610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  int kChunkSize = 1 << 26;
6164610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test149: malloc 8x%dM\n", kChunkSize / (1 << 20));
6165610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  void *mem[8];
6166610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int i = 0; i < 8; i++) {
6167610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    mem[i] = malloc(kChunkSize);
6168610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    memset(mem[i], 0, kChunkSize);
6169610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    printf("+");
6170610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
6171610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int i = 0; i < 8; i++) {
6172610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    free(mem[i]);
6173610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    printf("-");
6174610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
6175610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf(" Done\n");
6176610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6177610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST2(Run, 149, EXCLUDE_FROM_ALL)  // TODO(kcc): enable it back
6178610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test149
6179610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6180610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test150: race which is detected after one of the thread has joined. {{{1
6181610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test150 {
6182610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
6183610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovStealthNotification n;
6184610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Writer1() { GLOB++; }
6185610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Writer2() {
6186610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  n.wait();
6187610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB++;
6188610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6189610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(PositiveTests, RaceDetectedAfterJoin) {
6190610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "real race");
6191610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThread t1(Writer1);
6192610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThread t2(Writer2);
6193610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t1.Start();
6194610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t2.Start();
6195610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t1.Join();
6196610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  n.signal();
6197610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t2.Join();
6198610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\tGLOB=%d\n", GLOB);
6199610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6200610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test150
6201610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6202610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6203610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test151: stress for the size of vector time clock. {{{1
6204610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test151 {
6205610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint kNumThreads = 100;
6206610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint kNumSegments = 5000000;
6207610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Void() { }
6208610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
6209610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test151: stress\n");
6210610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("Creating %d threads\n", kNumThreads);
6211610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int i = 0; i < kNumThreads; i++) {
6212610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    MyThread t(Void);
6213610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    t.Start();
6214610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    t.Join();
6215610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
6216610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("Creating %d segments\n", kNumSegments);
6217610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int i = 0; i < kNumSegments; i++) {
6218610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    if (i % (kNumSegments / 50) == 0)
6219610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      printf(".");
6220610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    ANNOTATE_HAPPENS_BEFORE(NULL);
6221610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
6222610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf(" done\n");
6223610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6224610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST2(Run, 151, PERFORMANCE | EXCLUDE_FROM_ALL)  // TODO(kcc): enable
6225610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test151
6226610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6227610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test152: atexit -> exit creates a h-b arc. {{{1
6228610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test152 {
6229610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
6230610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMyThread *t;
6231610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6232610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid AtExitCallback() {
6233610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB++;
6234610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6235610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6236610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid AtExitThread() {
6237610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB++;
6238610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  atexit(AtExitCallback);
6239610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6240610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6241610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(NegativeTests, AtExitTest) {
6242610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t = new MyThread(AtExitThread);
6243610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t->Start(); // We don't join it.
6244610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6245610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test152
6246610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6247610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test153:  test for vanilla pthread_spinlock_t {{{1
6248610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test153 {
6249610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#ifndef NO_SPINLOCK
6250610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// pthread_spinlock_t is tricky because pthread_spin_unlock and
6251610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// pthread_spin_init are the same symbol.
6252610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
6253610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovpthread_spinlock_t lock;
6254610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6255610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker1() {
6256610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  pthread_spin_lock(&lock);
6257610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB++;
6258610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  pthread_spin_unlock(&lock);
6259610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6260610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6261610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker2() {
6262610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  while (pthread_spin_trylock(&lock) != 0) { }
6263610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB++;
6264610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  pthread_spin_unlock(&lock);
6265610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6266610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6267610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6268610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
6269610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test153: pthread_spin_t\n");
6270610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int i = 0; i < 3; i++) {
6271610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    // test few times on the same lock to check how init/destroy are handled.
6272610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    pthread_spin_init(&lock, 0);
6273610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    MyThreadArray t(Worker1, Worker1, Worker2, Worker2);
6274610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    t.Start();
6275610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    t.Join();
6276610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    pthread_spin_destroy(&lock);
6277610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
6278610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6279610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST(Run, 153)
6280610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#endif // NO_SPINLOCK
6281610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test153
6282610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6283610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test154: long test with lots of races. {{{1
6284610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test154 {
6285610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovconst int kNumIters = 100000;
6286610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovconst int kArraySize = 100000;
6287610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint *arr;
6288610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6289610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid RaceyAccess(int *a) {
6290610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  (*a)++;
6291610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6292610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6293610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid RaceyLoop() {
6294610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int j = 0; j < kArraySize; j++) {
6295610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    RaceyAccess(&arr[j]);
6296610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
6297610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6298610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6299610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker() {
6300610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int i = 0; i < kNumIters; i++) {
6301610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    usleep(1);
6302610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    printf(".");
6303610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    if ((i % 40) == 39)
6304610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      printf("\n");
6305610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    RaceyLoop();
6306610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
6307610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6308610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6309610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
6310610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  arr = new int[kArraySize];
6311610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test154: positive; long test with lots of races\n");
6312610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Worker, Worker);
6313610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
6314610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
6315610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  delete arr;
6316610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6317610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST2(Run, 154, EXCLUDE_FROM_ALL)
6318610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test154
6319610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6320610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace PositiveTests_RaceInMemcpy {  // {{{1
6321610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovchar *GLOB;
6322610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6323610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid DoMemcpy() {
6324610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  memcpy(GLOB, GLOB + 1, 1);
6325610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6326610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6327610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid DoMemmove() {
6328610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  memmove(GLOB, GLOB + 1, 1);
6329610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6330610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6331610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Write0() {
6332610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB[0] = 'z';
6333610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6334610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6335610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid DoStrlen() {
6336610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(strlen(GLOB) == 3);
6337610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6338610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6339610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid DoStrcpy() {
6340610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(strcpy(GLOB, "zzz") == GLOB);
6341610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6342610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6343610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid DoStrchr() {
6344610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(strchr(GLOB, 'o') == (GLOB + 1));
6345610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6346610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6347610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid DoMemchr() {
6348610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(memchr(GLOB, 'o', 4) == (GLOB + 1));
6349610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6350610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6351610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid DoStrrchr() {
6352610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(strrchr(GLOB, '!') == NULL);
6353610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6354610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6355610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid DoStrcmp() {
6356610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(strcmp(GLOB, "xxx") != 0);
6357610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6358610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6359610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid DoStrncmp() {
6360610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(strncmp(GLOB, "xxx", 3) != 0);
6361610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6362610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6363610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6364610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid RunThreads(void (*f1)(void), void (*f2)(void), char *mem) {
6365610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = mem;
6366610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  strcpy(GLOB, "foo");
6367610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_EXPECT_RACE_FOR_TSAN(GLOB, "expected race");
6368610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(f1, f2);
6369610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
6370610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
6371610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6372610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6373610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(PositiveTests, RaceInMemcpy) {
6374610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  static char mem[4];
6375610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  RunThreads(DoMemcpy, DoMemcpy, mem);
6376610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6377610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6378610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(PositiveTests, RaceInMemmove) {
6379610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  static char mem[4];
6380610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  RunThreads(DoMemmove, DoMemmove, mem);
6381610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6382610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6383610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(PositiveTests, RaceInStrlen1) {
6384610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  static char mem[4];
6385610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  RunThreads(DoStrlen, Write0, mem);
6386610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6387610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6388610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(PositiveTests, RaceInStrlen2) {
6389610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  static char mem[4];
6390610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  RunThreads(Write0, DoStrlen, mem);
6391610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6392610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6393610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(PositiveTests, RaceInStrcpy) {
6394610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  static char mem[4];
6395610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  RunThreads(Write0, DoStrcpy, mem);
6396610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6397610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6398610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(PositiveTests, RaceInStrchr) {
6399610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  static char mem[4];
6400610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  RunThreads(Write0, DoStrchr, mem);
6401610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6402610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6403610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(PositiveTests, RaceInMemchr) {
6404610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  static char mem[4];
6405610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  RunThreads(Write0, DoMemchr, mem);
6406610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6407610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6408610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(PositiveTests, RaceInStrrchr) {
6409610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  static char mem[4];
6410610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  RunThreads(Write0, DoStrrchr, mem);
6411610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6412610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6413610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(PositiveTests, RaceInStrcmp) {
6414610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  static char mem[4];
6415610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  RunThreads(Write0, DoStrcmp, mem);
6416610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6417610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6418610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(PositiveTests, RaceInStrncmp) {
6419610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  static char mem[4];
6420610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  RunThreads(Write0, DoStrncmp, mem);
6421610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6422610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6423610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace
6424610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6425610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test157: TN. Test for stack traces (using ANNOTATE_NO_OP). {{{1
6426610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test157 {
6427610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6428610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid func3() {
6429610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_NO_OP((void*)__LINE__);
6430610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6431610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid func2() {
6432610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  func3();
6433610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6434610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid func1() {
6435610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  func2();
6436610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6437610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker1() {
6438610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  func1();
6439610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_NO_OP((void*)__LINE__);
6440610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6441610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker2() {
6442610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  func2();
6443610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_NO_OP((void*)__LINE__);
6444610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6445610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker3() {
6446610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  func3();
6447610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_NO_OP((void*)__LINE__);
6448610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6449610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
6450610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_NO_OP((void*)__LINE__);
6451610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test157: negative\n");
6452610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_NO_OP((void*)__LINE__);
6453610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Worker1, Worker2, Worker3);
6454610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_NO_OP((void*)__LINE__);
6455610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
6456610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_NO_OP((void*)__LINE__);
6457610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
6458610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_NO_OP((void*)__LINE__);
6459610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6460610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST(Run, 157);
6461610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test157
6462610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6463610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6464610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace MemoryTypes {  // {{{1
6465610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  void WriteChar(void *param) {
6466610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    *(char*)param = 1;
6467610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    usleep(500000);  // let other threads hit this before exiting.
6468610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
6469610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6470610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  void RaceOnMemory(void (*callback)(void *), char *mem) {
6471610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    ANNOTATE_FLUSH_EXPECTED_RACES();
6472610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    ANNOTATE_EXPECT_RACE(mem, "race");
6473610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    MyThread t1(callback, mem),
6474610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov             t2(callback, mem);
6475610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    t1.Start();
6476610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    t2.Start();
6477610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    t1.Join();
6478610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    t2.Join();
6479610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    CHECK(*mem == 1);
6480610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    ANNOTATE_FLUSH_EXPECTED_RACES();
6481610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
6482610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6483610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  void RaceOnLocalStack(void (*callback)(void *)) {
6484610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    char object_on_stack = 0;
6485610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    // We may have had races on the main stack before -- forget about them.
6486610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    ANNOTATE_NEW_MEMORY(&object_on_stack, 1);
6487610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    RaceOnMemory(callback, &object_on_stack);
6488610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
6489610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6490610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // create a new function to make reports different.
6491610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  void WriteChar1(void *param) { WriteChar(param); }
6492610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6493610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  TEST(MemoryTypes, RaceOnMainThreadStack) {
6494610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    RaceOnLocalStack(WriteChar1);
6495610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
6496610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6497610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  void WriteChar2(void *param) { WriteChar(param); }
6498610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6499610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  TEST(MemoryTypes, RaceOnNonMainThreadStack) {
6500610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    MyThread t((void (*)(void*))(RaceOnLocalStack), (void*)WriteChar2);
6501610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    t.Start();
6502610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    t.Join();
6503610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
6504610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6505610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  void WriteChar3(void *param) { WriteChar(param); }
6506610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6507610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  TEST(MemoryTypes, RaceOnMallocedMemory) {
6508610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    char *mem = (char*)malloc(100);
6509610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    RaceOnMemory(WriteChar3, mem+42);
6510610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    free(mem);
6511610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
6512610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6513610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  void WriteChar4(void *param) { WriteChar(param); }
6514610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6515610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  TEST(MemoryTypes, RaceOnCallocedMemory) {
6516610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    char *mem = (char*)calloc(30, 4);
6517610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    RaceOnMemory(WriteChar4, mem+42);
6518610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    free(mem);
6519610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
6520610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6521610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  void WriteChar5(void *param) { WriteChar(param); }
6522610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6523610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  TEST(MemoryTypes, RaceOnMemoryFromNew) {
6524610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    char *mem = new char;
6525610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    RaceOnMemory(WriteChar5, mem);
6526610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    delete mem;
6527610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
6528610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6529610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  void WriteChar6(void *param) { WriteChar(param); }
6530610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6531610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  TEST(MemoryTypes, RaceOnMemoryFromNewA) {
6532610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    char *mem = new char [100];
6533610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    RaceOnMemory(WriteChar6, mem+42);
6534610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    delete [] mem;
6535610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
6536610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6537610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  void WriteChar7(void *param) { WriteChar(param); }
6538610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6539610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  TEST(MemoryTypes, RaceOnMemoryFromNewNoThrow) {
6540610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    char *mem = new (std::nothrow) char;
6541610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    RaceOnMemory(WriteChar7, mem);
6542610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    operator delete (mem, std::nothrow);
6543610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
6544610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  void WriteChar8(void *param) { WriteChar(param); }
6545610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6546610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  TEST(MemoryTypes, RaceOnMemoryFromNewNoThrowA) {
6547610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    char *mem = new (std::nothrow) char [100];
6548610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    RaceOnMemory(WriteChar8, mem+42);
6549610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    operator delete [] (mem, std::nothrow);
6550610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
6551610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6552610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  void AllocateAndDeallocateUsingVariousAllocs() {
6553610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    for (int i = 0; i < 10000; i++) {
6554610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      char *p;
6555610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      switch (i % 5) {
6556610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov        case 0:
6557610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov          p = (char*)malloc(10);
6558610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov          free(p);
6559610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov          break;
6560610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov        case 1:
6561610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov          p = new char;
6562610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov          delete p;
6563610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov          break;
6564610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov        case 2:
6565610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov          p = new char [10];
6566610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov          delete [] p;
6567610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov        case 3:
6568610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov          p = new (std::nothrow) char;
6569610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov          operator delete (p, std::nothrow);
6570610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov          break;
6571610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov        case 4:
6572610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov          p = new (std::nothrow) char[10];
6573610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov          operator delete [](p, std::nothrow);
6574610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov          break;
6575610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      }
6576610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    }
6577610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
6578610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  TEST(MemoryTypes, VariousAllocs) {
6579610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    void (*f)(void) = AllocateAndDeallocateUsingVariousAllocs;
6580610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    MyThreadArray t(f, f, f, f);
6581610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    t.Start();
6582610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    t.Join();
6583610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
6584610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6585610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  void ReallocThread() {
6586610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    void *ptr = NULL;
6587610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    for (int i = 8; i < 128; i++) {
6588610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      int size = (1 << (i / 8)) - 1;
6589610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      ptr = realloc(ptr, size);
6590610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      ANNOTATE_TRACE_MEMORY(ptr);
6591610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      memset(ptr, 42, size);
6592610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    }
6593610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    free(ptr);
6594610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
6595610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  TEST(MemoryTypes, Reallocs) {
6596610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    MyThreadArray t(ReallocThread, ReallocThread, ReallocThread, ReallocThread);
6597610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    t.Start();
6598610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    t.Join();
6599610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
6600610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace
6601610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6602610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6603610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace  StressTests_ThreadTree {  //{{{1
6604610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
6605610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6606610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Worker(N) will do 2^N increments of GLOB, each increment in a separate thread
6607610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker(int depth) {
6608610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(depth >= 0);
6609610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  if (depth > 0) {
6610610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    MyThread t1((MyThread::worker_t)Worker, (void*)(intptr_t)(depth - 1));
6611610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    MyThread t2((MyThread::worker_t)Worker, (void*)(intptr_t)(depth - 1));
6612610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    t1.Start();
6613610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    t2.Start();
6614610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    t1.Join();
6615610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    t2.Join();
6616610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  } else {
6617610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    GLOB++; // Race here
6618610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
6619610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6620610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6621610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(StressTests, ThreadTree3) {
6622610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_EXPECT_RACE(&GLOB, "StressTests.ThreadTree3 race");
6623610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_TRACE_MEMORY(&GLOB);
6624610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  Worker(3);
6625610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6626610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6627610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(StressTests, DISABLED_ThreadTree7) {
6628610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_EXPECT_RACE(&GLOB, "StressTests.ThreadTree7 race");
6629610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_TRACE_MEMORY(&GLOB);
6630610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  Worker(7);
6631610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6632610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test313
6633610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6634610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace  StressTests_StartAndJoinManyThreads {  //{{{1
6635610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6636610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker() {
6637610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6638610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6639610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Too slow. Need to run it separately.
6640610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(StressTests, StartAndJoinManyThreads) {
6641610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_FLUSH_STATE();
6642610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int i = 0; i < 1100; i++) {
6643610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    if ((i % 100) == 0)
6644610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      printf(".");
6645610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    MyThread t1(Worker);
6646610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    MyThread t2(Worker);
6647610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    t1.Start();
6648610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    t2.Start();
6649610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    t1.Join();
6650610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    t2.Join();
6651610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
6652610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\n");
6653610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6654610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace
6655610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6656610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace StressTests_ManyAccesses {  // {{{1
6657610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#ifndef NO_BARRIER
6658610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovconst int kArrayLen = 128;  // Small size, so that everything fits into cache.
6659610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovconst int kNumIter = 1024 * 1024 * 2;
6660610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint thread_id;
6661610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint *array = NULL;
6662610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovBarrier *barrier;
6663610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6664610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid IncrementMe(int *x) {
6665610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  (*x)++;
6666610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6667610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6668610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid NoRaceWorker() {
6669610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  int id = AtomicIncrement(&thread_id, 1);
6670610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  barrier->Block();
6671610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  int *ptr = array + id * (kArrayLen + 64);  // pad to avoid false sharing.
6672610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int it = 0; it < kNumIter; it++) {
6673610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    for (int i = 0; i < kArrayLen; i++) {
6674610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      IncrementMe(ptr + i);
6675610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    }
6676610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
6677610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6678610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6679610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid RunThreads(int n_threads, void (*f)(void)) {
6680610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  thread_id = -1;
6681610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  barrier = new Barrier(n_threads);
6682610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // Allocate a lot so that operator new uses mmap, unless forced to use brk.
6683610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  array = new int[(kArrayLen + 64) * n_threads + (1 << 22)];
6684610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("ptr = %p\n", array);
6685610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThread **t = new MyThread*[n_threads];
6686610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int i = 0; i < n_threads; i++) t[i] = new MyThread(NoRaceWorker);
6687610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int i = 0; i < n_threads; i++) t[i]->Start();
6688610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int i = 0; i < n_threads; i++) t[i]->Join();
6689610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int i = 0; i < n_threads; i++) delete t[i];
6690610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  delete [] t;
6691610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  delete [] array;
6692610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6693610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6694610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Just one thread.
6695610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(StressTests, DISABLED_ManyAccessesNoRace1Test) {
6696610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  RunThreads(1, NoRaceWorker);
6697610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6698610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6699610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 2 threads accessing different memory.
6700610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(StressTests, DISABLED_ManyAccessesNoRace2Test) {
6701610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  RunThreads(2, NoRaceWorker);
6702610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6703610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 4 threads accessing different memory.
6704610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(StressTests, DISABLED_ManyAccessesNoRace4Test) {
6705610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  RunThreads(4, NoRaceWorker);
6706610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6707610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 8 threads accessing different memory.
6708610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(StressTests, DISABLED_ManyAccessesNoRace8Test) {
6709610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  RunThreads(8, NoRaceWorker);
6710610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6711610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 16 threads accessing different memory.
6712610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(StressTests, DISABLED_ManyAccessesNoRace16Test) {
6713610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  RunThreads(16, NoRaceWorker);
6714610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6715610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#endif  // NO_BARRIER
6716610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace
6717610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6718610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace NegativeTests_EnableRaceDetectionTest {  // {{{1
6719610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovconst size_t size = 10000;
6720610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovconst size_t n_iter = 1000;
6721610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint GLOB[size];
6722610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6723610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker() {
6724610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (size_t i = 0; i < n_iter; i++) {
6725610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    for (size_t j = 0; j < size; j++) {
6726610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      GLOB[j]++;
6727610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    }
6728610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
6729610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6730610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6731610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(NegativeTests, EnableRaceDetectionTest) {
6732610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_ENABLE_RACE_DETECTION(0);
6733610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Worker, Worker, Worker, Worker);
6734610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
6735610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
6736610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_ENABLE_RACE_DETECTION(1);
6737610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6738610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6739610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6740610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace PositiveTests_MopVsFree {  // {{{1
6741610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint *p;
6742610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovconst int kIdx = 77;
6743610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovStealthNotification n;
6744610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6745610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Read() {
6746610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(p[kIdx] == 777);
6747610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  n.signal();
6748610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6749610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Free() {
6750610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  n.wait();
6751610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  free(p);
6752610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6753610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6754610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(PositiveTests, ReadVsFree) {
6755610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  p = (int*)malloc(100 * sizeof(int));
6756610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  p[kIdx] = 777;
6757610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_EXPECT_RACE(&p[kIdx], "race: read vs free");
6758610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Read, Free);
6759610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
6760610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
6761610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6762610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6763610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace
6764610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6765610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace ManySmallObjectsTest {  // {{{1
6766610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker() {
6767610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  const int N = 1 << 21;
6768610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  struct T {
6769610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    int a, b, c, d;
6770610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    T() : a(1), b(2), c(3), d(4) { }
6771610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  };
6772610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  T **a = new T*[N];
6773610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int i = 0; i < N; i++) {
6774610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    if ((i % (N / 16)) == 0)
6775610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      printf("+");
6776610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    a[i] = new T;
6777610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    CHECK(a[i]->a == 1);
6778610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
6779610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\n");
6780610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int i = 0; i < N; i++) {
6781610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    if ((i % (N / 16)) == 0)
6782610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      printf("-");
6783610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    delete a[i];
6784610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
6785610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("\n");
6786610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  delete [] a;
6787610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6788610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6789610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(StressTests, DISABLED_ManySmallObjectsOneThreadTest) {
6790610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  Worker();
6791610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6792610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6793610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(StressTests, DISABLED_ManySmallObjectsTwoThreadsTest) {
6794610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Worker, Worker);
6795610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
6796610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
6797610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6798610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace
6799610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6800610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace  RepPrefixedInstructionsTest {  //{{{1
6801610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6802610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#if defined (__GNUC__) && (defined(ARCH_x86) || defined(ARCH_amd64))
6803610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid rep_clr_1(uint8_t *s, long n)
6804610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov{
6805610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  intptr_t d0, d1;
6806610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      __asm__ __volatile__ (
6807610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      "rep ; stosb"
6808610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      : "=&c" (d0), "=&D" (d1)
6809610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      : "a" (0), "1" (s), "0" (n)
6810610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      : "memory");
6811610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6812610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6813610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovuint8_t mem1[1000];
6814610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6815610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Clr1_0_10()  { rep_clr_1(mem1+ 0, 10); }
6816610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Clr1_10_10() { rep_clr_1(mem1+10, 10); }
6817610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Clr1_10_0() { rep_clr_1(mem1+10, 0); }
6818610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6819610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Clr1_25_1() { rep_clr_1(mem1+25, 1); }
6820610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Clr1_25_0() { rep_clr_1(mem1+25, 0); }
6821610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6822610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Clr1_50_30() { rep_clr_1(mem1+50, 30); }
6823610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Clr1_60_0() { rep_clr_1(mem1+60, 0); }
6824610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Clr1_60_1() { rep_clr_1(mem1+60, 1); }
6825610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Clr1_70_10() { rep_clr_1(mem1+70, 10); }
6826610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6827610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6828610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid RunThreads(void (*f1)(void), void (*f2)(void)) {
6829610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(f1, f2);
6830610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
6831610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
6832610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6833610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6834610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(NegativeTests, RepSanityTest) {
6835610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  memset(mem1, 0xff, sizeof(mem1));
6836610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  rep_clr_1(mem1, 0);
6837610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(mem1[0] != 0);
6838610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  rep_clr_1(mem1, 1);
6839610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(mem1[0] == 0);
6840610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(mem1[1] != 0);
6841610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  rep_clr_1(mem1, 5);
6842610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(mem1[4] == 0);
6843610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(mem1[5] != 0);
6844610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6845610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6846610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(NegativeTests, RepNegativeTest) {
6847610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  memset(mem1, 0xff, sizeof(mem1));
6848610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  RunThreads(Clr1_0_10, Clr1_10_10);
6849610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  RunThreads(Clr1_10_0, Clr1_10_10);
6850610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  RunThreads(Clr1_25_0, Clr1_25_1);
6851610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  RunThreads(Clr1_50_30, Clr1_60_0);
6852610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6853610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6854610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(PositiveTests, RepPositive1Test) {
6855610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  memset(mem1, 0xff, sizeof(mem1));
6856610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_EXPECT_RACE(mem1+10, "real race");
6857610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int i = 11; i < 20; i++) ANNOTATE_BENIGN_RACE(mem1 + i, "");
6858610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  RunThreads(Clr1_10_10, Clr1_10_10);
6859610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6860610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(PositiveTests, RepPositive2Test) {
6861610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  memset(mem1, 0xff, sizeof(mem1));
6862610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_EXPECT_RACE(mem1+25, "real race");
6863610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  RunThreads(Clr1_25_1, Clr1_25_1);
6864610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6865610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6866610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(PositiveTests, RepPositive3Test) {
6867610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  memset(mem1, 0xff, sizeof(mem1));
6868610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_EXPECT_RACE(mem1+60, "real race");
6869610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  RunThreads(Clr1_50_30, Clr1_60_1);
6870610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6871610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6872610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(PositiveTests, RepPositive4Test) {
6873610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  memset(mem1, 0xff, sizeof(mem1));
6874610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_EXPECT_RACE(mem1+70, "real race");
6875610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int i = 71; i < 80; i++) ANNOTATE_BENIGN_RACE(mem1 + i, "");
6876610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  RunThreads(Clr1_50_30, Clr1_70_10);
6877610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6878610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#endif  // __GNUC__ ...
6879610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace
6880610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6881610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test400: Demo of a simple false positive. {{{1
6882610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test400 {
6883610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovstatic Mutex mu;
6884610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovstatic vector<int> *vec; // GUARDED_BY(mu);
6885610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6886610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid InitAllBeforeStartingThreads() {
6887610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  vec = new vector<int>;
6888610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  vec->push_back(1);
6889610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  vec->push_back(2);
6890610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6891610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6892610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Thread1() {
6893610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MutexLock lock(&mu);
6894610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  vec->pop_back();
6895610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6896610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6897610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Thread2() {
6898610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MutexLock lock(&mu);
6899610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  vec->pop_back();
6900610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6901610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6902610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//---- Sub-optimal code ---------
6903610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovsize_t NumberOfElementsLeft() {
6904610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MutexLock lock(&mu);
6905610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  return vec->size();
6906610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6907610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6908610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid WaitForAllThreadsToFinish_InefficientAndTsanUnfriendly() {
6909610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  while(NumberOfElementsLeft()) {
6910610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    ; // sleep or print or do nothing.
6911610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
6912610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // It is now safe to access vec w/o lock.
6913610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // But a hybrid detector (like ThreadSanitizer) can't see it.
6914610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // Solutions:
6915610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  //   1. Use pure happens-before detector (e.g. "tsan --pure-happens-before")
6916610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  //   2. Call ANNOTATE_PURE_HAPPENS_BEFORE_MUTEX(&mu)
6917610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  //      in InitAllBeforeStartingThreads()
6918610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  //   3. (preferred) Use WaitForAllThreadsToFinish_Good() (see below).
6919610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(vec->empty());
6920610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  delete vec;
6921610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6922610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6923610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//----- Better code -----------
6924610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6925610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovbool NoElementsLeft(vector<int> *v) {
6926610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  return v->empty();
6927610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6928610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6929610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid WaitForAllThreadsToFinish_Good() {
6930610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  mu.LockWhen(Condition(NoElementsLeft, vec));
6931610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  mu.Unlock();
6932610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6933610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // It is now safe to access vec w/o lock.
6934610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(vec->empty());
6935610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  delete vec;
6936610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6937610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6938610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6939610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
6940610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Thread1, Thread2);
6941610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  InitAllBeforeStartingThreads();
6942610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
6943610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  WaitForAllThreadsToFinish_InefficientAndTsanUnfriendly();
6944610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//  WaitForAllThreadsToFinish_Good();
6945610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
6946610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6947610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST2(Run, 400, RACE_DEMO)
6948610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test400
6949610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6950610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test401: Demo of false positive caused by reference counting. {{{1
6951610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test401 {
6952610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// A simplified example of reference counting.
6953610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// DecRef() does ref count increment in a way unfriendly to race detectors.
6954610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// DecRefAnnotated() does the same in a friendly way.
6955610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6956610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovstatic vector<int> *vec;
6957610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovstatic int ref_count;
6958610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6959610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid InitAllBeforeStartingThreads(int number_of_threads) {
6960610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  vec = new vector<int>;
6961610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  vec->push_back(1);
6962610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ref_count = number_of_threads;
6963610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6964610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6965610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Correct, but unfriendly to race detectors.
6966610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint DecRef() {
6967610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  return AtomicIncrement(&ref_count, -1);
6968610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6969610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6970610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Correct and friendly to race detectors.
6971610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint DecRefAnnotated() {
6972610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_HAPPENS_BEFORE(&ref_count);
6973610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  int res = AtomicIncrement(&ref_count, -1);
6974610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  if (res == 0) {
6975610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    ANNOTATE_HAPPENS_AFTER(&ref_count);
6976610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
6977610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  return res;
6978610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6979610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6980610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid ThreadWorker() {
6981610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(ref_count > 0);
6982610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(vec->size() == 1);
6983610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  if (DecRef() == 0) {  // Use DecRefAnnotated() instead!
6984610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    // No one uses vec now ==> delete it.
6985610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    delete vec;  // A false race may be reported here.
6986610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    vec = NULL;
6987610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
6988610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6989610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
6990610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
6991610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(ThreadWorker, ThreadWorker, ThreadWorker);
6992610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  InitAllBeforeStartingThreads(3 /*number of threads*/);
6993610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
6994610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
6995610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(vec == 0);
6996610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
6997610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST2(Run, 401, RACE_DEMO)
6998610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test401
6999610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7000610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7001610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test502: produce lots of segments without cross-thread relations {{{1
7002610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test502 {
7003610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7004610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov/*
7005610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov * This test produces ~1Gb of memory usage when run with the following options:
7006610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov *
7007610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov * --tool=helgrind
7008610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov * --trace-after-race=0
7009610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov * --num-callers=2
7010610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov * --more-context=no
7011610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov */
7012610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7013610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex MU;
7014610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
7015610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7016610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid TP() {
7017610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov   for (int i = 0; i < 750000; i++) {
7018610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      MU.Lock();
7019610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      GLOB++;
7020610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      MU.Unlock();
7021610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov   }
7022610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
7023610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7024610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
7025610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov   MyThreadArray t(TP, TP);
7026610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov   printf("test502: produce lots of segments without cross-thread relations\n");
7027610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7028610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov   t.Start();
7029610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov   t.Join();
7030610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
7031610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7032610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST2(Run, 502, MEMORY_USAGE | PRINT_STATS | EXCLUDE_FROM_ALL
7033610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov                              | PERFORMANCE)
7034610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test502
7035610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7036610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test503: produce lots of segments with simple HB-relations {{{1
7037610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// HB cache-miss rate is ~55%
7038610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test503 {
7039610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7040610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//  |- |  |  |  |  |
7041610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//  | \|  |  |  |  |
7042610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//  |  |- |  |  |  |
7043610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//  |  | \|  |  |  |
7044610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//  |  |  |- |  |  |
7045610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//  |  |  | \|  |  |
7046610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//  |  |  |  |- |  |
7047610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//  |  |  |  | \|  |
7048610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//  |  |  |  |  |- |
7049610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//  |  |  |  |  | \|
7050610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//  |  |  |  |  |  |----
7051610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//->|  |  |  |  |  |
7052610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//  |- |  |  |  |  |
7053610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//  | \|  |  |  |  |
7054610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov//     ...
7055610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7056610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovconst int N_threads = 32;
7057610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovconst int ARRAY_SIZE = 128;
7058610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint       GLOB[ARRAY_SIZE];
7059610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovProducerConsumerQueue *Q[N_threads];
7060610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint GLOB_limit = 100000;
7061610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint count = -1;
7062610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7063610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker(){
7064610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov   int myId = AtomicIncrement(&count, 1);
7065610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7066610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov   ProducerConsumerQueue &myQ = *Q[myId], &nextQ = *Q[(myId+1) % N_threads];
7067610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7068610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov   // this code produces a new SS with each new segment
7069610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov   while (myQ.Get() != NULL) {
7070610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      for (int i = 0; i < ARRAY_SIZE; i++)
7071610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov         GLOB[i]++;
7072610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7073610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      if (myId == 0 && GLOB[0] > GLOB_limit) {
7074610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov         // Stop all threads
7075610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov         for (int i = 0; i < N_threads; i++)
7076610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov            Q[i]->Put(NULL);
7077610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      } else
7078610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov         nextQ.Put(GLOB);
7079610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov   }
7080610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
7081610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7082610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
7083610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov   printf("test503: produce lots of segments with simple HB-relations\n");
7084610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov   for (int i = 0; i < N_threads; i++)
7085610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      Q[i] = new ProducerConsumerQueue(1);
7086610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov   Q[0]->Put(GLOB);
7087610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7088610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov   {
7089610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      ThreadPool pool(N_threads);
7090610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      pool.StartWorkers();
7091610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      for (int i = 0; i < N_threads; i++) {
7092610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov         pool.Add(NewCallback(Worker));
7093610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      }
7094610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov   } // all folks are joined here.
7095610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7096610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov   for (int i = 0; i < N_threads; i++)
7097610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      delete Q[i];
7098610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
7099610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7100610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST2(Run, 503, MEMORY_USAGE | PRINT_STATS
7101610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov                  | PERFORMANCE | EXCLUDE_FROM_ALL)
7102610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test503
7103610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7104610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test504: force massive cache fetch-wback (50% misses, mostly CacheLineZ) {{{1
7105610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test504 {
7106610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#if !defined(WINE) and !defined(ANDROID) // Valgrind+wine hate large static objects
7107610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovconst int N_THREADS = 2,
7108610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov          HG_CACHELINE_COUNT = 1 << 16,
7109610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov          HG_CACHELINE_SIZE  = 1 << 6,
7110610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov          HG_CACHE_SIZE = HG_CACHELINE_COUNT * HG_CACHELINE_SIZE;
7111610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7112610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// int gives us ~4x speed of the byte test
7113610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 4x array size gives us
7114610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// total multiplier of 16x over the cachesize
7115610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// so we can neglect the cached-at-the-end memory
7116610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovconst int ARRAY_SIZE = 4 * HG_CACHE_SIZE,
7117610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov          ITERATIONS = 30;
7118610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint array[ARRAY_SIZE];
7119610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7120610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint count = 0;
7121610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex count_mu;
7122610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7123610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker() {
7124610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov   count_mu.Lock();
7125610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov   int myId = ++count;
7126610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov   count_mu.Unlock();
7127610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7128610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov   // all threads write to different memory locations,
7129610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov   // so no synchronization mechanisms are needed
7130610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov   int lower_bound = ARRAY_SIZE * (myId-1) / N_THREADS,
7131610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov       upper_bound = ARRAY_SIZE * ( myId ) / N_THREADS;
7132610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov   for (int j = 0; j < ITERATIONS; j++)
7133610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov   for (int i = lower_bound; i < upper_bound;
7134610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov            i += HG_CACHELINE_SIZE / sizeof(array[0])) {
7135610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      array[i] = i; // each array-write generates a cache miss
7136610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov   }
7137610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
7138610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7139610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
7140610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov   printf("test504: force massive CacheLineZ fetch-wback\n");
7141610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov   MyThreadArray t(Worker, Worker);
7142610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov   t.Start();
7143610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov   t.Join();
7144610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
7145610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7146610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST2(Run, 504, PERFORMANCE | PRINT_STATS | EXCLUDE_FROM_ALL)
7147610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#endif // WINE
7148610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test504
7149610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7150610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test505: force massive cache fetch-wback (60% misses) {{{1
7151610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// modification of test504 - more threads, byte accesses and lots of mutexes
7152610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// so it produces lots of CacheLineF misses (30-50% of CacheLineZ misses)
7153610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test505 {
7154610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#if !defined(WINE) and !defined(ANDROID) // Valgrind+wine hate large static objects
7155610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7156610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovconst int N_THREADS = 2,
7157610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov          HG_CACHELINE_COUNT = 1 << 16,
7158610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov          HG_CACHELINE_SIZE  = 1 << 6,
7159610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov          HG_CACHE_SIZE = HG_CACHELINE_COUNT * HG_CACHELINE_SIZE;
7160610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7161610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovconst int ARRAY_SIZE = 4 * HG_CACHE_SIZE,
7162610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov          ITERATIONS = 3;
7163610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint64_t array[ARRAY_SIZE];
7164610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7165610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint count = 0;
7166610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex count_mu;
7167610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7168610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker() {
7169610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov   const int N_MUTEXES = 5;
7170610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov   Mutex mu[N_MUTEXES];
7171610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov   count_mu.Lock();
7172610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov   int myId = ++count;
7173610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov   count_mu.Unlock();
7174610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7175610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov   // all threads write to different memory locations,
7176610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov   // so no synchronization mechanisms are needed
7177610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov   int lower_bound = ARRAY_SIZE * (myId-1) / N_THREADS,
7178610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov       upper_bound = ARRAY_SIZE * ( myId ) / N_THREADS;
7179610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov   for (int j = 0; j < ITERATIONS; j++)
7180610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov   for (int mutex_id = 0; mutex_id < N_MUTEXES; mutex_id++) {
7181610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      Mutex *m = & mu[mutex_id];
7182610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      m->Lock();
7183610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      for (int i = lower_bound + mutex_id, cnt = 0;
7184610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov               i < upper_bound;
7185610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov               i += HG_CACHELINE_SIZE / sizeof(array[0]), cnt++) {
7186610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov         array[i] = i; // each array-write generates a cache miss
7187610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      }
7188610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      m->Unlock();
7189610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov   }
7190610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
7191610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7192610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
7193610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov   printf("test505: force massive CacheLineF fetch-wback\n");
7194610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov   MyThreadArray t(Worker, Worker);
7195610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov   t.Start();
7196610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov   t.Join();
7197610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
7198610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7199610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST2(Run, 505, PERFORMANCE | PRINT_STATS | EXCLUDE_FROM_ALL)
7200610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#endif // WINE
7201610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test505
7202610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7203610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test506: massive HB's using Barriers {{{1
7204610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// HB cache miss is ~40%
7205610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// segments consume 10x more memory than SSs
7206610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// modification of test39
7207610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test506 {
7208610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#ifndef NO_BARRIER
7209610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Same as test17 but uses Barrier class (pthread_barrier_t).
7210610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
7211610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovconst int N_threads = 64,
7212610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov          ITERATIONS = 1000;
7213610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovBarrier *barrier[ITERATIONS];
7214610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex   MU;
7215610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7216610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker() {
7217610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int i = 0; i < ITERATIONS; i++) {
7218610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov     MU.Lock();
7219610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov     GLOB++;
7220610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov     MU.Unlock();
7221610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov     barrier[i]->Block();
7222610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
7223610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
7224610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
7225610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test506: massive HB's using Barriers\n");
7226610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int i = 0; i < ITERATIONS; i++) {
7227610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov     barrier[i] = new Barrier(N_threads);
7228610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
7229610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  {
7230610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    ThreadPool pool(N_threads);
7231610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    pool.StartWorkers();
7232610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    for (int i = 0; i < N_threads; i++) {
7233610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      pool.Add(NewCallback(Worker));
7234610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    }
7235610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  } // all folks are joined here.
7236610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  CHECK(GLOB == N_threads * ITERATIONS);
7237610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int i = 0; i < ITERATIONS; i++) {
7238610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov     delete barrier[i];
7239610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
7240610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
7241610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST2(Run, 506, PERFORMANCE | PRINT_STATS | EXCLUDE_FROM_ALL);
7242610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#endif // NO_BARRIER
7243610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test506
7244610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7245610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test507: vgHelgrind_initIterAtFM/stackClear benchmark {{{1
7246610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// vgHelgrind_initIterAtFM/stackClear consume ~8.5%/5.5% CPU
7247610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test507 {
7248610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovconst int N_THREADS    = 1,
7249610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov          BUFFER_SIZE  = 1,
7250610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov          ITERATIONS   = 1 << 20;
7251610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7252610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Foo() {
7253610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  struct T {
7254610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    char temp;
7255610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    T() {
7256610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      ANNOTATE_RWLOCK_CREATE(&temp);
7257610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    }
7258610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    ~T() {
7259610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      ANNOTATE_RWLOCK_DESTROY(&temp);
7260610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    }
7261610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  } s[BUFFER_SIZE];
7262610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  s->temp = '\0';
7263610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
7264610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7265610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker() {
7266610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int j = 0; j < ITERATIONS; j++) {
7267610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    Foo();
7268610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
7269610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
7270610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7271610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
7272610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test507: vgHelgrind_initIterAtFM/stackClear benchmark\n");
7273610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  {
7274610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    ThreadPool pool(N_THREADS);
7275610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    pool.StartWorkers();
7276610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    for (int i = 0; i < N_THREADS; i++) {
7277610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      pool.Add(NewCallback(Worker));
7278610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    }
7279610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  } // all folks are joined here.
7280610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
7281610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST2(Run, 507, EXCLUDE_FROM_ALL);
7282610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test507
7283610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7284610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test508: cmp_WordVecs_for_FM benchmark {{{1
7285610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 50+% of CPU consumption by cmp_WordVecs_for_FM
7286610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test508 {
7287610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovconst int N_THREADS    = 1,
7288610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov          BUFFER_SIZE  = 1 << 10,
7289610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov          ITERATIONS   = 1 << 9;
7290610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7291610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Foo() {
7292610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  struct T {
7293610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    char temp;
7294610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    T() {
7295610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      ANNOTATE_RWLOCK_CREATE(&temp);
7296610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    }
7297610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    ~T() {
7298610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      ANNOTATE_RWLOCK_DESTROY(&temp);
7299610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    }
7300610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  } s[BUFFER_SIZE];
7301610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  s->temp = '\0';
7302610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
7303610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7304610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker() {
7305610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int j = 0; j < ITERATIONS; j++) {
7306610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    Foo();
7307610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
7308610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
7309610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7310610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
7311610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test508: cmp_WordVecs_for_FM benchmark\n");
7312610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  {
7313610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    ThreadPool pool(N_THREADS);
7314610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    pool.StartWorkers();
7315610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    for (int i = 0; i < N_THREADS; i++) {
7316610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      pool.Add(NewCallback(Worker));
7317610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    }
7318610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  } // all folks are joined here.
7319610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
7320610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST2(Run, 508, EXCLUDE_FROM_ALL);
7321610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test508
7322610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7323610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test509: avl_find_node benchmark {{{1
7324610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// 10+% of CPU consumption by avl_find_node
7325610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test509 {
7326610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovconst int N_THREADS    = 16,
7327610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov          ITERATIONS   = 1 << 8;
7328610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7329610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker() {
7330610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  std::vector<Mutex*> mu_list;
7331610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int i = 0; i < ITERATIONS; i++) {
7332610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    Mutex * mu = new Mutex();
7333610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    mu_list.push_back(mu);
7334610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    mu->Lock();
7335610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
7336610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int i = ITERATIONS - 1; i >= 0; i--) {
7337610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    Mutex * mu = mu_list[i];
7338610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    mu->Unlock();
7339610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    delete mu;
7340610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
7341610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
7342610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7343610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
7344610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test509: avl_find_node benchmark\n");
7345610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  {
7346610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    ThreadPool pool(N_THREADS);
7347610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    pool.StartWorkers();
7348610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    for (int i = 0; i < N_THREADS; i++) {
7349610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      pool.Add(NewCallback(Worker));
7350610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    }
7351610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  } // all folks are joined here.
7352610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
7353610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST2(Run, 509, EXCLUDE_FROM_ALL);
7354610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test509
7355610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7356610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test510: SS-recycle test {{{1
7357610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// this tests shows the case where only ~1% of SS are recycled
7358610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test510 {
7359610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovconst int N_THREADS    = 16,
7360610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov          ITERATIONS   = 1 << 10;
7361610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint GLOB = 0;
7362610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7363610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker() {
7364610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(100000);
7365610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int i = 0; i < ITERATIONS; i++) {
7366610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    ANNOTATE_CONDVAR_SIGNAL((void*)0xDeadBeef);
7367610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    GLOB++;
7368610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    usleep(10);
7369610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
7370610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
7371610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7372610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
7373610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  //ANNOTATE_BENIGN_RACE(&GLOB, "Test");
7374610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  printf("test510: SS-recycle test\n");
7375610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  {
7376610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    ThreadPool pool(N_THREADS);
7377610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    pool.StartWorkers();
7378610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    for (int i = 0; i < N_THREADS; i++) {
7379610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      pool.Add(NewCallback(Worker));
7380610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    }
7381610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  } // all folks are joined here.
7382610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
7383610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST2(Run, 510, MEMORY_USAGE | PRINT_STATS | EXCLUDE_FROM_ALL);
7384610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test510
7385610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7386610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test511: Segment refcounting test ('1' refcounting) {{{1
7387610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test511 {
7388610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint GLOB = 0;
7389610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7390610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run () {
7391610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov   for (int i = 0; i < 300; i++) {
7392610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      ANNOTATE_CONDVAR_SIGNAL(&GLOB);
7393610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      usleep(1000);
7394610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      GLOB++;
7395610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      ANNOTATE_CONDVAR_WAIT(&GLOB);
7396610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov   }
7397610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
7398610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST2(Run, 511, MEMORY_USAGE | PRINT_STATS | EXCLUDE_FROM_ALL);
7399610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test511
7400610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7401610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test512: Access the same memory with big intersecting LockSets {{{1
7402610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test512 {
7403610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovconst int N_MUTEXES = 128;
7404610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovconst int DATA_SIZE = 1024;
7405610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7406610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex mu[N_MUTEXES];
7407610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint   GLOB[DATA_SIZE];
7408610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7409610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid TP() {
7410610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  Mutex thread_mu;
7411610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  thread_mu.Lock();
7412610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int j = 0; j < 10; j++) {
7413610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    for (int m = 0; m < N_MUTEXES; m++)
7414610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      mu[m].Lock();
7415610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    for (int i = 0; i < 3000; i++) {
7416610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      ANNOTATE_CONDVAR_SIGNAL(&GLOB);  // Force new segment
7417610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      for (int k = 0; k < DATA_SIZE; k++)
7418610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov        GLOB[k] = 42;
7419610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    }
7420610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    for (int m = 0; m < N_MUTEXES; m++)
7421610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      mu[m].Unlock();
7422610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
7423610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  thread_mu.Unlock();
7424610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
7425610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7426610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
7427610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov   MyThreadArray t(TP, TP);
7428610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov   printf("test512: Access the same memory with big intersecting LockSets.\n");
7429610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7430610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov   t.Start();
7431610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov   t.Join();
7432610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
7433610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7434610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST2(Run, 512, EXCLUDE_FROM_ALL | PERFORMANCE)
7435610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test512
7436610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7437610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// test513: --fast-mode benchmark {{{1
7438610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace test513 {
7439610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7440610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovconst int N_THREADS = 2,
7441610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov          HG_CACHELINE_SIZE  = 1 << 6,
7442610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov          ARRAY_SIZE = HG_CACHELINE_SIZE * 512,
7443610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov          MUTEX_ID_BITS = 8,
7444610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov          MUTEX_ID_MASK = (1 << MUTEX_ID_BITS) - 1;
7445610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7446610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Each thread has its own cacheline and tackles with it intensively
7447610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovconst int ITERATIONS = 1024;
7448610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint array[N_THREADS][ARRAY_SIZE];
7449610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7450610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint count = 0;
7451610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex count_mu;
7452610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex mutex_arr[N_THREADS][MUTEX_ID_BITS];
7453610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7454610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker() {
7455610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov   count_mu.Lock();
7456610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov   int myId = count++;
7457610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov   count_mu.Unlock();
7458610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7459610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov   // all threads write to different memory locations
7460610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov   for (int j = 0; j < ITERATIONS; j++) {
7461610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      int mutex_mask = j & MUTEX_ID_BITS;
7462610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      for (int m = 0; m < MUTEX_ID_BITS; m++)
7463610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov         if (mutex_mask & (1 << m))
7464610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov            mutex_arr[myId][m].Lock();
7465610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7466610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      for (int i = 0; i < ARRAY_SIZE; i++) {
7467610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov         array[myId][i] = i;
7468610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      }
7469610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7470610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      for (int m = 0; m < MUTEX_ID_BITS; m++)
7471610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov         if (mutex_mask & (1 << m))
7472610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov            mutex_arr[myId][m].Unlock();
7473610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov   }
7474610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
7475610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7476610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Run() {
7477610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov   printf("test513: --fast-mode benchmark\n");
7478610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov   {
7479610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      ThreadPool pool(N_THREADS);
7480610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      pool.StartWorkers();
7481610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      for (int i = 0; i < N_THREADS; i++) {
7482610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov         pool.Add(NewCallback(Worker));
7483610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      }
7484610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov   } // all folks are joined here.
7485610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
7486610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7487610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovREGISTER_TEST2(Run, 513, PERFORMANCE | PRINT_STATS | EXCLUDE_FROM_ALL)
7488610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace test513
7489610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7490610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace ThreadChainTest {  // {{{1 Reg test for thread creation
7491610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Thread1() { }
7492610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Thread2() {
7493610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThread t(Thread1);
7494610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
7495610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
7496610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
7497610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Thread3() {
7498610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThread t(Thread2);
7499610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
7500610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
7501610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
7502610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Thread4() {
7503610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThread t(Thread3);
7504610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
7505610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
7506610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
7507610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7508610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(RegTests, ThreadChainTest) {
7509610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  Thread4();
7510610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
7511610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7512610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace
7513610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7514610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#ifndef ANDROID // GTest does not support ASSERT_DEBUG_DEATH.
7515610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace SimpleDeathTest {  // {{{1 Make sure that the tool handles death tests correctly
7516610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#ifdef WIN32
7517610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(DeathTests, DISABLED_SimpleDeathTest) {
7518610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#else
7519610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(DeathTests, SimpleDeathTest) {
7520610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#endif
7521610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ASSERT_DEBUG_DEATH(CHECK(false), "");
7522610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
7523610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace
7524610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#endif
7525610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7526610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace IgnoreTests {  // {{{1 Test how the tool works with indirect calls to fun_r functions
7527610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint GLOB = 0;
7528610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid (*f)() = NULL;
7529610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7530610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid NotIgnoredRacey() {
7531610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB++;
7532610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
7533610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7534610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid FunRFunction() {
7535610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  NotIgnoredRacey();
7536610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(1); // avoid tail call elimination
7537610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
7538610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7539610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid DoDirectCall() {
7540610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  FunRFunction();
7541610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(1); // avoid tail call elimination
7542610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
7543610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7544610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid DoIndirectCall() {
7545610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  (*f)();
7546610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  usleep(1); // avoid tail call elimination
7547610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
7548610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7549610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(IgnoreTests, DirectCallToFunR) {
7550610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray mta(DoDirectCall, DoDirectCall);
7551610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  mta.Start();
7552610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  mta.Join();
7553610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
7554610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7555610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(IgnoreTests, IndirectCallToFunR) {
7556610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  f = FunRFunction;
7557610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray mta(DoIndirectCall, DoIndirectCall);
7558610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  mta.Start();
7559610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  mta.Join();
7560610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
7561610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace
7562610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7563610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace MutexNotPhbTests {
7564610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7565610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint GLOB = 0;
7566610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovMutex mu;
7567610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovStealthNotification n;
7568610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7569610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid SignalThread() {
7570610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 1;
7571610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  mu.Lock();
7572610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  mu.Unlock();
7573610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  n.signal();
7574610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
7575610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7576610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid WaitThread() {
7577610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  n.wait();
7578610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  mu.Lock();
7579610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  mu.Unlock();
7580610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 2;
7581610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
7582610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7583610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(MutexNotPhbTests, MutexNotPhbTest) {
7584610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_NOT_HAPPENS_BEFORE_MUTEX(&mu);
7585610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_EXPECT_RACE(&GLOB, "MutexNotPhbTest. TP.");
7586610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray mta(SignalThread, WaitThread);
7587610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  mta.Start();
7588610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  mta.Join();
7589610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
7590610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov} // namespace
7591610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7592610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace RaceVerifierTests_Simple {
7593610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     GLOB = 0;
7594610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7595610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker1() {
7596610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 1;
7597610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
7598610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7599610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker2() {
7600610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 2;
7601610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
7602610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7603610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(RaceVerifierTests, Simple) {
7604610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_EXPECT_RACE(&GLOB, "SimpleRace.");
7605610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Worker1, Worker2);
7606610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
7607610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
7608610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
7609610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace
7610610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7611610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace RaceVerifierTests_Unverifiable {
7612610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovStealthNotification n;
7613610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint GLOB = 0;
7614610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7615610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker1() {
7616610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  if (!GLOB)
7617610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    GLOB = 1;
7618610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  n.signal();
7619610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
7620610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7621610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker2() {
7622610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  n.wait();
7623610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  GLOB = 2;
7624610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
7625610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7626610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(RaceVerifierTests, Unverifiable) {
7627610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_EXPECT_RACE(&GLOB, "SimpleRace. UNVERIFIABLE.");
7628610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Worker1, Worker2);
7629610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
7630610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
7631610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
7632610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace
7633610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7634610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7635610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace RaceVerifierTests_ManyRacesInOneTrace {
7636610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovStealthNotification n;
7637610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint     array[2];
7638610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7639610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker1() {
7640610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  array[0] = 1;
7641610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  array[1] = 2;
7642610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
7643610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7644610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker2() {
7645610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  array[1] = array[0];
7646610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
7647610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7648610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(RaceVerifierTests, ManyRacesInOneTrace) {
7649610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_EXPECT_RACE(array + 0, "RaceVerifierTests_ManyRacesInOneTrace: race 1.");
7650610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_EXPECT_RACE(array + 1, "RaceVerifierTests_ManyRacesInOneTrace: race 2.");
7651610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Worker1, Worker2);
7652610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
7653610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
7654610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
7655610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace
7656610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7657610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace PrintfTests_Simple {
7658610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7659610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker1() {
7660610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // This one is a printf() => vfprintf()
7661610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  fprintf(stderr, "Hello from a thread: %d\n", 2);
7662610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  // This one is a puts()
7663610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  fprintf(stderr, "Hello from a thread\n");
7664610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  fprintf(stdout, "Hello from a thread: %d\n", 2);
7665610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  fprintf(stdout, "Hello from a thread\n");
7666610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
7667610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7668610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(PrintfTests, DISABLED_Simple) {
7669610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Worker1, Worker1);
7670610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
7671610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
7672610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
7673610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace
7674610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7675610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace PrintfTests_RaceOnFwriteArgument {
7676610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7677610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovchar s[] = "abracadabra\n";
7678610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7679610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker1() {
7680610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  fwrite(s, 1, sizeof(s) - 1, stdout);
7681610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
7682610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7683610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker2() {
7684610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  s[3] = 'z';
7685610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
7686610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7687610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(PrintfTests, RaceOnFwriteArgument) {
7688610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_TRACE_MEMORY(s + 3);
7689610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_EXPECT_RACE(s + 3, "PrintfTests_RaceOnFwriteArgument.");
7690610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Worker1, Worker2);
7691610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
7692610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
7693610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
7694610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace
7695610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7696610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace PrintfTests_RaceOnPutsArgument {
7697610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7698610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovchar s[] = "abracadabra";
7699610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7700610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker1() {
7701610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  puts(s);
7702610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
7703610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7704610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker2() {
7705610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  s[3] = 'z';
7706610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
7707610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7708610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(PrintfTests, RaceOnPutsArgument) {
7709610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_TRACE_MEMORY(s + 3);
7710610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_EXPECT_RACE(s + 3, "PrintfTests_RaceOnPutsArgument.");
7711610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Worker1, Worker2);
7712610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
7713610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
7714610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
7715610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace
7716610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7717610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace PrintfTests_RaceOnPrintfArgument {
7718610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7719610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvolatile char s[] = "abracadabra";
7720610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvolatile char s2[] = "abracadabra";
7721610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7722610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker1() {
7723610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  fprintf(stdout, "printing a string: %s\n", s);
7724610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  fprintf(stderr, "printing a string: %s\n", s2);
7725610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
7726610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7727610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker2() {
7728610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  s[3] = 'z';
7729610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  s2[3] = 'z';
7730610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
7731610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7732610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(PrintfTests, DISABLED_RaceOnPrintfArgument) {
7733610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_EXPECT_RACE(s + 3, "PrintfTests_RaceOnPrintfArgument (stdout).");
7734610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_EXPECT_RACE(s2 + 3, "PrintfTests_RaceOnPrintfArgument (stderr).");
7735610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Worker1, Worker2);
7736610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
7737610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
7738610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
7739610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace
7740610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7741610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Apparently, %n is not supported in windows
7742610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#ifndef WIN32
7743610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace PrintfTests_RaceOnOutputArgument {
7744610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7745610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvolatile char s[] = "abracadabra";
7746610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvolatile int a = 0;
7747610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7748610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker1() {
7749610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  fprintf(stdout, "printing a string: %s%n\n", s, &a);
7750610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
7751610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7752610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker2() {
7753610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  fprintf(stdout, "the other thread have already printed %d characters\n", a);
7754610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
7755610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7756610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(PrintfTests, DISABLED_RaceOnOutputArgument) {
7757610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_EXPECT_RACE(&a, "PrintfTests_RaceOnOutputArgument:int.");
7758610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Worker1, Worker2);
7759610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
7760610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
7761610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
7762610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace
7763610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#endif
7764610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7765610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace PrintfTests_Fflush {
7766610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7767610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvolatile char s[] = "abracadabra";
7768610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvolatile int a = 0;
7769610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7770610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker1() {
7771610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  fflush(NULL);
7772610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
7773610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7774610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker2() {
7775610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  fflush(NULL);
7776610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
7777610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7778610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(PrintfTests, DISABLED_Fflush) {
7779610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Worker1, Worker2);
7780610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
7781610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
7782610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
7783610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace
7784610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7785610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace BenignRaceTest {  // {{{1
7786610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovconst int kArrayLen = 97;
7787610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovchar X[kArrayLen];
7788610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovchar *P;
7789610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7790610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint counter;
7791610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7792610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7793610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker() {
7794610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  (*P)++;
7795610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_HAPPENS_BEFORE(P);
7796610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  AtomicIncrement(&counter, -1);
7797610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
7798610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7799610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(NegativeTests, BenignRaceTest) {
7800610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ThreadPool pool1(1);
7801610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ThreadPool pool2(1);
7802610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ThreadPool pool3(1);
7803610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  pool1.StartWorkers();
7804610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  pool2.StartWorkers();
7805610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  pool3.StartWorkers();
7806610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7807610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  ANNOTATE_BENIGN_RACE(&counter, "");
7808610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  const int kNIter = 1000;
7809610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7810610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int i = 0; i < kNIter; i++) {
7811610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    counter = 3;
7812610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    long len = (i % (kArrayLen / 3)) + 1;
7813610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    long beg = i % (kArrayLen - len);
7814610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    long end = beg + len;
7815610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    CHECK(beg < kArrayLen);
7816610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    CHECK(end <= kArrayLen);
7817610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    bool is_expected = i % 2;
7818610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    long pos = i % len;
7819610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    P = X + beg + pos;
7820610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    CHECK(P < X + kArrayLen);
7821610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    // printf("[%d] b=%ld e=%ld p=%ld is_expected=%d\n",
7822610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    //       i, beg, end, pos, is_expected);
7823610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    ANNOTATE_NEW_MEMORY(X, kArrayLen);
7824610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    if (is_expected) {
7825610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      ANNOTATE_EXPECT_RACE(P, "expected race in BenignRaceTest");
7826610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    } else {
7827610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      ANNOTATE_BENIGN_RACE_SIZED(X + beg, len, "");
7828610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    }
7829610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    if ((i % (kNIter / 10)) == 0) {
7830610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      ANNOTATE_FLUSH_STATE();
7831610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    }
7832610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    pool1.Add(NewCallback(Worker));
7833610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    pool2.Add(NewCallback(Worker));
7834610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    pool3.Add(NewCallback(Worker));
7835610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7836610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    while(AtomicIncrement(&counter, 0) != 0)
7837610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      usleep(1000);
7838610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    ANNOTATE_HAPPENS_AFTER(P);
7839610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7840610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    ANNOTATE_FLUSH_EXPECTED_RACES();
7841610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
7842610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
7843610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
7844610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7845610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace StressTests_FlushStateTest {  // {{{1
7846610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Stress test for FlushState which happens in parallel with some work.
7847610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovconst int N = 1000;
7848610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint array[N];
7849610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7850610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Flusher() {
7851610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int i = 0; i < 10; i++) {
7852610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    usleep(1000);
7853610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    ANNOTATE_FLUSH_STATE();
7854610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
7855610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
7856610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7857610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Write1(int i) { array[i]++; }
7858610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Write2(int i) { array[i]--; }
7859610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint Read1(int i) { volatile int z = array[i]; return z; }
7860610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint Read2(int i) { volatile int z = array[i]; return z; }
7861610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7862610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid Worker() {
7863610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  for (int iter = 0; iter < 10; iter++) {
7864610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    usleep(1000);
7865610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    for (int i = 0; i < N; i++) {
7866610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      Write1(i);
7867610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      Write2(i);
7868610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      Read1(i);
7869610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov      Read2(i);
7870610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov    }
7871610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  }
7872610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
7873610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7874610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(StressTests, FlushStateTest) {
7875610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  MyThreadArray t(Flusher, Worker, Worker, Worker);
7876610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Start();
7877610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov  t.Join();
7878610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}
7879610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7880610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}  // namespace
7881610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov
7882610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// End {{{1
7883610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov // vim:shiftwidth=2:softtabstop=2:expandtab:foldmethod=marker
7884