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;
2594