2014-02-12 Richard Biener <rguenther@suse.de>
[official-gcc.git] / libsanitizer / tsan / tsan_interface_ann.cc
blob38224f429cd09eb762d3ce9ec6babd69a6da3fd3
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 "sanitizer_common/sanitizer_stacktrace.h"
15 #include "tsan_interface_ann.h"
16 #include "tsan_mutex.h"
17 #include "tsan_report.h"
18 #include "tsan_rtl.h"
19 #include "tsan_mman.h"
20 #include "tsan_flags.h"
21 #include "tsan_platform.h"
22 #include "tsan_vector.h"
24 #define CALLERPC ((uptr)__builtin_return_address(0))
26 using namespace __tsan; // NOLINT
28 namespace __tsan {
30 class ScopedAnnotation {
31 public:
32 ScopedAnnotation(ThreadState *thr, const char *aname, const char *f, int l,
33 uptr pc)
34 : thr_(thr)
35 , in_rtl_(thr->in_rtl) {
36 CHECK_EQ(thr_->in_rtl, 0);
37 FuncEntry(thr_, pc);
38 thr_->in_rtl++;
39 DPrintf("#%d: annotation %s() %s:%d\n", thr_->tid, aname, f, l);
42 ~ScopedAnnotation() {
43 thr_->in_rtl--;
44 CHECK_EQ(in_rtl_, thr_->in_rtl);
45 FuncExit(thr_);
47 private:
48 ThreadState *const thr_;
49 const int in_rtl_;
52 #define SCOPED_ANNOTATION(typ) \
53 if (!flags()->enable_annotations) \
54 return; \
55 ThreadState *thr = cur_thread(); \
56 const uptr caller_pc = (uptr)__builtin_return_address(0); \
57 StatInc(thr, StatAnnotation); \
58 StatInc(thr, Stat##typ); \
59 ScopedAnnotation sa(thr, __FUNCTION__, f, l, caller_pc); \
60 const uptr pc = __sanitizer::StackTrace::GetCurrentPc(); \
61 (void)pc; \
62 /**/
64 static const int kMaxDescLen = 128;
66 struct ExpectRace {
67 ExpectRace *next;
68 ExpectRace *prev;
69 int hitcount;
70 int addcount;
71 uptr addr;
72 uptr size;
73 char *file;
74 int line;
75 char desc[kMaxDescLen];
78 struct DynamicAnnContext {
79 Mutex mtx;
80 ExpectRace expect;
81 ExpectRace benign;
83 DynamicAnnContext()
84 : mtx(MutexTypeAnnotations, StatMtxAnnotations) {
88 static DynamicAnnContext *dyn_ann_ctx;
89 static char dyn_ann_ctx_placeholder[sizeof(DynamicAnnContext)] ALIGNED(64);
91 static void AddExpectRace(ExpectRace *list,
92 char *f, int l, uptr addr, uptr size, char *desc) {
93 ExpectRace *race = list->next;
94 for (; race != list; race = race->next) {
95 if (race->addr == addr && race->size == size) {
96 race->addcount++;
97 return;
100 race = (ExpectRace*)internal_alloc(MBlockExpectRace, sizeof(ExpectRace));
101 race->addr = addr;
102 race->size = size;
103 race->file = f;
104 race->line = l;
105 race->desc[0] = 0;
106 race->hitcount = 0;
107 race->addcount = 1;
108 if (desc) {
109 int i = 0;
110 for (; i < kMaxDescLen - 1 && desc[i]; i++)
111 race->desc[i] = desc[i];
112 race->desc[i] = 0;
114 race->prev = list;
115 race->next = list->next;
116 race->next->prev = race;
117 list->next = race;
120 static ExpectRace *FindRace(ExpectRace *list, uptr addr, uptr size) {
121 for (ExpectRace *race = list->next; race != list; race = race->next) {
122 uptr maxbegin = max(race->addr, addr);
123 uptr minend = min(race->addr + race->size, addr + size);
124 if (maxbegin < minend)
125 return race;
127 return 0;
130 static bool CheckContains(ExpectRace *list, uptr addr, uptr size) {
131 ExpectRace *race = FindRace(list, addr, size);
132 if (race == 0 && AlternativeAddress(addr))
133 race = FindRace(list, AlternativeAddress(addr), size);
134 if (race == 0)
135 return false;
136 DPrintf("Hit expected/benign race: %s addr=%zx:%d %s:%d\n",
137 race->desc, race->addr, (int)race->size, race->file, race->line);
138 race->hitcount++;
139 return true;
142 static void InitList(ExpectRace *list) {
143 list->next = list;
144 list->prev = list;
147 void InitializeDynamicAnnotations() {
148 dyn_ann_ctx = new(dyn_ann_ctx_placeholder) DynamicAnnContext;
149 InitList(&dyn_ann_ctx->expect);
150 InitList(&dyn_ann_ctx->benign);
153 bool IsExpectedReport(uptr addr, uptr size) {
154 Lock lock(&dyn_ann_ctx->mtx);
155 if (CheckContains(&dyn_ann_ctx->expect, addr, size))
156 return true;
157 if (CheckContains(&dyn_ann_ctx->benign, addr, size))
158 return true;
159 return false;
162 static void CollectMatchedBenignRaces(Vector<ExpectRace> *matched,
163 int *unique_count, int *hit_count, int ExpectRace::*counter) {
164 ExpectRace *list = &dyn_ann_ctx->benign;
165 for (ExpectRace *race = list->next; race != list; race = race->next) {
166 (*unique_count)++;
167 if (race->*counter == 0)
168 continue;
169 (*hit_count) += race->*counter;
170 uptr i = 0;
171 for (; i < matched->Size(); i++) {
172 ExpectRace *race0 = &(*matched)[i];
173 if (race->line == race0->line
174 && internal_strcmp(race->file, race0->file) == 0
175 && internal_strcmp(race->desc, race0->desc) == 0) {
176 race0->*counter += race->*counter;
177 break;
180 if (i == matched->Size())
181 matched->PushBack(*race);
185 void PrintMatchedBenignRaces() {
186 Lock lock(&dyn_ann_ctx->mtx);
187 int unique_count = 0;
188 int hit_count = 0;
189 int add_count = 0;
190 Vector<ExpectRace> hit_matched(MBlockScopedBuf);
191 CollectMatchedBenignRaces(&hit_matched, &unique_count, &hit_count,
192 &ExpectRace::hitcount);
193 Vector<ExpectRace> add_matched(MBlockScopedBuf);
194 CollectMatchedBenignRaces(&add_matched, &unique_count, &add_count,
195 &ExpectRace::addcount);
196 if (hit_matched.Size()) {
197 Printf("ThreadSanitizer: Matched %d \"benign\" races (pid=%d):\n",
198 hit_count, (int)internal_getpid());
199 for (uptr i = 0; i < hit_matched.Size(); i++) {
200 Printf("%d %s:%d %s\n",
201 hit_matched[i].hitcount, hit_matched[i].file,
202 hit_matched[i].line, hit_matched[i].desc);
205 if (hit_matched.Size()) {
206 Printf("ThreadSanitizer: Annotated %d \"benign\" races, %d unique"
207 " (pid=%d):\n",
208 add_count, unique_count, (int)internal_getpid());
209 for (uptr i = 0; i < add_matched.Size(); i++) {
210 Printf("%d %s:%d %s\n",
211 add_matched[i].addcount, add_matched[i].file,
212 add_matched[i].line, add_matched[i].desc);
217 static void ReportMissedExpectedRace(ExpectRace *race) {
218 Printf("==================\n");
219 Printf("WARNING: ThreadSanitizer: missed expected data race\n");
220 Printf(" %s addr=%zx %s:%d\n",
221 race->desc, race->addr, race->file, race->line);
222 Printf("==================\n");
224 } // namespace __tsan
226 using namespace __tsan; // NOLINT
228 extern "C" {
229 void INTERFACE_ATTRIBUTE AnnotateHappensBefore(char *f, int l, uptr addr) {
230 SCOPED_ANNOTATION(AnnotateHappensBefore);
231 Release(thr, pc, addr);
234 void INTERFACE_ATTRIBUTE AnnotateHappensAfter(char *f, int l, uptr addr) {
235 SCOPED_ANNOTATION(AnnotateHappensAfter);
236 Acquire(thr, pc, addr);
239 void INTERFACE_ATTRIBUTE AnnotateCondVarSignal(char *f, int l, uptr cv) {
240 SCOPED_ANNOTATION(AnnotateCondVarSignal);
243 void INTERFACE_ATTRIBUTE AnnotateCondVarSignalAll(char *f, int l, uptr cv) {
244 SCOPED_ANNOTATION(AnnotateCondVarSignalAll);
247 void INTERFACE_ATTRIBUTE AnnotateMutexIsNotPHB(char *f, int l, uptr mu) {
248 SCOPED_ANNOTATION(AnnotateMutexIsNotPHB);
251 void INTERFACE_ATTRIBUTE AnnotateCondVarWait(char *f, int l, uptr cv,
252 uptr lock) {
253 SCOPED_ANNOTATION(AnnotateCondVarWait);
256 void INTERFACE_ATTRIBUTE AnnotateRWLockCreate(char *f, int l, uptr m) {
257 SCOPED_ANNOTATION(AnnotateRWLockCreate);
258 MutexCreate(thr, pc, m, true, true, false);
261 void INTERFACE_ATTRIBUTE AnnotateRWLockCreateStatic(char *f, int l, uptr m) {
262 SCOPED_ANNOTATION(AnnotateRWLockCreateStatic);
263 MutexCreate(thr, pc, m, true, true, true);
266 void INTERFACE_ATTRIBUTE AnnotateRWLockDestroy(char *f, int l, uptr m) {
267 SCOPED_ANNOTATION(AnnotateRWLockDestroy);
268 MutexDestroy(thr, pc, m);
271 void INTERFACE_ATTRIBUTE AnnotateRWLockAcquired(char *f, int l, uptr m,
272 uptr is_w) {
273 SCOPED_ANNOTATION(AnnotateRWLockAcquired);
274 if (is_w)
275 MutexLock(thr, pc, m);
276 else
277 MutexReadLock(thr, pc, m);
280 void INTERFACE_ATTRIBUTE AnnotateRWLockReleased(char *f, int l, uptr m,
281 uptr is_w) {
282 SCOPED_ANNOTATION(AnnotateRWLockReleased);
283 if (is_w)
284 MutexUnlock(thr, pc, m);
285 else
286 MutexReadUnlock(thr, pc, m);
289 void INTERFACE_ATTRIBUTE AnnotateTraceMemory(char *f, int l, uptr mem) {
290 SCOPED_ANNOTATION(AnnotateTraceMemory);
293 void INTERFACE_ATTRIBUTE AnnotateFlushState(char *f, int l) {
294 SCOPED_ANNOTATION(AnnotateFlushState);
297 void INTERFACE_ATTRIBUTE AnnotateNewMemory(char *f, int l, uptr mem,
298 uptr size) {
299 SCOPED_ANNOTATION(AnnotateNewMemory);
302 void INTERFACE_ATTRIBUTE AnnotateNoOp(char *f, int l, uptr mem) {
303 SCOPED_ANNOTATION(AnnotateNoOp);
306 void INTERFACE_ATTRIBUTE AnnotateFlushExpectedRaces(char *f, int l) {
307 SCOPED_ANNOTATION(AnnotateFlushExpectedRaces);
308 Lock lock(&dyn_ann_ctx->mtx);
309 while (dyn_ann_ctx->expect.next != &dyn_ann_ctx->expect) {
310 ExpectRace *race = dyn_ann_ctx->expect.next;
311 if (race->hitcount == 0) {
312 CTX()->nmissed_expected++;
313 ReportMissedExpectedRace(race);
315 race->prev->next = race->next;
316 race->next->prev = race->prev;
317 internal_free(race);
321 void INTERFACE_ATTRIBUTE AnnotateEnableRaceDetection(
322 char *f, int l, int enable) {
323 SCOPED_ANNOTATION(AnnotateEnableRaceDetection);
324 // FIXME: Reconsider this functionality later. It may be irrelevant.
327 void INTERFACE_ATTRIBUTE AnnotateMutexIsUsedAsCondVar(
328 char *f, int l, uptr mu) {
329 SCOPED_ANNOTATION(AnnotateMutexIsUsedAsCondVar);
332 void INTERFACE_ATTRIBUTE AnnotatePCQGet(
333 char *f, int l, uptr pcq) {
334 SCOPED_ANNOTATION(AnnotatePCQGet);
337 void INTERFACE_ATTRIBUTE AnnotatePCQPut(
338 char *f, int l, uptr pcq) {
339 SCOPED_ANNOTATION(AnnotatePCQPut);
342 void INTERFACE_ATTRIBUTE AnnotatePCQDestroy(
343 char *f, int l, uptr pcq) {
344 SCOPED_ANNOTATION(AnnotatePCQDestroy);
347 void INTERFACE_ATTRIBUTE AnnotatePCQCreate(
348 char *f, int l, uptr pcq) {
349 SCOPED_ANNOTATION(AnnotatePCQCreate);
352 void INTERFACE_ATTRIBUTE AnnotateExpectRace(
353 char *f, int l, uptr mem, char *desc) {
354 SCOPED_ANNOTATION(AnnotateExpectRace);
355 Lock lock(&dyn_ann_ctx->mtx);
356 AddExpectRace(&dyn_ann_ctx->expect,
357 f, l, mem, 1, desc);
358 DPrintf("Add expected race: %s addr=%zx %s:%d\n", desc, mem, f, l);
361 static void BenignRaceImpl(
362 char *f, int l, uptr mem, uptr size, char *desc) {
363 Lock lock(&dyn_ann_ctx->mtx);
364 AddExpectRace(&dyn_ann_ctx->benign,
365 f, l, mem, size, desc);
366 DPrintf("Add benign race: %s addr=%zx %s:%d\n", desc, mem, f, l);
369 // FIXME: Turn it off later. WTF is benign race?1?? Go talk to Hans Boehm.
370 void INTERFACE_ATTRIBUTE AnnotateBenignRaceSized(
371 char *f, int l, uptr mem, uptr size, char *desc) {
372 SCOPED_ANNOTATION(AnnotateBenignRaceSized);
373 BenignRaceImpl(f, l, mem, size, desc);
376 void INTERFACE_ATTRIBUTE AnnotateBenignRace(
377 char *f, int l, uptr mem, char *desc) {
378 SCOPED_ANNOTATION(AnnotateBenignRace);
379 BenignRaceImpl(f, l, mem, 1, desc);
382 void INTERFACE_ATTRIBUTE AnnotateIgnoreReadsBegin(char *f, int l) {
383 SCOPED_ANNOTATION(AnnotateIgnoreReadsBegin);
384 ThreadIgnoreBegin(thr, pc);
387 void INTERFACE_ATTRIBUTE AnnotateIgnoreReadsEnd(char *f, int l) {
388 SCOPED_ANNOTATION(AnnotateIgnoreReadsEnd);
389 ThreadIgnoreEnd(thr, pc);
392 void INTERFACE_ATTRIBUTE AnnotateIgnoreWritesBegin(char *f, int l) {
393 SCOPED_ANNOTATION(AnnotateIgnoreWritesBegin);
394 ThreadIgnoreBegin(thr, pc);
397 void INTERFACE_ATTRIBUTE AnnotateIgnoreWritesEnd(char *f, int l) {
398 SCOPED_ANNOTATION(AnnotateIgnoreWritesEnd);
399 ThreadIgnoreEnd(thr, pc);
402 void INTERFACE_ATTRIBUTE AnnotateIgnoreSyncBegin(char *f, int l) {
403 SCOPED_ANNOTATION(AnnotateIgnoreSyncBegin);
404 ThreadIgnoreSyncBegin(thr, pc);
407 void INTERFACE_ATTRIBUTE AnnotateIgnoreSyncEnd(char *f, int l) {
408 SCOPED_ANNOTATION(AnnotateIgnoreSyncEnd);
409 ThreadIgnoreSyncEnd(thr, pc);
412 void INTERFACE_ATTRIBUTE AnnotatePublishMemoryRange(
413 char *f, int l, uptr addr, uptr size) {
414 SCOPED_ANNOTATION(AnnotatePublishMemoryRange);
417 void INTERFACE_ATTRIBUTE AnnotateUnpublishMemoryRange(
418 char *f, int l, uptr addr, uptr size) {
419 SCOPED_ANNOTATION(AnnotateUnpublishMemoryRange);
422 void INTERFACE_ATTRIBUTE AnnotateThreadName(
423 char *f, int l, char *name) {
424 SCOPED_ANNOTATION(AnnotateThreadName);
425 ThreadSetName(thr, name);
428 // We deliberately omit the implementation of WTFAnnotateHappensBefore() and
429 // WTFAnnotateHappensAfter(). Those are being used by Webkit to annotate
430 // atomic operations, which should be handled by ThreadSanitizer correctly.
431 void INTERFACE_ATTRIBUTE WTFAnnotateHappensBefore(char *f, int l, uptr addr) {
432 SCOPED_ANNOTATION(AnnotateHappensBefore);
435 void INTERFACE_ATTRIBUTE WTFAnnotateHappensAfter(char *f, int l, uptr addr) {
436 SCOPED_ANNOTATION(AnnotateHappensAfter);
439 void INTERFACE_ATTRIBUTE WTFAnnotateBenignRaceSized(
440 char *f, int l, uptr mem, uptr sz, char *desc) {
441 SCOPED_ANNOTATION(AnnotateBenignRaceSized);
442 BenignRaceImpl(f, l, mem, sz, desc);
445 int INTERFACE_ATTRIBUTE RunningOnValgrind() {
446 return flags()->running_on_valgrind;
449 double __attribute__((weak)) INTERFACE_ATTRIBUTE ValgrindSlowdown(void) {
450 return 10.0;
453 const char INTERFACE_ATTRIBUTE* ThreadSanitizerQuery(const char *query) {
454 if (internal_strcmp(query, "pure_happens_before") == 0)
455 return "1";
456 else
457 return "0";
460 void INTERFACE_ATTRIBUTE
461 AnnotateMemoryIsInitialized(char *f, int l, uptr mem, uptr sz) {}
462 } // extern "C"