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 few macros useful for implementing 29610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov unit-tests for data race detection tools. 30610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 31610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov*/ 32610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 33610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#ifndef TEST_UTILS_H__ 34610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#define TEST_UTILS_H__ 35610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 36610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// This test must not include any other file specific to threading library, 37610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// everything should be inside THREAD_WRAPPERS. 38610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#ifndef THREAD_WRAPPERS 39610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov# define THREAD_WRAPPERS "thread_wrappers.h" 40610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#endif 41610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#include THREAD_WRAPPERS 42610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 43610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#ifndef NEEDS_SEPERATE_RW_LOCK 44610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#define RWLock Mutex // Mutex does work as an rw-lock. 45610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#define WriterLockScoped MutexLock 46610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#define ReaderLockScoped ReaderMutexLock 47610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#endif // !NEEDS_SEPERATE_RW_LOCK 48610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 49610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovstatic bool ArgIsOne(int *arg) { return *arg == 1; }; 50610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovstatic bool ArgIsZero(int *arg) { return *arg == 0; }; 51610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovstatic bool ArgIsTrue(bool *arg) { return *arg == true; }; 52610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 53610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 54610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// If run under ThreadSanitizerQuery, this function is replaced by the tool 55610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// and a non-NULL string is returned. See the usage below. 56610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovextern "C" const char *ThreadSanitizerQuery(const char *query); 57610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 58610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Apply ANNOTATE_EXPECT_RACE only if running under ThreadSanitizer. 59610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#define ANNOTATE_EXPECT_RACE_FOR_TSAN(mem, descr) \ 60610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov do {\ 61610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov if (ThreadSanitizerQuery("") != NULL) {\ 62610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov ANNOTATE_EXPECT_RACE(mem, descr); \ 63610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov } \ 64610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov } while(0)\ 65610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 66610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovinline bool ThreadSanitizerQueryMatch(const char *query, const char *expected_answer) { 67610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov const char *answer = ThreadSanitizerQuery(query); 68610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov if (answer == NULL) { 69610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov // Not running under ThreadSanitizer at all. 70610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov return false; 71610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov } 72610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov return string(answer) == expected_answer; 73610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov} 74610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 75610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovinline bool Tsan_PureHappensBefore() { 76610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov static bool ret = ThreadSanitizerQueryMatch("pure_happens_before", "1"); 77610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov return ret; 78610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov} 79610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 80610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovinline bool Tsan_RaceVerifier() { 81610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov static bool ret = ThreadSanitizerQueryMatch("race_verifier", "1"); 82610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov return ret; 83610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov} 84610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 85610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// An array of threads. Create/start/join all elements at once. 86610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovclass MyThreadArray { 87610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov public: 88610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov static const int kSize = 5; 89610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov typedef void (*F) (void); 90610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov MyThreadArray(F f1, F f2 = NULL, F f3 = NULL, F f4 = NULL, F f5 = NULL) { 91610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov ar_[0] = new MyThread(f1); 92610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov ar_[1] = f2 ? new MyThread(f2) : NULL; 93610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov ar_[2] = f3 ? new MyThread(f3) : NULL; 94610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov ar_[3] = f4 ? new MyThread(f4) : NULL; 95610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov ar_[4] = f5 ? new MyThread(f5) : NULL; 96610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov } 97610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov void Start() { 98610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov for(int i = 0; i < kSize; i++) { 99610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov if(ar_[i]) { 100610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov ar_[i]->Start(); 101610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov usleep(10); 102610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov } 103610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov } 104610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov } 105610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 106610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov void Join() { 107610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov for(int i = 0; i < kSize; i++) { 108610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov if(ar_[i]) { 109610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov ar_[i]->Join(); 110610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov } 111610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov } 112610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov } 113610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 114610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov ~MyThreadArray() { 115610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov for(int i = 0; i < kSize; i++) { 116610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov delete ar_[i]; 117610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov } 118610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov } 119610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov private: 120610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov MyThread *ar_[kSize]; 121610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}; 122610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 123610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 124610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// This class does not implement a signal-wait synchronization 125610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// primitive, even if it looks like one. Its purpose is to enforce an 126610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// order of execution of threads in unit tests in a way that is 127610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// invisible to ThreadSanitizer and similar tools. It lacks memory 128610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// barriers, therefore it only works reliably if there is a real 129610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// synchronization primitive before signal() or after wait(). 130610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovclass StealthNotification { 131610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov public: 132610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov StealthNotification() : flag_(0) {} 133610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 134610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov void signal() { 135610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov ANNOTATE_IGNORE_READS_AND_WRITES_BEGIN(); 136610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov CHECK(!flag_); 137610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov flag_ = 1; 138610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov ANNOTATE_IGNORE_READS_AND_WRITES_END(); 139610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov } 140610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 141610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov void wait() { 142610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov while (!flag_) { 143610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#ifdef WIN32 144610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov usleep(1000); 145610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#else 146610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov sched_yield(); 147610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#endif 148610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov } 149610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov } 150610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 151610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov private: 152610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov volatile int flag_; 153610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}; 154610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 155610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#endif // TEST_UTILS_H__ 156610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// End {{{1 157610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov // vim:shiftwidth=2:softtabstop=2:expandtab:foldmethod=marker 158