tsan: better diagnostics if thread finishes with ignores enabled
[blocksruntime.git] / lib / tsan / rtl / tsan_interface_ann.cc
blobc6a57b339918af51bf56c1200dc9b29f4a471340
1 //===-- tsan_interface_ann.cc ---------------------------------------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file is a part of ThreadSanitizer (TSan), a race detector.
12 //===----------------------------------------------------------------------===//
13 #include "sanitizer_common/sanitizer_libc.h"
14 #include "sanitizer_common/sanitizer_internal_defs.h"
15 #include "sanitizer_common/sanitizer_placement_new.h"
16 #include "sanitizer_common/sanitizer_stacktrace.h"
17 #include "tsan_interface_ann.h"
18 #include "tsan_mutex.h"
19 #include "tsan_report.h"
20 #include "tsan_rtl.h"
21 #include "tsan_mman.h"
22 #include "tsan_flags.h"
23 #include "tsan_platform.h"
24 #include "tsan_vector.h"
26 #define CALLERPC ((uptr)__builtin_return_address(0))
28 using namespace __tsan; // NOLINT
30 namespace __tsan {
32 class ScopedAnnotation {
33 public:
34 ScopedAnnotation(ThreadState *thr, const char *aname, const char *f, int l,
35 uptr pc)
36 : thr_(thr)
37 , in_rtl_(thr->in_rtl) {
38 CHECK_EQ(thr_->in_rtl, 0);
39 FuncEntry(thr_, pc);
40 thr_->in_rtl++;
41 DPrintf("#%d: annotation %s() %s:%d\n", thr_->tid, aname, f, l);
44 ~ScopedAnnotation() {
45 thr_->in_rtl--;
46 CHECK_EQ(in_rtl_, thr_->in_rtl);
47 FuncExit(thr_);
49 private:
50 ThreadState *const thr_;
51 const int in_rtl_;
54 #define SCOPED_ANNOTATION(typ) \
55 if (!flags()->enable_annotations) \
56 return; \
57 ThreadState *thr = cur_thread(); \
58 const uptr caller_pc = (uptr)__builtin_return_address(0); \
59 StatInc(thr, StatAnnotation); \
60 StatInc(thr, Stat##typ); \
61 ScopedAnnotation sa(thr, __FUNCTION__, f, l, caller_pc); \
62 const uptr pc = __sanitizer::StackTrace::GetCurrentPc(); \
63 (void)pc; \
64 /**/
66 static const int kMaxDescLen = 128;
68 struct ExpectRace {
69 ExpectRace *next;
70 ExpectRace *prev;
71 int hitcount;
72 int addcount;
73 uptr addr;
74 uptr size;
75 char *file;
76 int line;
77 char desc[kMaxDescLen];
80 struct DynamicAnnContext {
81 Mutex mtx;
82 ExpectRace expect;
83 ExpectRace benign;
85 DynamicAnnContext()
86 : mtx(MutexTypeAnnotations, StatMtxAnnotations) {
90 static DynamicAnnContext *dyn_ann_ctx;
91 static char dyn_ann_ctx_placeholder[sizeof(DynamicAnnContext)] ALIGNED(64);
93 static void AddExpectRace(ExpectRace *list,
94 char *f, int l, uptr addr, uptr size, char *desc) {
95 ExpectRace *race = list->next;
96 for (; race != list; race = race->next) {
97 if (race->addr == addr && race->size == size) {
98 race->addcount++;
99 return;
102 race = (ExpectRace*)internal_alloc(MBlockExpectRace, sizeof(ExpectRace));
103 race->addr = addr;
104 race->size = size;
105 race->file = f;
106 race->line = l;
107 race->desc[0] = 0;
108 race->hitcount = 0;
109 race->addcount = 1;
110 if (desc) {
111 int i = 0;
112 for (; i < kMaxDescLen - 1 && desc[i]; i++)
113 race->desc[i] = desc[i];
114 race->desc[i] = 0;
116 race->prev = list;
117 race->next = list->next;
118 race->next->prev = race;
119 list->next = race;
122 static ExpectRace *FindRace(ExpectRace *list, uptr addr, uptr size) {
123 for (ExpectRace *race = list->next; race != list; race = race->next) {
124 uptr maxbegin = max(race->addr, addr);
125 uptr minend = min(race->addr + race->size, addr + size);
126 if (maxbegin < minend)
127 return race;
129 return 0;
132 static bool CheckContains(ExpectRace *list, uptr addr, uptr size) {
133 ExpectRace *race = FindRace(list, addr, size);
134 if (race == 0 && AlternativeAddress(addr))
135 race = FindRace(list, AlternativeAddress(addr), size);
136 if (race == 0)
137 return false;
138 DPrintf("Hit expected/benign race: %s addr=%zx:%d %s:%d\n",
139 race->desc, race->addr, (int)race->size, race->file, race->line);
140 race->hitcount++;
141 return true;
144 static void InitList(ExpectRace *list) {
145 list->next = list;
146 list->prev = list;
149 void InitializeDynamicAnnotations() {
150 dyn_ann_ctx = new(dyn_ann_ctx_placeholder) DynamicAnnContext;
151 InitList(&dyn_ann_ctx->expect);
152 InitList(&dyn_ann_ctx->benign);
155 bool IsExpectedReport(uptr addr, uptr size) {
156 Lock lock(&dyn_ann_ctx->mtx);
157 if (CheckContains(&dyn_ann_ctx->expect, addr, size))
158 return true;
159 if (CheckContains(&dyn_ann_ctx->benign, addr, size))
160 return true;
161 return false;
164 static void CollectMatchedBenignRaces(Vector<ExpectRace> *matched,
165 int *unique_count, int *hit_count, int ExpectRace::*counter) {
166 ExpectRace *list = &dyn_ann_ctx->benign;
167 for (ExpectRace *race = list->next; race != list; race = race->next) {
168 (*unique_count)++;
169 if (race->*counter == 0)
170 continue;
171 (*hit_count) += race->*counter;
172 uptr i = 0;
173 for (; i < matched->Size(); i++) {
174 ExpectRace *race0 = &(*matched)[i];
175 if (race->line == race0->line
176 && internal_strcmp(race->file, race0->file) == 0
177 && internal_strcmp(race->desc, race0->desc) == 0) {
178 race0->*counter += race->*counter;
179 break;
182 if (i == matched->Size())
183 matched->PushBack(*race);
187 void PrintMatchedBenignRaces() {
188 Lock lock(&dyn_ann_ctx->mtx);
189 int unique_count = 0;
190 int hit_count = 0;
191 int add_count = 0;
192 Vector<ExpectRace> hit_matched(MBlockScopedBuf);
193 CollectMatchedBenignRaces(&hit_matched, &unique_count, &hit_count,
194 &ExpectRace::hitcount);
195 Vector<ExpectRace> add_matched(MBlockScopedBuf);
196 CollectMatchedBenignRaces(&add_matched, &unique_count, &add_count,
197 &ExpectRace::addcount);
198 if (hit_matched.Size()) {
199 Printf("ThreadSanitizer: Matched %d \"benign\" races (pid=%d):\n",
200 hit_count, (int)internal_getpid());
201 for (uptr i = 0; i < hit_matched.Size(); i++) {
202 Printf("%d %s:%d %s\n",
203 hit_matched[i].hitcount, hit_matched[i].file,
204 hit_matched[i].line, hit_matched[i].desc);
207 if (hit_matched.Size()) {
208 Printf("ThreadSanitizer: Annotated %d \"benign\" races, %d unique"
209 " (pid=%d):\n",
210 add_count, unique_count, (int)internal_getpid());
211 for (uptr i = 0; i < add_matched.Size(); i++) {
212 Printf("%d %s:%d %s\n",
213 add_matched[i].addcount, add_matched[i].file,
214 add_matched[i].line, add_matched[i].desc);
219 static void ReportMissedExpectedRace(ExpectRace *race) {
220 Printf("==================\n");
221 Printf("WARNING: ThreadSanitizer: missed expected data race\n");
222 Printf(" %s addr=%zx %s:%d\n",
223 race->desc, race->addr, race->file, race->line);
224 Printf("==================\n");
226 } // namespace __tsan
228 using namespace __tsan; // NOLINT
230 extern "C" {
231 void INTERFACE_ATTRIBUTE AnnotateHappensBefore(char *f, int l, uptr addr) {
232 SCOPED_ANNOTATION(AnnotateHappensBefore);
233 Release(thr, pc, addr);
236 void INTERFACE_ATTRIBUTE AnnotateHappensAfter(char *f, int l, uptr addr) {
237 SCOPED_ANNOTATION(AnnotateHappensAfter);
238 Acquire(thr, pc, addr);
241 void INTERFACE_ATTRIBUTE AnnotateCondVarSignal(char *f, int l, uptr cv) {
242 SCOPED_ANNOTATION(AnnotateCondVarSignal);
245 void INTERFACE_ATTRIBUTE AnnotateCondVarSignalAll(char *f, int l, uptr cv) {
246 SCOPED_ANNOTATION(AnnotateCondVarSignalAll);
249 void INTERFACE_ATTRIBUTE AnnotateMutexIsNotPHB(char *f, int l, uptr mu) {
250 SCOPED_ANNOTATION(AnnotateMutexIsNotPHB);
253 void INTERFACE_ATTRIBUTE AnnotateCondVarWait(char *f, int l, uptr cv,
254 uptr lock) {
255 SCOPED_ANNOTATION(AnnotateCondVarWait);
258 void INTERFACE_ATTRIBUTE AnnotateRWLockCreate(char *f, int l, uptr m) {
259 SCOPED_ANNOTATION(AnnotateRWLockCreate);
260 MutexCreate(thr, pc, m, true, true, false);
263 void INTERFACE_ATTRIBUTE AnnotateRWLockCreateStatic(char *f, int l, uptr m) {
264 SCOPED_ANNOTATION(AnnotateRWLockCreateStatic);
265 MutexCreate(thr, pc, m, true, true, true);
268 void INTERFACE_ATTRIBUTE AnnotateRWLockDestroy(char *f, int l, uptr m) {
269 SCOPED_ANNOTATION(AnnotateRWLockDestroy);
270 MutexDestroy(thr, pc, m);
273 void INTERFACE_ATTRIBUTE AnnotateRWLockAcquired(char *f, int l, uptr m,
274 uptr is_w) {
275 SCOPED_ANNOTATION(AnnotateRWLockAcquired);
276 if (is_w)
277 MutexLock(thr, pc, m);
278 else
279 MutexReadLock(thr, pc, m);
282 void INTERFACE_ATTRIBUTE AnnotateRWLockReleased(char *f, int l, uptr m,
283 uptr is_w) {
284 SCOPED_ANNOTATION(AnnotateRWLockReleased);
285 if (is_w)
286 MutexUnlock(thr, pc, m);
287 else
288 MutexReadUnlock(thr, pc, m);
291 void INTERFACE_ATTRIBUTE AnnotateTraceMemory(char *f, int l, uptr mem) {
292 SCOPED_ANNOTATION(AnnotateTraceMemory);
295 void INTERFACE_ATTRIBUTE AnnotateFlushState(char *f, int l) {
296 SCOPED_ANNOTATION(AnnotateFlushState);
299 void INTERFACE_ATTRIBUTE AnnotateNewMemory(char *f, int l, uptr mem,
300 uptr size) {
301 SCOPED_ANNOTATION(AnnotateNewMemory);
304 void INTERFACE_ATTRIBUTE AnnotateNoOp(char *f, int l, uptr mem) {
305 SCOPED_ANNOTATION(AnnotateNoOp);
308 void INTERFACE_ATTRIBUTE AnnotateFlushExpectedRaces(char *f, int l) {
309 SCOPED_ANNOTATION(AnnotateFlushExpectedRaces);
310 Lock lock(&dyn_ann_ctx->mtx);
311 while (dyn_ann_ctx->expect.next != &dyn_ann_ctx->expect) {
312 ExpectRace *race = dyn_ann_ctx->expect.next;
313 if (race->hitcount == 0) {
314 CTX()->nmissed_expected++;
315 ReportMissedExpectedRace(race);
317 race->prev->next = race->next;
318 race->next->prev = race->prev;
319 internal_free(race);
323 void INTERFACE_ATTRIBUTE AnnotateEnableRaceDetection(
324 char *f, int l, int enable) {
325 SCOPED_ANNOTATION(AnnotateEnableRaceDetection);
326 // FIXME: Reconsider this functionality later. It may be irrelevant.
329 void INTERFACE_ATTRIBUTE AnnotateMutexIsUsedAsCondVar(
330 char *f, int l, uptr mu) {
331 SCOPED_ANNOTATION(AnnotateMutexIsUsedAsCondVar);
334 void INTERFACE_ATTRIBUTE AnnotatePCQGet(
335 char *f, int l, uptr pcq) {
336 SCOPED_ANNOTATION(AnnotatePCQGet);
339 void INTERFACE_ATTRIBUTE AnnotatePCQPut(
340 char *f, int l, uptr pcq) {
341 SCOPED_ANNOTATION(AnnotatePCQPut);
344 void INTERFACE_ATTRIBUTE AnnotatePCQDestroy(
345 char *f, int l, uptr pcq) {
346 SCOPED_ANNOTATION(AnnotatePCQDestroy);
349 void INTERFACE_ATTRIBUTE AnnotatePCQCreate(
350 char *f, int l, uptr pcq) {
351 SCOPED_ANNOTATION(AnnotatePCQCreate);
354 void INTERFACE_ATTRIBUTE AnnotateExpectRace(
355 char *f, int l, uptr mem, char *desc) {
356 SCOPED_ANNOTATION(AnnotateExpectRace);
357 Lock lock(&dyn_ann_ctx->mtx);
358 AddExpectRace(&dyn_ann_ctx->expect,
359 f, l, mem, 1, desc);
360 DPrintf("Add expected race: %s addr=%zx %s:%d\n", desc, mem, f, l);
363 static void BenignRaceImpl(
364 char *f, int l, uptr mem, uptr size, char *desc) {
365 Lock lock(&dyn_ann_ctx->mtx);
366 AddExpectRace(&dyn_ann_ctx->benign,
367 f, l, mem, size, desc);
368 DPrintf("Add benign race: %s addr=%zx %s:%d\n", desc, mem, f, l);
371 // FIXME: Turn it off later. WTF is benign race?1?? Go talk to Hans Boehm.
372 void INTERFACE_ATTRIBUTE AnnotateBenignRaceSized(
373 char *f, int l, uptr mem, uptr size, char *desc) {
374 SCOPED_ANNOTATION(AnnotateBenignRaceSized);
375 BenignRaceImpl(f, l, mem, size, desc);
378 void INTERFACE_ATTRIBUTE AnnotateBenignRace(
379 char *f, int l, uptr mem, char *desc) {
380 SCOPED_ANNOTATION(AnnotateBenignRace);
381 BenignRaceImpl(f, l, mem, 1, desc);
384 void INTERFACE_ATTRIBUTE AnnotateIgnoreReadsBegin(char *f, int l) {
385 SCOPED_ANNOTATION(AnnotateIgnoreReadsBegin);
386 ThreadIgnoreBegin(thr, pc);
389 void INTERFACE_ATTRIBUTE AnnotateIgnoreReadsEnd(char *f, int l) {
390 SCOPED_ANNOTATION(AnnotateIgnoreReadsEnd);
391 ThreadIgnoreEnd(thr, pc);
394 void INTERFACE_ATTRIBUTE AnnotateIgnoreWritesBegin(char *f, int l) {
395 SCOPED_ANNOTATION(AnnotateIgnoreWritesBegin);
396 ThreadIgnoreBegin(thr, pc);
399 void INTERFACE_ATTRIBUTE AnnotateIgnoreWritesEnd(char *f, int l) {
400 SCOPED_ANNOTATION(AnnotateIgnoreWritesEnd);
401 ThreadIgnoreEnd(thr, pc);
404 void INTERFACE_ATTRIBUTE AnnotateIgnoreSyncBegin(char *f, int l) {
405 SCOPED_ANNOTATION(AnnotateIgnoreSyncBegin);
406 ThreadIgnoreSyncBegin(thr, pc);
409 void INTERFACE_ATTRIBUTE AnnotateIgnoreSyncEnd(char *f, int l) {
410 SCOPED_ANNOTATION(AnnotateIgnoreSyncEnd);
411 ThreadIgnoreSyncEnd(thr, pc);
414 void INTERFACE_ATTRIBUTE AnnotatePublishMemoryRange(
415 char *f, int l, uptr addr, uptr size) {
416 SCOPED_ANNOTATION(AnnotatePublishMemoryRange);
419 void INTERFACE_ATTRIBUTE AnnotateUnpublishMemoryRange(
420 char *f, int l, uptr addr, uptr size) {
421 SCOPED_ANNOTATION(AnnotateUnpublishMemoryRange);
424 void INTERFACE_ATTRIBUTE AnnotateThreadName(
425 char *f, int l, char *name) {
426 SCOPED_ANNOTATION(AnnotateThreadName);
427 ThreadSetName(thr, name);
430 // We deliberately omit the implementation of WTFAnnotateHappensBefore() and
431 // WTFAnnotateHappensAfter(). Those are being used by Webkit to annotate
432 // atomic operations, which should be handled by ThreadSanitizer correctly.
433 void INTERFACE_ATTRIBUTE WTFAnnotateHappensBefore(char *f, int l, uptr addr) {
434 SCOPED_ANNOTATION(AnnotateHappensBefore);
437 void INTERFACE_ATTRIBUTE WTFAnnotateHappensAfter(char *f, int l, uptr addr) {
438 SCOPED_ANNOTATION(AnnotateHappensAfter);
441 void INTERFACE_ATTRIBUTE WTFAnnotateBenignRaceSized(
442 char *f, int l, uptr mem, uptr sz, char *desc) {
443 SCOPED_ANNOTATION(AnnotateBenignRaceSized);
444 BenignRaceImpl(f, l, mem, sz, desc);
447 int INTERFACE_ATTRIBUTE RunningOnValgrind() {
448 return flags()->running_on_valgrind;
451 double __attribute__((weak)) INTERFACE_ATTRIBUTE ValgrindSlowdown(void) {
452 return 10.0;
455 const char INTERFACE_ATTRIBUTE* ThreadSanitizerQuery(const char *query) {
456 if (internal_strcmp(query, "pure_happens_before") == 0)
457 return "1";
458 else
459 return "0";
462 void INTERFACE_ATTRIBUTE
463 AnnotateMemoryIsInitialized(char *f, int l, uptr mem, uptr sz) {}
464 } // extern "C"