1 /* Copyright (c) 2008-2010, Google Inc. 2 * All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Neither the name of Google Inc. nor the names of its 11 * contributors may be used to endorse or promote products derived from 12 * this software without specific prior written permission. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 15 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 16 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 17 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 18 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 19 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 20 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27 // This file is a part of a test suite for ThreadSanitizer, a race detector. 28 // Author: Konstantin Serebryany. 29 30 // These 4 lines need to go before any include from libstdc++. 31 // See include/bits/c++config in libstdc++ for details. 32 #include "dynamic_annotations.h" 33 #define _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(a) ANNOTATE_HAPPENS_BEFORE(a) 34 #define _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(a) ANNOTATE_HAPPENS_AFTER(a) 35 #define _GLIBCXX_EXTERN_TEMPLATE -1 36 37 #include <stdio.h> 38 #include <pthread.h> 39 #include <unistd.h> 40 #include <assert.h> 41 #include <memory> 42 #include <string> 43 44 #include "test_utils.h" 45 #include <gtest/gtest.h> 46 47 #if defined(__cplusplus) && defined(__GNUC__) 48 #include <features.h> 49 // These tests verify that no false positives are reported due to custom 50 // synchronization in libstdc++. 51 // As of gcc 4.6, libstdc++ has HAPPENS_BEFORE/AFTER annotations in key places. 52 53 namespace LibStdCPlusPlus_basic_string_Test { // {{{1 54 // If reference counting inside basic_string is not understood 55 // by a race detector, a false race may be reported between 56 // basic_string::some_accessor and basic_string::~basic_string 57 58 string *s; 59 60 pthread_mutex_t mu; 61 pthread_cond_t cv; 62 int done = 0; 63 64 void *Thread(void*) { 65 string x = *s; // calls _M_refcopy(). 66 67 pthread_mutex_lock(&mu); 68 done++; 69 pthread_cond_signal(&cv); 70 pthread_mutex_unlock(&mu); 71 72 assert(x == "foo"); 73 // x is destructed, calls _M_dispose 74 return NULL; 75 } 76 77 const int kNThreads = 3; 78 79 TEST(LibStdCPlusPlus, basic_string_Test) { 80 if (!__GNUC_PREREQ(4, 6)) { 81 printf("This test is likely to produce a false race report " 82 "with libstdc++ earlier than 4.6; not running\n"); 83 return; 84 } 85 86 s = new string("foo"); 87 pthread_t t[kNThreads]; 88 pthread_mutex_init(&mu, 0); 89 pthread_cond_init(&cv, 0); 90 // start threads. 91 for (int i = 0; i < kNThreads; i++) { 92 pthread_create(&t[i], 0, Thread, 0); 93 } 94 // wait for threads to copy 's', but don't wait for threads to exit. 95 pthread_mutex_lock(&mu); 96 while (done != kNThreads) 97 pthread_cond_wait(&cv, &mu); 98 pthread_mutex_unlock(&mu); 99 // s has been copied few times, now delete it. 100 // Last of the destructors (either here ot in Thread() will call _M_destroy). 101 delete s; // calls _M_dispose. 102 } 103 } // namespace 104 105 namespace LibStdCPlusPlus_shared_ptr_Test { // {{{1 106 // If reference counting inside shared_ptr is not understood 107 // by a race detector, a false race may be reported between 108 // Foo::Check() and Foo:~Foo(). 109 class Foo { 110 public: 111 Foo() : a_(777) { } 112 ~Foo() { 113 a_ = 0xDEAD; 114 } 115 void Check() { 116 assert(a_ == 777); 117 } 118 private: 119 int a_; 120 }; 121 122 shared_ptr<Foo> *s; 123 124 pthread_mutex_t mu; 125 pthread_cond_t cv; 126 int done = 0; 127 128 void *Thread(void*) { 129 shared_ptr<Foo> x(*s); 130 131 pthread_mutex_lock(&mu); 132 done++; 133 pthread_cond_signal(&cv); 134 pthread_mutex_unlock(&mu); 135 136 x->Check(); 137 // x is destructed. 138 return NULL; 139 } 140 141 TEST(LibStdCPlusPlus, shared_ptr_Test) { 142 143 if (!__GNUC_PREREQ(4, 6)) { 144 printf("This test is likely to produce a false race report " 145 "with libstdc++ earlier than 4.6; not running\n"); 146 return; 147 } 148 const int kNThreads = 3; 149 s = new shared_ptr<Foo>(new Foo); 150 pthread_t t[kNThreads]; 151 pthread_mutex_init(&mu, 0); 152 pthread_cond_init(&cv, 0); 153 // start threads. 154 for (int i = 0; i < kNThreads; i++) { 155 pthread_create(&t[i], 0, Thread, 0); 156 } 157 // wait for threads to copy 's', but don't wait for threads to exit. 158 pthread_mutex_lock(&mu); 159 while (done != kNThreads) 160 pthread_cond_wait(&cv, &mu); 161 pthread_mutex_unlock(&mu); 162 163 delete s; 164 } 165 } // namespace 166 167 #endif // __GNUC__ 168 // End {{{1 169 // vim:shiftwidth=2:softtabstop=2:expandtab:foldmethod=marker 170