2014-10-24 Richard Biener <rguenther@suse.de>
[official-gcc.git] / libsanitizer / tsan / tsan_interface_ann.cc
blob85de2e6221f1dcb2bcd9c9bbeb1005aceaab805f
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 FuncEntry(thr_, pc);
36 DPrintf("#%d: annotation %s() %s:%d\n", thr_->tid, aname, f, l);
39 ~ScopedAnnotation() {
40 FuncExit(thr_);
41 CheckNoLocks(thr_);
43 private:
44 ThreadState *const thr_;
47 #define SCOPED_ANNOTATION(typ) \
48 if (!flags()->enable_annotations) \
49 return; \
50 ThreadState *thr = cur_thread(); \
51 const uptr caller_pc = (uptr)__builtin_return_address(0); \
52 StatInc(thr, StatAnnotation); \
53 StatInc(thr, Stat##typ); \
54 ScopedAnnotation sa(thr, __func__, f, l, caller_pc); \
55 const uptr pc = __sanitizer::StackTrace::GetCurrentPc(); \
56 (void)pc; \
57 /**/
59 static const int kMaxDescLen = 128;
61 struct ExpectRace {
62 ExpectRace *next;
63 ExpectRace *prev;
64 int hitcount;
65 int addcount;
66 uptr addr;
67 uptr size;
68 char *file;
69 int line;
70 char desc[kMaxDescLen];
73 struct DynamicAnnContext {
74 Mutex mtx;
75 ExpectRace expect;
76 ExpectRace benign;
78 DynamicAnnContext()
79 : mtx(MutexTypeAnnotations, StatMtxAnnotations) {
83 static DynamicAnnContext *dyn_ann_ctx;
84 static char dyn_ann_ctx_placeholder[sizeof(DynamicAnnContext)] ALIGNED(64);
86 static void AddExpectRace(ExpectRace *list,
87 char *f, int l, uptr addr, uptr size, char *desc) {
88 ExpectRace *race = list->next;
89 for (; race != list; race = race->next) {
90 if (race->addr == addr && race->size == size) {
91 race->addcount++;
92 return;
95 race = (ExpectRace*)internal_alloc(MBlockExpectRace, sizeof(ExpectRace));
96 race->addr = addr;
97 race->size = size;
98 race->file = f;
99 race->line = l;
100 race->desc[0] = 0;
101 race->hitcount = 0;
102 race->addcount = 1;
103 if (desc) {
104 int i = 0;
105 for (; i < kMaxDescLen - 1 && desc[i]; i++)
106 race->desc[i] = desc[i];
107 race->desc[i] = 0;
109 race->prev = list;
110 race->next = list->next;
111 race->next->prev = race;
112 list->next = race;
115 static ExpectRace *FindRace(ExpectRace *list, uptr addr, uptr size) {
116 for (ExpectRace *race = list->next; race != list; race = race->next) {
117 uptr maxbegin = max(race->addr, addr);
118 uptr minend = min(race->addr + race->size, addr + size);
119 if (maxbegin < minend)
120 return race;
122 return 0;
125 static bool CheckContains(ExpectRace *list, uptr addr, uptr size) {
126 ExpectRace *race = FindRace(list, addr, size);
127 if (race == 0)
128 return false;
129 DPrintf("Hit expected/benign race: %s addr=%zx:%d %s:%d\n",
130 race->desc, race->addr, (int)race->size, race->file, race->line);
131 race->hitcount++;
132 return true;
135 static void InitList(ExpectRace *list) {
136 list->next = list;
137 list->prev = list;
140 void InitializeDynamicAnnotations() {
141 dyn_ann_ctx = new(dyn_ann_ctx_placeholder) DynamicAnnContext;
142 InitList(&dyn_ann_ctx->expect);
143 InitList(&dyn_ann_ctx->benign);
146 bool IsExpectedReport(uptr addr, uptr size) {
147 Lock lock(&dyn_ann_ctx->mtx);
148 if (CheckContains(&dyn_ann_ctx->expect, addr, size))
149 return true;
150 if (CheckContains(&dyn_ann_ctx->benign, addr, size))
151 return true;
152 return false;
155 static void CollectMatchedBenignRaces(Vector<ExpectRace> *matched,
156 int *unique_count, int *hit_count, int ExpectRace::*counter) {
157 ExpectRace *list = &dyn_ann_ctx->benign;
158 for (ExpectRace *race = list->next; race != list; race = race->next) {
159 (*unique_count)++;
160 if (race->*counter == 0)
161 continue;
162 (*hit_count) += race->*counter;
163 uptr i = 0;
164 for (; i < matched->Size(); i++) {
165 ExpectRace *race0 = &(*matched)[i];
166 if (race->line == race0->line
167 && internal_strcmp(race->file, race0->file) == 0
168 && internal_strcmp(race->desc, race0->desc) == 0) {
169 race0->*counter += race->*counter;
170 break;
173 if (i == matched->Size())
174 matched->PushBack(*race);
178 void PrintMatchedBenignRaces() {
179 Lock lock(&dyn_ann_ctx->mtx);
180 int unique_count = 0;
181 int hit_count = 0;
182 int add_count = 0;
183 Vector<ExpectRace> hit_matched(MBlockScopedBuf);
184 CollectMatchedBenignRaces(&hit_matched, &unique_count, &hit_count,
185 &ExpectRace::hitcount);
186 Vector<ExpectRace> add_matched(MBlockScopedBuf);
187 CollectMatchedBenignRaces(&add_matched, &unique_count, &add_count,
188 &ExpectRace::addcount);
189 if (hit_matched.Size()) {
190 Printf("ThreadSanitizer: Matched %d \"benign\" races (pid=%d):\n",
191 hit_count, (int)internal_getpid());
192 for (uptr i = 0; i < hit_matched.Size(); i++) {
193 Printf("%d %s:%d %s\n",
194 hit_matched[i].hitcount, hit_matched[i].file,
195 hit_matched[i].line, hit_matched[i].desc);
198 if (hit_matched.Size()) {
199 Printf("ThreadSanitizer: Annotated %d \"benign\" races, %d unique"
200 " (pid=%d):\n",
201 add_count, unique_count, (int)internal_getpid());
202 for (uptr i = 0; i < add_matched.Size(); i++) {
203 Printf("%d %s:%d %s\n",
204 add_matched[i].addcount, add_matched[i].file,
205 add_matched[i].line, add_matched[i].desc);
210 static void ReportMissedExpectedRace(ExpectRace *race) {
211 Printf("==================\n");
212 Printf("WARNING: ThreadSanitizer: missed expected data race\n");
213 Printf(" %s addr=%zx %s:%d\n",
214 race->desc, race->addr, race->file, race->line);
215 Printf("==================\n");
217 } // namespace __tsan
219 using namespace __tsan; // NOLINT
221 extern "C" {
222 void INTERFACE_ATTRIBUTE AnnotateHappensBefore(char *f, int l, uptr addr) {
223 SCOPED_ANNOTATION(AnnotateHappensBefore);
224 Release(thr, pc, addr);
227 void INTERFACE_ATTRIBUTE AnnotateHappensAfter(char *f, int l, uptr addr) {
228 SCOPED_ANNOTATION(AnnotateHappensAfter);
229 Acquire(thr, pc, addr);
232 void INTERFACE_ATTRIBUTE AnnotateCondVarSignal(char *f, int l, uptr cv) {
233 SCOPED_ANNOTATION(AnnotateCondVarSignal);
236 void INTERFACE_ATTRIBUTE AnnotateCondVarSignalAll(char *f, int l, uptr cv) {
237 SCOPED_ANNOTATION(AnnotateCondVarSignalAll);
240 void INTERFACE_ATTRIBUTE AnnotateMutexIsNotPHB(char *f, int l, uptr mu) {
241 SCOPED_ANNOTATION(AnnotateMutexIsNotPHB);
244 void INTERFACE_ATTRIBUTE AnnotateCondVarWait(char *f, int l, uptr cv,
245 uptr lock) {
246 SCOPED_ANNOTATION(AnnotateCondVarWait);
249 void INTERFACE_ATTRIBUTE AnnotateRWLockCreate(char *f, int l, uptr m) {
250 SCOPED_ANNOTATION(AnnotateRWLockCreate);
251 MutexCreate(thr, pc, m, true, true, false);
254 void INTERFACE_ATTRIBUTE AnnotateRWLockCreateStatic(char *f, int l, uptr m) {
255 SCOPED_ANNOTATION(AnnotateRWLockCreateStatic);
256 MutexCreate(thr, pc, m, true, true, true);
259 void INTERFACE_ATTRIBUTE AnnotateRWLockDestroy(char *f, int l, uptr m) {
260 SCOPED_ANNOTATION(AnnotateRWLockDestroy);
261 MutexDestroy(thr, pc, m);
264 void INTERFACE_ATTRIBUTE AnnotateRWLockAcquired(char *f, int l, uptr m,
265 uptr is_w) {
266 SCOPED_ANNOTATION(AnnotateRWLockAcquired);
267 if (is_w)
268 MutexLock(thr, pc, m);
269 else
270 MutexReadLock(thr, pc, m);
273 void INTERFACE_ATTRIBUTE AnnotateRWLockReleased(char *f, int l, uptr m,
274 uptr is_w) {
275 SCOPED_ANNOTATION(AnnotateRWLockReleased);
276 if (is_w)
277 MutexUnlock(thr, pc, m);
278 else
279 MutexReadUnlock(thr, pc, m);
282 void INTERFACE_ATTRIBUTE AnnotateTraceMemory(char *f, int l, uptr mem) {
283 SCOPED_ANNOTATION(AnnotateTraceMemory);
286 void INTERFACE_ATTRIBUTE AnnotateFlushState(char *f, int l) {
287 SCOPED_ANNOTATION(AnnotateFlushState);
290 void INTERFACE_ATTRIBUTE AnnotateNewMemory(char *f, int l, uptr mem,
291 uptr size) {
292 SCOPED_ANNOTATION(AnnotateNewMemory);
295 void INTERFACE_ATTRIBUTE AnnotateNoOp(char *f, int l, uptr mem) {
296 SCOPED_ANNOTATION(AnnotateNoOp);
299 void INTERFACE_ATTRIBUTE AnnotateFlushExpectedRaces(char *f, int l) {
300 SCOPED_ANNOTATION(AnnotateFlushExpectedRaces);
301 Lock lock(&dyn_ann_ctx->mtx);
302 while (dyn_ann_ctx->expect.next != &dyn_ann_ctx->expect) {
303 ExpectRace *race = dyn_ann_ctx->expect.next;
304 if (race->hitcount == 0) {
305 ctx->nmissed_expected++;
306 ReportMissedExpectedRace(race);
308 race->prev->next = race->next;
309 race->next->prev = race->prev;
310 internal_free(race);
314 void INTERFACE_ATTRIBUTE AnnotateEnableRaceDetection(
315 char *f, int l, int enable) {
316 SCOPED_ANNOTATION(AnnotateEnableRaceDetection);
317 // FIXME: Reconsider this functionality later. It may be irrelevant.
320 void INTERFACE_ATTRIBUTE AnnotateMutexIsUsedAsCondVar(
321 char *f, int l, uptr mu) {
322 SCOPED_ANNOTATION(AnnotateMutexIsUsedAsCondVar);
325 void INTERFACE_ATTRIBUTE AnnotatePCQGet(
326 char *f, int l, uptr pcq) {
327 SCOPED_ANNOTATION(AnnotatePCQGet);
330 void INTERFACE_ATTRIBUTE AnnotatePCQPut(
331 char *f, int l, uptr pcq) {
332 SCOPED_ANNOTATION(AnnotatePCQPut);
335 void INTERFACE_ATTRIBUTE AnnotatePCQDestroy(
336 char *f, int l, uptr pcq) {
337 SCOPED_ANNOTATION(AnnotatePCQDestroy);
340 void INTERFACE_ATTRIBUTE AnnotatePCQCreate(
341 char *f, int l, uptr pcq) {
342 SCOPED_ANNOTATION(AnnotatePCQCreate);
345 void INTERFACE_ATTRIBUTE AnnotateExpectRace(
346 char *f, int l, uptr mem, char *desc) {
347 SCOPED_ANNOTATION(AnnotateExpectRace);
348 Lock lock(&dyn_ann_ctx->mtx);
349 AddExpectRace(&dyn_ann_ctx->expect,
350 f, l, mem, 1, desc);
351 DPrintf("Add expected race: %s addr=%zx %s:%d\n", desc, mem, f, l);
354 static void BenignRaceImpl(
355 char *f, int l, uptr mem, uptr size, char *desc) {
356 Lock lock(&dyn_ann_ctx->mtx);
357 AddExpectRace(&dyn_ann_ctx->benign,
358 f, l, mem, size, desc);
359 DPrintf("Add benign race: %s addr=%zx %s:%d\n", desc, mem, f, l);
362 // FIXME: Turn it off later. WTF is benign race?1?? Go talk to Hans Boehm.
363 void INTERFACE_ATTRIBUTE AnnotateBenignRaceSized(
364 char *f, int l, uptr mem, uptr size, char *desc) {
365 SCOPED_ANNOTATION(AnnotateBenignRaceSized);
366 BenignRaceImpl(f, l, mem, size, desc);
369 void INTERFACE_ATTRIBUTE AnnotateBenignRace(
370 char *f, int l, uptr mem, char *desc) {
371 SCOPED_ANNOTATION(AnnotateBenignRace);
372 BenignRaceImpl(f, l, mem, 1, desc);
375 void INTERFACE_ATTRIBUTE AnnotateIgnoreReadsBegin(char *f, int l) {
376 SCOPED_ANNOTATION(AnnotateIgnoreReadsBegin);
377 ThreadIgnoreBegin(thr, pc);
380 void INTERFACE_ATTRIBUTE AnnotateIgnoreReadsEnd(char *f, int l) {
381 SCOPED_ANNOTATION(AnnotateIgnoreReadsEnd);
382 ThreadIgnoreEnd(thr, pc);
385 void INTERFACE_ATTRIBUTE AnnotateIgnoreWritesBegin(char *f, int l) {
386 SCOPED_ANNOTATION(AnnotateIgnoreWritesBegin);
387 ThreadIgnoreBegin(thr, pc);
390 void INTERFACE_ATTRIBUTE AnnotateIgnoreWritesEnd(char *f, int l) {
391 SCOPED_ANNOTATION(AnnotateIgnoreWritesEnd);
392 ThreadIgnoreEnd(thr, pc);
395 void INTERFACE_ATTRIBUTE AnnotateIgnoreSyncBegin(char *f, int l) {
396 SCOPED_ANNOTATION(AnnotateIgnoreSyncBegin);
397 ThreadIgnoreSyncBegin(thr, pc);
400 void INTERFACE_ATTRIBUTE AnnotateIgnoreSyncEnd(char *f, int l) {
401 SCOPED_ANNOTATION(AnnotateIgnoreSyncEnd);
402 ThreadIgnoreSyncEnd(thr, pc);
405 void INTERFACE_ATTRIBUTE AnnotatePublishMemoryRange(
406 char *f, int l, uptr addr, uptr size) {
407 SCOPED_ANNOTATION(AnnotatePublishMemoryRange);
410 void INTERFACE_ATTRIBUTE AnnotateUnpublishMemoryRange(
411 char *f, int l, uptr addr, uptr size) {
412 SCOPED_ANNOTATION(AnnotateUnpublishMemoryRange);
415 void INTERFACE_ATTRIBUTE AnnotateThreadName(
416 char *f, int l, char *name) {
417 SCOPED_ANNOTATION(AnnotateThreadName);
418 ThreadSetName(thr, name);
421 // We deliberately omit the implementation of WTFAnnotateHappensBefore() and
422 // WTFAnnotateHappensAfter(). Those are being used by Webkit to annotate
423 // atomic operations, which should be handled by ThreadSanitizer correctly.
424 void INTERFACE_ATTRIBUTE WTFAnnotateHappensBefore(char *f, int l, uptr addr) {
425 SCOPED_ANNOTATION(AnnotateHappensBefore);
428 void INTERFACE_ATTRIBUTE WTFAnnotateHappensAfter(char *f, int l, uptr addr) {
429 SCOPED_ANNOTATION(AnnotateHappensAfter);
432 void INTERFACE_ATTRIBUTE WTFAnnotateBenignRaceSized(
433 char *f, int l, uptr mem, uptr sz, char *desc) {
434 SCOPED_ANNOTATION(AnnotateBenignRaceSized);
435 BenignRaceImpl(f, l, mem, sz, desc);
438 int INTERFACE_ATTRIBUTE RunningOnValgrind() {
439 return flags()->running_on_valgrind;
442 double __attribute__((weak)) INTERFACE_ATTRIBUTE ValgrindSlowdown(void) {
443 return 10.0;
446 const char INTERFACE_ATTRIBUTE* ThreadSanitizerQuery(const char *query) {
447 if (internal_strcmp(query, "pure_happens_before") == 0)
448 return "1";
449 else
450 return "0";
453 void INTERFACE_ATTRIBUTE
454 AnnotateMemoryIsInitialized(char *f, int l, uptr mem, uptr sz) {}
455 } // extern "C"