2013-02-04 Paul Thomas <pault@gcc.gnu.org>
[official-gcc.git] / libsanitizer / tsan / tsan_interface_ann.cc
blob7e49fb8b059cc6f80735d678564c20354bcf0948
1 //===-- tsan_interface_ann.cc ---------------------------------------------===//
2 //
3 // This file is distributed under the University of Illinois Open Source
4 // License. See LICENSE.TXT for details.
5 //
6 //===----------------------------------------------------------------------===//
7 //
8 // This file is a part of ThreadSanitizer (TSan), a race detector.
9 //
10 //===----------------------------------------------------------------------===//
11 #include "sanitizer_common/sanitizer_libc.h"
12 #include "sanitizer_common/sanitizer_internal_defs.h"
13 #include "sanitizer_common/sanitizer_placement_new.h"
14 #include "tsan_interface_ann.h"
15 #include "tsan_mutex.h"
16 #include "tsan_report.h"
17 #include "tsan_rtl.h"
18 #include "tsan_mman.h"
19 #include "tsan_flags.h"
20 #include "tsan_platform.h"
22 #define CALLERPC ((uptr)__builtin_return_address(0))
24 using namespace __tsan; // NOLINT
26 namespace __tsan {
28 class ScopedAnnotation {
29 public:
30 ScopedAnnotation(ThreadState *thr, const char *aname, const char *f, int l,
31 uptr pc)
32 : thr_(thr)
33 , in_rtl_(thr->in_rtl) {
34 CHECK_EQ(thr_->in_rtl, 0);
35 FuncEntry(thr_, pc);
36 thr_->in_rtl++;
37 DPrintf("#%d: annotation %s() %s:%d\n", thr_->tid, aname, f, l);
40 ~ScopedAnnotation() {
41 thr_->in_rtl--;
42 CHECK_EQ(in_rtl_, thr_->in_rtl);
43 FuncExit(thr_);
45 private:
46 ThreadState *const thr_;
47 const int in_rtl_;
50 #define SCOPED_ANNOTATION(typ) \
51 if (!flags()->enable_annotations) \
52 return; \
53 ThreadState *thr = cur_thread(); \
54 const uptr pc = (uptr)__builtin_return_address(0); \
55 StatInc(thr, StatAnnotation); \
56 StatInc(thr, Stat##typ); \
57 ScopedAnnotation sa(thr, __FUNCTION__, f, l, \
58 (uptr)__builtin_return_address(0)); \
59 (void)pc; \
60 /**/
62 static const int kMaxDescLen = 128;
64 struct ExpectRace {
65 ExpectRace *next;
66 ExpectRace *prev;
67 int hitcount;
68 uptr addr;
69 uptr size;
70 char *file;
71 int line;
72 char desc[kMaxDescLen];
75 struct DynamicAnnContext {
76 Mutex mtx;
77 ExpectRace expect;
78 ExpectRace benign;
80 DynamicAnnContext()
81 : mtx(MutexTypeAnnotations, StatMtxAnnotations) {
85 static DynamicAnnContext *dyn_ann_ctx;
86 static char dyn_ann_ctx_placeholder[sizeof(DynamicAnnContext)] ALIGNED(64);
88 static void AddExpectRace(ExpectRace *list,
89 char *f, int l, uptr addr, uptr size, char *desc) {
90 ExpectRace *race = list->next;
91 for (; race != list; race = race->next) {
92 if (race->addr == addr && race->size == size)
93 return;
95 race = (ExpectRace*)internal_alloc(MBlockExpectRace, sizeof(ExpectRace));
96 race->hitcount = 0;
97 race->addr = addr;
98 race->size = size;
99 race->file = f;
100 race->line = l;
101 race->desc[0] = 0;
102 if (desc) {
103 int i = 0;
104 for (; i < kMaxDescLen - 1 && desc[i]; i++)
105 race->desc[i] = desc[i];
106 race->desc[i] = 0;
108 race->prev = list;
109 race->next = list->next;
110 race->next->prev = race;
111 list->next = race;
114 static ExpectRace *FindRace(ExpectRace *list, uptr addr, uptr size) {
115 for (ExpectRace *race = list->next; race != list; race = race->next) {
116 uptr maxbegin = max(race->addr, addr);
117 uptr minend = min(race->addr + race->size, addr + size);
118 if (maxbegin < minend)
119 return race;
121 return 0;
124 static bool CheckContains(ExpectRace *list, uptr addr, uptr size) {
125 ExpectRace *race = FindRace(list, addr, size);
126 if (race == 0 && AlternativeAddress(addr))
127 race = FindRace(list, AlternativeAddress(addr), size);
128 if (race == 0)
129 return false;
130 DPrintf("Hit expected/benign race: %s addr=%zx:%d %s:%d\n",
131 race->desc, race->addr, (int)race->size, race->file, race->line);
132 race->hitcount++;
133 return true;
136 static void InitList(ExpectRace *list) {
137 list->next = list;
138 list->prev = list;
141 void InitializeDynamicAnnotations() {
142 dyn_ann_ctx = new(dyn_ann_ctx_placeholder) DynamicAnnContext;
143 InitList(&dyn_ann_ctx->expect);
144 InitList(&dyn_ann_ctx->benign);
147 bool IsExpectedReport(uptr addr, uptr size) {
148 Lock lock(&dyn_ann_ctx->mtx);
149 if (CheckContains(&dyn_ann_ctx->expect, addr, size))
150 return true;
151 if (CheckContains(&dyn_ann_ctx->benign, addr, size))
152 return true;
153 return false;
156 } // namespace __tsan
158 using namespace __tsan; // NOLINT
160 extern "C" {
161 void INTERFACE_ATTRIBUTE AnnotateHappensBefore(char *f, int l, uptr addr) {
162 SCOPED_ANNOTATION(AnnotateHappensBefore);
163 Release(cur_thread(), CALLERPC, addr);
166 void INTERFACE_ATTRIBUTE AnnotateHappensAfter(char *f, int l, uptr addr) {
167 SCOPED_ANNOTATION(AnnotateHappensAfter);
168 Acquire(cur_thread(), CALLERPC, addr);
171 void INTERFACE_ATTRIBUTE AnnotateCondVarSignal(char *f, int l, uptr cv) {
172 SCOPED_ANNOTATION(AnnotateCondVarSignal);
175 void INTERFACE_ATTRIBUTE AnnotateCondVarSignalAll(char *f, int l, uptr cv) {
176 SCOPED_ANNOTATION(AnnotateCondVarSignalAll);
179 void INTERFACE_ATTRIBUTE AnnotateMutexIsNotPHB(char *f, int l, uptr mu) {
180 SCOPED_ANNOTATION(AnnotateMutexIsNotPHB);
183 void INTERFACE_ATTRIBUTE AnnotateCondVarWait(char *f, int l, uptr cv,
184 uptr lock) {
185 SCOPED_ANNOTATION(AnnotateCondVarWait);
188 void INTERFACE_ATTRIBUTE AnnotateRWLockCreate(char *f, int l, uptr m) {
189 SCOPED_ANNOTATION(AnnotateRWLockCreate);
190 MutexCreate(thr, pc, m, true, true, false);
193 void INTERFACE_ATTRIBUTE AnnotateRWLockCreateStatic(char *f, int l, uptr m) {
194 SCOPED_ANNOTATION(AnnotateRWLockCreateStatic);
195 MutexCreate(thr, pc, m, true, true, true);
198 void INTERFACE_ATTRIBUTE AnnotateRWLockDestroy(char *f, int l, uptr m) {
199 SCOPED_ANNOTATION(AnnotateRWLockDestroy);
200 MutexDestroy(thr, pc, m);
203 void INTERFACE_ATTRIBUTE AnnotateRWLockAcquired(char *f, int l, uptr m,
204 uptr is_w) {
205 SCOPED_ANNOTATION(AnnotateRWLockAcquired);
206 if (is_w)
207 MutexLock(thr, pc, m);
208 else
209 MutexReadLock(thr, pc, m);
212 void INTERFACE_ATTRIBUTE AnnotateRWLockReleased(char *f, int l, uptr m,
213 uptr is_w) {
214 SCOPED_ANNOTATION(AnnotateRWLockReleased);
215 if (is_w)
216 MutexUnlock(thr, pc, m);
217 else
218 MutexReadUnlock(thr, pc, m);
221 void INTERFACE_ATTRIBUTE AnnotateTraceMemory(char *f, int l, uptr mem) {
222 SCOPED_ANNOTATION(AnnotateTraceMemory);
225 void INTERFACE_ATTRIBUTE AnnotateFlushState(char *f, int l) {
226 SCOPED_ANNOTATION(AnnotateFlushState);
229 void INTERFACE_ATTRIBUTE AnnotateNewMemory(char *f, int l, uptr mem,
230 uptr size) {
231 SCOPED_ANNOTATION(AnnotateNewMemory);
234 void INTERFACE_ATTRIBUTE AnnotateNoOp(char *f, int l, uptr mem) {
235 SCOPED_ANNOTATION(AnnotateNoOp);
238 static void ReportMissedExpectedRace(ExpectRace *race) {
239 Printf("==================\n");
240 Printf("WARNING: ThreadSanitizer: missed expected data race\n");
241 Printf(" %s addr=%zx %s:%d\n",
242 race->desc, race->addr, race->file, race->line);
243 Printf("==================\n");
246 void INTERFACE_ATTRIBUTE AnnotateFlushExpectedRaces(char *f, int l) {
247 SCOPED_ANNOTATION(AnnotateFlushExpectedRaces);
248 Lock lock(&dyn_ann_ctx->mtx);
249 while (dyn_ann_ctx->expect.next != &dyn_ann_ctx->expect) {
250 ExpectRace *race = dyn_ann_ctx->expect.next;
251 if (race->hitcount == 0) {
252 CTX()->nmissed_expected++;
253 ReportMissedExpectedRace(race);
255 race->prev->next = race->next;
256 race->next->prev = race->prev;
257 internal_free(race);
261 void INTERFACE_ATTRIBUTE AnnotateEnableRaceDetection(
262 char *f, int l, int enable) {
263 SCOPED_ANNOTATION(AnnotateEnableRaceDetection);
264 // FIXME: Reconsider this functionality later. It may be irrelevant.
267 void INTERFACE_ATTRIBUTE AnnotateMutexIsUsedAsCondVar(
268 char *f, int l, uptr mu) {
269 SCOPED_ANNOTATION(AnnotateMutexIsUsedAsCondVar);
272 void INTERFACE_ATTRIBUTE AnnotatePCQGet(
273 char *f, int l, uptr pcq) {
274 SCOPED_ANNOTATION(AnnotatePCQGet);
277 void INTERFACE_ATTRIBUTE AnnotatePCQPut(
278 char *f, int l, uptr pcq) {
279 SCOPED_ANNOTATION(AnnotatePCQPut);
282 void INTERFACE_ATTRIBUTE AnnotatePCQDestroy(
283 char *f, int l, uptr pcq) {
284 SCOPED_ANNOTATION(AnnotatePCQDestroy);
287 void INTERFACE_ATTRIBUTE AnnotatePCQCreate(
288 char *f, int l, uptr pcq) {
289 SCOPED_ANNOTATION(AnnotatePCQCreate);
292 void INTERFACE_ATTRIBUTE AnnotateExpectRace(
293 char *f, int l, uptr mem, char *desc) {
294 SCOPED_ANNOTATION(AnnotateExpectRace);
295 Lock lock(&dyn_ann_ctx->mtx);
296 AddExpectRace(&dyn_ann_ctx->expect,
297 f, l, mem, 1, desc);
298 DPrintf("Add expected race: %s addr=%zx %s:%d\n", desc, mem, f, l);
301 static void BenignRaceImpl(
302 char *f, int l, uptr mem, uptr size, char *desc) {
303 Lock lock(&dyn_ann_ctx->mtx);
304 AddExpectRace(&dyn_ann_ctx->benign,
305 f, l, mem, size, desc);
306 DPrintf("Add benign race: %s addr=%zx %s:%d\n", desc, mem, f, l);
309 // FIXME: Turn it off later. WTF is benign race?1?? Go talk to Hans Boehm.
310 void INTERFACE_ATTRIBUTE AnnotateBenignRaceSized(
311 char *f, int l, uptr mem, uptr size, char *desc) {
312 SCOPED_ANNOTATION(AnnotateBenignRaceSized);
313 BenignRaceImpl(f, l, mem, size, desc);
316 void INTERFACE_ATTRIBUTE AnnotateBenignRace(
317 char *f, int l, uptr mem, char *desc) {
318 SCOPED_ANNOTATION(AnnotateBenignRace);
319 BenignRaceImpl(f, l, mem, 1, desc);
322 void INTERFACE_ATTRIBUTE AnnotateIgnoreReadsBegin(char *f, int l) {
323 SCOPED_ANNOTATION(AnnotateIgnoreReadsBegin);
324 IgnoreCtl(cur_thread(), false, true);
327 void INTERFACE_ATTRIBUTE AnnotateIgnoreReadsEnd(char *f, int l) {
328 SCOPED_ANNOTATION(AnnotateIgnoreReadsEnd);
329 IgnoreCtl(cur_thread(), false, false);
332 void INTERFACE_ATTRIBUTE AnnotateIgnoreWritesBegin(char *f, int l) {
333 SCOPED_ANNOTATION(AnnotateIgnoreWritesBegin);
334 IgnoreCtl(cur_thread(), true, true);
337 void INTERFACE_ATTRIBUTE AnnotateIgnoreWritesEnd(char *f, int l) {
338 SCOPED_ANNOTATION(AnnotateIgnoreWritesEnd);
339 IgnoreCtl(thr, true, false);
342 void INTERFACE_ATTRIBUTE AnnotatePublishMemoryRange(
343 char *f, int l, uptr addr, uptr size) {
344 SCOPED_ANNOTATION(AnnotatePublishMemoryRange);
347 void INTERFACE_ATTRIBUTE AnnotateUnpublishMemoryRange(
348 char *f, int l, uptr addr, uptr size) {
349 SCOPED_ANNOTATION(AnnotateUnpublishMemoryRange);
352 void INTERFACE_ATTRIBUTE AnnotateThreadName(
353 char *f, int l, char *name) {
354 SCOPED_ANNOTATION(AnnotateThreadName);
355 ThreadSetName(thr, name);
358 void INTERFACE_ATTRIBUTE WTFAnnotateHappensBefore(char *f, int l, uptr addr) {
359 SCOPED_ANNOTATION(AnnotateHappensBefore);
362 void INTERFACE_ATTRIBUTE WTFAnnotateHappensAfter(char *f, int l, uptr addr) {
363 SCOPED_ANNOTATION(AnnotateHappensAfter);
366 void INTERFACE_ATTRIBUTE WTFAnnotateBenignRaceSized(
367 char *f, int l, uptr mem, uptr sz, char *desc) {
368 SCOPED_ANNOTATION(AnnotateBenignRaceSized);
371 int INTERFACE_ATTRIBUTE RunningOnValgrind() {
372 return flags()->running_on_valgrind;
375 double __attribute__((weak)) INTERFACE_ATTRIBUTE ValgrindSlowdown(void) {
376 return 10.0;
379 const char INTERFACE_ATTRIBUTE* ThreadSanitizerQuery(const char *query) {
380 if (internal_strcmp(query, "pure_happens_before") == 0)
381 return "1";
382 else
383 return "0";
385 } // extern "C"