1610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov/* Copyright (c) 2008-2010, Google Inc. 2610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov * All rights reserved. 3610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov * 4610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov * Redistribution and use in source and binary forms, with or without 5610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov * modification, are permitted provided that the following conditions are 6610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov * met: 7610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov * 8610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov * * Redistributions of source code must retain the above copyright 9610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov * notice, this list of conditions and the following disclaimer. 10610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov * * Neither the name of Google Inc. nor the names of its 11610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov * contributors may be used to endorse or promote products derived from 12610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov * this software without specific prior written permission. 13610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov * 14610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 15610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 16610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 17610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 18610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 19610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 20610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov */ 26610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 27610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// This file is a part of a test suite for ThreadSanitizer, a race detector. 28610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Author: Konstantin Serebryany. 29610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 30610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// These 4 lines need to go before any include from libstdc++. 31610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// See include/bits/c++config in libstdc++ for details. 32610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#include "dynamic_annotations.h" 33610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#define _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(a) ANNOTATE_HAPPENS_BEFORE(a) 34610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#define _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(a) ANNOTATE_HAPPENS_AFTER(a) 35610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#define _GLIBCXX_EXTERN_TEMPLATE -1 36610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 37610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#include <stdio.h> 38610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#include <pthread.h> 39610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#include <unistd.h> 40610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#include <assert.h> 41610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#include <memory> 42610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#include <string> 43610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 44610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#include "test_utils.h" 45610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#include <gtest/gtest.h> 46610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 47610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#if defined(__cplusplus) && defined(__GNUC__) 48610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#include <features.h> 49610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// These tests verify that no false positives are reported due to custom 50610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// synchronization in libstdc++. 51610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// As of gcc 4.6, libstdc++ has HAPPENS_BEFORE/AFTER annotations in key places. 52610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 53610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace LibStdCPlusPlus_basic_string_Test { // {{{1 54610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// If reference counting inside basic_string is not understood 55610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// by a race detector, a false race may be reported between 56610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// basic_string::some_accessor and basic_string::~basic_string 57610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 58610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovstring *s; 59610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 60610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovpthread_mutex_t mu; 61610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovpthread_cond_t cv; 62610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint done = 0; 63610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 64610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid *Thread(void*) { 65610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov string x = *s; // calls _M_refcopy(). 66610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 67610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov pthread_mutex_lock(&mu); 68610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov done++; 69610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov pthread_cond_signal(&cv); 70610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov pthread_mutex_unlock(&mu); 71610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 72610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov assert(x == "foo"); 73610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov // x is destructed, calls _M_dispose 74610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov return NULL; 75610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov} 76610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 77610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovconst int kNThreads = 3; 78610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 79610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(LibStdCPlusPlus, basic_string_Test) { 80610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov if (!__GNUC_PREREQ(4, 6)) { 81610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov printf("This test is likely to produce a false race report " 82610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov "with libstdc++ earlier than 4.6; not running\n"); 83610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov return; 84610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov } 85610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 86610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov s = new string("foo"); 87610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov pthread_t t[kNThreads]; 88610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov pthread_mutex_init(&mu, 0); 89610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov pthread_cond_init(&cv, 0); 90610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov // start threads. 91610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov for (int i = 0; i < kNThreads; i++) { 92610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov pthread_create(&t[i], 0, Thread, 0); 93610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov } 94610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov // wait for threads to copy 's', but don't wait for threads to exit. 95610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov pthread_mutex_lock(&mu); 96610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov while (done != kNThreads) 97610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov pthread_cond_wait(&cv, &mu); 98610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov pthread_mutex_unlock(&mu); 99610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov // s has been copied few times, now delete it. 100610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov // Last of the destructors (either here ot in Thread() will call _M_destroy). 101610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov delete s; // calls _M_dispose. 102610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov} 103610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov} // namespace 104610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 105610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovnamespace LibStdCPlusPlus_shared_ptr_Test { // {{{1 106610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// If reference counting inside shared_ptr is not understood 107610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// by a race detector, a false race may be reported between 108610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// Foo::Check() and Foo:~Foo(). 109610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovclass Foo { 110610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov public: 111610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov Foo() : a_(777) { } 112610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov ~Foo() { 113610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov a_ = 0xDEAD; 114610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov } 115610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov void Check() { 116610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov assert(a_ == 777); 117610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov } 118610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov private: 119610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov int a_; 120610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov}; 121610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 122610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovshared_ptr<Foo> *s; 123610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 124610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovpthread_mutex_t mu; 125610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovpthread_cond_t cv; 126610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovint done = 0; 127610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 128610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanovvoid *Thread(void*) { 129610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov shared_ptr<Foo> x(*s); 130610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 131610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov pthread_mutex_lock(&mu); 132610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov done++; 133610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov pthread_cond_signal(&cv); 134610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov pthread_mutex_unlock(&mu); 135610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 136610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov x->Check(); 137610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov // x is destructed. 138610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov return NULL; 139610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov} 140610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 141610969f87667a485b9207086b3ff475bab909f95Evgeniy StepanovTEST(LibStdCPlusPlus, shared_ptr_Test) { 142610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 143610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov if (!__GNUC_PREREQ(4, 6)) { 144610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov printf("This test is likely to produce a false race report " 145610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov "with libstdc++ earlier than 4.6; not running\n"); 146610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov return; 147610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov } 148610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov const int kNThreads = 3; 149610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov s = new shared_ptr<Foo>(new Foo); 150610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov pthread_t t[kNThreads]; 151610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov pthread_mutex_init(&mu, 0); 152610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov pthread_cond_init(&cv, 0); 153610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov // start threads. 154610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov for (int i = 0; i < kNThreads; i++) { 155610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov pthread_create(&t[i], 0, Thread, 0); 156610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov } 157610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov // wait for threads to copy 's', but don't wait for threads to exit. 158610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov pthread_mutex_lock(&mu); 159610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov while (done != kNThreads) 160610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov pthread_cond_wait(&cv, &mu); 161610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov pthread_mutex_unlock(&mu); 162610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 163610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov delete s; 164610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov} 165610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov} // namespace 166610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov 167610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov#endif // __GNUC__ 168610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov// End {{{1 169610969f87667a485b9207086b3ff475bab909f95Evgeniy Stepanov // vim:shiftwidth=2:softtabstop=2:expandtab:foldmethod=marker 170