tsan_unittest.cpp revision b32f58018498ea2225959b0ba11c18f0c433deef
1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  This file is part of Valgrind, a dynamic binary instrumentation
3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  framework.
4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Copyright (C) 2008-2008 Google Inc
6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     opensource@google.com
7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  This program is free software; you can redistribute it and/or
9ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  modify it under the terms of the GNU General Public License as
10ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  published by the Free Software Foundation; either version 2 of the
11ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  License, or (at your option) any later version.
12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  This program is distributed in the hope that it will be useful, but
14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  WITHOUT ANY WARRANTY; without even the implied warranty of
15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  General Public License for more details.
17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  You should have received a copy of the GNU General Public License
19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  along with this program; if not, write to the Free Software
20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  02111-1307, USA.
22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  The GNU General Public License is contained in the file COPYING.
24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Author: Konstantin Serebryany <opensource@google.com>
27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// This file contains a set of unit tests for a data race detection tool.
29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// This test can be compiled with pthreads (default) or
33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// with any other library that supports threads, locks, cond vars, etc.
34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// To compile with pthreads:
36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   g++  racecheck_unittest.cc dynamic_annotations.cc
37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//        -lpthread -g -DDYNAMIC_ANNOTATIONS=1
38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// To compile with different library:
40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   1. cp thread_wrappers_pthread.h thread_wrappers_yourlib.h
41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   2. edit thread_wrappers_yourlib.h
42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   3. add '-DTHREAD_WRAPPERS="thread_wrappers_yourlib.h"' to your compilation.
43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// This test must not include any other file specific to threading library,
47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// everything should be inside THREAD_WRAPPERS.
48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifndef THREAD_WRAPPERS
49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown# define THREAD_WRAPPERS "thread_wrappers_pthread.h"
50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include THREAD_WRAPPERS
52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifndef NEEDS_SEPERATE_RW_LOCK
54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define RWLock Mutex // Mutex does work as an rw-lock.
55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define WriterLockScoped MutexLock
56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ReaderLockScoped ReaderMutexLock
57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif // !NEEDS_SEPERATE_RW_LOCK
58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Helgrind memory usage testing stuff
61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// If not present in dynamic_annotations.h/.cc - ignore
62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifndef ANNOTATE_RESET_STATS
63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ANNOTATE_RESET_STATS() do { } while(0)
64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifndef ANNOTATE_PRINT_STATS
66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ANNOTATE_PRINT_STATS() do { } while(0)
67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifndef ANNOTATE_PRINT_MEMORY_USAGE
69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ANNOTATE_PRINT_MEMORY_USAGE(a) do { } while(0)
70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// A function that allows to suppress gcc's warnings about
74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// unused return values in a portable way.
75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntemplate <typename T>
76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic inline void IGNORE_RETURN_VALUE(T v)
77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{ }
78ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
79ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <vector>
80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <string>
81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <map>
82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <queue>
83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <algorithm>
84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <cstring>      // strlen(), index(), rindex()
85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <ctime>
86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <sys/time.h>
87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <sys/types.h>
88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <sys/stat.h>
89ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <fcntl.h>
90ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <sys/mman.h>  // mmap
91ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <errno.h>
92ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <stdint.h>    // uintptr_t
93ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <stdlib.h>
94ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <dirent.h>
95ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
96b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#ifndef VGO_darwin
97ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include <malloc.h>
98ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
99ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// The tests are
101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// - Stability tests (marked STAB)
102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// - Performance tests (marked PERF)
103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// - Feature tests
104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   - TN (true negative) : no race exists and the tool is silent.
105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   - TP (true positive) : a race exists and reported.
106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   - FN (false negative): a race exists but not reported.
107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   - FP (false positive): no race exists but the tool reports it.
108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// The feature tests are marked according to the behavior of helgrind 3.3.0.
110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// TP and FP tests are annotated with ANNOTATE_EXPECT_RACE,
112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// so, no error reports should be seen when running under helgrind.
113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// When some of the FP cases are fixed in helgrind we'll need
115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// to update this test.
116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Each test resides in its own namespace.
118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Namespaces are named test01, test02, ...
119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Please, *DO NOT* change the logic of existing tests nor rename them.
120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Create a new test instead.
121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Some tests use sleep()/usleep().
123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// This is not a synchronization, but a simple way to trigger
124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// some specific behaviour of the race detector's scheduler.
125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Globals and utilities used by several tests. {{{1
127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownCondVar CV;
128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     COND = 0;
129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef void (*void_func_void_t)(void);
132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownenum TEST_FLAG {
133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  FEATURE           = 1 << 0,
134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  STABILITY         = 1 << 1,
135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  PERFORMANCE       = 1 << 2,
136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  EXCLUDE_FROM_ALL  = 1 << 3,
137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  NEEDS_ANNOTATIONS = 1 << 4,
138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  RACE_DEMO         = 1 << 5,
139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MEMORY_USAGE      = 1 << 6,
140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  PRINT_STATS       = 1 << 7
141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown};
142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Put everything into stderr.
144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex printf_mu;
145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define printf(args...) \
146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    do{ \
147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      printf_mu.Lock();\
148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fprintf(stderr, args);\
149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      printf_mu.Unlock(); \
150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }while(0)
151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownlong GetTimeInMs() {
153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   struct timeval tv;
154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   gettimeofday(&tv, NULL);
155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return (tv.tv_sec * 1000L) + (tv.tv_usec / 1000L);
156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstruct Test{
159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  void_func_void_t f_;
160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  int flags_;
161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Test(void_func_void_t f, int flags)
162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    : f_(f)
163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    , flags_(flags)
164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  {}
165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Test() : f_(0), flags_(0) {}
166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  void Run() {
167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     ANNOTATE_RESET_STATS();
168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (flags_ & PERFORMANCE) {
169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        long start = GetTimeInMs();
170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        f_();
171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        long end = GetTimeInMs();
172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        printf ("Time: %4ldms\n", end-start);
173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     } else
174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        f_();
175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (flags_ & PRINT_STATS)
176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ANNOTATE_PRINT_STATS();
177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     if (flags_ & MEMORY_USAGE)
178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ANNOTATE_PRINT_MEMORY_USAGE(0);
179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown};
181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstd::map<int, Test> TheMapOfTests;
182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define NOINLINE __attribute__ ((noinline))
184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownextern "C" void NOINLINE AnnotateSetVerbosity(const char *, int, int) {};
185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstruct TestAdder {
188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  TestAdder(void_func_void_t f, int id, int flags = FEATURE) {
189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    // AnnotateSetVerbosity(__FILE__, __LINE__, 0);
190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CHECK(TheMapOfTests.count(id) == 0);
191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    TheMapOfTests[id] = Test(f, flags);
192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown};
194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define REGISTER_TEST(f, id)         TestAdder add_test_##id (f, id);
196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define REGISTER_TEST2(f, id, flags) TestAdder add_test_##id (f, id, flags);
197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic bool ArgIsOne(int *arg) { return *arg == 1; };
199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic bool ArgIsZero(int *arg) { return *arg == 0; };
200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic bool ArgIsTrue(bool *arg) { return *arg == true; };
201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Call ANNOTATE_EXPECT_RACE only if 'machine' env variable is defined.
203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Useful to test against several different machines.
204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Supported machines so far:
205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   MSM_HYBRID1             -- aka MSMProp1
206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   MSM_HYBRID1_INIT_STATE  -- aka MSMProp1 with --initialization-state=yes
207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   MSM_THREAD_SANITIZER    -- ThreadSanitizer's state machine
208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ANNOTATE_EXPECT_RACE_FOR_MACHINE(mem, descr, machine) \
209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    while(getenv(machine)) {\
210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ANNOTATE_EXPECT_RACE(mem, descr); \
211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;\
212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }\
213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define ANNOTATE_EXPECT_RACE_FOR_TSAN(mem, descr) \
215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ANNOTATE_EXPECT_RACE_FOR_MACHINE(mem, descr, "MSM_THREAD_SANITIZER")
216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browninline bool Tsan_PureHappensBefore() {
218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  return true;
219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browninline bool Tsan_FastMode()           {
222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  return getenv("TSAN_FAST_MODE") != NULL;
223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Initialize *(mem) to 0 if Tsan_FastMode.
226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define FAST_MODE_INIT(mem) do { if (Tsan_FastMode()) { *(mem) = 0; } } while(0)
227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifndef MAIN_INIT_ACTION
229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define MAIN_INIT_ACTION
230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint main(int argc, char** argv) { // {{{1
235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MAIN_INIT_ACTION;
236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("FLAGS [phb=%i, fm=%i]\n", Tsan_PureHappensBefore(), Tsan_FastMode());
237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if (argc == 2 && !strcmp(argv[1], "benchmark")) {
238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     for (std::map<int,Test>::iterator it = TheMapOfTests.begin();
239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         it != TheMapOfTests.end(); ++it) {
240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       if(!(it->second.flags_ & PERFORMANCE)) continue;
241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       it->second.Run();
242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  } else if (argc == 2 && !strcmp(argv[1], "demo")) {
244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     for (std::map<int,Test>::iterator it = TheMapOfTests.begin();
245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         it != TheMapOfTests.end();  ++it) {
246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       if(!(it->second.flags_ & RACE_DEMO)) continue;
247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       it->second.Run();
248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     }
249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  } else if (argc > 1) {
250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    // the tests are listed in command line flags
251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for (int i = 1; i < argc; i++) {
252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      int f_num = atoi(argv[i]);
253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      CHECK(TheMapOfTests.count(f_num));
254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      TheMapOfTests[f_num].Run();
255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  } else {
257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    bool run_tests_with_annotations = false;
258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (getenv("DRT_ALLOW_ANNOTATIONS")) {
259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      run_tests_with_annotations = true;
260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for (std::map<int,Test>::iterator it = TheMapOfTests.begin();
262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        it != TheMapOfTests.end();
263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ++it) {
264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if(it->second.flags_ & EXCLUDE_FROM_ALL) continue;
265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if(it->second.flags_ & RACE_DEMO) continue;
266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if((it->second.flags_ & NEEDS_ANNOTATIONS)
267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         && run_tests_with_annotations == false) continue;
268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      it->second.Run();
269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifdef THREAD_WRAPPERS_PTHREAD_H
274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// An array of threads. Create/start/join all elements at once. {{{1
278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownclass MyThreadArray {
279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown public:
280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  static const int kSize = 5;
281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  typedef void (*F) (void);
282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray(F f1, F f2 = NULL, F f3 = NULL, F f4 = NULL, F f5 = NULL) {
283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ar_[0] = new MyThread(f1);
284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ar_[1] = f2 ? new MyThread(f2) : NULL;
285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ar_[2] = f3 ? new MyThread(f3) : NULL;
286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ar_[3] = f4 ? new MyThread(f4) : NULL;
287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ar_[4] = f5 ? new MyThread(f5) : NULL;
288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  void Start() {
290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(int i = 0; i < kSize; i++) {
291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if(ar_[i]) {
292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ar_[i]->Start();
293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        usleep(10);
294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  void Join() {
299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(int i = 0; i < kSize; i++) {
300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if(ar_[i]) {
301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ar_[i]->Join();
302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ~MyThreadArray() {
307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for(int i = 0; i < kSize; i++) {
308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      delete ar_[i];
309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown private:
312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThread *ar_[kSize];
313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown};
314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test00: {{{1
318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test00 {
319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test00: negative\n");
322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB=%d\n", GLOB);
323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST(Run, 00)
325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test00
326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test01: TP. Simple race (write vs write). {{{1
329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test01 {
330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker() {
332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = 1;
333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Parent() {
336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThread t(Worker);
337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
338b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  const timespec delay = { 0, 100 * 1000 * 1000 };
339b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  nanosleep(&delay, 0);
340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = 2;
341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  FAST_MODE_INIT(&GLOB);
345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test01. TP.");
346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_TRACE_MEMORY(&GLOB);
347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test01: positive\n");
348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Parent();
349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  const int tmp = GLOB;
350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB=%d\n", tmp);
351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST(Run, 1);
353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test01
354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test02: TN. Synchronization via CondVar. {{{1
357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test02 {
358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Two write accesses to GLOB are synchronized because
360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// the pair of CV.Signal() and CV.Wait() establish happens-before relation.
361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Waiter:                      Waker:
363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 1. COND = 0
364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 2. Start(Waker)
365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 3. MU.Lock()                 a. write(GLOB)
366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                              b. MU.Lock()
367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                              c. COND = 1
368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                         /--- d. CV.Signal()
369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//  4. while(COND)        /     e. MU.Unlock()
370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//       CV.Wait(MU) <---/
371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//  5. MU.Unlock()
372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//  6. write(GLOB)
373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex   MU;
374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Waker() {
376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(100000);  // Make sure the waiter blocks.
377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = 1;
378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  COND = 1;
381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CV.Signal();
382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();
383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Waiter() {
386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ThreadPool pool(1);
387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  pool.StartWorkers();
388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  COND = 0;
389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  pool.Add(NewCallback(Waker));
390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  while(COND != 1)
392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CV.Wait(&MU);
393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();
394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = 2;
395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test02: negative\n");
398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Waiter();
399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB=%d\n", GLOB);
400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST(Run, 2);
402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test02
403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test03: TN. Synchronization via LockWhen, signaller gets there first. {{{1
406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test03 {
407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Two write accesses to GLOB are synchronized via conditional critical section.
409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Note that LockWhen() happens first (we use sleep(1) to make sure)!
410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Waiter:                           Waker:
412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 1. COND = 0
413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 2. Start(Waker)
414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                                   a. write(GLOB)
415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                                   b. MU.Lock()
416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                                   c. COND = 1
417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                              /--- d. MU.Unlock()
418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 3. MU.LockWhen(COND==1) <---/
419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 4. MU.Unlock()
420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 5. write(GLOB)
421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex   MU;
422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Waker() {
424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(100000);  // Make sure the waiter blocks.
425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = 1;
426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  COND = 1; // We are done! Tell the Waiter.
429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock(); // calls ANNOTATE_CONDVAR_SIGNAL;
430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Waiter() {
432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ThreadPool pool(1);
433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  pool.StartWorkers();
434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  COND = 0;
435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  pool.Add(NewCallback(Waker));
436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.LockWhen(Condition(&ArgIsOne, &COND));  // calls ANNOTATE_CONDVAR_WAIT
437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();  // Waker is done!
438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = 2;
440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test03: negative\n");
443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Waiter();
444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB=%d\n", GLOB);
445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 3, FEATURE|NEEDS_ANNOTATIONS);
447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test03
448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test04: TN. Synchronization via PCQ. {{{1
450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test04 {
451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownProducerConsumerQueue Q(INT_MAX);
453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Two write accesses to GLOB are separated by PCQ Put/Get.
454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Putter:                        Getter:
456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 1. write(GLOB)
457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 2. Q.Put() ---------\          .
458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                      \-------> a. Q.Get()
459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                                b. write(GLOB)
460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Putter() {
463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = 1;
464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Q.Put(NULL);
465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Getter() {
468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Q.Get();
469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = 2;
470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test04: negative\n");
474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Putter, Getter);
475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB=%d\n", GLOB);
478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST(Run, 4);
480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test04
481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test05: FP. Synchronization via CondVar, but waiter does not block. {{{1
484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Since CondVar::Wait() is not called, we get a false positive.
485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test05 {
486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Two write accesses to GLOB are synchronized via CondVar.
488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// But race detector can not see it.
489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// See this for details:
490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// http://www.valgrind.org/docs/manual/hg-manual.html#hg-manual.effective-use.
491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Waiter:                                  Waker:
493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 1. COND = 0
494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 2. Start(Waker)
495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 3. MU.Lock()                             a. write(GLOB)
496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                                          b. MU.Lock()
497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                                          c. COND = 1
498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                                          d. CV.Signal()
499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//  4. while(COND)                          e. MU.Unlock()
500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//       CV.Wait(MU) <<< not called
501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//  5. MU.Unlock()
502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//  6. write(GLOB)
503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex   MU;
504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Waker() {
506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = 1;
507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  COND = 1;
509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CV.Signal();
510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();
511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Waiter() {
514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ThreadPool pool(1);
515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  pool.StartWorkers();
516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  COND = 0;
517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  pool.Add(NewCallback(Waker));
518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(100000);  // Make sure the signaller gets first.
519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  while(COND != 1)
521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CV.Wait(&MU);
522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();
523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = 2;
524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  FAST_MODE_INIT(&GLOB);
527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if (!Tsan_PureHappensBefore())
528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test05. FP. Unavoidable in hybrid scheme.");
529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test05: unavoidable false positive\n");
530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Waiter();
531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB=%d\n", GLOB);
532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST(Run, 5);
534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test05
535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test06: TN. Synchronization via CondVar, but Waker gets there first.  {{{1
538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test06 {
539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Same as test05 but we annotated the Wait() loop.
541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Waiter:                                            Waker:
543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 1. COND = 0
544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 2. Start(Waker)
545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 3. MU.Lock()                                       a. write(GLOB)
546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                                                    b. MU.Lock()
547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                                                    c. COND = 1
548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                                           /------- d. CV.Signal()
549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//  4. while(COND)                          /         e. MU.Unlock()
550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//       CV.Wait(MU) <<< not called        /
551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//  6. ANNOTATE_CONDVAR_WAIT(CV, MU) <----/
552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//  5. MU.Unlock()
553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//  6. write(GLOB)
554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex   MU;
556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Waker() {
558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = 1;
559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  COND = 1;
561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CV.Signal();
562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();
563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Waiter() {
566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ThreadPool pool(1);
567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  pool.StartWorkers();
568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  COND = 0;
569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  pool.Add(NewCallback(Waker));
570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(100000);  // Make sure the signaller gets first.
571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  while(COND != 1)
573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CV.Wait(&MU);
574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_CONDVAR_LOCK_WAIT(&CV, &MU);
575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();
577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = 2;
578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test06: negative\n");
581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Waiter();
582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB=%d\n", GLOB);
583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 6, FEATURE|NEEDS_ANNOTATIONS);
585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test06
586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test07: TN. Synchronization via LockWhen(), Signaller is observed first. {{{1
589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test07 {
590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownbool    COND = 0;
592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Two write accesses to GLOB are synchronized via conditional critical section.
593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// LockWhen() is observed after COND has been set (due to sleep).
594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Unlock() calls ANNOTATE_CONDVAR_SIGNAL().
595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Waiter:                           Signaller:
597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 1. COND = 0
598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 2. Start(Signaller)
599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                                   a. write(GLOB)
600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                                   b. MU.Lock()
601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                                   c. COND = 1
602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                              /--- d. MU.Unlock calls ANNOTATE_CONDVAR_SIGNAL
603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 3. MU.LockWhen(COND==1) <---/
604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 4. MU.Unlock()
605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 5. write(GLOB)
606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex   MU;
608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Signaller() {
609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = 1;
610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  COND = true; // We are done! Tell the Waiter.
612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock(); // calls ANNOTATE_CONDVAR_SIGNAL;
613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Waiter() {
615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  COND = false;
616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThread t(Signaller);
617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(100000);  // Make sure the signaller gets there first.
619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.LockWhen(Condition(&ArgIsTrue, &COND));  // calls ANNOTATE_CONDVAR_WAIT
621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();  // Signaller is done!
622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = 2; // If LockWhen didn't catch the signal, a race may be reported here.
624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test07: negative\n");
628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Waiter();
629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB=%d\n", GLOB);
630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 7, FEATURE|NEEDS_ANNOTATIONS);
632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test07
633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test08: TN. Synchronization via thread start/join. {{{1
635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test08 {
636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Three accesses to GLOB are separated by thread start/join.
638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Parent:                        Worker:
640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 1. write(GLOB)
641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 2. Start(Worker) ------------>
642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                                a. write(GLOB)
643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 3. Join(Worker) <------------
644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 4. write(GLOB)
645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker() {
646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = 2;
647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Parent() {
650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThread t(Worker);
651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = 1;
652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = 3;
655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test08: negative\n");
658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Parent();
659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB=%d\n", GLOB);
660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST(Run, 8);
662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test08
663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test09: TP. Simple race (read vs write). {{{1
666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test09 {
667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// A simple data race between writer and reader.
669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Write happens after read (enforced by sleep).
670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Usually, easily detectable by a race detector.
671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Writer() {
672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(100000);
673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = 3;
674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Reader() {
676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(GLOB != -777);
677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_TRACE_MEMORY(&GLOB);
681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  FAST_MODE_INIT(&GLOB);
682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test09. TP.");
683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test09: positive\n");
684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Writer, Reader);
685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB=%d\n", GLOB);
688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST(Run, 9);
690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test09
691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test10: FN. Simple race (write vs read). {{{1
694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test10 {
695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// A simple data race between writer and reader.
697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Write happens before Read (enforced by sleep),
698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// otherwise this test is the same as test09.
699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Writer:                    Reader:
701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 1. write(GLOB)             a. sleep(long enough so that GLOB
702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                                is most likely initialized by Writer)
703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                            b. read(GLOB)
704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Eraser algorithm does not detect the race here,
707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// see Section 2.2 of http://citeseer.ist.psu.edu/savage97eraser.html.
708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Writer() {
710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = 3;
711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Reader() {
713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(100000);
714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(GLOB != -777);
715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  FAST_MODE_INIT(&GLOB);
719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test10. TP. FN in MSMHelgrind.");
720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test10: positive\n");
721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Writer, Reader);
722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB=%d\n", GLOB);
725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST(Run, 10);
727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test10
728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test11: FP. Synchronization via CondVar, 2 workers. {{{1
731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// This test is properly synchronized, but currently (Dec 2007)
732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// helgrind reports a false positive.
733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Parent:                              Worker1, Worker2:
735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 1. Start(workers)                    a. read(GLOB)
736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 2. MU.Lock()                         b. MU.Lock()
737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 3. while(COND != 2)        /-------- c. CV.Signal()
738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//      CV.Wait(&MU) <-------/          d. MU.Unlock()
739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 4. MU.Unlock()
740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 5. write(GLOB)
741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test11 {
743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex   MU;
745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker() {
746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(200000);
747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(GLOB != 777);
748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  COND++;
751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CV.Signal();
752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();
753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Parent() {
756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  COND = 0;
757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Worker, Worker);
759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  while(COND != 2) {
763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CV.Wait(&MU);
764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();
766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = 2;
768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//  ANNOTATE_EXPECT_RACE(&GLOB, "test11. FP. Fixed by MSMProp1.");
774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test11: negative\n");
775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Parent();
776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB=%d\n", GLOB);
777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST(Run, 11);
779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test11
780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test12: FP. Synchronization via Mutex, then via PCQ. {{{1
783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test12 {
784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// This test is properly synchronized, but currently (Dec 2007)
786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// helgrind reports a false positive.
787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// First, we write to GLOB under MU, then we synchronize via PCQ,
789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// which is essentially a semaphore.
790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Putter:                       Getter:
792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 1. MU.Lock()                  a. MU.Lock()
793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 2. write(GLOB) <---- MU ----> b. write(GLOB)
794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 3. MU.Unlock()                c. MU.Unlock()
795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 4. Q.Put()   ---------------> d. Q.Get()
796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                               e. write(GLOB)
797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownProducerConsumerQueue Q(INT_MAX);
799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex   MU;
800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Putter() {
802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB++;
804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();
805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Q.Put(NULL);
807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Getter() {
810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB++;
812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();
813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Q.Get();
815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB++;
816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//  ANNOTATE_EXPECT_RACE(&GLOB, "test12. FP. Fixed by MSMProp1.");
820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test12: negative\n");
821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Putter, Getter);
822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB=%d\n", GLOB);
825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST(Run, 12);
827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test12
828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test13: FP. Synchronization via Mutex, then via LockWhen. {{{1
831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test13 {
832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// This test is essentially the same as test12, but uses LockWhen
834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// instead of PCQ.
835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Waker:                                     Waiter:
837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 1. MU.Lock()                               a. MU.Lock()
838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 2. write(GLOB) <---------- MU ---------->  b. write(GLOB)
839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 3. MU.Unlock()                             c. MU.Unlock()
840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 4. MU.Lock()                               .
841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 5. COND = 1                                .
842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 6. ANNOTATE_CONDVAR_SIGNAL -------\        .
843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 7. MU.Unlock()                     \       .
844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                                     \----> d. MU.LockWhen(COND == 1)
845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                                            e. MU.Unlock()
846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                                            f. write(GLOB)
847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex   MU;
848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Waker() {
850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB++;
852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();
853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  COND = 1;
856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_CONDVAR_SIGNAL(&MU);
857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();
858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Waiter() {
861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB++;
863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();
864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.LockWhen(Condition(&ArgIsOne, &COND));
866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();
867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB++;
868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//  ANNOTATE_EXPECT_RACE(&GLOB, "test13. FP. Fixed by MSMProp1.");
872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test13: negative\n");
873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  COND = 0;
874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Waker, Waiter);
876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB=%d\n", GLOB);
880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 13, FEATURE|NEEDS_ANNOTATIONS);
882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test13
883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test14: FP. Synchronization via PCQ, reads, 2 workers. {{{1
886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test14 {
887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// This test is properly synchronized, but currently (Dec 2007)
889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// helgrind reports a false positive.
890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// This test is similar to test11, but uses PCQ (semaphore).
892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Putter2:                  Putter1:                     Getter:
894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 1. read(GLOB)             a. read(GLOB)
895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 2. Q2.Put() ----\         b. Q1.Put() -----\           .
896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                  \                          \--------> A. Q1.Get()
897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                   \----------------------------------> B. Q2.Get()
898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                                                        C. write(GLOB)
899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownProducerConsumerQueue Q1(INT_MAX), Q2(INT_MAX);
900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Putter1() {
902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(GLOB != 777);
903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Q1.Put(NULL);
904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Putter2() {
906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(GLOB != 777);
907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Q2.Put(NULL);
908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Getter() {
910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Q1.Get();
911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Q2.Get();
912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB++;
913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//  ANNOTATE_EXPECT_RACE(&GLOB, "test14. FP. Fixed by MSMProp1.");
916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test14: negative\n");
917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Getter, Putter1, Putter2);
918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB=%d\n", GLOB);
921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST(Run, 14);
923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test14
924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test15: TN. Synchronization via LockWhen. One waker and 2 waiters. {{{1
927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test15 {
928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Waker:                                   Waiter1, Waiter2:
929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 1. write(GLOB)
930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 2. MU.Lock()
931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 3. COND = 1
932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 4. ANNOTATE_CONDVAR_SIGNAL ------------> a. MU.LockWhen(COND == 1)
933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 5. MU.Unlock()                           b. MU.Unlock()
934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                                          c. read(GLOB)
935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex   MU;
938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Waker() {
940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = 2;
941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  COND = 1;
944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_CONDVAR_SIGNAL(&MU);
945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();
946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown};
947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Waiter() {
949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.LockWhen(Condition(&ArgIsOne, &COND));
950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();
951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(GLOB != 777);
952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  COND = 0;
957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test15: negative\n");
958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Waker, Waiter, Waiter);
959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB=%d\n", GLOB);
962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST(Run, 15);
964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test15
965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test16: FP. Barrier (emulated by CV), 2 threads. {{{1
968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test16 {
969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Worker1:                                     Worker2:
970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 1. MU.Lock()                                 a. MU.Lock()
971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 2. write(GLOB) <------------ MU ---------->  b. write(GLOB)
972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 3. MU.Unlock()                               c. MU.Unlock()
973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 4. MU2.Lock()                                d. MU2.Lock()
974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 5. COND--                                    e. COND--
975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 6. ANNOTATE_CONDVAR_SIGNAL(MU2) ---->V       .
976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 7. MU2.Await(COND == 0) <------------+------ f. ANNOTATE_CONDVAR_SIGNAL(MU2)
977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 8. MU2.Unlock()                      V-----> g. MU2.Await(COND == 0)
978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 9. read(GLOB)                                h. MU2.Unlock()
979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                                              i. read(GLOB)
980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// TODO: This way we may create too many edges in happens-before graph.
983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Arndt Mühlenfeld in his PhD (TODO: link) suggests creating special nodes in
984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// happens-before graph to reduce the total number of edges.
985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// See figure 3.14.
986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex   MU;
990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex MU2;
991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker() {
993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB++;
995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();
996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU2.Lock();
998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  COND--;
999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_CONDVAR_SIGNAL(&MU2);
1000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU2.Await(Condition(&ArgIsZero, &COND));
1001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU2.Unlock();
1002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(GLOB == 2);
1004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
1007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//  ANNOTATE_EXPECT_RACE(&GLOB, "test16. FP. Fixed by MSMProp1 + Barrier support.");
1008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  COND = 2;
1009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test16: negative\n");
1010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Worker, Worker);
1011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
1012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
1013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB=%d\n", GLOB);
1014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 16, FEATURE|NEEDS_ANNOTATIONS);
1016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test16
1017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test17: FP. Barrier (emulated by CV), 3 threads. {{{1
1020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test17 {
1021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Same as test16, but with 3 threads.
1022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
1023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex   MU;
1024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex MU2;
1025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker() {
1027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
1028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB++;
1029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();
1030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU2.Lock();
1032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  COND--;
1033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_CONDVAR_SIGNAL(&MU2);
1034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU2.Await(Condition(&ArgIsZero, &COND));
1035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU2.Unlock();
1036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(GLOB == 3);
1038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
1041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//  ANNOTATE_EXPECT_RACE(&GLOB, "test17. FP. Fixed by MSMProp1 + Barrier support.");
1042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  COND = 3;
1043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test17: negative\n");
1044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Worker, Worker, Worker);
1045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
1046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
1047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB=%d\n", GLOB);
1048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 17, FEATURE|NEEDS_ANNOTATIONS);
1050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test17
1051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test18: TN. Synchronization via Await(), signaller gets there first. {{{1
1054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test18 {
1055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
1056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex   MU;
1057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Same as test03, but uses Mutex::Await() instead of Mutex::LockWhen().
1058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Waker() {
1060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(100000);  // Make sure the waiter blocks.
1061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = 1;
1062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
1064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  COND = 1; // We are done! Tell the Waiter.
1065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock(); // calls ANNOTATE_CONDVAR_SIGNAL;
1066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Waiter() {
1068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ThreadPool pool(1);
1069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  pool.StartWorkers();
1070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  COND = 0;
1071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  pool.Add(NewCallback(Waker));
1072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
1074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Await(Condition(&ArgIsOne, &COND));  // calls ANNOTATE_CONDVAR_WAIT
1075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();  // Waker is done!
1076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = 2;
1078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
1080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test18: negative\n");
1081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Waiter();
1082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB=%d\n", GLOB);
1083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 18, FEATURE|NEEDS_ANNOTATIONS);
1085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test18
1086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test19: TN. Synchronization via AwaitWithTimeout(). {{{1
1088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test19 {
1089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
1090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Same as test18, but with AwaitWithTimeout. Do not timeout.
1091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex   MU;
1092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Waker() {
1093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(100000);  // Make sure the waiter blocks.
1094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = 1;
1095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
1097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  COND = 1; // We are done! Tell the Waiter.
1098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock(); // calls ANNOTATE_CONDVAR_SIGNAL;
1099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Waiter() {
1101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ThreadPool pool(1);
1102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  pool.StartWorkers();
1103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  COND = 0;
1104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  pool.Add(NewCallback(Waker));
1105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
1107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(MU.AwaitWithTimeout(Condition(&ArgIsOne, &COND), INT_MAX));
1108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();
1109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = 2;
1111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
1113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test19: negative\n");
1114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Waiter();
1115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB=%d\n", GLOB);
1116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 19, FEATURE|NEEDS_ANNOTATIONS);
1118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test19
1119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test20: TP. Incorrect synchronization via AwaitWhen(), timeout. {{{1
1121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test20 {
1122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
1123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex   MU;
1124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// True race. We timeout in AwaitWhen.
1125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Waker() {
1126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = 1;
1127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(100 * 1000);
1128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Waiter() {
1130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ThreadPool pool(1);
1131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  pool.StartWorkers();
1132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  COND = 0;
1133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  pool.Add(NewCallback(Waker));
1134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
1136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(!MU.AwaitWithTimeout(Condition(&ArgIsOne, &COND), 100));
1137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();
1138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = 2;
1140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
1142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  FAST_MODE_INIT(&GLOB);
1143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test20. TP.");
1144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test20: positive\n");
1145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Waiter();
1146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB=%d\n", GLOB);
1147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 20, FEATURE|NEEDS_ANNOTATIONS);
1149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test20
1150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test21: TP. Incorrect synchronization via LockWhenWithTimeout(). {{{1
1152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test21 {
1153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
1154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// True race. We timeout in LockWhenWithTimeout().
1155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex   MU;
1156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Waker() {
1157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = 1;
1158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(100 * 1000);
1159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Waiter() {
1161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ThreadPool pool(1);
1162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  pool.StartWorkers();
1163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  COND = 0;
1164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  pool.Add(NewCallback(Waker));
1165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(!MU.LockWhenWithTimeout(Condition(&ArgIsOne, &COND), 100));
1167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();
1168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = 2;
1170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
1172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  FAST_MODE_INIT(&GLOB);
1173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test21. TP.");
1174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test21: positive\n");
1175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Waiter();
1176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB=%d\n", GLOB);
1177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 21, FEATURE|NEEDS_ANNOTATIONS);
1179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test21
1180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test22: TP. Incorrect synchronization via CondVar::WaitWithTimeout(). {{{1
1182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test22 {
1183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
1184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex   MU;
1185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// True race. We timeout in CondVar::WaitWithTimeout().
1186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Waker() {
1187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = 1;
1188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(100 * 1000);
1189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Waiter() {
1191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ThreadPool pool(1);
1192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  pool.StartWorkers();
1193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  COND = 0;
1194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  pool.Add(NewCallback(Waker));
1195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  int64_t ms_left_to_wait = 100;
1197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  int64_t deadline_ms = GetCurrentTimeMillis() + ms_left_to_wait;
1198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
1199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  while(COND != 1 && ms_left_to_wait > 0) {
1200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CV.WaitWithTimeout(&MU, ms_left_to_wait);
1201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ms_left_to_wait = deadline_ms - GetCurrentTimeMillis();
1202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
1203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();
1204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = 2;
1206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
1208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  FAST_MODE_INIT(&GLOB);
1209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test22. TP.");
1210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test22: positive\n");
1211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Waiter();
1212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB=%d\n", GLOB);
1213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST(Run, 22);
1215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test22
1216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test23: TN. TryLock, ReaderLock, ReaderTryLock. {{{1
1218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test23 {
1219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Correct synchronization with TryLock, Lock, ReaderTryLock, ReaderLock.
1220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
1221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex   MU;
1222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker_TryLock() {
1223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  for (int i = 0; i < 20; i++) {
1224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    while (true) {
1225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (MU.TryLock()) {
1226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        GLOB++;
1227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        MU.Unlock();
1228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
1229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      usleep(1000);
1231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
1232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
1233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker_ReaderTryLock() {
1236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  for (int i = 0; i < 20; i++) {
1237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    while (true) {
1238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (MU.ReaderTryLock()) {
1239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        CHECK(GLOB != 777);
1240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        MU.ReaderUnlock();
1241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
1242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      usleep(1000);
1244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
1245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
1246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker_ReaderLock() {
1249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  for (int i = 0; i < 20; i++) {
1250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    MU.ReaderLock();
1251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CHECK(GLOB != 777);
1252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    MU.ReaderUnlock();
1253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    usleep(1000);
1254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
1255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker_Lock() {
1258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  for (int i = 0; i < 20; i++) {
1259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    MU.Lock();
1260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    GLOB++;
1261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    MU.Unlock();
1262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    usleep(1000);
1263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
1264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
1267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test23: negative\n");
1268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Worker_TryLock,
1269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  Worker_ReaderTryLock,
1270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  Worker_ReaderLock,
1271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  Worker_Lock
1272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  );
1273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
1274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
1275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB=%d\n", GLOB);
1276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST(Run, 23);
1278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test23
1279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test24: TN. Synchronization via ReaderLockWhen(). {{{1
1281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test24 {
1282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
1283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex   MU;
1284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Same as test03, but uses ReaderLockWhen().
1285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Waker() {
1287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(100000);  // Make sure the waiter blocks.
1288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = 1;
1289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
1291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  COND = 1; // We are done! Tell the Waiter.
1292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock(); // calls ANNOTATE_CONDVAR_SIGNAL;
1293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Waiter() {
1295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ThreadPool pool(1);
1296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  pool.StartWorkers();
1297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  COND = 0;
1298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  pool.Add(NewCallback(Waker));
1299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.ReaderLockWhen(Condition(&ArgIsOne, &COND));
1300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.ReaderUnlock();
1301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = 2;
1303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
1305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test24: negative\n");
1306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Waiter();
1307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB=%d\n", GLOB);
1308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 24, FEATURE|NEEDS_ANNOTATIONS);
1310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test24
1311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test25: TN. Synchronization via ReaderLockWhenWithTimeout(). {{{1
1313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test25 {
1314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
1315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex   MU;
1316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Same as test24, but uses ReaderLockWhenWithTimeout().
1317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// We do not timeout.
1318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Waker() {
1320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(100000);  // Make sure the waiter blocks.
1321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = 1;
1322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
1324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  COND = 1; // We are done! Tell the Waiter.
1325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock(); // calls ANNOTATE_CONDVAR_SIGNAL;
1326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Waiter() {
1328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ThreadPool pool(1);
1329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  pool.StartWorkers();
1330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  COND = 0;
1331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  pool.Add(NewCallback(Waker));
1332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(MU.ReaderLockWhenWithTimeout(Condition(&ArgIsOne, &COND), INT_MAX));
1333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.ReaderUnlock();
1334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = 2;
1336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
1338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test25: negative\n");
1339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Waiter();
1340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB=%d\n", GLOB);
1341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 25, FEATURE|NEEDS_ANNOTATIONS);
1343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test25
1344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test26: TP. Incorrect synchronization via ReaderLockWhenWithTimeout(). {{{1
1346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test26 {
1347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
1348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex   MU;
1349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Same as test25, but we timeout and incorrectly assume happens-before.
1350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Waker() {
1352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = 1;
1353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(10000);
1354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Waiter() {
1356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ThreadPool pool(1);
1357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  pool.StartWorkers();
1358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  COND = 0;
1359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  pool.Add(NewCallback(Waker));
1360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(!MU.ReaderLockWhenWithTimeout(Condition(&ArgIsOne, &COND), 100));
1361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.ReaderUnlock();
1362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = 2;
1364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
1366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  FAST_MODE_INIT(&GLOB);
1367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test26. TP");
1368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test26: positive\n");
1369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Waiter();
1370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB=%d\n", GLOB);
1371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 26, FEATURE|NEEDS_ANNOTATIONS);
1373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test26
1374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test27: TN. Simple synchronization via SpinLock. {{{1
1377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test27 {
1378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifndef NO_SPINLOCK
1379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
1380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownSpinLock MU;
1381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker() {
1382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
1383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB++;
1384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();
1385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(10000);
1386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
1389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test27: negative\n");
1390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Worker, Worker, Worker, Worker);
1391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
1392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
1393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB=%d\n", GLOB);
1394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 27, FEATURE|NEEDS_ANNOTATIONS);
1396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif // NO_SPINLOCK
1397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test27
1398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test28: TN. Synchronization via Mutex, then PCQ. 3 threads {{{1
1401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test28 {
1402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Putter1:                       Getter:                         Putter2:
1403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 1. MU.Lock()                                                   A. MU.Lock()
1404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 2. write(GLOB)                                                 B. write(GLOB)
1405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 3. MU.Unlock()                                                 C. MU.Unlock()
1406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 4. Q.Put() ---------\                                 /------- D. Q.Put()
1407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 5. MU.Lock()         \-------> a. Q.Get()            /         E. MU.Lock()
1408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 6. read(GLOB)                  b. Q.Get() <---------/          F. read(GLOB)
1409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 7. MU.Unlock()                   (sleep)                       G. MU.Unlock()
1410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                                c. read(GLOB)
1411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownProducerConsumerQueue Q(INT_MAX);
1412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
1413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex   MU;
1414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Putter() {
1416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
1417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB++;
1418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();
1419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Q.Put(NULL);
1421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
1423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(GLOB != 777);
1424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();
1425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Getter() {
1428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Q.Get();
1429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Q.Get();
1430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(100000);
1431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(GLOB == 2);
1432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
1435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test28: negative\n");
1436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Getter, Putter, Putter);
1437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
1438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
1439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB=%d\n", GLOB);
1440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST(Run, 28);
1442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test28
1443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test29: TN. Synchronization via Mutex, then PCQ. 4 threads. {{{1
1446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test29 {
1447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Similar to test28, but has two Getters and two PCQs.
1448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownProducerConsumerQueue *Q1, *Q2;
1449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex   MU;
1450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
1451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Putter(ProducerConsumerQueue *q) {
1453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
1454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB++;
1455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();
1456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  q->Put(NULL);
1458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  q->Put(NULL);
1459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
1461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(GLOB != 777);
1462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();
1463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Putter1() { Putter(Q1); }
1467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Putter2() { Putter(Q2); }
1468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Getter() {
1470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Q1->Get();
1471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Q2->Get();
1472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(100000);
1473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(GLOB == 2);
1474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(48000); //  TODO: remove this when FP in test32 is fixed.
1475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
1478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test29: negative\n");
1479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Q1 = new ProducerConsumerQueue(INT_MAX);
1480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Q2 = new ProducerConsumerQueue(INT_MAX);
1481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Getter, Getter, Putter1, Putter2);
1482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
1483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
1484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB=%d\n", GLOB);
1485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  delete Q1;
1486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  delete Q2;
1487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST(Run, 29);
1489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test29
1490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test30: TN. Synchronization via 'safe' race. Writer vs multiple Readers. {{{1
1493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test30 {
1494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// This test shows a very risky kind of synchronization which is very easy
1495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// to get wrong. Actually, I am not sure I've got it right.
1496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
1497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Writer:                                 Reader1, Reader2, ..., ReaderN:
1498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 1. write(GLOB[i]: i >= BOUNDARY)        a. n = BOUNDARY
1499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 2. HAPPENS_BEFORE(BOUNDARY+1)  -------> b. HAPPENS_AFTER(n)
1500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 3. BOUNDARY++;                          c. read(GLOB[i]: i < n)
1501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
1502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Here we have a 'safe' race on accesses to BOUNDARY and
1503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// no actual races on accesses to GLOB[]:
1504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Writer writes to GLOB[i] where i>=BOUNDARY and then increments BOUNDARY.
1505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Readers read BOUNDARY and read GLOB[i] where i<BOUNDARY.
1506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
1507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// I am not completely sure that this scheme guaranties no race between
1508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// accesses to GLOB since compilers and CPUs
1509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// are free to rearrange memory operations.
1510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// I am actually sure that this scheme is wrong unless we use
1511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// some smart memory fencing...
1512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownconst int N = 48;
1515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int GLOB[N];
1516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvolatile int BOUNDARY = 0;
1517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Writer() {
1519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  for (int i = 0; i < N; i++) {
1520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CHECK(BOUNDARY == i);
1521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for (int j = i; j < N; j++) {
1522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      GLOB[j] = j;
1523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
1524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ANNOTATE_HAPPENS_BEFORE(reinterpret_cast<void*>(BOUNDARY+1));
1525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    BOUNDARY++;
1526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    usleep(1000);
1527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
1528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Reader() {
1531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  int n;
1532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  do {
1533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    n = BOUNDARY;
1534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (n == 0) continue;
1535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ANNOTATE_HAPPENS_AFTER(reinterpret_cast<void*>(n));
1536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for (int i = 0; i < n; i++) {
1537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      CHECK(GLOB[i] == i);
1538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
1539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    usleep(100);
1540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  } while(n < N);
1541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
1544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  FAST_MODE_INIT(&BOUNDARY);
1545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_EXPECT_RACE((void*)(&BOUNDARY), "test30. Sync via 'safe' race.");
1546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test30: negative\n");
1547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Writer, Reader, Reader, Reader);
1548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
1549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
1550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB=%d\n", GLOB[N-1]);
1551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 30, FEATURE|NEEDS_ANNOTATIONS);
1553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test30
1554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test31: TN. Synchronization via 'safe' race. Writer vs Writer. {{{1
1557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test31 {
1558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// This test is similar to test30, but
1559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// it has one Writer instead of mulitple Readers.
1560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
1561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Writer1:                                Writer2
1562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 1. write(GLOB[i]: i >= BOUNDARY)        a. n = BOUNDARY
1563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 2. HAPPENS_BEFORE(BOUNDARY+1)  -------> b. HAPPENS_AFTER(n)
1564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 3. BOUNDARY++;                          c. write(GLOB[i]: i < n)
1565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
1566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownconst int N = 48;
1568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int GLOB[N];
1569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvolatile int BOUNDARY = 0;
1570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Writer1() {
1572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  for (int i = 0; i < N; i++) {
1573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CHECK(BOUNDARY == i);
1574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for (int j = i; j < N; j++) {
1575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      GLOB[j] = j;
1576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
1577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ANNOTATE_HAPPENS_BEFORE(reinterpret_cast<void*>(BOUNDARY+1));
1578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    BOUNDARY++;
1579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    usleep(1000);
1580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
1581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Writer2() {
1584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  int n;
1585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  do {
1586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    n = BOUNDARY;
1587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (n == 0) continue;
1588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ANNOTATE_HAPPENS_AFTER(reinterpret_cast<void*>(n));
1589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for (int i = 0; i < n; i++) {
1590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if(GLOB[i] == i) {
1591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        GLOB[i]++;
1592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
1593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
1594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    usleep(100);
1595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  } while(n < N);
1596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
1599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  FAST_MODE_INIT(&BOUNDARY);
1600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_EXPECT_RACE((void*)(&BOUNDARY), "test31. Sync via 'safe' race.");
1601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test31: negative\n");
1602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Writer1, Writer2);
1603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
1604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
1605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB=%d\n", GLOB[N-1]);
1606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 31, FEATURE|NEEDS_ANNOTATIONS);
1608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test31
1609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test32: FP. Synchronization via thread create/join. W/R. {{{1
1612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test32 {
1613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// This test is well synchronized but helgrind 3.3.0 reports a race.
1614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
1615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Parent:                   Writer:               Reader:
1616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 1. Start(Reader) -----------------------\       .
1617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                                          \      .
1618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 2. Start(Writer) ---\                     \     .
1619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                      \---> a. MU.Lock()    \--> A. sleep(long enough)
1620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                            b. write(GLOB)
1621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                      /---- c. MU.Unlock()
1622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 3. Join(Writer) <---/
1623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                                                 B. MU.Lock()
1624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                                                 C. read(GLOB)
1625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                                   /------------ D. MU.Unlock()
1626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 4. Join(Reader) <----------------/
1627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 5. write(GLOB)
1628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
1629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
1630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// The call to sleep() in Reader is not part of synchronization,
1631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// it is required to trigger the false positive in helgrind 3.3.0.
1632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
1633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
1634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex   MU;
1635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Writer() {
1637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
1638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = 1;
1639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();
1640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Reader() {
1643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(480000);
1644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
1645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(GLOB != 777);
1646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();
1647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Parent() {
1650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThread r(Reader);
1651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThread w(Writer);
1652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  r.Start();
1653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  w.Start();
1654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  w.Join();  // 'w' joins first.
1656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  r.Join();
1657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = 2;
1659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
1662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//  ANNOTATE_EXPECT_RACE(&GLOB, "test32. FP. Fixed by MSMProp1.");
1663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test32: negative\n");
1664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Parent();
1665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB=%d\n", GLOB);
1666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST(Run, 32);
1669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test32
1670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test33: STAB. Stress test for the number of thread sets (TSETs). {{{1
1673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test33 {
1674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
1675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Here we access N memory locations from within log(N) threads.
1676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// We do it in such a way that helgrind creates nearly all possible TSETs.
1677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Then we join all threads and start again (N_iter times).
1678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownconst int N_iter = 48;
1679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownconst int Nlog  = 15;
1680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownconst int N     = 1 << Nlog;
1681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int ARR[N];
1682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex   MU;
1683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker() {
1685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
1686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  int n = ++GLOB;
1687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();
1688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  n %= Nlog;
1690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  for (int i = 0; i < N; i++) {
1691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    // ARR[i] is accessed by threads from i-th subset
1692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (i & (1 << n)) {
1693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        CHECK(ARR[i] == 0);
1694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
1695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
1696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
1699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test33:\n");
1700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  std::vector<MyThread*> vec(Nlog);
1702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  for (int j = 0; j < N_iter; j++) {
1704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    // Create and start Nlog threads
1705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for (int i = 0; i < Nlog; i++) {
1706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vec[i] = new MyThread(Worker);
1707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
1708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for (int i = 0; i < Nlog; i++) {
1709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vec[i]->Start();
1710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
1711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    // Join all threads.
1712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for (int i = 0; i < Nlog; i++) {
1713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vec[i]->Join();
1714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      delete vec[i];
1715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
1716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    printf("------------------\n");
1717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
1718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB=%d; ARR[1]=%d; ARR[7]=%d; ARR[N-1]=%d\n",
1720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         GLOB, ARR[1], ARR[7], ARR[N-1]);
1721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 33, STABILITY|EXCLUDE_FROM_ALL);
1723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test33
1724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test34: STAB. Stress test for the number of locks sets (LSETs). {{{1
1727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test34 {
1728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Similar to test33, but for lock sets.
1729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
1730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownconst int N_iter = 48;
1731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownconst int Nlog = 10;
1732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownconst int N    = 1 << Nlog;
1733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int ARR[N];
1734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Mutex *MUs[Nlog];
1735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker() {
1737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for (int i = 0; i < N; i++) {
1738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // ARR[i] is protected by MUs from i-th subset of all MUs
1739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (int j = 0; j < Nlog; j++)  if (i & (1 << j)) MUs[j]->Lock();
1740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      CHECK(ARR[i] == 0);
1741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (int j = 0; j < Nlog; j++)  if (i & (1 << j)) MUs[j]->Unlock();
1742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
1743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
1746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test34:\n");
1747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  for (int iter = 0; iter < N_iter; iter++) {
1748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for (int i = 0; i < Nlog; i++) {
1749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      MUs[i] = new Mutex;
1750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
1751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    MyThreadArray t(Worker, Worker);
1752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    t.Start();
1753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    t.Join();
1754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for (int i = 0; i < Nlog; i++) {
1755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      delete MUs[i];
1756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
1757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    printf("------------------\n");
1758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
1759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB=%d\n", GLOB);
1760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 34, STABILITY|EXCLUDE_FROM_ALL);
1762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test34
1763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test35: PERF. Lots of mutexes and lots of call to free().  {{{1
1766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test35 {
1767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Helgrind 3.3.0 has very slow in shadow_mem_make_NoAccess(). Fixed locally.
1768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// With the fix helgrind runs this test about a minute.
1769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Without the fix -- about 5 minutes. (on c2d 2.4GHz).
1770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
1771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// TODO: need to figure out the best way for performance testing.
1772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint **ARR;
1773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownconst int N_mu   = 25000;
1774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownconst int N_free = 48000;
1775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker() {
1777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  for (int i = 0; i < N_free; i++)
1778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CHECK(777 == *ARR[i]);
1779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
1782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test35:\n");
1783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  std::vector<Mutex*> mus;
1784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ARR = new int *[N_free];
1786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  for (int i = 0; i < N_free; i++) {
1787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    const int c = N_free / N_mu;
1788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if ((i % c) == 0) {
1789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      mus.push_back(new Mutex);
1790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      mus.back()->Lock();
1791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      mus.back()->Unlock();
1792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
1793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ARR[i] = new int(777);
1794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
1795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  // Need to put all ARR[i] into shared state in order
1797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  // to trigger the performance bug.
1798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Worker, Worker);
1799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
1800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
1801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  for (int i = 0; i < N_free; i++) delete ARR[i];
1803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  delete [] ARR;
1804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  for (size_t i = 0; i < mus.size(); i++) {
1806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    delete mus[i];
1807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
1808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 35, PERFORMANCE|EXCLUDE_FROM_ALL);
1810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test35
1811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test36: TN. Synchronization via Mutex, then PCQ. 3 threads. W/W {{{1
1814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test36 {
1815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// variation of test28 (W/W instead of W/R)
1816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Putter1:                       Getter:                         Putter2:
1818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 1. MU.Lock();                                                  A. MU.Lock()
1819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 2. write(GLOB)                                                 B. write(GLOB)
1820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 3. MU.Unlock()                                                 C. MU.Unlock()
1821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 4. Q.Put() ---------\                                 /------- D. Q.Put()
1822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 5. MU1.Lock()        \-------> a. Q.Get()            /         E. MU1.Lock()
1823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 6. MU.Lock()                   b. Q.Get() <---------/          F. MU.Lock()
1824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 7. write(GLOB)                                                 G. write(GLOB)
1825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 8. MU.Unlock()                                                 H. MU.Unlock()
1826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 9. MU1.Unlock()                  (sleep)                       I. MU1.Unlock()
1827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                                c. MU1.Lock()
1828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                                d. write(GLOB)
1829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                                e. MU1.Unlock()
1830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownProducerConsumerQueue Q(INT_MAX);
1831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
1832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex   MU, MU1;
1833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Putter() {
1835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
1836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB++;
1837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();
1838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Q.Put(NULL);
1840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU1.Lock();
1842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
1843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB++;
1844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();
1845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU1.Unlock();
1846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Getter() {
1849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Q.Get();
1850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Q.Get();
1851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(100000);
1852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU1.Lock();
1853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB++;
1854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU1.Unlock();
1855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
1858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test36: negative \n");
1859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Getter, Putter, Putter);
1860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
1861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
1862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB=%d\n", GLOB);
1863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST(Run, 36);
1865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test36
1866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test37: TN. Simple synchronization (write vs read). {{{1
1869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test37 {
1870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
1871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex   MU;
1872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Similar to test10, but properly locked.
1873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Writer:             Reader:
1874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 1. MU.Lock()
1875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 2. write
1876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 3. MU.Unlock()
1877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                    a. MU.Lock()
1878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                    b. read
1879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                    c. MU.Unlock();
1880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Writer() {
1882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
1883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = 3;
1884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();
1885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Reader() {
1887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(100000);
1888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
1889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(GLOB != -777);
1890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();
1891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
1894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test37: negative\n");
1895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Writer, Reader);
1896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
1897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
1898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB=%d\n", GLOB);
1899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST(Run, 37);
1901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test37
1902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test38: TN. Synchronization via Mutexes and PCQ. 4 threads. W/W {{{1
1905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test38 {
1906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Fusion of test29 and test36.
1907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Putter1:            Putter2:           Getter1:       Getter2:
1909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//    MU1.Lock()          MU1.Lock()
1910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//    write(GLOB)         write(GLOB)
1911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//    MU1.Unlock()        MU1.Unlock()
1912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//    Q1.Put()            Q2.Put()
1913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//    Q1.Put()            Q2.Put()
1914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//    MU1.Lock()          MU1.Lock()
1915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//    MU2.Lock()          MU2.Lock()
1916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//    write(GLOB)         write(GLOB)
1917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//    MU2.Unlock()        MU2.Unlock()
1918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//    MU1.Unlock()        MU1.Unlock()     sleep          sleep
1919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                                         Q1.Get()       Q1.Get()
1920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                                         Q2.Get()       Q2.Get()
1921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                                         MU2.Lock()     MU2.Lock()
1922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                                         write(GLOB)    write(GLOB)
1923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                                         MU2.Unlock()   MU2.Unlock()
1924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
1925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownProducerConsumerQueue *Q1, *Q2;
1928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
1929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex   MU, MU1, MU2;
1930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Putter(ProducerConsumerQueue *q) {
1932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU1.Lock();
1933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB++;
1934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU1.Unlock();
1935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  q->Put(NULL);
1937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  q->Put(NULL);
1938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU1.Lock();
1940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU2.Lock();
1941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB++;
1942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU2.Unlock();
1943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU1.Unlock();
1944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Putter1() { Putter(Q1); }
1948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Putter2() { Putter(Q2); }
1949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Getter() {
1951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(100000);
1952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Q1->Get();
1953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Q2->Get();
1954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU2.Lock();
1956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB++;
1957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU2.Unlock();
1958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(48000); //  TODO: remove this when FP in test32 is fixed.
1960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
1963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test38: negative\n");
1964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Q1 = new ProducerConsumerQueue(INT_MAX);
1965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Q2 = new ProducerConsumerQueue(INT_MAX);
1966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Getter, Getter, Putter1, Putter2);
1967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
1968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
1969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB=%d\n", GLOB);
1970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  delete Q1;
1971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  delete Q2;
1972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST(Run, 38);
1974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test38
1975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test39: FP. Barrier. {{{1
1977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test39 {
1978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifndef NO_BARRIER
1979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Same as test17 but uses Barrier class (pthread_barrier_t).
1980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
1981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownconst int N_threads = 3;
1982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBarrier barrier(N_threads);
1983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex   MU;
1984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker() {
1986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
1987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB++;
1988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();
1989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  barrier.Block();
1990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(GLOB == N_threads);
1991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
1993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_TRACE_MEMORY(&GLOB);
1994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//  ANNOTATE_EXPECT_RACE(&GLOB, "test39. FP. Fixed by MSMProp1. Barrier.");
1995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test39: negative\n");
1996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  {
1997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ThreadPool pool(N_threads);
1998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    pool.StartWorkers();
1999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for (int i = 0; i < N_threads; i++) {
2000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      pool.Add(NewCallback(Worker));
2001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
2002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  } // all folks are joined here.
2003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB=%d\n", GLOB);
2004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST(Run, 39);
2006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif // NO_BARRIER
2007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test39
2008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test40: FP. Synchronization via Mutexes and PCQ. 4 threads. W/W {{{1
2011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test40 {
2012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Similar to test38 but with different order of events (due to sleep).
2013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Putter1:            Putter2:           Getter1:       Getter2:
2015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//    MU1.Lock()          MU1.Lock()
2016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//    write(GLOB)         write(GLOB)
2017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//    MU1.Unlock()        MU1.Unlock()
2018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//    Q1.Put()            Q2.Put()
2019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//    Q1.Put()            Q2.Put()
2020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                                        Q1.Get()       Q1.Get()
2021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                                        Q2.Get()       Q2.Get()
2022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                                        MU2.Lock()     MU2.Lock()
2023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                                        write(GLOB)    write(GLOB)
2024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                                        MU2.Unlock()   MU2.Unlock()
2025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
2026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//    MU1.Lock()          MU1.Lock()
2027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//    MU2.Lock()          MU2.Lock()
2028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//    write(GLOB)         write(GLOB)
2029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//    MU2.Unlock()        MU2.Unlock()
2030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//    MU1.Unlock()        MU1.Unlock()
2031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownProducerConsumerQueue *Q1, *Q2;
2034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
2035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex   MU, MU1, MU2;
2036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Putter(ProducerConsumerQueue *q) {
2038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU1.Lock();
2039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB++;
2040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU1.Unlock();
2041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  q->Put(NULL);
2043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  q->Put(NULL);
2044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(100000);
2045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU1.Lock();
2047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU2.Lock();
2048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB++;
2049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU2.Unlock();
2050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU1.Unlock();
2051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Putter1() { Putter(Q1); }
2055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Putter2() { Putter(Q2); }
2056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Getter() {
2058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Q1->Get();
2059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Q2->Get();
2060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU2.Lock();
2062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB++;
2063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU2.Unlock();
2064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(48000); //  TODO: remove this when FP in test32 is fixed.
2066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
2069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//  ANNOTATE_EXPECT_RACE(&GLOB, "test40. FP. Fixed by MSMProp1. Complex Stuff.");
2070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test40: negative\n");
2071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Q1 = new ProducerConsumerQueue(INT_MAX);
2072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Q2 = new ProducerConsumerQueue(INT_MAX);
2073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Getter, Getter, Putter1, Putter2);
2074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
2075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
2076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB=%d\n", GLOB);
2077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  delete Q1;
2078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  delete Q2;
2079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST(Run, 40);
2081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test40
2082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test41: TN. Test for race that appears when loading a dynamic symbol. {{{1
2084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test41 {
2085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker() {
2086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_NO_OP(NULL); // An empty function, loaded from dll.
2087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
2089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test41: negative\n");
2090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Worker, Worker, Worker);
2091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
2092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
2093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 41, FEATURE|NEEDS_ANNOTATIONS);
2095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test41
2096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test42: TN. Using the same cond var several times. {{{1
2099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test42 {
2100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint GLOB = 0;
2101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint COND = 0;
2102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint N_threads = 3;
2103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex   MU;
2104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker1() {
2106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB=1;
2107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
2109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  COND = 1;
2110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CV.Signal();
2111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();
2112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
2114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  while (COND != 0)
2115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CV.Wait(&MU);
2116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_CONDVAR_LOCK_WAIT(&CV, &MU);
2117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();
2118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB=3;
2120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker2() {
2124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
2126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  while (COND != 1)
2127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CV.Wait(&MU);
2128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_CONDVAR_LOCK_WAIT(&CV, &MU);
2129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();
2130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB=2;
2132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
2134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  COND = 0;
2135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CV.Signal();
2136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();
2137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
2141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//  ANNOTATE_EXPECT_RACE(&GLOB, "test42. TN. debugging.");
2142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test42: negative\n");
2143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Worker1, Worker2);
2144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
2145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
2146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB=%d\n", GLOB);
2147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 42, FEATURE|NEEDS_ANNOTATIONS);
2149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test42
2150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test43: TN. {{{1
2154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test43 {
2155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
2156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Putter:            Getter:
2157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 1. write
2158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 2. Q.Put() --\     .
2159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 3. read       \--> a. Q.Get()
2160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                    b. read
2161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
2162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownProducerConsumerQueue Q(INT_MAX);
2163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Putter() {
2164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = 1;
2165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Q.Put(NULL);
2166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(GLOB == 1);
2167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Getter() {
2169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Q.Get();
2170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(100000);
2171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(GLOB == 1);
2172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
2174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test43: negative\n");
2175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Putter, Getter);
2176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
2177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
2178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB=%d\n", GLOB);
2179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST(Run, 43)
2181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test43
2182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test44: FP. {{{1
2185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test44 {
2186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
2187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Putter:            Getter:
2188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 1. read
2189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 2. Q.Put() --\     .
2190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 3. MU.Lock()  \--> a. Q.Get()
2191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 4. write
2192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 5. MU.Unlock()
2193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                    b. MU.Lock()
2194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                    c. write
2195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                    d. MU.Unlock();
2196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
2197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex   MU;
2198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownProducerConsumerQueue Q(INT_MAX);
2199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Putter() {
2200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(GLOB == 0);
2201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Q.Put(NULL);
2202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
2203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = 1;
2204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();
2205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Getter() {
2207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Q.Get();
2208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(100000);
2209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
2210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = 1;
2211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();
2212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
2214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//  ANNOTATE_EXPECT_RACE(&GLOB, "test44. FP. Fixed by MSMProp1.");
2215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test44: negative\n");
2216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Putter, Getter);
2217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
2218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
2219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB=%d\n", GLOB);
2220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST(Run, 44)
2222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test44
2223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test45: TN. {{{1
2226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test45 {
2227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
2228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Putter:            Getter:
2229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 1. read
2230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 2. Q.Put() --\     .
2231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 3. MU.Lock()  \--> a. Q.Get()
2232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 4. write
2233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 5. MU.Unlock()
2234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                    b. MU.Lock()
2235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                    c. read
2236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                    d. MU.Unlock();
2237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
2238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex   MU;
2239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownProducerConsumerQueue Q(INT_MAX);
2240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Putter() {
2241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(GLOB == 0);
2242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Q.Put(NULL);
2243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
2244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB++;
2245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();
2246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Getter() {
2248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Q.Get();
2249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(100000);
2250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
2251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(GLOB <= 1);
2252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();
2253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
2255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test45: negative\n");
2256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Putter, Getter);
2257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
2258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
2259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB=%d\n", GLOB);
2260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST(Run, 45)
2262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test45
2263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test46: FN. {{{1
2266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test46 {
2267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
2268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// First:                             Second:
2269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 1. write
2270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 2. MU.Lock()
2271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 3. write
2272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 4. MU.Unlock()                      (sleep)
2273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                                    a. MU.Lock()
2274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                                    b. write
2275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                                    c. MU.Unlock();
2276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
2277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex   MU;
2278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid First() {
2279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB++;
2280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
2281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB++;
2282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();
2283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Second() {
2285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(480000);
2286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
2287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB++;
2288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();
2289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  // just a print.
2291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  // If we move it to Run()  we will get report in MSMHelgrind
2292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  // due to its false positive (test32).
2293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
2294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB=%d\n", GLOB);
2295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();
2296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
2298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_TRACE_MEMORY(&GLOB);
2299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(First, Second);
2300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
2301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
2302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST(Run, 46)
2304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test46
2305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test47: TP. Not detected by pure happens-before detectors. {{{1
2308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test47 {
2309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// A true race that can not be detected by a pure happens-before
2310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// race detector.
2311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
2312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// First:                             Second:
2313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 1. write
2314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 2. MU.Lock()
2315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 3. MU.Unlock()                      (sleep)
2316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                                    a. MU.Lock()
2317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                                    b. MU.Unlock();
2318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                                    c. write
2319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
2320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex   MU;
2321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid First() {
2322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB=1;
2323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
2324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();
2325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Second() {
2327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(480000);
2328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
2329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();
2330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB++;
2331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
2333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  FAST_MODE_INIT(&GLOB);
2334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if (!Tsan_PureHappensBefore())
2335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test47. TP. Not detected by pure HB.");
2336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test47: positive\n");
2337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(First, Second);
2338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
2339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
2340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB=%d\n", GLOB);
2341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST(Run, 47)
2343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test47
2344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test48: FN. Simple race (single write vs multiple reads). {{{1
2347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test48 {
2348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
2349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// same as test10 but with single writer and  multiple readers
2350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// A simple data race between single writer and  multiple readers.
2351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Write happens before Reads (enforced by sleep(1)),
2352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
2354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Writer:                    Readers:
2355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 1. write(GLOB)             a. sleep(long enough so that GLOB
2356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                                is most likely initialized by Writer)
2357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                            b. read(GLOB)
2358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
2359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
2360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Eraser algorithm does not detect the race here,
2361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// see Section 2.2 of http://citeseer.ist.psu.edu/savage97eraser.html.
2362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
2363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Writer() {
2364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = 3;
2365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Reader() {
2367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(100000);
2368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(GLOB != -777);
2369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
2372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  FAST_MODE_INIT(&GLOB);
2373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test48. TP. FN in MSMHelgrind.");
2374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test48: positive\n");
2375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Writer, Reader,Reader,Reader);
2376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
2377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
2378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB=%d\n", GLOB);
2379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST(Run, 48)
2381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test48
2382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test49: FN. Simple race (single write vs multiple reads). {{{1
2385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test49 {
2386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
2387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// same as test10 but with multiple read operations done by a single reader
2388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// A simple data race between writer and readers.
2389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Write happens before Read (enforced by sleep(1)),
2390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
2391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Writer:                    Reader:
2392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 1. write(GLOB)             a. sleep(long enough so that GLOB
2393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                                is most likely initialized by Writer)
2394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                            b. read(GLOB)
2395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                            c. read(GLOB)
2396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                            d. read(GLOB)
2397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                            e. read(GLOB)
2398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
2399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
2400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Eraser algorithm does not detect the race here,
2401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// see Section 2.2 of http://citeseer.ist.psu.edu/savage97eraser.html.
2402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
2403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Writer() {
2404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = 3;
2405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Reader() {
2407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(100000);
2408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(GLOB != -777);
2409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(GLOB != -777);
2410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(GLOB != -777);
2411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(GLOB != -777);
2412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
2415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  FAST_MODE_INIT(&GLOB);
2416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test49. TP. FN in MSMHelgrind.");
2417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test49: positive\n");
2418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Writer, Reader);
2419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
2420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
2421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB=%d\n", GLOB);
2422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST(Run, 49);
2424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test49
2425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test50: TP. Synchronization via CondVar. {{{1
2428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test50 {
2429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
2430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex   MU;
2431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Two last write accesses to GLOB are not synchronized
2432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
2433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Waiter:                      Waker:
2434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 1. COND = 0
2435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 2. Start(Waker)
2436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 3. MU.Lock()                 a. write(GLOB)
2437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                              b. MU.Lock()
2438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                              c. COND = 1
2439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                         /--- d. CV.Signal()
2440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//  4. while(COND != 1)   /     e. MU.Unlock()
2441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//       CV.Wait(MU) <---/
2442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//  5. MU.Unlock()
2443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//  6. write(GLOB)              f. MU.Lock()
2444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                              g. write(GLOB)
2445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                              h. MU.Unlock()
2446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Waker() {
2449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(100000);  // Make sure the waiter blocks.
2450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = 1;
2452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
2454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  COND = 1;
2455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CV.Signal();
2456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();
2457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(100000);
2459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
2460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = 3;
2461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();
2462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Waiter() {
2465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ThreadPool pool(1);
2466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  pool.StartWorkers();
2467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  COND = 0;
2468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  pool.Add(NewCallback(Waker));
2469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
2471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  while(COND != 1)
2472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CV.Wait(&MU);
2473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_CONDVAR_LOCK_WAIT(&CV, &MU);
2474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();
2475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = 2;
2477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
2479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  FAST_MODE_INIT(&GLOB);
2480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test50. TP.");
2481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test50: positive\n");
2482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Waiter();
2483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB=%d\n", GLOB);
2484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 50, FEATURE|NEEDS_ANNOTATIONS);
2486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test50
2487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test51: TP. Synchronization via CondVar: problem with several signals. {{{1
2490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test51 {
2491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
2492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     COND = 0;
2493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex   MU;
2494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// scheduler dependent results because of several signals
2497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// second signal will be lost
2498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
2499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Waiter:                      Waker:
2500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 1. Start(Waker)
2501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 2. MU.Lock()
2502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 3. while(COND)
2503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//       CV.Wait(MU)<-\         .
2504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 4. MU.Unlock()      \        .
2505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 5. write(GLOB)       \       a. write(GLOB)
2506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                       \      b. MU.Lock()
2507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                        \     c. COND = 1
2508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                         \--- d. CV.Signal()
2509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                              e. MU.Unlock()
2510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
2511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                              f. write(GLOB)
2512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
2513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                              g. MU.Lock()
2514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                              h. COND = 1
2515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                    LOST<---- i. CV.Signal()
2516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                              j. MU.Unlock()
2517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Waker() {
2519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(10000);  // Make sure the waiter blocks.
2521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = 1;
2523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
2525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  COND = 1;
2526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CV.Signal();
2527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();
2528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(10000);  // Make sure the waiter is signalled.
2530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = 2;
2532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
2534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  COND = 1;
2535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CV.Signal();   //Lost Signal
2536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();
2537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Waiter() {
2540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ThreadPool pool(1);
2542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  pool.StartWorkers();
2543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  pool.Add(NewCallback(Waker));
2544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
2546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  while(COND != 1)
2547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CV.Wait(&MU);
2548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();
2549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = 3;
2552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
2554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  FAST_MODE_INIT(&GLOB);
2555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_EXPECT_RACE(&GLOB, "test51. TP.");
2556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test51: positive\n");
2557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Waiter();
2558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB=%d\n", GLOB);
2559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST(Run, 51);
2561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test51
2562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test52: TP. Synchronization via CondVar: problem with several signals. {{{1
2565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test52 {
2566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
2567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     COND = 0;
2568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex   MU;
2569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// same as test51 but the first signal will be lost
2571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// scheduler dependent results because of several signals
2572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
2573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Waiter:                      Waker:
2574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 1. Start(Waker)
2575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                              a. write(GLOB)
2576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                              b. MU.Lock()
2577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                              c. COND = 1
2578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                    LOST<---- d. CV.Signal()
2579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                              e. MU.Unlock()
2580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
2581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 2. MU.Lock()
2582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 3. while(COND)
2583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//       CV.Wait(MU)<-\         .
2584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 4. MU.Unlock()      \        f. write(GLOB)
2585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 5. write(GLOB)       \       .
2586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                       \      g. MU.Lock()
2587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                        \     h. COND = 1
2588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                         \--- i. CV.Signal()
2589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                              j. MU.Unlock()
2590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Waker() {
2592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = 1;
2594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
2596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  COND = 1;
2597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CV.Signal();    //lost signal
2598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();
2599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(20000);  // Make sure the waiter blocks
2601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = 2;
2603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
2605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  COND = 1;
2606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CV.Signal();
2607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();
2608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Waiter() {
2611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ThreadPool pool(1);
2612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  pool.StartWorkers();
2613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  pool.Add(NewCallback(Waker));
2614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(10000);  // Make sure the first signal will be lost
2616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
2618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  while(COND != 1)
2619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CV.Wait(&MU);
2620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();
2621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = 3;
2623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
2625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  FAST_MODE_INIT(&GLOB);
2626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_EXPECT_RACE(&GLOB, "test52. TP.");
2627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test52: positive\n");
2628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Waiter();
2629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB=%d\n", GLOB);
2630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST(Run, 52);
2632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test52
2633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test53: FP. Synchronization via implicit semaphore. {{{1
2636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test53 {
2637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Correctly synchronized test, but the common lockset is empty.
2638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// The variable FLAG works as an implicit semaphore.
2639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// MSMHelgrind still does not complain since it does not maintain the lockset
2640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// at the exclusive state. But MSMProp1 does complain.
2641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// See also test54.
2642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
2643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
2644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Initializer:                  Users
2645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 1. MU1.Lock()
2646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 2. write(GLOB)
2647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 3. FLAG = true
2648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 4. MU1.Unlock()
2649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                               a. MU1.Lock()
2650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                               b. f = FLAG;
2651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                               c. MU1.Unlock()
2652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                               d. if (!f) goto a.
2653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                               e. MU2.Lock()
2654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                               f. write(GLOB)
2655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                               g. MU2.Unlock()
2656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
2657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
2659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownbool    FLAG = false;
2660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex   MU1, MU2;
2661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Initializer() {
2663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU1.Lock();
2664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = 1000;
2665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  FLAG = true;
2666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU1.Unlock();
2667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(100000); // just in case
2668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid User() {
2671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  bool f = false;
2672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  while(!f) {
2673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    MU1.Lock();
2674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    f = FLAG;
2675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    MU1.Unlock();
2676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    usleep(10000);
2677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
2678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  // at this point Initializer will not access GLOB again
2679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU2.Lock();
2680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(GLOB >= 1000);
2681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB++;
2682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU2.Unlock();
2683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
2686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  FAST_MODE_INIT(&GLOB);
2687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if (!Tsan_PureHappensBefore())
2688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test53. FP. Implicit semaphore");
2689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test53: FP. false positive, Implicit semaphore\n");
2690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Initializer, User, User);
2691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
2692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
2693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB=%d\n", GLOB);
2694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST(Run, 53)
2696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test53
2697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test54: TN. Synchronization via implicit semaphore. Annotated {{{1
2700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test54 {
2701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Same as test53, but annotated.
2702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
2703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownbool    FLAG = false;
2704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex   MU1, MU2;
2705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Initializer() {
2707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU1.Lock();
2708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = 1000;
2709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  FLAG = true;
2710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_CONDVAR_SIGNAL(&GLOB);
2711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU1.Unlock();
2712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(100000); // just in case
2713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid User() {
2716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  bool f = false;
2717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  while(!f) {
2718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    MU1.Lock();
2719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    f = FLAG;
2720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    MU1.Unlock();
2721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    usleep(10000);
2722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
2723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  // at this point Initializer will not access GLOB again
2724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_CONDVAR_WAIT(&GLOB);
2725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU2.Lock();
2726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(GLOB >= 1000);
2727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB++;
2728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU2.Unlock();
2729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
2732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test54: negative\n");
2733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Initializer, User, User);
2734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
2735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
2736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB=%d\n", GLOB);
2737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 54, FEATURE|NEEDS_ANNOTATIONS)
2739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test54
2740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test55: FP. Synchronization with TryLock. Not easy for race detectors {{{1
2743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test55 {
2744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// "Correct" synchronization with TryLock and Lock.
2745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
2746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// This scheme is actually very risky.
2747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// It is covered in detail in this video:
2748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// http://youtube.com/watch?v=mrvAqvtWYb4 (slide 36, near 50-th minute).
2749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
2750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex   MU;
2751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker_Lock() {
2753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = 1;
2754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
2755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker_TryLock() {
2758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  while (true) {
2759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (!MU.TryLock()) {
2760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      MU.Unlock();
2761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
2762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
2763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    else
2764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      MU.Unlock();
2765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    usleep(100);
2766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
2767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = 2;
2768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
2771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test55:\n");
2772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Worker_Lock, Worker_TryLock);
2773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
2774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
2775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB=%d\n", GLOB);
2776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 55, FEATURE|EXCLUDE_FROM_ALL);
2778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test55
2779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test56: TP. Use of ANNOTATE_BENIGN_RACE. {{{1
2783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test56 {
2784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// For whatever reason the user wants to treat
2785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// a race on GLOB as a benign race.
2786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
2787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB2 = 0;
2788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker() {
2790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB++;
2791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
2794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_BENIGN_RACE(&GLOB, "test56. Use of ANNOTATE_BENIGN_RACE.");
2795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_BENIGN_RACE(&GLOB2, "No race. The tool should be silent");
2796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test56: positive\n");
2797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Worker, Worker, Worker, Worker);
2798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
2799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
2800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB=%d\n", GLOB);
2801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 56, FEATURE|NEEDS_ANNOTATIONS)
2803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test56
2804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test57: TN: Correct use of atomics. {{{1
2807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test57 {
2808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
2809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Writer() {
2810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  for (int i = 0; i < 10; i++) {
2811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AtomicIncrement(&GLOB, 1);
2812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    usleep(1000);
2813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
2814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Reader() {
2816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  while (GLOB < 20) usleep(1000);
2817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
2819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test57: negative\n");
2820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Writer, Writer, Reader, Reader);
2821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
2822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
2823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(GLOB == 20);
2824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB=%d\n", GLOB);
2825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST(Run, 57)
2827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test57
2828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test58: TN. User defined synchronization. {{{1
2831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test58 {
2832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB1 = 1;
2833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB2 = 2;
2834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     FLAG1 = 0;
2835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     FLAG2 = 0;
2836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Correctly synchronized test, but the common lockset is empty.
2838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// The variables FLAG1 and FLAG2 used for synchronization and as
2839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// temporary variables for swapping two global values.
2840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Such kind of synchronization is rarely used (Excluded from all tests??).
2841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker2() {
2843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  FLAG1=GLOB2;
2844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  while(!FLAG2)
2846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ;
2847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB2=FLAG2;
2848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker1() {
2851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  FLAG2=GLOB1;
2852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  while(!FLAG1)
2854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ;
2855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB1=FLAG1;
2856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
2859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test58:\n");
2860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Worker1, Worker2);
2861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
2862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
2863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB1=%d\n", GLOB1);
2864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB2=%d\n", GLOB2);
2865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 58, FEATURE|EXCLUDE_FROM_ALL)
2867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test58
2868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test59: TN. User defined synchronization. Annotated {{{1
2872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test59 {
2873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     COND1 = 0;
2874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     COND2 = 0;
2875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB1 = 1;
2876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB2 = 2;
2877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     FLAG1 = 0;
2878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     FLAG2 = 0;
2879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// same as test 58 but annotated
2880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker2() {
2882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  FLAG1=GLOB2;
2883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_CONDVAR_SIGNAL(&COND2);
2884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  while(!FLAG2) usleep(1);
2885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_CONDVAR_WAIT(&COND1);
2886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB2=FLAG2;
2887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker1() {
2890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  FLAG2=GLOB1;
2891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_CONDVAR_SIGNAL(&COND1);
2892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  while(!FLAG1) usleep(1);
2893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_CONDVAR_WAIT(&COND2);
2894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB1=FLAG1;
2895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
2898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test59: negative\n");
2899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_BENIGN_RACE(&FLAG1, "synchronization via 'safe' race");
2900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_BENIGN_RACE(&FLAG2, "synchronization via 'safe' race");
2901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Worker1, Worker2);
2902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
2903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
2904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB1=%d\n", GLOB1);
2905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB2=%d\n", GLOB2);
2906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 59, FEATURE|NEEDS_ANNOTATIONS)
2908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test59
2909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test60: TN. Correct synchronization using signal-wait {{{1
2912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test60 {
2913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     COND1 = 0;
2914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     COND2 = 0;
2915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB1 = 1;
2916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB2 = 2;
2917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     FLAG2 = 0;
2918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     FLAG1 = 0;
2919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex   MU;
2920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// same as test 59 but synchronized with signal-wait.
2921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker2() {
2923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  FLAG1=GLOB2;
2924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
2926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  COND1 = 1;
2927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CV.Signal();
2928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();
2929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
2931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  while(COND2 != 1)
2932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CV.Wait(&MU);
2933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_CONDVAR_LOCK_WAIT(&CV, &MU);
2934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();
2935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB2=FLAG2;
2937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker1() {
2940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  FLAG2=GLOB1;
2941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
2943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  COND2 = 1;
2944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CV.Signal();
2945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();
2946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
2948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  while(COND1 != 1)
2949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CV.Wait(&MU);
2950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_CONDVAR_LOCK_WAIT(&CV, &MU);
2951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();
2952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB1=FLAG1;
2954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
2957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test60: negative\n");
2958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Worker1, Worker2);
2959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
2960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
2961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB1=%d\n", GLOB1);
2962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB2=%d\n", GLOB2);
2963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 60, FEATURE|NEEDS_ANNOTATIONS)
2965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test60
2966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test61: TN. Synchronization via Mutex as in happens-before, annotated. {{{1
2969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test61 {
2970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex MU;
2971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
2972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     *P1 = NULL, *P2 = NULL;
2973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// In this test Mutex lock/unlock operations introduce happens-before relation.
2975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// We annotate the code so that MU is treated as in pure happens-before detector.
2976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Putter() {
2979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_MUTEX_IS_USED_AS_CONDVAR(&MU);
2980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
2981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if (P1 == NULL) {
2982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    P1 = &GLOB;
2983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    *P1 = 1;
2984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
2985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();
2986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Getter() {
2989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  bool done  = false;
2990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  while (!done) {
2991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    MU.Lock();
2992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (P1) {
2993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      done = true;
2994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      P2 = P1;
2995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      P1 = NULL;
2996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
2997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    MU.Unlock();
2998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
2999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  *P2 = 2;
3000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
3004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test61: negative\n");
3005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Putter, Getter);
3006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
3007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
3008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB=%d\n", GLOB);
3009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 61, FEATURE|NEEDS_ANNOTATIONS)
3011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test61
3012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test62: STAB. Create as many segments as possible. {{{1
3015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test62 {
3016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Helgrind 3.3.0 will fail as it has a hard limit of < 2^24 segments.
3017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// A better scheme is to implement garbage collection for segments.
3018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownProducerConsumerQueue Q(INT_MAX);
3019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownconst int N = 1 << 22;
3020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Putter() {
3022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  for (int i = 0; i < N; i++){
3023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if ((i % (N / 8)) == 0) {
3024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      printf("i=%d\n", i);
3025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
3026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Q.Put(NULL);
3027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
3028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Getter() {
3031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  for (int i = 0; i < N; i++)
3032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Q.Get();
3033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
3036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test62:\n");
3037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Putter, Getter);
3038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
3039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
3040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 62, STABILITY|EXCLUDE_FROM_ALL)
3042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test62
3043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test63: STAB. Create as many segments as possible and do it fast. {{{1
3046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test63 {
3047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Helgrind 3.3.0 will fail as it has a hard limit of < 2^24 segments.
3048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// A better scheme is to implement garbage collection for segments.
3049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownconst int N = 1 << 24;
3050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint C = 0;
3051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Putter() {
3053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  for (int i = 0; i < N; i++){
3054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if ((i % (N / 8)) == 0) {
3055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      printf("i=%d\n", i);
3056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
3057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ANNOTATE_CONDVAR_SIGNAL(&C);
3058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
3059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Getter() {
3062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
3065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test63:\n");
3066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Putter, Getter);
3067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
3068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
3069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 63, STABILITY|EXCLUDE_FROM_ALL)
3071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test63
3072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test64: TP. T2 happens-before T3, but T1 is independent. Reads in T1/T2. {{{1
3075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test64 {
3076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// True race between T1 and T3:
3077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
3078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// T1:                   T2:                   T3:
3079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 1. read(GLOB)         (sleep)
3080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                       a. read(GLOB)
3081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                       b. Q.Put() ----->    A. Q.Get()
3082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                                            B. write(GLOB)
3083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
3084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
3085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
3087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownProducerConsumerQueue Q(INT_MAX);
3088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid T1() {
3090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(GLOB == 0);
3091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid T2() {
3094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(100000);
3095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(GLOB == 0);
3096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Q.Put(NULL);
3097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid T3() {
3100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Q.Get();
3101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = 1;
3102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
3106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  FAST_MODE_INIT(&GLOB);
3107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test64: TP.");
3108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test64: positive\n");
3109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(T1, T2, T3);
3110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
3111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
3112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB=%d\n", GLOB);
3113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST(Run, 64)
3115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test64
3116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test65: TP. T2 happens-before T3, but T1 is independent. Writes in T1/T2. {{{1
3119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test65 {
3120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Similar to test64.
3121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// True race between T1 and T3:
3122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
3123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// T1:                   T2:                   T3:
3124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 1. MU.Lock()
3125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 2. write(GLOB)
3126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 3. MU.Unlock()         (sleep)
3127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                       a. MU.Lock()
3128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                       b. write(GLOB)
3129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                       c. MU.Unlock()
3130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                       d. Q.Put() ----->    A. Q.Get()
3131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                                            B. write(GLOB)
3132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
3133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
3134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
3136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex   MU;
3137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownProducerConsumerQueue Q(INT_MAX);
3138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid T1() {
3140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
3141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB++;
3142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();
3143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid T2() {
3146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(100000);
3147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
3148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB++;
3149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();
3150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Q.Put(NULL);
3151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid T3() {
3154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Q.Get();
3155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = 1;
3156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
3160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  FAST_MODE_INIT(&GLOB);
3161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if (!Tsan_PureHappensBefore())
3162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test65. TP.");
3163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test65: positive\n");
3164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(T1, T2, T3);
3165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
3166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
3167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB=%d\n", GLOB);
3168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST(Run, 65)
3170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test65
3171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test66: TN. Two separate pairs of signaller/waiter using the same CV. {{{1
3174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test66 {
3175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB1 = 0;
3176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB2 = 0;
3177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     C1 = 0;
3178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     C2 = 0;
3179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex   MU;
3180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Signaller1() {
3182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB1 = 1;
3183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
3184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  C1 = 1;
3185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CV.Signal();
3186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();
3187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Signaller2() {
3190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB2 = 1;
3191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(100000);
3192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
3193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  C2 = 1;
3194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CV.Signal();
3195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();
3196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Waiter1() {
3199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
3200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  while (C1 != 1) CV.Wait(&MU);
3201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_CONDVAR_WAIT(&CV);
3202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();
3203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB1 = 2;
3204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Waiter2() {
3207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
3208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  while (C2 != 1) CV.Wait(&MU);
3209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_CONDVAR_WAIT(&CV);
3210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();
3211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB2 = 2;
3212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
3215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test66: negative\n");
3216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Signaller1, Signaller2, Waiter1, Waiter2);
3217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
3218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
3219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB=%d/%d\n", GLOB1, GLOB2);
3220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 66, FEATURE|NEEDS_ANNOTATIONS)
3222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test66
3223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test67: FN. Race between Signaller1 and Waiter2 {{{1
3226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test67 {
3227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Similar to test66, but there is a real race here.
3228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
3229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Here we create a happens-before arc between Signaller1 and Waiter2
3230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// even though there should be no such arc.
3231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// However, it's probably improssible (or just very hard) to avoid it.
3232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
3233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     C1 = 0;
3234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     C2 = 0;
3235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex   MU;
3236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Signaller1() {
3238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = 1;
3239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
3240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  C1 = 1;
3241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CV.Signal();
3242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();
3243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Signaller2() {
3246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(100000);
3247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
3248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  C2 = 1;
3249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CV.Signal();
3250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();
3251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Waiter1() {
3254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
3255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  while (C1 != 1) CV.Wait(&MU);
3256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_CONDVAR_WAIT(&CV);
3257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();
3258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Waiter2() {
3261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
3262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  while (C2 != 1) CV.Wait(&MU);
3263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_CONDVAR_WAIT(&CV);
3264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();
3265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = 2;
3266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
3269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  FAST_MODE_INIT(&GLOB);
3270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_EXPECT_RACE(&GLOB, "test67. FN. Race between Signaller1 and Waiter2");
3271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test67: positive\n");
3272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Signaller1, Signaller2, Waiter1, Waiter2);
3273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
3274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
3275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB=%d\n", GLOB);
3276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 67, FEATURE|NEEDS_ANNOTATIONS|EXCLUDE_FROM_ALL)
3278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test67
3279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test68: TP. Writes are protected by MU, reads are not. {{{1
3282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test68 {
3283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// In this test, all writes to GLOB are protected by a mutex
3284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// but some reads go unprotected.
3285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// This is certainly a race, but in some cases such code could occur in
3286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// a correct program. For example, the unprotected reads may be used
3287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// for showing statistics and are not required to be precise.
3288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
3289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     COND = 0;
3290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownconst int N_writers = 3;
3291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex MU, MU1;
3292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Writer() {
3294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  for (int i = 0; i < 100; i++) {
3295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    MU.Lock();
3296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    GLOB++;
3297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    MU.Unlock();
3298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
3299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  // we are done
3301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU1.Lock();
3302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  COND++;
3303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU1.Unlock();
3304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Reader() {
3307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  bool cont = true;
3308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  while (cont) {
3309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CHECK(GLOB >= 0);
3310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    // are we done?
3312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    MU1.Lock();
3313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (COND == N_writers)
3314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      cont = false;
3315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    MU1.Unlock();
3316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    usleep(100);
3317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
3318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
3321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  FAST_MODE_INIT(&GLOB);
3322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_EXPECT_RACE(&GLOB, "TP. Writes are protected, reads are not.");
3323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test68: positive\n");
3324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Reader, Writer, Writer, Writer);
3325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
3326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
3327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB=%d\n", GLOB);
3328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST(Run, 68)
3330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test68
3331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test69:  {{{1
3334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test69 {
3335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// This is the same as test68, but annotated.
3336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// We do not want to annotate GLOB as a benign race
3337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// because we want to allow racy reads only in certain places.
3338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
3339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// TODO:
3340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
3341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     COND = 0;
3342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownconst int N_writers = 3;
3343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     FAKE_MU = 0;
3344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex MU, MU1;
3345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Writer() {
3347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  for (int i = 0; i < 10; i++) {
3348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    MU.Lock();
3349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    GLOB++;
3350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    MU.Unlock();
3351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
3352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  // we are done
3354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU1.Lock();
3355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  COND++;
3356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU1.Unlock();
3357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Reader() {
3360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  bool cont = true;
3361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  while (cont) {
3362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ANNOTATE_IGNORE_READS_BEGIN();
3363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CHECK(GLOB >= 0);
3364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ANNOTATE_IGNORE_READS_END();
3365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    // are we done?
3367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    MU1.Lock();
3368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (COND == N_writers)
3369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      cont = false;
3370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    MU1.Unlock();
3371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    usleep(100);
3372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
3373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
3376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test69: negative\n");
3377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Reader, Writer, Writer, Writer);
3378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
3379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
3380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB=%d\n", GLOB);
3381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST(Run, 69)
3383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test69
3384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test70: STAB. Check that TRACE_MEMORY works. {{{1
3386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test70 {
3387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
3388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
3389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test70: negative\n");
3390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_TRACE_MEMORY(&GLOB);
3391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = 1;
3392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB=%d\n", GLOB);
3393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST(Run, 70)
3395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test70
3396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test71: TN. strlen, index. {{{1
3400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test71 {
3401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// This test is a reproducer for a benign race in strlen (as well as index, etc).
3402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Some implementations of strlen may read up to 7 bytes past the end of the string
3403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// thus touching memory which may not belong to this string.
3404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Such race is benign because the data read past the end of the string is not used.
3405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
3406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Here, we allocate a 8-byte aligned string str and initialize first 5 bytes.
3407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Then one thread calls strlen(str) (as well as index & rindex)
3408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// and another thread initializes str[5]..str[7].
3409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
3410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// This can be fixed in Helgrind by intercepting strlen and replacing it
3411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// with a simpler implementation.
3412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownchar    *str;
3414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid WorkerX() {
3415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(100000);
3416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(strlen(str) == 4);
3417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(index(str, 'X') == str);
3418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(index(str, 'x') == str+1);
3419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(index(str, 'Y') == NULL);
3420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(rindex(str, 'X') == str+2);
3421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(rindex(str, 'x') == str+3);
3422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(rindex(str, 'Y') == NULL);
3423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid WorkerY() {
3425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  str[5] = 'Y';
3426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  str[6] = 'Y';
3427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  str[7] = '\0';
3428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
3431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  str = new char[8];
3432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  str[0] = 'X';
3433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  str[1] = 'x';
3434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  str[2] = 'X';
3435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  str[3] = 'x';
3436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  str[4] = '\0';
3437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test71: negative (strlen & index)\n");
3439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThread t1(WorkerY);
3440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThread t2(WorkerX);
3441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t1.Start();
3442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t2.Start();
3443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t1.Join();
3444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t2.Join();
3445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tstrX=%s; strY=%s\n", str, str+5);
3446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST(Run, 71)
3448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test71
3449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test72: STAB. Stress test for the number of segment sets (SSETs). {{{1
3452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test72 {
3453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifndef NO_BARRIER
3454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Variation of test33.
3455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Instead of creating Nlog*N_iter threads,
3456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// we create Nlog threads and do N_iter barriers.
3457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
3458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownconst int N_iter = 30;
3459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownconst int Nlog  = 16;
3460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownconst int N     = 1 << Nlog;
3461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int64_t ARR1[N];
3462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int64_t ARR2[N];
3463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBarrier *barriers[N_iter];
3464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex   MU;
3465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker() {
3467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
3468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  int n = ++GLOB;
3469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();
3470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  n %= Nlog;
3472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  long t0 = clock();
3474b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  long t __attribute__((unused)) = t0;
3475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  for (int it = 0; it < N_iter; it++) {
3477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if(n == 0) {
3478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      //printf("Iter: %d; %ld %ld\n", it, clock() - t, clock() - t0);
3479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      t = clock();
3480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
3481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    // Iterate N_iter times, block on barrier after each iteration.
3482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    // This way Helgrind will create new segments after each barrier.
3483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for (int x = 0; x < 2; x++) {
3485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // run the inner loop twice.
3486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // When a memory location is accessed second time it is likely
3487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // that the state (SVal) will be unchanged.
3488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      // The memory machine may optimize this case.
3489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (int i = 0; i < N; i++) {
3490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        // ARR1[i] and ARR2[N-1-i] are accessed by threads from i-th subset
3491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (i & (1 << n)) {
3492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          CHECK(ARR1[i] == 0);
3493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          CHECK(ARR2[N-1-i] == 0);
3494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
3495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
3497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    barriers[it]->Block();
3498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
3499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
3503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test72:\n");
3504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  std::vector<MyThread*> vec(Nlog);
3506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  for (int i = 0; i < N_iter; i++)
3508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    barriers[i] = new Barrier(Nlog);
3509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  // Create and start Nlog threads
3511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  for (int i = 0; i < Nlog; i++) {
3512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    vec[i] = new MyThread(Worker);
3513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    vec[i]->Start();
3514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
3515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  // Join all threads.
3517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  for (int i = 0; i < Nlog; i++) {
3518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    vec[i]->Join();
3519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    delete vec[i];
3520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
3521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  for (int i = 0; i < N_iter; i++)
3522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    delete barriers[i];
3523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  /*printf("\tGLOB=%d; ARR[1]=%d; ARR[7]=%d; ARR[N-1]=%d\n",
3525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         GLOB, (int)ARR1[1], (int)ARR1[7], (int)ARR1[N-1]);*/
3526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 72, STABILITY|PERFORMANCE|EXCLUDE_FROM_ALL);
3528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif // NO_BARRIER
3529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test72
3530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test73: STAB. Stress test for the number of (SSETs), different access sizes. {{{1
3533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test73 {
3534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifndef NO_BARRIER
3535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Variation of test72.
3536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// We perform accesses of different sizes to the same location.
3537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
3538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownconst int N_iter = 2;
3539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownconst int Nlog  = 16;
3540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownconst int N     = 1 << Nlog;
3541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownunion uint64_union {
3542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  uint64_t u64[1];
3543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  uint32_t u32[2];
3544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  uint16_t u16[4];
3545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  uint8_t  u8 [8];
3546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown};
3547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic uint64_union ARR1[N];
3548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownunion uint32_union {
3549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  uint32_t u32[1];
3550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  uint16_t u16[2];
3551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  uint8_t  u8 [4];
3552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown};
3553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic uint32_union ARR2[N];
3554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBarrier *barriers[N_iter];
3555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex   MU;
3556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker() {
3558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
3559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  int n = ++GLOB;
3560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();
3561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  n %= Nlog;
3563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  for (int it = 0; it < N_iter; it++) {
3565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    // Iterate N_iter times, block on barrier after each iteration.
3566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    // This way Helgrind will create new segments after each barrier.
3567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for (int x = 0; x < 4; x++) {
3569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (int i = 0; i < N; i++) {
3570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        // ARR1[i] are accessed by threads from i-th subset
3571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        if (i & (1 << n)) {
3572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          for (int off = 0; off < (1 << x); off++) {
3573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            switch(x) {
3574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              case 0: CHECK(ARR1[i].u64[off] == 0); break;
3575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              case 1: CHECK(ARR1[i].u32[off] == 0); break;
3576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              case 2: CHECK(ARR1[i].u16[off] == 0); break;
3577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              case 3: CHECK(ARR1[i].u8 [off] == 0); break;
3578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
3579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            switch(x) {
3580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              case 1: CHECK(ARR2[i].u32[off] == 0); break;
3581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              case 2: CHECK(ARR2[i].u16[off] == 0); break;
3582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown              case 3: CHECK(ARR2[i].u8 [off] == 0); break;
3583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            }
3584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          }
3585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        }
3586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
3588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    barriers[it]->Block();
3589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
3590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
3595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test73:\n");
3596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  std::vector<MyThread*> vec(Nlog);
3598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  for (int i = 0; i < N_iter; i++)
3600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    barriers[i] = new Barrier(Nlog);
3601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  // Create and start Nlog threads
3603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  for (int i = 0; i < Nlog; i++) {
3604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    vec[i] = new MyThread(Worker);
3605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    vec[i]->Start();
3606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
3607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  // Join all threads.
3609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  for (int i = 0; i < Nlog; i++) {
3610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    vec[i]->Join();
3611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    delete vec[i];
3612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
3613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  for (int i = 0; i < N_iter; i++)
3614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    delete barriers[i];
3615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  /*printf("\tGLOB=%d; ARR[1]=%d; ARR[7]=%d; ARR[N-1]=%d\n",
3617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         GLOB, (int)ARR1[1], (int)ARR1[7], (int)ARR1[N-1]);*/
3618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 73, STABILITY|PERFORMANCE|EXCLUDE_FROM_ALL);
3620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif // NO_BARRIER
3621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test73
3622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test74: PERF. A lot of lock/unlock calls. {{{1
3625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace    test74 {
3626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownconst int N = 100000;
3627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex   MU;
3628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
3629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test74: perf\n");
3630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  for (int i = 0; i < N; i++ ) {
3631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    MU.Lock();
3632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    MU.Unlock();
3633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
3634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST(Run, 74)
3636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test74
3637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test75: TN. Test for sem_post, sem_wait, sem_trywait. {{{1
3640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test75 {
3641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
3642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownsem_t   sem[2];
3643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Poster() {
3645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = 1;
3646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  sem_post(&sem[0]);
3647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  sem_post(&sem[1]);
3648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Waiter() {
3651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  sem_wait(&sem[0]);
3652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(GLOB==1);
3653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid TryWaiter() {
3655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(500000);
3656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  sem_trywait(&sem[1]);
3657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(GLOB==1);
3658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
3661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifndef DRT_NO_SEM
3662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  sem_init(&sem[0], 0, 0);
3663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  sem_init(&sem[1], 0, 0);
3664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test75: negative\n");
3666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  {
3667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    MyThreadArray t(Poster, Waiter);
3668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    t.Start();
3669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    t.Join();
3670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
3671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = 2;
3672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  {
3673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    MyThreadArray t(Poster, TryWaiter);
3674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    t.Start();
3675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    t.Join();
3676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
3677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB=%d\n", GLOB);
3678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  sem_destroy(&sem[0]);
3680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  sem_destroy(&sem[1]);
3681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
3682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST(Run, 75)
3684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test75
3685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// RefCountedClass {{{1
3687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstruct RefCountedClass {
3688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown public:
3689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  RefCountedClass() {
3690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    annotate_unref_ = false;
3691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ref_ = 0;
3692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    data_ = 0;
3693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
3694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ~RefCountedClass() {
3696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CHECK(ref_ == 0);     // race may be reported here
3697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int data_val = data_; // and here
3698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          // if MU is not annotated
3699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    data_ = 0;
3700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ref_ = -1;
3701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    printf("\tRefCountedClass::data_ = %d\n", data_val);
3702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
3703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  void AccessData() {
3705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    this->mu_.Lock();
3706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    this->data_++;
3707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    this->mu_.Unlock();
3708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
3709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  void Ref() {
3711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    MU.Lock();
3712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CHECK(ref_ >= 0);
3713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ref_++;
3714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    MU.Unlock();
3715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
3716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  void Unref() {
3718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    MU.Lock();
3719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CHECK(ref_ > 0);
3720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ref_--;
3721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    bool do_delete = ref_ == 0;
3722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (annotate_unref_) {
3723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ANNOTATE_CONDVAR_SIGNAL(this);
3724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
3725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    MU.Unlock();
3726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (do_delete) {
3727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (annotate_unref_) {
3728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ANNOTATE_CONDVAR_WAIT(this);
3729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
3730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      delete this;
3731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
3732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
3733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  static void Annotate_MU() {
3735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ANNOTATE_MUTEX_IS_USED_AS_CONDVAR(&MU);
3736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
3737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  void AnnotateUnref() {
3738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    annotate_unref_ = true;
3739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
3740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  void Annotate_Race() {
3741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ANNOTATE_BENIGN_RACE(&this->data_, "needs annotation");
3742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ANNOTATE_BENIGN_RACE(&this->ref_, "needs annotation");
3743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
3744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown private:
3745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  bool annotate_unref_;
3746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  int data_;
3748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Mutex mu_; // protects data_
3749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  int ref_;
3751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  static Mutex MU; // protects ref_
3752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown};
3753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex RefCountedClass::MU;
3755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test76: FP. Ref counting, no annotations. {{{1
3757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test76 {
3758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifndef NO_BARRIER
3759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
3760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBarrier barrier(4);
3761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownRefCountedClass *object = NULL;
3762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker() {
3763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  object->Ref();
3764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  barrier.Block();
3765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  object->AccessData();
3766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  object->Unref();
3767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
3769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test76: false positive (ref counting)\n");
3770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  object = new RefCountedClass;
3771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  object->Annotate_Race();
3772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Worker, Worker, Worker, Worker);
3773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
3774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
3775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 76, FEATURE)
3777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif // NO_BARRIER
3778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test76
3779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test77: TN. Ref counting, MU is annotated. {{{1
3783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test77 {
3784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifndef NO_BARRIER
3785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// same as test76, but RefCountedClass::MU is annotated.
3786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
3787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBarrier barrier(4);
3788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownRefCountedClass *object = NULL;
3789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker() {
3790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  object->Ref();
3791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  barrier.Block();
3792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  object->AccessData();
3793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  object->Unref();
3794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
3796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test77: true negative (ref counting), mutex is annotated\n");
3797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  RefCountedClass::Annotate_MU();
3798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  object = new RefCountedClass;
3799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Worker, Worker, Worker, Worker);
3800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
3801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
3802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST(Run, 77)
3804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif // NO_BARRIER
3805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test77
3806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test78: TN. Ref counting, Unref is annotated. {{{1
3810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test78 {
3811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifndef NO_BARRIER
3812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// same as test76, but RefCountedClass::Unref is annotated.
3813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
3814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBarrier barrier(4);
3815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownRefCountedClass *object = NULL;
3816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker() {
3817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  object->Ref();
3818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  barrier.Block();
3819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  object->AccessData();
3820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  object->Unref();
3821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
3823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test78: true negative (ref counting), Unref is annotated\n");
3824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  RefCountedClass::Annotate_MU();
3825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  object = new RefCountedClass;
3826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Worker, Worker, Worker, Worker);
3827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
3828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
3829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST(Run, 78)
3831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif // NO_BARRIER
3832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test78
3833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test79 TN. Swap. {{{1
3837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test79 {
3838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if 0
3839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef __gnu_cxx::hash_map<int, int> map_t;
3840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else
3841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef std::map<int, int> map_t;
3842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
3843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownmap_t   MAP;
3844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex   MU;
3845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Here we use swap to pass MAP between threads.
3847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// The synchronization is correct, but w/o ANNOTATE_MUTEX_IS_USED_AS_CONDVAR
3848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Helgrind will complain.
3849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker1() {
3851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  map_t tmp;
3852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
3853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  // We swap the new empty map 'tmp' with 'MAP'.
3854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MAP.swap(tmp);
3855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();
3856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  // tmp (which is the old version of MAP) is destroyed here.
3857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker2() {
3860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
3861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MAP[1]++;  // Just update MAP under MU.
3862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();
3863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker3() { Worker1(); }
3866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker4() { Worker2(); }
3867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
3869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_MUTEX_IS_USED_AS_CONDVAR(&MU);
3870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test79: negative\n");
3871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Worker1, Worker2, Worker3, Worker4);
3872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
3873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
3874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST(Run, 79)
3876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test79
3877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// AtomicRefCountedClass. {{{1
3880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Same as RefCountedClass, but using atomic ops instead of mutex.
3881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstruct AtomicRefCountedClass {
3882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown public:
3883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  AtomicRefCountedClass() {
3884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    annotate_unref_ = false;
3885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ref_ = 0;
3886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    data_ = 0;
3887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
3888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ~AtomicRefCountedClass() {
3890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CHECK(ref_ == 0);     // race may be reported here
3891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int data_val = data_; // and here
3892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    data_ = 0;
3893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ref_ = -1;
3894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    printf("\tRefCountedClass::data_ = %d\n", data_val);
3895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
3896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  void AccessData() {
3898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    this->mu_.Lock();
3899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    this->data_++;
3900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    this->mu_.Unlock();
3901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
3902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  void Ref() {
3904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AtomicIncrement(&ref_, 1);
3905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
3906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  void Unref() {
3908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    // DISCLAIMER: I am not sure I've implemented this correctly
3909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    // (might require some memory barrier, etc).
3910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    // But this implementation of reference counting is enough for
3911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    // the purpose of Helgrind demonstration.
3912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    AtomicIncrement(&ref_, -1);
3913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (annotate_unref_) { ANNOTATE_CONDVAR_SIGNAL(this); }
3914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (ref_ == 0) {
3915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (annotate_unref_) { ANNOTATE_CONDVAR_WAIT(this); }
3916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      delete this;
3917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
3918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
3919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  void AnnotateUnref() {
3921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    annotate_unref_ = true;
3922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
3923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  void Annotate_Race() {
3924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ANNOTATE_BENIGN_RACE(&this->data_, "needs annotation");
3925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
3926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown private:
3927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  bool annotate_unref_;
3928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Mutex mu_;
3930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  int data_; // under mu_
3931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  int ref_;  // used in atomic ops.
3933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown};
3934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test80: FP. Ref counting with atomics, no annotations. {{{1
3936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test80 {
3937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifndef NO_BARRIER
3938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
3939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBarrier barrier(4);
3940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownAtomicRefCountedClass *object = NULL;
3941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker() {
3942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  object->Ref();
3943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  barrier.Block();
3944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  object->AccessData();
3945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  object->Unref(); // All the tricky stuff is here.
3946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
3948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test80: false positive (ref counting)\n");
3949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  object = new AtomicRefCountedClass;
3950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  object->Annotate_Race();
3951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Worker, Worker, Worker, Worker);
3952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
3953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
3954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 80, FEATURE|EXCLUDE_FROM_ALL)
3956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif // NO_BARRIER
3957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test80
3958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test81: TN. Ref counting with atomics, Unref is annotated. {{{1
3961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test81 {
3962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifndef NO_BARRIER
3963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// same as test80, but Unref is annotated.
3964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
3965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBarrier barrier(4);
3966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownAtomicRefCountedClass *object = NULL;
3967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker() {
3968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  object->Ref();
3969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  barrier.Block();
3970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  object->AccessData();
3971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  object->Unref(); // All the tricky stuff is here.
3972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
3974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test81: negative (annotated ref counting)\n");
3975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  object = new AtomicRefCountedClass;
3976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  object->AnnotateUnref();
3977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Worker, Worker, Worker, Worker);
3978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
3979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
3980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
3981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 81, FEATURE|EXCLUDE_FROM_ALL)
3982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif // NO_BARRIER
3983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test81
3984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test82: Object published w/o synchronization. {{{1
3987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test82 {
3988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
3989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Writer creates a new object and makes the pointer visible to the Reader.
3990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Reader waits until the object pointer is non-null and reads the object.
3991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
3992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// On Core 2 Duo this test will sometimes (quite rarely) fail in
3993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// the CHECK below, at least if compiled with -O2.
3994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
3995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// The sequence of events::
3996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Thread1:                  Thread2:
3997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   a. arr_[...] = ...
3998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   b. foo[i]    = ...
3999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                           A. ... = foo[i]; // non NULL
4000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                           B. ... = arr_[...];
4001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
4002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//  Since there is no proper synchronization, during the even (B)
4003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//  Thread2 may not see the result of the event (a).
4004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//  On x86 and x86_64 this happens due to compiler reordering instructions.
4005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//  On other arcitectures it may also happen due to cashe inconsistency.
4006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownclass FOO {
4008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown public:
4009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  FOO() {
4010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    idx_ = rand() % 1024;
4011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    arr_[idx_] = 77777;
4012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  //   __asm__ __volatile__("" : : : "memory"); // this fixes!
4013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
4014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  static void check(volatile FOO *foo) {
4015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CHECK(foo->arr_[foo->idx_] == 77777);
4016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
4017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown private:
4018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  int idx_;
4019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  int arr_[1024];
4020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown};
4021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownconst int N = 100000;
4023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic volatile FOO *foo[N];
4024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex   MU;
4025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Writer() {
4027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  for (int i = 0; i < N; i++) {
4028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    foo[i] = new FOO;
4029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    usleep(100);
4030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
4031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Reader() {
4034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  for (int i = 0; i < N; i++) {
4035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    while (!foo[i]) {
4036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      MU.Lock();   // this is NOT a synchronization,
4037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      MU.Unlock(); // it just helps foo[i] to become visible in Reader.
4038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
4039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if ((i % 100) == 0) {
4040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      printf("rd %d\n", i);
4041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
4042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    // At this point Reader() sees the new value of foo[i]
4043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    // but in very rare cases will not see the new value of foo[i]->arr_.
4044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    // Thus this CHECK will sometimes fail.
4045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    FOO::check(foo[i]);
4046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
4047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
4050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test82: positive\n");
4051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Writer, Reader);
4052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
4053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
4054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 82, FEATURE|EXCLUDE_FROM_ALL)
4056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test82
4057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test83: Object published w/o synchronization (simple version){{{1
4060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test83 {
4061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// A simplified version of test83 (example of a wrong code).
4062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// This test, though incorrect, will almost never fail.
4063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvolatile static int *ptr = NULL;
4064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex   MU;
4065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Writer() {
4067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(100);
4068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ptr = new int(777);
4069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Reader() {
4072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  while(!ptr) {
4073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    MU.Lock(); // Not a synchronization!
4074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    MU.Unlock();
4075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
4076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(*ptr == 777);
4077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
4080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//  printf("test83: positive\n");
4081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Writer, Reader);
4082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
4083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
4084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 83, FEATURE|EXCLUDE_FROM_ALL)
4086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test83
4087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test84: TP. True race (regression test for a bug related to atomics){{{1
4090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test84 {
4091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Helgrind should not create HB arcs for the bus lock even when
4092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// --pure-happens-before=yes is used.
4093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Bug found in by Bart Van Assche, the test is taken from
4094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// valgrind file drd/tests/atomic_var.c.
4095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int s_x = 0;
4096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* s_dummy[] ensures that s_x and s_y are not in the same cache line. */
4097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic char s_dummy[512] = {0};
4098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int s_y;
4099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid thread_func_1()
4101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  s_y = 1;
4103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  AtomicIncrement(&s_x, 1);
4104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid thread_func_2()
4107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
4108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  while (AtomicIncrement(&s_x, 0) == 0)
4109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ;
4110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("y = %d\n", s_y);
4111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
4115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(s_dummy[0] == 0);  // Avoid compiler warning about 's_dummy unused'.
4116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test84: positive\n");
4117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  FAST_MODE_INIT(&s_y);
4118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_EXPECT_RACE_FOR_TSAN(&s_y, "test84: TP. true race.");
4119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(thread_func_1, thread_func_2);
4120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
4121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
4122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST(Run, 84)
4124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test84
4125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test85: Test for RunningOnValgrind(). {{{1
4128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace  test85 {
4129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
4130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
4131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test85: RunningOnValgrind() = %d\n", RunningOnValgrind());
4132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST(Run, 85)
4134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test85
4135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test86: Test for race inside DTOR: racey write to vptr. Benign. {{{1
4138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test86 {
4139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// This test shows a racey access to vptr (the pointer to vtbl).
4140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// We have class A and class B derived from A.
4141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Both classes have a virtual function f() and a virtual DTOR.
4142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// We create an object 'A *a = new B'
4143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// and pass this object from Thread1 to Thread2.
4144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Thread2 calls a->f(). This call reads a->vtpr.
4145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Thread1 deletes the object. B::~B waits untill the object can be destroyed
4146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// (flag_stopped == true) but at the very beginning of B::~B
4147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// a->vptr is written to.
4148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// So, we have a race on a->vptr.
4149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// On this particular test this race is benign, but test87 shows
4150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// how such race could harm.
4151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
4152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
4153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
4154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Threa1:                                            Thread2:
4155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 1. A a* = new B;
4156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 2. Q.Put(a); ------------\                         .
4157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                           \-------------------->   a. a = Q.Get();
4158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                                                    b. a->f();
4159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                                       /---------   c. flag_stopped = true;
4160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 3. delete a;                         /
4161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//    waits untill flag_stopped <------/
4162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//    inside the dtor
4163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
4164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownbool flag_stopped = false;
4166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex mu;
4167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownProducerConsumerQueue Q(INT_MAX);  // Used to pass A* between threads.
4169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstruct A {
4171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  A()  { printf("A::A()\n"); }
4172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  virtual ~A() { printf("A::~A()\n"); }
4173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  virtual void f() { }
4174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  uintptr_t padding[15];
4176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} __attribute__ ((aligned (64)));
4177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstruct B: A {
4179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  B()  { printf("B::B()\n"); }
4180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  virtual ~B() {
4181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    // The race is here.    <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
4182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    printf("B::~B()\n");
4183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    // wait until flag_stopped is true.
4184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    mu.LockWhen(Condition(&ArgIsTrue, &flag_stopped));
4185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    mu.Unlock();
4186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    printf("B::~B() done\n");
4187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
4188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  virtual void f() { }
4189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown};
4190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Waiter() {
4192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  A *a = new B;
4193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if (!Tsan_FastMode())
4194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ANNOTATE_EXPECT_RACE(a, "test86: expected race on a->vptr");
4195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("Waiter: B created\n");
4196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Q.Put(a);
4197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(100000); // so that Worker calls a->f() first.
4198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("Waiter: deleting B\n");
4199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  delete a;
4200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("Waiter: B deleted\n");
4201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(100000);
4202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("Waiter: done\n");
4203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker() {
4206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  A *a = reinterpret_cast<A*>(Q.Get());
4207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("Worker: got A\n");
4208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  a->f();
4209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  mu.Lock();
4211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  flag_stopped = true;
4212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  mu.Unlock();
4213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(200000);
4214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("Worker: done\n");
4215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
4218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test86: positive, race inside DTOR\n");
4219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Waiter, Worker);
4220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
4221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
4222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST(Run, 86)
4224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test86
4225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test87: Test for race inside DTOR: racey write to vptr. Harmful.{{{1
4228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test87 {
4229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// A variation of test86 where the race is harmful.
4230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Here we have class C derived from B.
4231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// We create an object 'A *a = new C' in Thread1 and pass it to Thread2.
4232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Thread2 calls a->f().
4233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Thread1 calls 'delete a'.
4234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// It first calls C::~C, then B::~B where it rewrites the vptr to point
4235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// to B::vtbl. This is a problem because Thread2 might not have called a->f()
4236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// and now it will call B::f instead of C::f.
4237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
4238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownbool flag_stopped = false;
4239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex mu;
4240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownProducerConsumerQueue Q(INT_MAX);  // Used to pass A* between threads.
4242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstruct A {
4244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  A()  { printf("A::A()\n"); }
4245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  virtual ~A() { printf("A::~A()\n"); }
4246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  virtual void f() = 0; // pure virtual.
4247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown};
4248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstruct B: A {
4250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  B()  { printf("B::B()\n"); }
4251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  virtual ~B() {
4252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    // The race is here.    <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
4253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    printf("B::~B()\n");
4254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    // wait until flag_stopped is true.
4255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    mu.LockWhen(Condition(&ArgIsTrue, &flag_stopped));
4256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    mu.Unlock();
4257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    printf("B::~B() done\n");
4258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
4259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  virtual void f() = 0; // pure virtual.
4260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown};
4261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstruct C: B {
4263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  C()  { printf("C::C()\n"); }
4264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  virtual ~C() { printf("C::~C()\n"); }
4265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  virtual void f() { }
4266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown};
4267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Waiter() {
4269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  A *a = new C;
4270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Q.Put(a);
4271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  delete a;
4272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker() {
4275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  A *a = reinterpret_cast<A*>(Q.Get());
4276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  a->f();
4277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  mu.Lock();
4279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  flag_stopped = true;
4280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_CONDVAR_SIGNAL(&mu);
4281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  mu.Unlock();
4282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
4285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test87: positive, race inside DTOR\n");
4286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Waiter, Worker);
4287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
4288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
4289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 87, FEATURE|EXCLUDE_FROM_ALL)
4291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test87
4292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test88: Test for ANNOTATE_IGNORE_WRITES_*{{{1
4295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test88 {
4296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// a recey write annotated with ANNOTATE_IGNORE_WRITES_BEGIN/END.
4297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
4298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker() {
4299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_IGNORE_WRITES_BEGIN();
4300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = 1;
4301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_IGNORE_WRITES_END();
4302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
4304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test88: negative, test for ANNOTATE_IGNORE_WRITES_*\n");
4305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThread t(Worker);
4306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
4307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = 1;
4308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
4309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB=%d\n", GLOB);
4310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST(Run, 88)
4312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test88
4313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test89: Test for debug info. {{{1
4316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test89 {
4317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Simlpe races with different objects (stack, heap globals; scalars, structs).
4318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Also, if run with --trace-level=2 this test will show a sequence of
4319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// CTOR and DTOR calls.
4320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstruct STRUCT {
4321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  int a, b, c;
4322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown};
4323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstruct A {
4325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  int a;
4326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  A() {
4327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ANNOTATE_TRACE_MEMORY(&a);
4328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    a = 1;
4329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
4330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  virtual ~A() {
4331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    a = 4;
4332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
4333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown};
4334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstruct B : A {
4336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  B()  { CHECK(a == 1); }
4337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  virtual ~B() { CHECK(a == 3); }
4338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown};
4339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstruct C : B {
4340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  C()  { a = 2; }
4341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  virtual ~C() { a = 3; }
4342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown};
4343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint            GLOBAL = 0;
4345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint           *STACK  = 0;
4346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownSTRUCT         GLOB_STRUCT;
4347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownSTRUCT        *STACK_STRUCT;
4348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownSTRUCT        *HEAP_STRUCT;
4349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker() {
4351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOBAL = 1;
4352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  *STACK = 1;
4353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB_STRUCT.b   = 1;
4354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  STACK_STRUCT->b = 1;
4355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  HEAP_STRUCT->b  = 1;
4356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
4359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  int stack_var = 0;
4360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  STACK = &stack_var;
4361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  STRUCT stack_struct;
4363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  STACK_STRUCT = &stack_struct;
4364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  HEAP_STRUCT = new STRUCT;
4366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test89: negative\n");
4368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Worker, Worker);
4369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
4370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
4371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  delete HEAP_STRUCT;
4373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  A *a = new C;
4375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("Using 'a->a':  %d\n", a->a);
4376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  delete a;
4377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 89, FEATURE|EXCLUDE_FROM_ALL)
4379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test89
4380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test90: FP. Test for a safely-published pointer (read-only). {{{1
4383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test90 {
4384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// The Publisher creates an object and safely publishes it under a mutex.
4385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Readers access the object read-only.
4386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// See also test91.
4387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
4388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Without annotations Helgrind will issue a false positive in Reader().
4389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
4390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Choices for annotations:
4391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   -- ANNOTATE_CONDVAR_SIGNAL/ANNOTATE_CONDVAR_WAIT
4392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   -- ANNOTATE_MUTEX_IS_USED_AS_CONDVAR
4393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   -- ANNOTATE_PUBLISH_MEMORY_RANGE.
4394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     *GLOB = 0;
4396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex   MU;
4397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Publisher() {
4399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
4400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = (int*)memalign(64, sizeof(int));
4401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  *GLOB = 777;
4402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if (!Tsan_PureHappensBefore() && !Tsan_FastMode())
4403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ANNOTATE_EXPECT_RACE_FOR_TSAN(GLOB, "test90. FP. This is a false positve");
4404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();
4405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(200000);
4406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Reader() {
4409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(10000);
4410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  while (true) {
4411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    MU.Lock();
4412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int *p = GLOB;
4413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    MU.Unlock();
4414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (p) {
4415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      CHECK(*p == 777);  // Race is reported here.
4416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
4417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
4418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
4419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
4422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test90: false positive (safely published pointer).\n");
4423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Publisher, Reader, Reader, Reader);
4424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
4425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
4426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\t*GLOB=%d\n", *GLOB);
4427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  free(GLOB);
4428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST(Run, 90)
4430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test90
4431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test91: FP. Test for a safely-published pointer (read-write). {{{1
4434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test91 {
4435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Similar to test90.
4436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// The Publisher creates an object and safely publishes it under a mutex MU1.
4437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Accessors get the object under MU1 and access it (read/write) under MU2.
4438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
4439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Without annotations Helgrind will issue a false positive in Accessor().
4440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
4441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     *GLOB = 0;
4443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex   MU, MU1, MU2;
4444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Publisher() {
4446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU1.Lock();
4447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = (int*)memalign(64, sizeof(int));
4448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  *GLOB = 777;
4449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if (!Tsan_PureHappensBefore() && !Tsan_FastMode())
4450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ANNOTATE_EXPECT_RACE_FOR_TSAN(GLOB, "test91. FP. This is a false positve");
4451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU1.Unlock();
4452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Accessor() {
4455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(10000);
4456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  while (true) {
4457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    MU1.Lock();
4458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int *p = GLOB;
4459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    MU1.Unlock();
4460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (p) {
4461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      MU2.Lock();
4462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      (*p)++;  // Race is reported here.
4463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      CHECK(*p >  777);
4464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      MU2.Unlock();
4465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
4466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
4467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
4468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
4471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test91: false positive (safely published pointer, read/write).\n");
4472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Publisher, Accessor, Accessor, Accessor);
4473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
4474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
4475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\t*GLOB=%d\n", *GLOB);
4476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  free(GLOB);
4477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST(Run, 91)
4479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test91
4480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test92: TN. Test for a safely-published pointer (read-write), annotated. {{{1
4483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test92 {
4484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Similar to test91, but annotated with ANNOTATE_PUBLISH_MEMORY_RANGE.
4485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
4486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
4487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Publisher:                                       Accessors:
4488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
4489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 1. MU1.Lock()
4490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 2. Create GLOB.
4491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 3. ANNOTATE_PUBLISH_...(GLOB) -------\            .
4492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 4. MU1.Unlock()                       \           .
4493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                                        \          a. MU1.Lock()
4494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                                         \         b. Get GLOB
4495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                                          \        c. MU1.Unlock()
4496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//                                           \-->    d. Access GLOB
4497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
4498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//  A happens-before arc is created between ANNOTATE_PUBLISH_MEMORY_RANGE and
4499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//  accesses to GLOB.
4500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstruct ObjType {
4502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  int arr[10];
4503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown};
4504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownObjType *GLOB = 0;
4506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex   MU, MU1, MU2;
4507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Publisher() {
4509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU1.Lock();
4510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = new ObjType;
4511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  for (int i = 0; i < 10; i++) {
4512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    GLOB->arr[i] = 777;
4513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
4514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  // This annotation should go right before the object is published.
4515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_PUBLISH_MEMORY_RANGE(GLOB, sizeof(*GLOB));
4516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU1.Unlock();
4517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Accessor(int index) {
4520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  while (true) {
4521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    MU1.Lock();
4522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ObjType *p = GLOB;
4523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    MU1.Unlock();
4524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (p) {
4525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      MU2.Lock();
4526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      p->arr[index]++;  // W/o the annotations the race will be reported here.
4527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      CHECK(p->arr[index] ==  778);
4528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      MU2.Unlock();
4529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
4530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
4531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
4532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Accessor0() { Accessor(0); }
4535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Accessor5() { Accessor(5); }
4536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Accessor9() { Accessor(9); }
4537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
4539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test92: safely published pointer, read/write, annotated.\n");
4540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Publisher, Accessor0, Accessor5, Accessor9);
4541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
4542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
4543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\t*GLOB=%d\n", GLOB->arr[0]);
4544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST(Run, 92)
4546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test92
4547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test93: TP. Test for incorrect usage of ANNOTATE_PUBLISH_MEMORY_RANGE. {{{1
4550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test93 {
4551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
4552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Reader() {
4554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(GLOB == 0);
4555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Publisher() {
4558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(10000);
4559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  // Incorrect, used after the memory has been accessed in another thread.
4560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_PUBLISH_MEMORY_RANGE(&GLOB, sizeof(GLOB));
4561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
4564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test93: positive, misuse of ANNOTATE_PUBLISH_MEMORY_RANGE\n");
4565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Reader, Publisher);
4566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
4567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
4568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB=%d\n", GLOB);
4569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 93, FEATURE|EXCLUDE_FROM_ALL)
4571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test93
4572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test94: TP. Check do_cv_signal/fake segment logic {{{1
4575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test94 {
4576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB;
4577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint COND  = 0;
4579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint COND2 = 0;
4580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex MU, MU2;
4581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownCondVar CV, CV2;
4582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Thr1() {
4584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(10000);  // Make sure the waiter blocks.
4585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = 1; // WRITE
4587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
4589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  COND = 1;
4590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CV.Signal();
4591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();
4592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Thr2() {
4594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(1000*1000); // Make sure CV2.Signal() "happens after" CV.Signal()
4595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(10000);  // Make sure the waiter blocks.
4596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU2.Lock();
4598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  COND2 = 1;
4599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CV2.Signal();
4600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU2.Unlock();
4601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Thr3() {
4603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
4604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  while(COND != 1)
4605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CV.Wait(&MU);
4606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();
4607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Thr4() {
4609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU2.Lock();
4610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  while(COND2 != 1)
4611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CV2.Wait(&MU2);
4612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU2.Unlock();
4613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = 2; // READ: no HB-relation between CV.Signal and CV2.Wait !
4614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
4616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  FAST_MODE_INIT(&GLOB);
4617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test94: TP.");
4618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test94: TP. Check do_cv_signal/fake segment logic\n");
4619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray mta(Thr1, Thr2, Thr3, Thr4);
4620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  mta.Start();
4621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  mta.Join();
4622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB=%d\n", GLOB);
4623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST(Run, 94);
4625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test94
4626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test95: TP. Check do_cv_signal/fake segment logic {{{1
4628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test95 {
4629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
4630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint COND  = 0;
4632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint COND2 = 0;
4633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex MU, MU2;
4634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownCondVar CV, CV2;
4635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Thr1() {
4637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(1000*1000); // Make sure CV2.Signal() "happens before" CV.Signal()
4638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(10000);  // Make sure the waiter blocks.
4639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = 1; // WRITE
4641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
4643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  COND = 1;
4644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CV.Signal();
4645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();
4646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Thr2() {
4648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(10000);  // Make sure the waiter blocks.
4649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU2.Lock();
4651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  COND2 = 1;
4652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CV2.Signal();
4653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU2.Unlock();
4654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Thr3() {
4656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
4657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  while(COND != 1)
4658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CV.Wait(&MU);
4659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();
4660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Thr4() {
4662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU2.Lock();
4663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  while(COND2 != 1)
4664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CV2.Wait(&MU2);
4665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU2.Unlock();
4666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = 2; // READ: no HB-relation between CV.Signal and CV2.Wait !
4667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
4669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  FAST_MODE_INIT(&GLOB);
4670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test95: TP.");
4671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test95: TP. Check do_cv_signal/fake segment logic\n");
4672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray mta(Thr1, Thr2, Thr3, Thr4);
4673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  mta.Start();
4674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  mta.Join();
4675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB=%d\n", GLOB);
4676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST(Run, 95);
4678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test95
4679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test96: TN. tricky LockSet behaviour {{{1
4681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 3 threads access the same memory with three different
4682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// locksets: {A, B}, {B, C}, {C, A}.
4683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// These locksets have empty intersection
4684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test96 {
4685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
4686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex A, B, C;
4688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Thread1() {
4690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MutexLock a(&A);
4691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MutexLock b(&B);
4692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB++;
4693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Thread2() {
4696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MutexLock b(&B);
4697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MutexLock c(&C);
4698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB++;
4699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Thread3() {
4702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MutexLock a(&A);
4703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MutexLock c(&C);
4704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB++;
4705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
4708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test96: FP. tricky LockSet behaviour\n");
4709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_TRACE_MEMORY(&GLOB);
4710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray mta(Thread1, Thread2, Thread3);
4711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  mta.Start();
4712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  mta.Join();
4713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(GLOB == 3);
4714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB=%d\n", GLOB);
4715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST(Run, 96);
4717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test96
4718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test97: This test shows false negative with --fast-mode=yes {{{1
4720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test97 {
4721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownconst int HG_CACHELINE_SIZE = 64;
4722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex MU;
4724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownconst int ARRAY_SIZE = HG_CACHELINE_SIZE * 4 / sizeof(int);
4726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint array[ARRAY_SIZE];
4727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint * GLOB = &array[ARRAY_SIZE/2];
4728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
4729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  We use sizeof(array) == 4 * HG_CACHELINE_SIZE to be sure that GLOB points
4730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  to a memory inside a CacheLineZ which is inside array's memory range
4731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
4732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Reader() {
4734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(500000);
4735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(777 == *GLOB);
4736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
4739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Reader);
4740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if (!Tsan_FastMode())
4741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ANNOTATE_EXPECT_RACE_FOR_TSAN(GLOB, "test97: TP. FN with --fast-mode=yes");
4742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test97: This test shows false negative with --fast-mode=yes\n");
4743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
4745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  *GLOB = 777;
4746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
4747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 97, FEATURE)
4750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test97
4751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test98: Synchronization via read/write (or send/recv). {{{1
4753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test98 {
4754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// The synchronization here is done by a pair of read/write calls
4755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// that create a happens-before arc. Same may be done with send/recv.
4756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Such synchronization is quite unusual in real programs
4757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// (why would one synchronizae via a file or socket?), but
4758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// quite possible in unittests where one threads runs for producer
4759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// and one for consumer.
4760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
4761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// A race detector has to create a happens-before arcs for
4762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// {read,send}->{write,recv} even if the file descriptors are different.
4763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
4764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
4765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint fd_out = -1;
4766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint fd_in  = -1;
4767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Writer() {
4769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(1000);
4770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = 1;
4771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  const char *str = "Hey there!\n";
4772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  IGNORE_RETURN_VALUE(write(fd_out, str, strlen(str) + 1));
4773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Reader() {
4776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  char buff[100];
4777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  while (read(fd_in, buff, 100) == 0)
4778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    sleep(1);
4779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("read: %s\n", buff);
4780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = 2;
4781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
4784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test98: negative, synchronization via I/O\n");
4785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  char in_name[100];
4786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  char out_name[100];
4787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  // we open two files, on for reading and one for writing,
4788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  // but the files are actually the same (symlinked).
4789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  sprintf(out_name, "/tmp/racecheck_unittest_out.%d", getpid());
4790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  fd_out = creat(out_name, O_WRONLY | S_IRWXU);
4791b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov#ifdef VGO_darwin
4792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  // symlink() is not supported on Darwin. Copy the output file name.
4793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  strcpy(in_name, out_name);
4794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else
4795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  sprintf(in_name,  "/tmp/racecheck_unittest_in.%d", getpid());
4796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  IGNORE_RETURN_VALUE(symlink(out_name, in_name));
4797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
4798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  fd_in  = open(in_name, 0, O_RDONLY);
4799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(fd_out >= 0);
4800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(fd_in  >= 0);
4801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Writer, Reader);
4802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
4803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
4804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB=%d\n", GLOB);
4805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  // cleanup
4806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  close(fd_in);
4807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  close(fd_out);
4808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  unlink(in_name);
4809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  unlink(out_name);
4810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST(Run, 98)
4812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test98
4813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test99: TP. Unit test for a bug in LockWhen*. {{{1
4816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test99 {
4817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownbool GLOB = false;
4820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex mu;
4821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void Thread1() {
4823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  for (int i = 0; i < 100; i++) {
4824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    mu.LockWhenWithTimeout(Condition(&ArgIsTrue, &GLOB), 5);
4825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    GLOB = false;
4826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    mu.Unlock();
4827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    usleep(10000);
4828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
4829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void Thread2() {
4832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  for (int i = 0; i < 100; i++) {
4833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    mu.Lock();
4834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    mu.Unlock();
4835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    usleep(10000);
4836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
4837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
4840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test99: regression test for LockWhen*\n");
4841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Thread1, Thread2);
4842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
4843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
4844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST(Run, 99);
4846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test99
4847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test100: Test for initialization bit. {{{1
4850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test100 {
4851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     G1 = 0;
4852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     G2 = 0;
4853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     G3 = 0;
4854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     G4 = 0;
4855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Creator() {
4857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  G1 = 1; CHECK(G1);
4858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  G2 = 1;
4859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  G3 = 1; CHECK(G3);
4860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  G4 = 1;
4861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker1() {
4864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(100000);
4865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(G1);
4866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(G2);
4867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  G3 = 3;
4868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  G4 = 3;
4869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker2() {
4872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
4877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test100: test for initialization bit. \n");
4878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Creator, Worker1, Worker2);
4879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_TRACE_MEMORY(&G1);
4880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_TRACE_MEMORY(&G2);
4881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_TRACE_MEMORY(&G3);
4882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_TRACE_MEMORY(&G4);
4883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
4884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
4885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 100, FEATURE|EXCLUDE_FROM_ALL)
4887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test100
4888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test101: TN. Two signals and two waits. {{{1
4891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test101 {
4892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex MU;
4893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownCondVar CV;
4894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
4895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint C1 = 0, C2 = 0;
4897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Signaller() {
4899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(100000);
4900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
4901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  C1 = 1;
4902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CV.Signal();
4903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("signal\n");
4904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();
4905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = 1;
4907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(500000);
4909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
4910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  C2 = 1;
4911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CV.Signal();
4912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("signal\n");
4913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();
4914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Waiter() {
4917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
4918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  while(!C1)
4919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CV.Wait(&MU);
4920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("wait\n");
4921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();
4922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
4924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  while(!C2)
4925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CV.Wait(&MU);
4926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("wait\n");
4927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();
4928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = 2;
4930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
4934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test101: negative\n");
4935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Waiter, Signaller);
4936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
4937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
4938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB=%d\n", GLOB);
4939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST(Run, 101)
4941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test101
4942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test102: --fast-mode=yes vs. --initialization-bit=yes {{{1
4944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test102 {
4945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownconst int HG_CACHELINE_SIZE = 64;
4946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex MU;
4948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownconst int ARRAY_SIZE = HG_CACHELINE_SIZE * 4 / sizeof(int);
4950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint array[ARRAY_SIZE + 1];
4951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint * GLOB = &array[ARRAY_SIZE/2];
4952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
4953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  We use sizeof(array) == 4 * HG_CACHELINE_SIZE to be sure that GLOB points
4954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  to a memory inside a CacheLineZ which is inside array's memory range
4955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
4956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Reader() {
4958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(200000);
4959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(777 == GLOB[0]);
4960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(400000);
4961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(777 == GLOB[1]);
4962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
4965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Reader);
4966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if (!Tsan_FastMode())
4967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ANNOTATE_EXPECT_RACE_FOR_TSAN(GLOB+0, "test102: TP. FN with --fast-mode=yes");
4968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_EXPECT_RACE_FOR_TSAN(GLOB+1, "test102: TP");
4969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test102: --fast-mode=yes vs. --initialization-bit=yes\n");
4970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
4972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB[0] = 777;
4973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(400000);
4974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB[1] = 777;
4975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
4976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 102, FEATURE)
4979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test102
4980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test103: Access different memory locations with different LockSets {{{1
4982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test103 {
4983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownconst int N_MUTEXES = 6;
4984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownconst int LOCKSET_INTERSECTION_SIZE = 3;
4985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint data[1 << LOCKSET_INTERSECTION_SIZE] = {0};
4987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex MU[N_MUTEXES];
4988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browninline int LS_to_idx (int ls) {
4990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  return (ls >> (N_MUTEXES - LOCKSET_INTERSECTION_SIZE))
4991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      & ((1 << LOCKSET_INTERSECTION_SIZE) - 1);
4992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
4993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
4994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker() {
4995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  for (int ls = 0; ls < (1 << N_MUTEXES); ls++) {
4996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (LS_to_idx(ls) == 0)
4997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      continue;
4998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for (int m = 0; m < N_MUTEXES; m++)
4999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ls & (1 << m))
5000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        MU[m].Lock();
5001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    data[LS_to_idx(ls)]++;
5003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for (int m = N_MUTEXES - 1; m >= 0; m--)
5005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ls & (1 << m))
5006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        MU[m].Unlock();
5007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
5008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
5011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test103: Access different memory locations with different LockSets\n");
5012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Worker, Worker, Worker, Worker);
5013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
5014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
5015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 103, FEATURE)
5017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test103
5018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test104: TP. Simple race (write vs write). Heap mem. {{{1
5020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test104 {
5021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     *GLOB = NULL;
5022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker() {
5023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  *GLOB = 1;
5024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Parent() {
5027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThread t(Worker);
5028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
5029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(100000);
5030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  *GLOB = 2;
5031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
5032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
5034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = (int*)memalign(64, sizeof(int));
5035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  *GLOB = 0;
5036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_EXPECT_RACE(GLOB, "test104. TP.");
5037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_TRACE_MEMORY(GLOB);
5038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test104: positive\n");
5039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Parent();
5040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB=%d\n", *GLOB);
5041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  free(GLOB);
5042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST(Run, 104);
5044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test104
5045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test105: Checks how stack grows. {{{1
5048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test105 {
5049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
5050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid F1() {
5052b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  int ar[32] __attribute__((unused));
5053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//  ANNOTATE_TRACE_MEMORY(&ar[0]);
5054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//  ANNOTATE_TRACE_MEMORY(&ar[31]);
5055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ar[0] = 1;
5056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ar[31] = 1;
5057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker() {
5060b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanov  int ar[32] __attribute__((unused));
5061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//  ANNOTATE_TRACE_MEMORY(&ar[0]);
5062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//  ANNOTATE_TRACE_MEMORY(&ar[31]);
5063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ar[0] = 1;
5064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ar[31] = 1;
5065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  F1();
5066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
5069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test105: negative\n");
5070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Worker();
5071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThread t(Worker);
5072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
5073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
5074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB=%d\n", GLOB);
5075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST(Run, 105)
5077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test105
5078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test106: TN. pthread_once. {{{1
5081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test106 {
5082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     *GLOB = NULL;
5083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic pthread_once_t once = PTHREAD_ONCE_INIT;
5084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Init() {
5085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = new int;
5086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_TRACE_MEMORY(GLOB);
5087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  *GLOB = 777;
5088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker0() {
5091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  pthread_once(&once, Init);
5092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker1() {
5094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(100000);
5095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  pthread_once(&once, Init);
5096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(*GLOB == 777);
5097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
5101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test106: negative\n");
5102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Worker0, Worker1, Worker1, Worker1);
5103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
5104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
5105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB=%d\n", *GLOB);
5106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 106, FEATURE)
5108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test106
5109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test107: Test for ANNOTATE_EXPECT_RACE {{{1
5112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test107 {
5113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
5114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
5115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test107: negative\n");
5116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_EXPECT_RACE(&GLOB, "No race in fact. Just checking the tool.");
5117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB=%d\n", GLOB);
5118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 107, FEATURE|EXCLUDE_FROM_ALL)
5120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test107
5121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test108: TN. initialization of static object. {{{1
5124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test108 {
5125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Here we have a function-level static object.
5126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Starting from gcc 4 this is therad safe,
5127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// but is is not thread safe with many other compilers.
5128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
5129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Helgrind supports this kind of initialization by
5130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// intercepting __cxa_guard_acquire/__cxa_guard_release
5131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// and ignoring all accesses between them.
5132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Helgrind also intercepts pthread_once in the same manner.
5133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownclass Foo {
5134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown public:
5135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Foo() {
5136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ANNOTATE_TRACE_MEMORY(&a_);
5137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    a_ = 42;
5138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
5139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  void Check() const { CHECK(a_ == 42); }
5140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown private:
5141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  int a_;
5142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown};
5143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownconst Foo *GetFoo() {
5145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  static const Foo *foo = new Foo();
5146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  return foo;
5147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker0() {
5149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GetFoo();
5150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker() {
5153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(200000);
5154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  const Foo *foo = GetFoo();
5155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  foo->Check();
5156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
5160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test108: negative, initialization of static object\n");
5161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Worker0, Worker, Worker);
5162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
5163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
5164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 108, FEATURE)
5166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test108
5167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test109: TN. Checking happens before between parent and child threads. {{{1
5170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test109 {
5171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Check that the detector correctly connects
5172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   pthread_create with the new thread
5173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// and
5174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   thread exit with pthread_join
5175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownconst int N = 32;
5176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int GLOB[N];
5177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker(void *a) {
5179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(10000);
5180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//  printf("--Worker : %ld %p\n", (int*)a - GLOB, (void*)pthread_self());
5181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  int *arg = (int*)a;
5182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  (*arg)++;
5183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
5186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test109: negative\n");
5187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThread *t[N];
5188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  for (int i  = 0; i < N; i++) {
5189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    t[i] = new MyThread(Worker, &GLOB[i]);
5190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
5191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  for (int i  = 0; i < N; i++) {
5192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ANNOTATE_TRACE_MEMORY(&GLOB[i]);
5193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    GLOB[i] = 1;
5194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    t[i]->Start();
5195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//    printf("--Started: %p\n", (void*)t[i]->tid());
5196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
5197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  for (int i  = 0; i < N; i++) {
5198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//    printf("--Joining: %p\n", (void*)t[i]->tid());
5199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    t[i]->Join();
5200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//    printf("--Joined : %p\n", (void*)t[i]->tid());
5201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    GLOB[i]++;
5202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
5203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  for (int i  = 0; i < N; i++) delete t[i];
5204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB=%d\n", GLOB[13]);
5206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST(Run, 109)
5208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test109
5209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test110: TP. Simple races with stack, global and heap objects. {{{1
5212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test110 {
5213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint        GLOB = 0;
5214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int STATIC;
5215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint       *STACK = 0;
5217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint       *MALLOC;
5219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint       *CALLOC;
5220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint       *REALLOC;
5221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint       *VALLOC;
5222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint       *PVALLOC;
5223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint       *MEMALIGN;
5224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownunion pi_pv_union { int* pi; void* pv; } POSIX_MEMALIGN;
5225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint       *MMAP;
5226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint       *NEW;
5228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint       *NEW_ARR;
5229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker() {
5231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB++;
5232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  STATIC++;
5233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  (*STACK)++;
5235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  (*MALLOC)++;
5237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  (*CALLOC)++;
5238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  (*REALLOC)++;
5239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  (*VALLOC)++;
5240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  (*PVALLOC)++;
5241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  (*MEMALIGN)++;
5242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  (*(POSIX_MEMALIGN.pi))++;
5243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  (*MMAP)++;
5244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  (*NEW)++;
5246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  (*NEW_ARR)++;
5247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
5249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  int x = 0;
5250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  STACK = &x;
5251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MALLOC = (int*)malloc(sizeof(int));
5253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CALLOC = (int*)calloc(1, sizeof(int));
5254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  REALLOC = (int*)realloc(NULL, sizeof(int));
5255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  VALLOC = (int*)valloc(sizeof(int));
5256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  PVALLOC = (int*)valloc(sizeof(int));  // TODO: pvalloc breaks helgrind.
5257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MEMALIGN = (int*)memalign(64, sizeof(int));
5258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(0 == posix_memalign(&POSIX_MEMALIGN.pv, 64, sizeof(int)));
5259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MMAP = (int*)mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE,
5260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    MAP_PRIVATE | MAP_ANON, -1, 0);
5261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  NEW     = new int;
5263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  NEW_ARR = new int[10];
5264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  FAST_MODE_INIT(STACK);
5267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_EXPECT_RACE(STACK, "real race on stack object");
5268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  FAST_MODE_INIT(&GLOB);
5269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_EXPECT_RACE(&GLOB, "real race on global object");
5270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  FAST_MODE_INIT(&STATIC);
5271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_EXPECT_RACE(&STATIC, "real race on a static global object");
5272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  FAST_MODE_INIT(MALLOC);
5273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_EXPECT_RACE(MALLOC, "real race on a malloc-ed object");
5274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  FAST_MODE_INIT(CALLOC);
5275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_EXPECT_RACE(CALLOC, "real race on a calloc-ed object");
5276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  FAST_MODE_INIT(REALLOC);
5277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_EXPECT_RACE(REALLOC, "real race on a realloc-ed object");
5278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  FAST_MODE_INIT(VALLOC);
5279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_EXPECT_RACE(VALLOC, "real race on a valloc-ed object");
5280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  FAST_MODE_INIT(PVALLOC);
5281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_EXPECT_RACE(PVALLOC, "real race on a pvalloc-ed object");
5282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  FAST_MODE_INIT(MEMALIGN);
5283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_EXPECT_RACE(MEMALIGN, "real race on a memalign-ed object");
5284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  FAST_MODE_INIT(POSIX_MEMALIGN.pi);
5285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_EXPECT_RACE(POSIX_MEMALIGN.pi, "real race on a posix_memalign-ed object");
5286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  FAST_MODE_INIT(MMAP);
5287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_EXPECT_RACE(MMAP, "real race on a mmap-ed object");
5288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  FAST_MODE_INIT(NEW);
5290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_EXPECT_RACE(NEW, "real race on a new-ed object");
5291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  FAST_MODE_INIT(NEW_ARR);
5292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_EXPECT_RACE(NEW_ARR, "real race on a new[]-ed object");
5293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Worker, Worker, Worker);
5295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
5296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
5297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test110: positive (race on a stack object)\n");
5298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tSTACK=%d\n", *STACK);
5299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(GLOB <= 3);
5300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(STATIC <= 3);
5301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  free(MALLOC);
5303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  free(CALLOC);
5304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  free(REALLOC);
5305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  free(VALLOC);
5306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  free(PVALLOC);
5307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  free(MEMALIGN);
5308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  free(POSIX_MEMALIGN.pv);
5309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  munmap(MMAP, sizeof(int));
5310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  delete NEW;
5311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  delete [] NEW_ARR;
5312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST(Run, 110)
5314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test110
5315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test111: TN. Unit test for a bug related to stack handling. {{{1
5318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test111 {
5319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownchar     *GLOB = 0;
5320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownbool COND = false;
5321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex mu;
5322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownconst int N = 3000;
5323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid write_to_p(char *p, int val) {
5325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  for (int i = 0; i < N; i++)
5326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    p[i] = val;
5327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic bool ArgIsTrue(bool *arg) {
5330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//  printf("ArgIsTrue: %d tid=%d\n", *arg, (int)pthread_self());
5331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  return *arg == true;
5332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid f1() {
5335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  char some_stack[N];
5336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  write_to_p(some_stack, 1);
5337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  mu.LockWhen(Condition(&ArgIsTrue, &COND));
5338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  mu.Unlock();
5339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid f2() {
5342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  char some_stack[N];
5343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  char some_more_stack[N];
5344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  write_to_p(some_stack, 2);
5345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  write_to_p(some_more_stack, 2);
5346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid f0() { f2(); }
5349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker1() {
5351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  f0();
5352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  f1();
5353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  f2();
5354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker2() {
5357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(100000);
5358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  mu.Lock();
5359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  COND = true;
5360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  mu.Unlock();
5361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
5364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test111: regression test\n");
5365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Worker1, Worker1, Worker2);
5366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//  AnnotateSetVerbosity(__FILE__, __LINE__, 3);
5367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
5368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
5369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//  AnnotateSetVerbosity(__FILE__, __LINE__, 1);
5370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 111, FEATURE)
5372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test111
5373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test112: STAB. Test for ANNOTATE_PUBLISH_MEMORY_RANGE{{{1
5375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test112 {
5376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownchar     *GLOB = 0;
5377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownconst int N = 64 * 5;
5378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex mu;
5379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownbool ready = false; // under mu
5380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint beg, end; // under mu
5381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex mu1;
5383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker() {
5385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  bool is_ready = false;
5387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  int b, e;
5388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  while (!is_ready) {
5389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    mu.Lock();
5390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    is_ready = ready;
5391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    b = beg;
5392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    e = end;
5393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    mu.Unlock();
5394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    usleep(1000);
5395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
5396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  mu1.Lock();
5398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  for (int i = b; i < e; i++) {
5399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    GLOB[i]++;
5400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
5401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  mu1.Unlock();
5402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid PublishRange(int b, int e) {
5405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Worker, Worker);
5406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ready = false; // runs before other threads
5407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
5408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_NEW_MEMORY(GLOB + b, e - b);
5410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_TRACE_MEMORY(GLOB + b);
5411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  for (int j = b; j < e; j++) {
5412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    GLOB[j] = 0;
5413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
5414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_PUBLISH_MEMORY_RANGE(GLOB + b, e - b);
5415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  // hand off
5417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  mu.Lock();
5418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ready = true;
5419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  beg = b;
5420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  end = e;
5421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  mu.Unlock();
5422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
5424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
5427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test112: stability (ANNOTATE_PUBLISH_MEMORY_RANGE)\n");
5428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = new char [N];
5429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  PublishRange(0, 10);
5431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  PublishRange(3, 5);
5432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  PublishRange(12, 13);
5434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  PublishRange(10, 14);
5435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  PublishRange(15, 17);
5437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  PublishRange(16, 18);
5438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  // do few more random publishes.
5440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  for (int i = 0; i < 20; i++) {
5441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    const int begin = rand() % N;
5442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    const int size = (rand() % (N - begin)) + 1;
5443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CHECK(size > 0);
5444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CHECK(begin + size <= N);
5445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    PublishRange(begin, begin + size);
5446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
5447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("GLOB = %d\n", (int)GLOB[0]);
5449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 112, STABILITY)
5451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test112
5452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test113: PERF. A lot of lock/unlock calls. Many locks {{{1
5455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace    test113 {
5456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownconst int kNumIter = 100000;
5457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownconst int kNumLocks = 7;
5458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex   MU[kNumLocks];
5459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
5460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test113: perf\n");
5461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  for (int i = 0; i < kNumIter; i++ ) {
5462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for (int j = 0; j < kNumLocks; j++) {
5463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (i & (1 << j)) MU[j].Lock();
5464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
5465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for (int j = kNumLocks - 1; j >= 0; j--) {
5466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (i & (1 << j)) MU[j].Unlock();
5467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
5468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
5469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST(Run, 113)
5471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test113
5472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test114: STAB. Recursive lock. {{{1
5475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace    test114 {
5476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint Bar() {
5477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  static int bar = 1;
5478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  return bar;
5479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint Foo() {
5481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  static int foo = Bar();
5482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  return foo;
5483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker() {
5485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  static int x = Foo();
5486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(x == 1);
5487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
5489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test114: stab\n");
5490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Worker, Worker);
5491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
5492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
5493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST(Run, 114)
5495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test114
5496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test115: TN. sem_open. {{{1
5499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace    test115 {
5500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint tid = 0;
5501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex mu;
5502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownconst char *kSemName = "drt-test-sem";
5503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint GLOB = 0;
5505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownsem_t *DoSemOpen() {
5507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  // TODO: there is some race report inside sem_open
5508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  // for which suppressions do not work... (???)
5509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_IGNORE_WRITES_BEGIN();
5510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  sem_t *sem = sem_open(kSemName, O_CREAT, 0600, 3);
5511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_IGNORE_WRITES_END();
5512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  return sem;
5513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker() {
5516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  mu.Lock();
5517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  int my_tid = tid++;
5518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  mu.Unlock();
5519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if (my_tid == 0) {
5521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    GLOB = 1;
5522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
5523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  // if the detector observes a happens-before arc between
5525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  // sem_open and sem_wait, it will be silent.
5526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  sem_t *sem = DoSemOpen();
5527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(100000);
5528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(sem != SEM_FAILED);
5529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(sem_wait(sem) == 0);
5530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if (my_tid > 0) {
5532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CHECK(GLOB == 1);
5533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
5534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
5537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test115: stab (sem_open())\n");
5538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  // just check that sem_open is not completely broken
5540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  sem_unlink(kSemName);
5541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  sem_t* sem = DoSemOpen();
5542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(sem != SEM_FAILED);
5543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(sem_wait(sem) == 0);
5544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  sem_unlink(kSemName);
5545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  // check that sem_open and sem_wait create a happens-before arc.
5547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Worker, Worker, Worker);
5548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
5549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
5550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  // clean up
5551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  sem_unlink(kSemName);
5552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST(Run, 115)
5554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test115
5555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test116: TN. some operations with string<> objects. {{{1
5558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test116 {
5559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker() {
5561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  string A[10], B[10], C[10];
5562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  for (int i = 0; i < 1000; i++) {
5563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for (int j = 0; j < 10; j++) {
5564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      string &a = A[j];
5565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      string &b = B[j];
5566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      string &c = C[j];
5567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      a = "sdl;fkjhasdflksj df";
5568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      b = "sdf sdf;ljsd ";
5569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      c = "'sfdf df";
5570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      c = b;
5571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      a = c;
5572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      b = a;
5573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      swap(a,b);
5574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      swap(b,c);
5575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
5576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for (int j = 0; j < 10; j++) {
5577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      string &a = A[j];
5578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      string &b = B[j];
5579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      string &c = C[j];
5580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      a.clear();
5581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      b.clear();
5582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      c.clear();
5583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
5584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
5585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
5588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test116: negative (strings)\n");
5589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Worker, Worker, Worker);
5590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
5591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
5592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 116, FEATURE|EXCLUDE_FROM_ALL)
5594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test116
5595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test117: TN. Many calls to function-scope static init. {{{1
5597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test117 {
5598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownconst int N = 50;
5599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint Foo() {
5601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(20000);
5602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  return 1;
5603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker(void *a) {
5606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  static int foo = Foo();
5607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(foo == 1);
5608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
5611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test117: negative\n");
5612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThread *t[N];
5613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  for (int i  = 0; i < N; i++) {
5614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    t[i] = new MyThread(Worker);
5615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
5616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  for (int i  = 0; i < N; i++) {
5617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    t[i]->Start();
5618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
5619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  for (int i  = 0; i < N; i++) {
5620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    t[i]->Join();
5621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
5622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  for (int i  = 0; i < N; i++) delete t[i];
5623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST(Run, 117)
5625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test117
5626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test118 PERF: One signal, multiple waits. {{{1
5630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace   test118 {
5631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
5632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownconst int kNumIter = 2000000;
5633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Signaller() {
5634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(50000);
5635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_CONDVAR_SIGNAL(&GLOB);
5636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Waiter() {
5638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  for (int i = 0; i < kNumIter; i++) {
5639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ANNOTATE_CONDVAR_WAIT(&GLOB);
5640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (i == kNumIter / 2)
5641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      usleep(100000);
5642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
5643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
5645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test118: perf\n");
5646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Signaller, Waiter, Signaller, Waiter);
5647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
5648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
5649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB=%d\n", GLOB);
5650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST(Run, 118)
5652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test118
5653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test119: TP. Testing that malloc does not introduce any HB arc. {{{1
5656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test119 {
5657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
5658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker1() {
5659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = 1;
5660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  free(malloc(123));
5661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker2() {
5663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(100000);
5664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  free(malloc(345));
5665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = 2;
5666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
5668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test119: positive (checking if malloc creates HB arcs)\n");
5669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  FAST_MODE_INIT(&GLOB);
5670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if (!(Tsan_PureHappensBefore() && kMallocUsesMutex))
5671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "true race");
5672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Worker1, Worker2);
5673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
5674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
5675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB=%d\n", GLOB);
5676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST(Run, 119)
5678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test119
5679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test120: TP. Thread1: write then read. Thread2: read. {{{1
5682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test120 {
5683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
5684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Thread1() {
5686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = 1;           // write
5687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(GLOB);        // read
5688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Thread2() {
5691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(100000);
5692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(GLOB >= 0);   // read
5693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
5696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  FAST_MODE_INIT(&GLOB);
5697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "TP (T1: write then read, T2: read)");
5698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test120: positive\n");
5699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Thread1, Thread2);
5700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = 1;
5701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
5702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
5703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB=%d\n", GLOB);
5704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST(Run, 120)
5706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test120
5707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test121: TP. Example of double-checked-locking  {{{1
5710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test121 {
5711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstruct Foo {
5712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  uintptr_t a, b[15];
5713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown} __attribute__ ((aligned (64)));
5714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Mutex mu;
5716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Foo  *foo;
5717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid InitMe() {
5719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if (!foo) {
5720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    MutexLock lock(&mu);
5721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (!foo) {
5722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ANNOTATE_EXPECT_RACE_FOR_TSAN(&foo, "test121. Double-checked locking (ptr)");
5723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      foo = new Foo;
5724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!Tsan_FastMode())
5725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        ANNOTATE_EXPECT_RACE_FOR_TSAN(&foo->a, "test121. Double-checked locking (obj)");
5726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      foo->a = 42;
5727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
5728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
5729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid UseMe() {
5732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  InitMe();
5733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(foo && foo->a == 42);
5734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker1() { UseMe(); }
5737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker2() { UseMe(); }
5738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker3() { UseMe(); }
5739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
5742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  FAST_MODE_INIT(&foo);
5743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test121: TP. Example of double-checked-locking\n");
5744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t1(Worker1, Worker2, Worker3);
5745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t1.Start();
5746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t1.Join();
5747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  delete foo;
5748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST(Run, 121)
5750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test121
5751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test122 TP: Simple test with RWLock {{{1
5753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace  test122 {
5754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     VAR1 = 0;
5755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     VAR2 = 0;
5756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownRWLock mu;
5757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid WriteWhileHoldingReaderLock(int *p) {
5759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(100000);
5760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ReaderLockScoped lock(&mu);  // Reader lock for writing. -- bug.
5761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  (*p)++;
5762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid CorrectWrite(int *p) {
5765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  WriterLockScoped lock(&mu);
5766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  (*p)++;
5767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Thread1() { WriteWhileHoldingReaderLock(&VAR1); }
5770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Thread2() { CorrectWrite(&VAR1); }
5771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Thread3() { CorrectWrite(&VAR2); }
5772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Thread4() { WriteWhileHoldingReaderLock(&VAR2); }
5773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
5776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test122: positive (rw-lock)\n");
5777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  VAR1 = 0;
5778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  VAR2 = 0;
5779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_TRACE_MEMORY(&VAR1);
5780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_TRACE_MEMORY(&VAR2);
5781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if (!Tsan_PureHappensBefore()) {
5782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ANNOTATE_EXPECT_RACE_FOR_TSAN(&VAR1, "test122. TP. ReaderLock-ed while writing");
5783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ANNOTATE_EXPECT_RACE_FOR_TSAN(&VAR2, "test122. TP. ReaderLock-ed while writing");
5784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
5785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Thread1, Thread2, Thread3, Thread4);
5786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
5787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
5788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST(Run, 122)
5790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test122
5791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test123 TP: accesses of different sizes. {{{1
5794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test123 {
5795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownunion uint_union {
5797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  uint64_t u64[1];
5798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  uint32_t u32[2];
5799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  uint16_t u16[4];
5800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  uint8_t  u8[8];
5801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown};
5802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownuint_union MEM[8];
5804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Q. Hey dude, why so many functions?
5806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// A. I need different stack traces for different accesses.
5807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Wr64_0() { MEM[0].u64[0] = 1; }
5809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Wr64_1() { MEM[1].u64[0] = 1; }
5810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Wr64_2() { MEM[2].u64[0] = 1; }
5811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Wr64_3() { MEM[3].u64[0] = 1; }
5812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Wr64_4() { MEM[4].u64[0] = 1; }
5813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Wr64_5() { MEM[5].u64[0] = 1; }
5814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Wr64_6() { MEM[6].u64[0] = 1; }
5815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Wr64_7() { MEM[7].u64[0] = 1; }
5816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Wr32_0() { MEM[0].u32[0] = 1; }
5818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Wr32_1() { MEM[1].u32[1] = 1; }
5819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Wr32_2() { MEM[2].u32[0] = 1; }
5820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Wr32_3() { MEM[3].u32[1] = 1; }
5821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Wr32_4() { MEM[4].u32[0] = 1; }
5822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Wr32_5() { MEM[5].u32[1] = 1; }
5823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Wr32_6() { MEM[6].u32[0] = 1; }
5824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Wr32_7() { MEM[7].u32[1] = 1; }
5825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Wr16_0() { MEM[0].u16[0] = 1; }
5827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Wr16_1() { MEM[1].u16[1] = 1; }
5828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Wr16_2() { MEM[2].u16[2] = 1; }
5829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Wr16_3() { MEM[3].u16[3] = 1; }
5830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Wr16_4() { MEM[4].u16[0] = 1; }
5831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Wr16_5() { MEM[5].u16[1] = 1; }
5832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Wr16_6() { MEM[6].u16[2] = 1; }
5833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Wr16_7() { MEM[7].u16[3] = 1; }
5834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Wr8_0() { MEM[0].u8[0] = 1; }
5836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Wr8_1() { MEM[1].u8[1] = 1; }
5837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Wr8_2() { MEM[2].u8[2] = 1; }
5838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Wr8_3() { MEM[3].u8[3] = 1; }
5839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Wr8_4() { MEM[4].u8[4] = 1; }
5840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Wr8_5() { MEM[5].u8[5] = 1; }
5841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Wr8_6() { MEM[6].u8[6] = 1; }
5842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Wr8_7() { MEM[7].u8[7] = 1; }
5843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid WriteAll64() {
5845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Wr64_0();
5846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Wr64_1();
5847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Wr64_2();
5848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Wr64_3();
5849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Wr64_4();
5850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Wr64_5();
5851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Wr64_6();
5852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Wr64_7();
5853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid WriteAll32() {
5856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Wr32_0();
5857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Wr32_1();
5858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Wr32_2();
5859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Wr32_3();
5860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Wr32_4();
5861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Wr32_5();
5862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Wr32_6();
5863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Wr32_7();
5864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid WriteAll16() {
5867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Wr16_0();
5868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Wr16_1();
5869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Wr16_2();
5870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Wr16_3();
5871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Wr16_4();
5872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Wr16_5();
5873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Wr16_6();
5874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Wr16_7();
5875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid WriteAll8() {
5878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Wr8_0();
5879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Wr8_1();
5880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Wr8_2();
5881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Wr8_3();
5882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Wr8_4();
5883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Wr8_5();
5884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Wr8_6();
5885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Wr8_7();
5886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid W00() { WriteAll64(); }
5889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid W01() { WriteAll64(); }
5890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid W02() { WriteAll64(); }
5891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid W10() { WriteAll32(); }
5893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid W11() { WriteAll32(); }
5894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid W12() { WriteAll32(); }
5895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid W20() { WriteAll16(); }
5897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid W21() { WriteAll16(); }
5898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid W22() { WriteAll16(); }
5899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid W30() { WriteAll8(); }
5901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid W31() { WriteAll8(); }
5902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid W32() { WriteAll8(); }
5903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef void (*F)(void);
5905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid TestTwoSizes(F f1, F f2) {
5907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  // first f1, then f2
5908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_NEW_MEMORY(&MEM, sizeof(MEM));
5909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  memset(&MEM, 0, sizeof(MEM));
5910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t1(f1, f2);
5911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t1.Start();
5912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t1.Join();
5913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  // reverse order
5914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_NEW_MEMORY(&MEM, sizeof(MEM));
5915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  memset(&MEM, 0, sizeof(MEM));
5916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t2(f2, f1);
5917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t2.Start();
5918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t2.Join();
5919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
5922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test123: positive (different sizes)\n");
5923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  TestTwoSizes(W00, W10);
5924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//  TestTwoSizes(W01, W20);
5925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//  TestTwoSizes(W02, W30);
5926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//  TestTwoSizes(W11, W21);
5927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//  TestTwoSizes(W12, W31);
5928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//  TestTwoSizes(W22, W32);
5929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 123, FEATURE|EXCLUDE_FROM_ALL)
5932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test123
5933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test124: What happens if we delete an unlocked lock? {{{1
5936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test124 {
5937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// This test does not worg with pthreads (you can't call
5938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// pthread_mutex_destroy on a locked lock).
5939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
5940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownconst int N = 1000;
5941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker() {
5942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Mutex *a_large_local_array_of_mutexes;
5943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  a_large_local_array_of_mutexes = new Mutex[N];
5944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  for (int i = 0; i < N; i++) {
5945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    a_large_local_array_of_mutexes[i].Lock();
5946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
5947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  delete []a_large_local_array_of_mutexes;
5948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = 1;
5949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
5952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test124: negative\n");
5953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Worker, Worker, Worker);
5954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
5955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
5956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB=%d\n", GLOB);
5957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 124, FEATURE|EXCLUDE_FROM_ALL)
5959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test124
5960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test125 TN: Backwards lock (annotated). {{{1
5963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test125 {
5964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// This test uses "Backwards mutex" locking protocol.
5965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// We take a *reader* lock when writing to a per-thread data
5966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// (GLOB[thread_num])  and we take a *writer* lock when we
5967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// are reading from the entire array at once.
5968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
5969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Such locking protocol is not understood by ThreadSanitizer's
5970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// hybrid state machine. So, you either have to use a pure-happens-before
5971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// detector ("tsan --pure-happens-before") or apply pure happens-before mode
5972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// to this particular lock by using ANNOTATE_MUTEX_IS_USED_AS_CONDVAR(&mu).
5973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownconst int n_threads = 3;
5975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownRWLock   mu;
5976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB[n_threads];
5977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint adder_num; // updated atomically.
5979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Adder() {
5981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  int my_num = AtomicIncrement(&adder_num, 1);
5982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ReaderLockScoped lock(&mu);
5984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB[my_num]++;
5985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Aggregator() {
5988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  int sum = 0;
5989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  {
5990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    WriterLockScoped lock(&mu);
5991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for (int i = 0; i < n_threads; i++) {
5992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      sum += GLOB[i];
5993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
5994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
5995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("sum=%d\n", sum);
5996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
5997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
5998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
5999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test125: negative\n");
6000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_MUTEX_IS_USED_AS_CONDVAR(&mu);
6002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  // run Adders, then Aggregator
6004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  {
6005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    MyThreadArray t(Adder, Adder, Adder, Aggregator);
6006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    t.Start();
6007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    t.Join();
6008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
6009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  // Run Aggregator first.
6011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  adder_num = 0;
6012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  {
6013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    MyThreadArray t(Aggregator, Adder, Adder, Adder);
6014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    t.Start();
6015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    t.Join();
6016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
6017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST(Run, 125)
6020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test125
6021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test126 TN: test for BlockingCounter {{{1
6023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace  test126 {
6024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBlockingCounter *blocking_counter;
6025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
6026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker() {
6027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(blocking_counter);
6028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(GLOB == 0);
6029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  blocking_counter->DecrementCount();
6030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
6032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test126: negative\n");
6033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Worker, Worker, Worker);
6034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  blocking_counter = new BlockingCounter(3);
6035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
6036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  blocking_counter->Wait();
6037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = 1;
6038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
6039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB=%d\n", GLOB);
6040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST(Run, 126)
6042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test126
6043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test127. Bad code: unlocking a mutex locked by another thread. {{{1
6046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test127 {
6047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex mu;
6048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Thread1() {
6049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  mu.Lock();
6050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Thread2() {
6052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(100000);
6053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  mu.Unlock();
6054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
6056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test127: unlocking a mutex locked by another thread.\n");
6057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Thread1, Thread2);
6058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
6059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
6060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST(Run, 127)
6062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test127
6063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test128. Suppressed code in concurrent accesses {{{1
6065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Please use --suppressions=unittest.supp flag when running this test.
6066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test128 {
6067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex mu;
6068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint GLOB = 0;
6069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker() {
6070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(100000);
6071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  mu.Lock();
6072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB++;
6073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  mu.Unlock();
6074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid ThisFunctionShouldBeSuppressed() {
6076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB++;
6077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
6079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test128: Suppressed code in concurrent accesses.\n");
6080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Worker, ThisFunctionShouldBeSuppressed);
6081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
6082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
6083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 128, FEATURE | EXCLUDE_FROM_ALL)
6085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test128
6086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test129: TN. Synchronization via ReaderLockWhen(). {{{1
6088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test129 {
6089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
6090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex   MU;
6091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownbool WeirdCondition(int* param) {
6092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  *param = GLOB;  // a write into Waiter's memory
6093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  return GLOB > 0;
6094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Waiter() {
6096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  int param = 0;
6097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.ReaderLockWhen(Condition(WeirdCondition, &param));
6098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.ReaderUnlock();
6099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(GLOB > 0);
6100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(param > 0);
6101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Waker() {
6103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(100000);  // Make sure the waiter blocks.
6104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock();
6105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB++;
6106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Unlock();     // calls ANNOTATE_CONDVAR_SIGNAL;
6107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
6109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test129: Synchronization via ReaderLockWhen()\n");
6110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThread mt(Waiter, NULL, "Waiter Thread");
6111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  mt.Start();
6112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Waker();
6113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  mt.Join();
6114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB=%d\n", GLOB);
6115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 129, FEATURE);
6117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test129
6118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test130: TN. Per-thread. {{{1
6120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test130 {
6121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifndef NO_TLS
6122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// This test verifies that the race detector handles
6123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// thread-local storage (TLS) correctly.
6124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// As of 09-03-30 ThreadSanitizer has a bug:
6125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   - Thread1 starts
6126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   - Thread1 touches per_thread_global
6127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   - Thread1 ends
6128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   - Thread2 starts (and there is no happens-before relation between it and
6129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   Thread1)
6130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   - Thread2 touches per_thread_global
6131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// It may happen so that Thread2 will have per_thread_global in the same address
6132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// as Thread1. Since there is no happens-before relation between threads,
6133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// ThreadSanitizer reports a race.
6134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
6135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test131 does the same for stack.
6136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic __thread int per_thread_global[10] = {0};
6138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid RealWorker() {  // Touch per_thread_global.
6140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  per_thread_global[1]++;
6141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  errno++;
6142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker() {  // Spawn few threads that touch per_thread_global.
6145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(RealWorker, RealWorker);
6146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
6147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
6148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker0() { sleep(0); Worker(); }
6150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker1() { sleep(1); Worker(); }
6151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker2() { sleep(2); Worker(); }
6152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker3() { sleep(3); Worker(); }
6153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
6155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test130: Per-thread\n");
6156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t1(Worker0, Worker1, Worker2, Worker3);
6157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t1.Start();
6158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t1.Join();
6159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tper_thread_global=%d\n", per_thread_global[1]);
6160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST(Run, 130)
6162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif // NO_TLS
6163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test130
6164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test131: TN. Stack. {{{1
6167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test131 {
6168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Same as test130, but for stack.
6169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid RealWorker() {  // Touch stack.
6171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  int stack_var = 0;
6172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  stack_var++;
6173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker() {  // Spawn few threads that touch stack.
6176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(RealWorker, RealWorker);
6177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
6178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
6179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker0() { sleep(0); Worker(); }
6181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker1() { sleep(1); Worker(); }
6182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker2() { sleep(2); Worker(); }
6183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker3() { sleep(3); Worker(); }
6184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
6186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test131: stack\n");
6187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Worker0, Worker1, Worker2, Worker3);
6188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
6189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
6190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST(Run, 131)
6192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test131
6193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test132: TP. Simple race (write vs write). Works in fast-mode. {{{1
6196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test132 {
6197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
6198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker() { GLOB = 1; }
6199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run1() {
6201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  FAST_MODE_INIT(&GLOB);
6202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test132");
6203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test132: positive; &GLOB=%p\n", &GLOB);
6204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_TRACE_MEMORY(&GLOB);
6205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = 7;
6206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Worker, Worker);
6207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
6208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
6209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
6212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Run1();
6213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST(Run, 132);
6215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test132
6216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test133: TP. Simple race (write vs write). Works in fast mode. {{{1
6219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test133 {
6220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Same as test132, but everything is run from a separate thread spawned from
6221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// the main thread.
6222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
6223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker() { GLOB = 1; }
6224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run1() {
6226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  FAST_MODE_INIT(&GLOB);
6227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "test133");
6228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test133: positive; &GLOB=%p\n", &GLOB);
6229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_TRACE_MEMORY(&GLOB);
6230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = 7;
6231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Worker, Worker);
6232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
6233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
6234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
6236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThread t(Run1);
6237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
6238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
6239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST(Run, 133);
6241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test133
6242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test134 TN. Swap. Variant of test79. {{{1
6245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test134 {
6246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if 0
6247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef __gnu_cxx::hash_map<int, int> map_t;
6248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else
6249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef std::map<int, int> map_t;
6250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
6251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownmap_t   map;
6252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex   mu;
6253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Here we use swap to pass map between threads.
6254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// The synchronization is correct, but w/o the annotation
6255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// any hybrid detector will complain.
6256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Swap is very unfriendly to the lock-set (and hybrid) race detectors.
6258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Since tmp is destructed outside the mutex, we need to have a happens-before
6259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// arc between any prior access to map and here.
6260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Since the internals of tmp are created ouside the mutex and are passed to
6261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// other thread, we need to have a h-b arc between here and any future access.
6262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// These arcs can be created by HAPPENS_{BEFORE,AFTER} annotations, but it is
6263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// much simpler to apply pure-happens-before mode to the mutex mu.
6264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Swapper() {
6265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  map_t tmp;
6266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MutexLock lock(&mu);
6267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_HAPPENS_AFTER(&map);
6268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  // We swap the new empty map 'tmp' with 'map'.
6269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  map.swap(tmp);
6270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_HAPPENS_BEFORE(&map);
6271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  // tmp (which is the old version of map) is destroyed here.
6272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker() {
6275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MutexLock lock(&mu);
6276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_HAPPENS_AFTER(&map);
6277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  map[1]++;
6278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_HAPPENS_BEFORE(&map);
6279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
6282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test134: negative (swap)\n");
6283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  // ********************** Shorter way: ***********************
6284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  // ANNOTATE_MUTEX_IS_USED_AS_CONDVAR(&mu);
6285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Worker, Worker, Swapper, Worker, Worker);
6286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
6287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
6288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST(Run, 134)
6290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test134
6291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test135 TN. Swap. Variant of test79. {{{1
6293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test135 {
6294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid SubWorker() {
6296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  const long SIZE = 65536;
6297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  for (int i = 0; i < 32; i++) {
6298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int *ptr = (int*)mmap(NULL, SIZE, PROT_READ | PROT_WRITE,
6299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          MAP_PRIVATE | MAP_ANON, -1, 0);
6300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    *ptr = 42;
6301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    munmap(ptr, SIZE);
6302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
6303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker() {
6306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(SubWorker, SubWorker, SubWorker, SubWorker);
6307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
6308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
6309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
6312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test135: negative (mmap)\n");
6313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Worker, Worker, Worker, Worker);
6314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
6315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
6316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST(Run, 135)
6318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test135
6319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test136. Unlock twice. {{{1
6321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test136 {
6322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
6323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test136: unlock twice\n");
6324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  pthread_mutexattr_t attr;
6325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(0 == pthread_mutexattr_init(&attr));
6326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(0 == pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK));
6327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  pthread_mutex_t mu;
6329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(0 == pthread_mutex_init(&mu, &attr));
6330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(0 == pthread_mutex_lock(&mu));
6331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(0 == pthread_mutex_unlock(&mu));
6332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  int ret_unlock = pthread_mutex_unlock(&mu);  // unlocking twice.
6333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  int ret_destroy = pthread_mutex_destroy(&mu);
6334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("  pthread_mutex_unlock returned %d\n", ret_unlock);
6335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("  pthread_mutex_destroy returned %d\n", ret_destroy);
6336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST(Run, 136)
6340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test136
6341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test137 TP. Races on stack variables. {{{1
6343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test137 {
6344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint GLOB = 0;
6345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownProducerConsumerQueue q(10);
6346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker() {
6348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  int stack;
6349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  int *tmp = (int*)q.Get();
6350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  (*tmp)++;
6351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  int *racey = &stack;
6352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  q.Put(racey);
6353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  (*racey)++;
6354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(150000);
6355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  // We may miss the races if we sleep less due to die_memory events...
6356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
6359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  int tmp = 0;
6360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test137: TP. Races on stack variables.\n");
6361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  q.Put(&tmp);
6362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Worker, Worker, Worker, Worker);
6363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
6364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
6365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  q.Get();
6366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 137, FEATURE | EXCLUDE_FROM_ALL)
6369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test137
6370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test138 FN. Two closures hit the same thread in ThreadPool. {{{1
6372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test138 {
6373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint GLOB = 0;
6374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker() {
6376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(100000);
6377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB++;
6378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
6381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  FAST_MODE_INIT(&GLOB);
6382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test138: FN. Two closures hit the same thread in ThreadPool.\n");
6383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  // When using thread pools, two concurrent callbacks might be scheduled
6385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  // onto the same executor thread. As a result, unnecessary happens-before
6386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  // relation may be introduced between callbacks.
6387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  // If we set the number of executor threads to 1, any known data
6388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  // race detector will be silent. However, the same situation may happen
6389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  // with any number of executor threads (with some probability).
6390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ThreadPool tp(1);
6391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  tp.StartWorkers();
6392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  tp.Add(NewCallback(Worker));
6393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  tp.Add(NewCallback(Worker));
6394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 138, FEATURE)
6397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test138
6398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test139: FN. A true race hidden by reference counting annotation. {{{1
6400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test139 {
6401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint GLOB = 0;
6402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownRefCountedClass *obj;
6403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker1() {
6405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB++;  // First access.
6406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  obj->Unref();
6407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker2() {
6410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(100000);
6411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  obj->Unref();
6412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB++;  // Second access.
6413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
6416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  FAST_MODE_INIT(&GLOB);
6417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test139: FN. A true race hidden by reference counting annotation.\n");
6418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  obj = new RefCountedClass;
6420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  obj->AnnotateUnref();
6421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  obj->Ref();
6422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  obj->Ref();
6423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray mt(Worker1, Worker2);
6424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  mt.Start();
6425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  mt.Join();
6426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 139, FEATURE)
6429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test139
6430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test140 TN. Swap. Variant of test79 and test134. {{{1
6432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test140 {
6433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if 0
6434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef __gnu_cxx::hash_map<int, int> Container;
6435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#else
6436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Browntypedef std::map<int,int>             Container;
6437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif
6438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex mu;
6439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Container container;
6440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Here we use swap to pass a Container between threads.
6442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// The synchronization is correct, but w/o the annotation
6443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// any hybrid detector will complain.
6444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
6445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Unlike the test134, we try to have a minimal set of annotations
6446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// so that extra h-b arcs do not hide other races.
6447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Swap is very unfriendly to the lock-set (and hybrid) race detectors.
6449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Since tmp is destructed outside the mutex, we need to have a happens-before
6450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// arc between any prior access to map and here.
6451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Since the internals of tmp are created ouside the mutex and are passed to
6452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// other thread, we need to have a h-b arc between here and any future access.
6453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
6454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// We want to be able to annotate swapper so that we don't need to annotate
6455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// anything else.
6456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Swapper() {
6457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Container tmp;
6458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  tmp[1] = tmp[2] = tmp[3] = 0;
6459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  {
6460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    MutexLock lock(&mu);
6461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    container.swap(tmp);
6462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    // we are unpublishing the old container.
6463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ANNOTATE_UNPUBLISH_MEMORY_RANGE(&container, sizeof(container));
6464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    // we are publishing the new container.
6465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ANNOTATE_PUBLISH_MEMORY_RANGE(&container, sizeof(container));
6466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
6467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  tmp[1]++;
6468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  tmp[2]++;
6469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  // tmp (which is the old version of container) is destroyed here.
6470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker() {
6473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MutexLock lock(&mu);
6474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  container[1]++;
6475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  int *v = &container[2];
6476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  for (int i = 0; i < 10; i++) {
6477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    // if uncommented, this will break ANNOTATE_UNPUBLISH_MEMORY_RANGE():
6478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    // ANNOTATE_HAPPENS_BEFORE(v);
6479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (i % 3) {
6480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      (*v)++;
6481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
6482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
6483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
6486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test140: negative (swap) %p\n", &container);
6487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Worker, Worker, Swapper, Worker, Worker);
6488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
6489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
6490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST(Run, 140)
6492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test140
6493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test141 FP. unlink/fopen, rmdir/opendir. {{{1
6495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test141 {
6496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint GLOB1 = 0,
6497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    GLOB2 = 0;
6498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownchar *dir_name = NULL,
6499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     *filename = NULL;
6500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Waker1() {
6502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(100000);
6503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB1 = 1;  // Write
6504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  // unlink deletes a file 'filename'
6505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  // which exits spin-loop in Waiter1().
6506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("  Deleting file...\n");
6507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(unlink(filename) == 0);
6508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Waiter1() {
6511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  FILE *tmp;
6512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  while ((tmp = fopen(filename, "r")) != NULL) {
6513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    fclose(tmp);
6514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    usleep(10000);
6515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
6516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("  ...file has been deleted\n");
6517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB1 = 2;  // Write
6518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Waker2() {
6521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(100000);
6522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB2 = 1;  // Write
6523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  // rmdir deletes a directory 'dir_name'
6524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  // which exit spin-loop in Waker().
6525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("  Deleting directory...\n");
6526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(rmdir(dir_name) == 0);
6527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Waiter2() {
6530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  DIR *tmp;
6531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  while ((tmp = opendir(dir_name)) != NULL) {
6532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    closedir(tmp);
6533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    usleep(10000);
6534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
6535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("  ...directory has been deleted\n");
6536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB2 = 2;
6537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
6540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  FAST_MODE_INIT(&GLOB1);
6541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  FAST_MODE_INIT(&GLOB2);
6542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test141: FP. unlink/fopen, rmdir/opendir.\n");
6543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  dir_name = strdup("/tmp/tsan-XXXXXX");
6545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  IGNORE_RETURN_VALUE(mkdtemp(dir_name));
6546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  filename = strdup((std::string() + dir_name + "/XXXXXX").c_str());
6548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  const int fd = mkstemp(filename);
6549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(fd >= 0);
6550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  close(fd);
6551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray mta1(Waker1, Waiter1);
6553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  mta1.Start();
6554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  mta1.Join();
6555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray mta2(Waker2, Waiter2);
6557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  mta2.Start();
6558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  mta2.Join();
6559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  free(filename);
6560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  filename = 0;
6561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  free(dir_name);
6562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  dir_name = 0;
6563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST(Run, 141)
6565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test141
6566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Simple FIFO queue annotated with PCQ annotations. {{{1
6569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownclass FifoMessageQueue {
6570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown public:
6571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  FifoMessageQueue() { ANNOTATE_PCQ_CREATE(this); }
6572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ~FifoMessageQueue() { ANNOTATE_PCQ_DESTROY(this); }
6573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  // Send a message. 'message' should be positive.
6574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  void Put(int message) {
6575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    CHECK(message);
6576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    MutexLock lock(&mu_);
6577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ANNOTATE_PCQ_PUT(this);
6578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    q_.push(message);
6579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
6580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  // Return the message from the queue and pop it
6581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  // or return 0 if there are no messages.
6582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  int Get() {
6583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    MutexLock lock(&mu_);
6584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (q_.empty()) return 0;
6585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int res = q_.front();
6586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    q_.pop();
6587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ANNOTATE_PCQ_GET(this);
6588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    return res;
6589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
6590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown private:
6591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Mutex mu_;
6592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  queue<int> q_;
6593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown};
6594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test142: TN. Check PCQ_* annotations. {{{1
6597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test142 {
6598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Putter writes to array[i] and sends a message 'i'.
6599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Getters receive messages and read array[message].
6600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// PCQ_* annotations calm down the hybrid detectors.
6601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownconst int N = 1000;
6603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint array[N+1];
6604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownFifoMessageQueue q;
6606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Putter() {
6608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  for (int i = 1; i <= N; i++) {
6609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    array[i] = i*i;
6610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    q.Put(i);
6611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    usleep(1000);
6612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
6613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Getter() {
6616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  int non_zero_received  = 0;
6617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  for (int i = 1; i <= N; i++) {
6618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    int res = q.Get();
6619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (res > 0) {
6620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      CHECK(array[res] = res * res);
6621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      non_zero_received++;
6622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
6623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    usleep(1000);
6624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
6625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("T=%zd: non_zero_received=%d\n",
6626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         (size_t)pthread_self(), non_zero_received);
6627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
6630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test142: tests PCQ annotations\n");
6631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Putter, Getter, Getter);
6632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
6633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
6634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST(Run, 142)
6636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test142
6637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test143: TP. Check PCQ_* annotations. {{{1
6640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test143 {
6641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// True positive.
6642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// We have a race on GLOB between Putter and one of the Getters.
6643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Pure h-b will not see it.
6644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// If FifoMessageQueue was annotated using HAPPENS_BEFORE/AFTER, the race would
6645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// be missed too.
6646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// PCQ_* annotations do not hide this race.
6647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
6648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownFifoMessageQueue q;
6650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Putter() {
6652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = 1;
6653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  q.Put(1);
6654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Getter() {
6657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(10000);
6658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  q.Get();
6659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(GLOB == 1);  // Race here
6660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
6663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  q.Put(1);
6664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if (!Tsan_PureHappensBefore()) {
6665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ANNOTATE_EXPECT_RACE_FOR_TSAN(&GLOB, "true races");
6666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
6667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test143: tests PCQ annotations (true positive)\n");
6668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Putter, Getter, Getter);
6669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
6670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
6671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST(Run, 143);
6673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test143
6674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test300: {{{1
6679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test300 {
6680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
6681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
6682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 300, RACE_DEMO)
6684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test300
6685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test301: Simple race.  {{{1
6687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test301 {
6688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex mu1;  // This Mutex guards var.
6689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex mu2;  // This Mutex is not related to var.
6690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint   var;  // GUARDED_BY(mu1)
6691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Thread1() {  // Runs in thread named 'test-thread-1'.
6693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MutexLock lock(&mu1);  // Correct Mutex.
6694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  var = 1;
6695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Thread2() {  // Runs in thread named 'test-thread-2'.
6698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MutexLock lock(&mu2);  // Wrong Mutex.
6699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  var = 2;
6700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
6703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  var = 0;
6704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test301: simple race.\n");
6705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThread t1(Thread1, NULL, "test-thread-1");
6706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThread t2(Thread2, NULL, "test-thread-2");
6707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t1.Start();
6708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t2.Start();
6709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t1.Join();
6710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t2.Join();
6711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 301, RACE_DEMO)
6713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test301
6714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test302: Complex race which happens at least twice.  {{{1
6716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test302 {
6717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// In this test we have many different accesses to GLOB and only one access
6718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// is not synchronized properly.
6719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
6720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex MU1;
6722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex MU2;
6723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker() {
6724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  for(int i = 0; i < 100; i++) {
6725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    switch(i % 4) {
6726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 0:
6727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        // This read is protected correctly.
6728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        MU1.Lock(); CHECK(GLOB >= 0); MU1.Unlock();
6729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
6730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 1:
6731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        // Here we used the wrong lock! The reason of the race is here.
6732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        MU2.Lock(); CHECK(GLOB >= 0); MU2.Unlock();
6733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
6734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 2:
6735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        // This read is protected correctly.
6736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        MU1.Lock(); CHECK(GLOB >= 0); MU1.Unlock();
6737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
6738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      case 3:
6739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        // This write is protected correctly.
6740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        MU1.Lock(); GLOB++; MU1.Unlock();
6741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        break;
6742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
6743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    // sleep a bit so that the threads interleave
6744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    // and the race happens at least twice.
6745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    usleep(100);
6746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
6747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
6750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test302: Complex race that happens twice.\n");
6751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThread t1(Worker), t2(Worker);
6752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t1.Start();
6753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t2.Start();
6754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t1.Join();   t2.Join();
6755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 302, RACE_DEMO)
6757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test302
6758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test303: Need to trace the memory to understand the report. {{{1
6761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test303 {
6762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
6763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex MU;
6765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker1() { CHECK(GLOB >= 0); }
6766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker2() { MU.Lock(); GLOB=1;  MU.Unlock();}
6767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
6769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test303: a race that needs annotations.\n");
6770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_TRACE_MEMORY(&GLOB);
6771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Worker1, Worker2);
6772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
6773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
6774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 303, RACE_DEMO)
6776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test303
6777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test304: Can not trace the memory, since it is a library object. {{{1
6781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test304 {
6782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstring *STR;
6783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex   MU;
6784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker1() {
6786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  sleep(0);
6787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_CONDVAR_SIGNAL((void*)0xDEADBEAF);
6788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock(); CHECK(STR->length() >= 4); MU.Unlock();
6789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker2() {
6791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  sleep(1);
6792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_CONDVAR_SIGNAL((void*)0xDEADBEAF);
6793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(STR->length() >= 4); // Unprotected!
6794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker3() {
6796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  sleep(2);
6797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_CONDVAR_SIGNAL((void*)0xDEADBEAF);
6798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock(); CHECK(STR->length() >= 4); MU.Unlock();
6799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker4() {
6801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  sleep(3);
6802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_CONDVAR_SIGNAL((void*)0xDEADBEAF);
6803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MU.Lock(); *STR += " + a very very long string"; MU.Unlock();
6804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
6807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  STR = new string ("The String");
6808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test304: a race where memory tracing does not work.\n");
6809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Worker1, Worker2, Worker3, Worker4);
6810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
6811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
6812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("%s\n", STR->c_str());
6814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  delete STR;
6815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 304, RACE_DEMO)
6817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test304
6818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test305: A bit more tricky: two locks used inconsistenly. {{{1
6822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test305 {
6823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
6824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// In this test GLOB is protected by MU1 and MU2, but inconsistently.
6826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// The TRACES observed by helgrind are:
6827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// TRACE[1]: Access{T2/S2 wr} -> new State{Mod; #LS=2; #SS=1; T2/S2}
6828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// TRACE[2]: Access{T4/S9 wr} -> new State{Mod; #LS=1; #SS=2; T2/S2, T4/S9}
6829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// TRACE[3]: Access{T5/S13 wr} -> new State{Mod; #LS=1; #SS=3; T2/S2, T4/S9, T5/S13}
6830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// TRACE[4]: Access{T6/S19 wr} -> new State{Mod; #LS=0; #SS=4; T2/S2, T4/S9, T5/S13, T6/S19}
6831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
6832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// The guilty access is either Worker2() or Worker4(), depending on
6833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// which mutex is supposed to protect GLOB.
6834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex MU1;
6835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex MU2;
6836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker1() { MU1.Lock(); MU2.Lock(); GLOB=1; MU2.Unlock(); MU1.Unlock(); }
6837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker2() { MU1.Lock();             GLOB=2;               MU1.Unlock(); }
6838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker3() { MU1.Lock(); MU2.Lock(); GLOB=3; MU2.Unlock(); MU1.Unlock(); }
6839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker4() {             MU2.Lock(); GLOB=4; MU2.Unlock();               }
6840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
6842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_TRACE_MEMORY(&GLOB);
6843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test305: simple race.\n");
6844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThread t1(Worker1), t2(Worker2), t3(Worker3), t4(Worker4);
6845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t1.Start(); usleep(100);
6846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t2.Start(); usleep(100);
6847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t3.Start(); usleep(100);
6848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t4.Start(); usleep(100);
6849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t1.Join(); t2.Join(); t3.Join(); t4.Join();
6850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 305, RACE_DEMO)
6852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test305
6853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test306: Two locks are used to protect a var.  {{{1
6855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test306 {
6856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
6857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Thread1 and Thread2 access the var under two locks.
6858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Thread3 uses no locks.
6859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex MU1;
6861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex MU2;
6862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker1() { MU1.Lock(); MU2.Lock(); GLOB=1; MU2.Unlock(); MU1.Unlock(); }
6863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker2() { MU1.Lock(); MU2.Lock(); GLOB=3; MU2.Unlock(); MU1.Unlock(); }
6864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker3() {                         GLOB=4;               }
6865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
6867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_TRACE_MEMORY(&GLOB);
6868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test306: simple race.\n");
6869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThread t1(Worker1), t2(Worker2), t3(Worker3);
6870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t1.Start(); usleep(100);
6871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t2.Start(); usleep(100);
6872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t3.Start(); usleep(100);
6873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t1.Join(); t2.Join(); t3.Join();
6874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 306, RACE_DEMO)
6876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test306
6877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test307: Simple race, code with control flow  {{{1
6879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test307 {
6880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     *GLOB = 0;
6881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvolatile /*to fake the compiler*/ bool some_condition = true;
6882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid SomeFunc() { }
6885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint FunctionWithControlFlow() {
6887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  int unrelated_stuff = 0;
6888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  unrelated_stuff++;
6889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  SomeFunc();                // "--keep-history=1" will point somewhere here.
6890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if (some_condition) {      // Or here
6891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    if (some_condition) {
6892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      unrelated_stuff++;     // Or here.
6893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      unrelated_stuff++;
6894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      (*GLOB)++;             // "--keep-history=2" will point here (experimental).
6895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
6896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
6897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(100000);
6898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  return unrelated_stuff;
6899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker1() { FunctionWithControlFlow(); }
6902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker2() { Worker1(); }
6903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker3() { Worker2(); }
6904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker4() { Worker3(); }
6905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
6907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB = new int;
6908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  *GLOB = 1;
6909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test307: simple race, code with control flow\n");
6910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t1(Worker1, Worker2, Worker3, Worker4);
6911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t1.Start();
6912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t1.Join();
6913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 307, RACE_DEMO)
6915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test307
6916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test308: Example of double-checked-locking  {{{1
6918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test308 {
6919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstruct Foo {
6920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  int a;
6921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown};
6922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int   is_inited = 0;
6924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Mutex lock;
6925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Foo  *foo;
6926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid InitMe() {
6928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if (!is_inited) {
6929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    lock.Lock();
6930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!is_inited) {
6931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        foo = new Foo;
6932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        foo->a = 42;
6933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        is_inited = 1;
6934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
6935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    lock.Unlock();
6936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
6937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid UseMe() {
6940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  InitMe();
6941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(foo && foo->a == 42);
6942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker1() { UseMe(); }
6945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker2() { UseMe(); }
6946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker3() { UseMe(); }
6947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
6950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_TRACE_MEMORY(&is_inited);
6951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test308: Example of double-checked-locking\n");
6952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t1(Worker1, Worker2, Worker3);
6953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t1.Start();
6954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t1.Join();
6955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 308, RACE_DEMO)
6957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test308
6958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test309: Simple race on an STL object.  {{{1
6960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test309 {
6961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstring  GLOB;
6962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker1() {
6964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB="Thread1";
6965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker2() {
6967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(100000);
6968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  GLOB="Booooooooooo";
6969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
6972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test309: simple race on an STL object.\n");
6973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThread t1(Worker1), t2(Worker2);
6974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t1.Start();
6975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t2.Start();
6976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t1.Join();   t2.Join();
6977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 309, RACE_DEMO)
6979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test309
6980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test310: One more simple race.  {{{1
6982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test310 {
6983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     *PTR = NULL;  // GUARDED_BY(mu1)
6984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex mu1;  // Protects PTR.
6986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex mu2;  // Unrelated to PTR.
6987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex mu3;  // Unrelated to PTR.
6988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Writer1() {
6990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MutexLock lock3(&mu3);  // This lock is unrelated to PTR.
6991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MutexLock lock1(&mu1);  // Protect PTR.
6992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  *PTR = 1;
6993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
6994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Writer2() {
6996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MutexLock lock2(&mu2);  // This lock is unrelated to PTR.
6997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MutexLock lock1(&mu1);  // Protect PTR.
6998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  int some_unrelated_stuff = 0;
6999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if (some_unrelated_stuff == 0)
7000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    some_unrelated_stuff++;
7001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  *PTR = 2;
7002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Reader() {
7006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MutexLock lock2(&mu2);  // Oh, gosh, this is a wrong mutex!
7007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(*PTR <= 2);
7008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Some functions to make the stack trace non-trivial.
7011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid DoWrite1() { Writer1();  }
7012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Thread1()  { DoWrite1(); }
7013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid DoWrite2() { Writer2();  }
7015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Thread2()  { DoWrite2(); }
7016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid DoRead()  { Reader();  }
7018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Thread3() { DoRead();  }
7019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
7021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test310: simple race.\n");
7022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  PTR = new int;
7023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_TRACE_MEMORY(PTR);
7024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  *PTR = 0;
7025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThread t1(Thread1, NULL, "writer1"),
7026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           t2(Thread2, NULL, "writer2"),
7027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           t3(Thread3, NULL, "buggy reader");
7028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t1.Start();
7029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t2.Start();
7030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(100000);  // Let the writers go first.
7031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t3.Start();
7032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t1.Join();
7034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t2.Join();
7035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t3.Join();
7036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 310, RACE_DEMO)
7038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test310
7039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test311: Yet another simple race.  {{{1
7041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test311 {
7042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     *PTR = NULL;  // GUARDED_BY(mu1)
7043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex mu1;  // Protects PTR.
7045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex mu2;  // Unrelated to PTR.
7046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex mu3;  // Unrelated to PTR.
7047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid GoodWriter1() {
7049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MutexLock lock3(&mu3);  // This lock is unrelated to PTR.
7050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MutexLock lock1(&mu1);  // Protect PTR.
7051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  *PTR = 1;
7052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid GoodWriter2() {
7055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MutexLock lock2(&mu2);  // This lock is unrelated to PTR.
7056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MutexLock lock1(&mu1);  // Protect PTR.
7057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  *PTR = 2;
7058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid GoodReader() {
7061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MutexLock lock1(&mu1);  // Protect PTR.
7062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(*PTR >= 0);
7063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid BuggyWriter() {
7066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MutexLock lock2(&mu2);  // Wrong mutex!
7067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  *PTR = 3;
7068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Some functions to make the stack trace non-trivial.
7071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid DoWrite1() { GoodWriter1();  }
7072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Thread1()  { DoWrite1(); }
7073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid DoWrite2() { GoodWriter2();  }
7075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Thread2()  { DoWrite2(); }
7076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid DoGoodRead()  { GoodReader();  }
7078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Thread3()     { DoGoodRead();  }
7079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid DoBadWrite()  { BuggyWriter(); }
7081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Thread4()     { DoBadWrite(); }
7082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
7084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test311: simple race.\n");
7085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  PTR = new int;
7086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_TRACE_MEMORY(PTR);
7087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  *PTR = 0;
7088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThread t1(Thread1, NULL, "good writer1"),
7089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           t2(Thread2, NULL, "good writer2"),
7090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           t3(Thread3, NULL, "good reader"),
7091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           t4(Thread4, NULL, "buggy writer");
7092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t1.Start();
7093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t3.Start();
7094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  // t2 goes after t3. This way a pure happens-before detector has no chance.
7095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(10000);
7096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t2.Start();
7097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(100000);  // Let the good folks go first.
7098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t4.Start();
7099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t1.Join();
7101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t2.Join();
7102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t3.Join();
7103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t4.Join();
7104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 311, RACE_DEMO)
7106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test311
7107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test312: A test with a very deep stack. {{{1
7109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test312 {
7110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
7111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid RaceyWrite() { GLOB++; }
7112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Func1() { RaceyWrite(); }
7113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Func2() { Func1(); }
7114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Func3() { Func2(); }
7115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Func4() { Func3(); }
7116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Func5() { Func4(); }
7117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Func6() { Func5(); }
7118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Func7() { Func6(); }
7119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Func8() { Func7(); }
7120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Func9() { Func8(); }
7121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Func10() { Func9(); }
7122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Func11() { Func10(); }
7123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Func12() { Func11(); }
7124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Func13() { Func12(); }
7125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Func14() { Func13(); }
7126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Func15() { Func14(); }
7127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Func16() { Func15(); }
7128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Func17() { Func16(); }
7129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Func18() { Func17(); }
7130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Func19() { Func18(); }
7131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker() { Func19(); }
7132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
7133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test312: simple race with deep stack.\n");
7134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Worker, Worker, Worker);
7135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
7136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
7137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 312, RACE_DEMO)
7139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test312
7140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test313 TP: test for thread graph output {{{1
7142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace  test313 {
7143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBlockingCounter *blocking_counter;
7144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
7145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Worker(N) will do 2^N increments of GLOB, each increment in a separate thread
7147b32f58018498ea2225959b0ba11c18f0c433deefEvgeniy Stepanovvoid Worker(long depth) {
7148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(depth >= 0);
7149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if (depth > 0) {
7150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ThreadPool pool(2);
7151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    pool.StartWorkers();
7152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    pool.Add(NewCallback(Worker, depth-1));
7153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    pool.Add(NewCallback(Worker, depth-1));
7154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  } else {
7155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    GLOB++; // Race here
7156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
7157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
7159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test313: positive\n");
7160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  Worker(4);
7161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("\tGLOB=%d\n", GLOB);
7162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 313, RACE_DEMO)
7164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test313
7165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test400: Demo of a simple false positive. {{{1
7169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test400 {
7170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Mutex mu;
7171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic vector<int> *vec; // GUARDED_BY(mu);
7172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid InitAllBeforeStartingThreads() {
7174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  vec = new vector<int>;
7175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  vec->push_back(1);
7176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  vec->push_back(2);
7177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Thread1() {
7180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MutexLock lock(&mu);
7181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  vec->pop_back();
7182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Thread2() {
7185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MutexLock lock(&mu);
7186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  vec->pop_back();
7187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//---- Sub-optimal code ---------
7190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownsize_t NumberOfElementsLeft() {
7191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MutexLock lock(&mu);
7192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  return vec->size();
7193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid WaitForAllThreadsToFinish_InefficientAndTsanUnfriendly() {
7196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  while(NumberOfElementsLeft()) {
7197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ; // sleep or print or do nothing.
7198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
7199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  // It is now safe to access vec w/o lock.
7200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  // But a hybrid detector (like ThreadSanitizer) can't see it.
7201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  // Solutions:
7202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  //   1. Use pure happens-before detector (e.g. "tsan --pure-happens-before")
7203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  //   2. Call ANNOTATE_MUTEX_IS_USED_AS_CONDVAR(&mu)
7204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  //      in InitAllBeforeStartingThreads()
7205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  //   3. (preferred) Use WaitForAllThreadsToFinish_Good() (see below).
7206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(vec->empty());
7207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  delete vec;
7208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//----- Better code -----------
7211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownbool NoElementsLeft(vector<int> *v) {
7213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  return v->empty();
7214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid WaitForAllThreadsToFinish_Good() {
7217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  mu.LockWhen(Condition(NoElementsLeft, vec));
7218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  mu.Unlock();
7219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  // It is now safe to access vec w/o lock.
7221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(vec->empty());
7222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  delete vec;
7223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
7227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(Thread1, Thread2);
7228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  InitAllBeforeStartingThreads();
7229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
7230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  WaitForAllThreadsToFinish_InefficientAndTsanUnfriendly();
7231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//  WaitForAllThreadsToFinish_Good();
7232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
7233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 400, RACE_DEMO)
7235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test400
7236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test401: Demo of false positive caused by reference counting. {{{1
7238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test401 {
7239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// A simplified example of reference counting.
7240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// DecRef() does ref count increment in a way unfriendly to race detectors.
7241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// DecRefAnnotated() does the same in a friendly way.
7242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic vector<int> *vec;
7244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic int ref_count;
7245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid InitAllBeforeStartingThreads(int number_of_threads) {
7247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  vec = new vector<int>;
7248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  vec->push_back(1);
7249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ref_count = number_of_threads;
7250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Correct, but unfriendly to race detectors.
7253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint DecRef() {
7254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  return AtomicIncrement(&ref_count, -1);
7255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Correct and friendly to race detectors.
7258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint DecRefAnnotated() {
7259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  ANNOTATE_CONDVAR_SIGNAL(&ref_count);
7260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  int res = AtomicIncrement(&ref_count, -1);
7261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if (res == 0) {
7262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ANNOTATE_CONDVAR_WAIT(&ref_count);
7263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
7264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  return res;
7265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid ThreadWorker() {
7268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(ref_count > 0);
7269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(vec->size() == 1);
7270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  if (DecRef() == 0) {  // Use DecRefAnnotated() instead!
7271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    // No one uses vec now ==> delete it.
7272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    delete vec;  // A false race may be reported here.
7273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    vec = NULL;
7274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
7275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
7278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  MyThreadArray t(ThreadWorker, ThreadWorker, ThreadWorker);
7279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  InitAllBeforeStartingThreads(3 /*number of threads*/);
7280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Start();
7281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  t.Join();
7282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(vec == 0);
7283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 401, RACE_DEMO)
7285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test401
7286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test501: Manually call PRINT_* annotations {{{1
7288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test501 {
7289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint  COUNTER = 0;
7290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
7291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex muCounter, muGlob[65];
7292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker() {
7294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   muCounter.Lock();
7295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int myId = ++COUNTER;
7296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   muCounter.Unlock();
7297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   usleep(100);
7299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   muGlob[myId].Lock();
7301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   muGlob[0].Lock();
7302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GLOB++;
7303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   muGlob[0].Unlock();
7304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   muGlob[myId].Unlock();
7305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker_1() {
7308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   MyThreadArray ta (Worker, Worker, Worker, Worker);
7309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ta.Start();
7310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   usleep(500000);
7311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ta.Join ();
7312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker_2() {
7315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   MyThreadArray ta (Worker_1, Worker_1, Worker_1, Worker_1);
7316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ta.Start();
7317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   usleep(300000);
7318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ta.Join ();
7319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
7322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ANNOTATE_RESET_STATS();
7323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   printf("test501: Manually call PRINT_* annotations.\n");
7324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   MyThreadArray ta (Worker_2, Worker_2, Worker_2, Worker_2);
7325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ta.Start();
7326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   usleep(100000);
7327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ta.Join ();
7328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ANNOTATE_PRINT_MEMORY_USAGE(0);
7329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ANNOTATE_PRINT_STATS();
7330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 501, FEATURE | EXCLUDE_FROM_ALL)
7333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test501
7334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test502: produce lots of segments without cross-thread relations {{{1
7336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test502 {
7337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
7339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * This test produces ~1Gb of memory usage when run with the following options:
7340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *
7341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * --tool=helgrind
7342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * --trace-after-race=0
7343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * --num-callers=2
7344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * --more-context=no
7345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
7346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex MU;
7348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
7349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid TP() {
7351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (int i = 0; i < 750000; i++) {
7352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      MU.Lock();
7353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      GLOB++;
7354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      MU.Unlock();
7355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
7356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
7359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   MyThreadArray t(TP, TP);
7360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   printf("test502: produce lots of segments without cross-thread relations\n");
7361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   t.Start();
7363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   t.Join();
7364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 502, MEMORY_USAGE | PRINT_STATS | EXCLUDE_FROM_ALL
7367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              | PERFORMANCE)
7368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test502
7369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test503: produce lots of segments with simple HB-relations {{{1
7371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// HB cache-miss rate is ~55%
7372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test503 {
7373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//  |- |  |  |  |  |
7375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//  | \|  |  |  |  |
7376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//  |  |- |  |  |  |
7377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//  |  | \|  |  |  |
7378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//  |  |  |- |  |  |
7379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//  |  |  | \|  |  |
7380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//  |  |  |  |- |  |
7381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//  |  |  |  | \|  |
7382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//  |  |  |  |  |- |
7383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//  |  |  |  |  | \|
7384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//  |  |  |  |  |  |----
7385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//->|  |  |  |  |  |
7386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//  |- |  |  |  |  |
7387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//  | \|  |  |  |  |
7388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//     ...
7389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownconst int N_threads = 32;
7391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownconst int ARRAY_SIZE = 128;
7392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint       GLOB[ARRAY_SIZE];
7393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownProducerConsumerQueue *Q[N_threads];
7394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint GLOB_limit = 100000;
7395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint count = -1;
7396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker(){
7398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int myId = AtomicIncrement(&count, 1);
7399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ProducerConsumerQueue &myQ = *Q[myId], &nextQ = *Q[(myId+1) % N_threads];
7401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // this code produces a new SS with each new segment
7403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   while (myQ.Get() != NULL) {
7404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (int i = 0; i < ARRAY_SIZE; i++)
7405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         GLOB[i]++;
7406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (myId == 0 && GLOB[0] > GLOB_limit) {
7408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         // Stop all threads
7409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         for (int i = 0; i < N_threads; i++)
7410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            Q[i]->Put(NULL);
7411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      } else
7412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         nextQ.Put(GLOB);
7413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
7414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
7417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   printf("test503: produce lots of segments with simple HB-relations\n");
7418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (int i = 0; i < N_threads; i++)
7419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Q[i] = new ProducerConsumerQueue(1);
7420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Q[0]->Put(GLOB);
7421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
7423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ThreadPool pool(N_threads);
7424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      pool.StartWorkers();
7425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (int i = 0; i < N_threads; i++) {
7426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         pool.Add(NewCallback(Worker));
7427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
7428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } // all folks are joined here.
7429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (int i = 0; i < N_threads; i++)
7431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      delete Q[i];
7432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 503, MEMORY_USAGE | PRINT_STATS
7435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  | PERFORMANCE | EXCLUDE_FROM_ALL)
7436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test503
7437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test504: force massive cache fetch-wback (50% misses, mostly CacheLineZ) {{{1
7439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test504 {
7440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownconst int N_THREADS = 2,
7442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          HG_CACHELINE_COUNT = 1 << 16,
7443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          HG_CACHELINE_SIZE  = 1 << 6,
7444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          HG_CACHE_SIZE = HG_CACHELINE_COUNT * HG_CACHELINE_SIZE;
7445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// int gives us ~4x speed of the byte test
7447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 4x array size gives us
7448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// total multiplier of 16x over the cachesize
7449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// so we can neglect the cached-at-the-end memory
7450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownconst int ARRAY_SIZE = 4 * HG_CACHE_SIZE,
7451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          ITERATIONS = 30;
7452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint array[ARRAY_SIZE];
7453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint count = 0;
7455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex count_mu;
7456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker() {
7458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   count_mu.Lock();
7459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int myId = ++count;
7460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   count_mu.Unlock();
7461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // all threads write to different memory locations,
7463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // so no synchronization mechanisms are needed
7464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int lower_bound = ARRAY_SIZE * (myId-1) / N_THREADS,
7465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       upper_bound = ARRAY_SIZE * ( myId ) / N_THREADS;
7466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (int j = 0; j < ITERATIONS; j++)
7467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (int i = lower_bound; i < upper_bound;
7468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            i += HG_CACHELINE_SIZE / sizeof(array[0])) {
7469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      array[i] = i; // each array-write generates a cache miss
7470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
7471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
7474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   printf("test504: force massive CacheLineZ fetch-wback\n");
7475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   MyThreadArray t(Worker, Worker);
7476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   t.Start();
7477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   t.Join();
7478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 504, PERFORMANCE | PRINT_STATS | EXCLUDE_FROM_ALL)
7481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test504
7482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test505: force massive cache fetch-wback (60% misses) {{{1
7484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// modification of test504 - more threads, byte accesses and lots of mutexes
7485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// so it produces lots of CacheLineF misses (30-50% of CacheLineZ misses)
7486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test505 {
7487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownconst int N_THREADS = 2,
7489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          HG_CACHELINE_COUNT = 1 << 16,
7490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          HG_CACHELINE_SIZE  = 1 << 6,
7491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          HG_CACHE_SIZE = HG_CACHELINE_COUNT * HG_CACHELINE_SIZE;
7492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownconst int ARRAY_SIZE = 4 * HG_CACHE_SIZE,
7494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          ITERATIONS = 3;
7495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint64_t array[ARRAY_SIZE];
7496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint count = 0;
7498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex count_mu;
7499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker() {
7501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   const int N_MUTEXES = 5;
7502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Mutex mu[N_MUTEXES];
7503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   count_mu.Lock();
7504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int myId = ++count;
7505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   count_mu.Unlock();
7506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // all threads write to different memory locations,
7508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // so no synchronization mechanisms are needed
7509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int lower_bound = ARRAY_SIZE * (myId-1) / N_THREADS,
7510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       upper_bound = ARRAY_SIZE * ( myId ) / N_THREADS;
7511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (int j = 0; j < ITERATIONS; j++)
7512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (int mutex_id = 0; mutex_id < N_MUTEXES; mutex_id++) {
7513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Mutex *m = & mu[mutex_id];
7514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      m->Lock();
7515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (int i = lower_bound + mutex_id, cnt = 0;
7516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               i < upper_bound;
7517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown               i += HG_CACHELINE_SIZE / sizeof(array[0]), cnt++) {
7518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         array[i] = i; // each array-write generates a cache miss
7519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
7520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      m->Unlock();
7521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
7522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
7525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   printf("test505: force massive CacheLineF fetch-wback\n");
7526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   MyThreadArray t(Worker, Worker);
7527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   t.Start();
7528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   t.Join();
7529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 505, PERFORMANCE | PRINT_STATS | EXCLUDE_FROM_ALL)
7532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test505
7533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test506: massive HB's using Barriers {{{1
7535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// HB cache miss is ~40%
7536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// segments consume 10x more memory than SSs
7537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// modification of test39
7538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test506 {
7539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#ifndef NO_BARRIER
7540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Same as test17 but uses Barrier class (pthread_barrier_t).
7541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint     GLOB = 0;
7542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownconst int N_threads = 64,
7543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          ITERATIONS = 1000;
7544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownBarrier *barrier[ITERATIONS];
7545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex   MU;
7546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker() {
7548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  for (int i = 0; i < ITERATIONS; i++) {
7549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     MU.Lock();
7550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     GLOB++;
7551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     MU.Unlock();
7552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     barrier[i]->Block();
7553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
7554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
7556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test506: massive HB's using Barriers\n");
7557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  for (int i = 0; i < ITERATIONS; i++) {
7558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     barrier[i] = new Barrier(N_threads);
7559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
7560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  {
7561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ThreadPool pool(N_threads);
7562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    pool.StartWorkers();
7563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for (int i = 0; i < N_threads; i++) {
7564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      pool.Add(NewCallback(Worker));
7565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
7566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  } // all folks are joined here.
7567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  CHECK(GLOB == N_threads * ITERATIONS);
7568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  for (int i = 0; i < ITERATIONS; i++) {
7569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     delete barrier[i];
7570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
7571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 506, PERFORMANCE | PRINT_STATS | EXCLUDE_FROM_ALL);
7573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif // NO_BARRIER
7574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test506
7575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test507: vgHelgrind_initIterAtFM/stackClear benchmark {{{1
7577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// vgHelgrind_initIterAtFM/stackClear consume ~8.5%/5.5% CPU
7578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test507 {
7579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownconst int N_THREADS    = 1,
7580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          BUFFER_SIZE  = 1,
7581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          ITERATIONS   = 1 << 20;
7582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Foo() {
7584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  struct T {
7585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    char temp;
7586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    T() {
7587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ANNOTATE_RWLOCK_CREATE(&temp);
7588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
7589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ~T() {
7590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ANNOTATE_RWLOCK_DESTROY(&temp);
7591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
7592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  } s[BUFFER_SIZE];
7593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  s->temp = '\0';
7594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker() {
7597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  for (int j = 0; j < ITERATIONS; j++) {
7598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Foo();
7599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
7600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
7603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test507: vgHelgrind_initIterAtFM/stackClear benchmark\n");
7604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  {
7605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ThreadPool pool(N_THREADS);
7606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    pool.StartWorkers();
7607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for (int i = 0; i < N_THREADS; i++) {
7608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      pool.Add(NewCallback(Worker));
7609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
7610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  } // all folks are joined here.
7611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 507, EXCLUDE_FROM_ALL);
7613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test507
7614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test508: cmp_WordVecs_for_FM benchmark {{{1
7616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 50+% of CPU consumption by cmp_WordVecs_for_FM
7617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test508 {
7618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownconst int N_THREADS    = 1,
7619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          BUFFER_SIZE  = 1 << 10,
7620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          ITERATIONS   = 1 << 9;
7621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Foo() {
7623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  struct T {
7624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    char temp;
7625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    T() {
7626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ANNOTATE_RWLOCK_CREATE(&temp);
7627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
7628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ~T() {
7629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ANNOTATE_RWLOCK_DESTROY(&temp);
7630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
7631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  } s[BUFFER_SIZE];
7632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  s->temp = '\0';
7633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker() {
7636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  for (int j = 0; j < ITERATIONS; j++) {
7637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Foo();
7638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
7639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
7642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test508: cmp_WordVecs_for_FM benchmark\n");
7643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  {
7644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ThreadPool pool(N_THREADS);
7645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    pool.StartWorkers();
7646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for (int i = 0; i < N_THREADS; i++) {
7647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      pool.Add(NewCallback(Worker));
7648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
7649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  } // all folks are joined here.
7650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 508, EXCLUDE_FROM_ALL);
7652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test508
7653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test509: avl_find_node benchmark {{{1
7655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 10+% of CPU consumption by avl_find_node
7656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test509 {
7657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownconst int N_THREADS    = 16,
7658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          ITERATIONS   = 1 << 8;
7659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker() {
7661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  std::vector<Mutex*> mu_list;
7662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  for (int i = 0; i < ITERATIONS; i++) {
7663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Mutex * mu = new Mutex();
7664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    mu_list.push_back(mu);
7665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    mu->Lock();
7666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
7667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  for (int i = ITERATIONS - 1; i >= 0; i--) {
7668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    Mutex * mu = mu_list[i];
7669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    mu->Unlock();
7670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    delete mu;
7671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
7672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
7675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test509: avl_find_node benchmark\n");
7676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  {
7677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ThreadPool pool(N_THREADS);
7678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    pool.StartWorkers();
7679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for (int i = 0; i < N_THREADS; i++) {
7680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      pool.Add(NewCallback(Worker));
7681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
7682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  } // all folks are joined here.
7683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 509, EXCLUDE_FROM_ALL);
7685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test509
7686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test510: SS-recycle test {{{1
7688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// this tests shows the case where only ~1% of SS are recycled
7689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test510 {
7690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownconst int N_THREADS    = 16,
7691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          ITERATIONS   = 1 << 10;
7692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint GLOB = 0;
7693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker() {
7695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  usleep(100000);
7696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  for (int i = 0; i < ITERATIONS; i++) {
7697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ANNOTATE_CONDVAR_SIGNAL((void*)0xDeadBeef);
7698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    GLOB++;
7699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    usleep(10);
7700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  }
7701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
7704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  //ANNOTATE_BENIGN_RACE(&GLOB, "Test");
7705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  printf("test510: SS-recycle test\n");
7706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  {
7707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    ThreadPool pool(N_THREADS);
7708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    pool.StartWorkers();
7709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    for (int i = 0; i < N_THREADS; i++) {
7710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      pool.Add(NewCallback(Worker));
7711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown    }
7712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  } // all folks are joined here.
7713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 510, MEMORY_USAGE | PRINT_STATS | EXCLUDE_FROM_ALL);
7715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test510
7716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test511: Segment refcounting test ('1' refcounting) {{{1
7718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test511 {
7719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint GLOB = 0;
7720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run () {
7722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (int i = 0; i < 300; i++) {
7723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ANNOTATE_CONDVAR_SIGNAL(&GLOB);
7724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      usleep(1000);
7725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      GLOB++;
7726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ANNOTATE_CONDVAR_WAIT(&GLOB);
7727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (i % 100 == 0)
7728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ANNOTATE_PRINT_MEMORY_USAGE(0);
7729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
7730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 511, MEMORY_USAGE | PRINT_STATS | EXCLUDE_FROM_ALL);
7732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test511
7733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test512: Segment refcounting test ('S' refcounting) {{{1
7735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test512 {
7736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint GLOB = 0;
7737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownsem_t SEM;
7738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run () {
7740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sem_init(&SEM, 0, 0);
7741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (int i = 0; i < 300; i++) {
7742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      sem_post(&SEM);
7743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      usleep(1000);
7744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      GLOB++;
7745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      sem_wait(&SEM);
7746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /*if (i % 100 == 0)
7747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ANNOTATE_PRINT_MEMORY_USAGE(0);*/
7748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
7749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   sem_destroy(&SEM);
7750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 512, MEMORY_USAGE | PRINT_STATS | EXCLUDE_FROM_ALL);
7752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test512
7753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// test513: --fast-mode benchmark {{{1
7755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownnamespace test513 {
7756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownconst int N_THREADS = 2,
7758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          HG_CACHELINE_SIZE  = 1 << 6,
7759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          ARRAY_SIZE = HG_CACHELINE_SIZE * 512,
7760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          MUTEX_ID_BITS = 8,
7761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          MUTEX_ID_MASK = (1 << MUTEX_ID_BITS) - 1;
7762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Each thread has its own cacheline and tackles with it intensively
7764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownconst int ITERATIONS = 1024;
7765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint array[N_THREADS][ARRAY_SIZE];
7766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownint count = 0;
7768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex count_mu;
7769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownMutex mutex_arr[N_THREADS][MUTEX_ID_BITS];
7770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Worker() {
7772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   count_mu.Lock();
7773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   int myId = count++;
7774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   count_mu.Unlock();
7775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // all threads write to different memory locations
7777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (int j = 0; j < ITERATIONS; j++) {
7778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      int mutex_mask = j & MUTEX_ID_BITS;
7779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (int m = 0; m < MUTEX_ID_BITS; m++)
7780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (mutex_mask & (1 << m))
7781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            mutex_arr[myId][m].Lock();
7782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (int i = 0; i < ARRAY_SIZE; i++) {
7784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         array[myId][i] = i;
7785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
7786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (int m = 0; m < MUTEX_ID_BITS; m++)
7788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (mutex_mask & (1 << m))
7789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            mutex_arr[myId][m].Unlock();
7790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
7791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid Run() {
7794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   printf("test513: --fast-mode benchmark\n");
7795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
7796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ThreadPool pool(N_THREADS);
7797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      pool.StartWorkers();
7798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (int i = 0; i < N_THREADS; i++) {
7799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         pool.Add(NewCallback(Worker));
7800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
7801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } // all folks are joined here.
7802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
7803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownREGISTER_TEST2(Run, 513, PERFORMANCE | PRINT_STATS | EXCLUDE_FROM_ALL)
7805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}  // namespace test513
7806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
7807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// End {{{1
7808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// vim:shiftwidth=2:softtabstop=2:expandtab:foldmethod=marker
7809