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