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