1 //===-- tsan_interface_ann.cc ---------------------------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
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"
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
32 class ScopedAnnotation {
34 ScopedAnnotation(ThreadState *thr, const char *aname, const char *f, int l,
38 DPrintf("#%d: annotation %s() %s:%d\n", thr_->tid, aname, f, l);
46 ThreadState *const thr_;
49 #define SCOPED_ANNOTATION(typ) \
50 if (!flags()->enable_annotations) \
52 ThreadState *thr = cur_thread(); \
53 const uptr caller_pc = (uptr)__builtin_return_address(0); \
54 StatInc(thr, StatAnnotation); \
55 StatInc(thr, Stat##typ); \
56 ScopedAnnotation sa(thr, __func__, f, l, caller_pc); \
57 const uptr pc = StackTrace::GetCurrentPc(); \
61 static const int kMaxDescLen = 128;
72 char desc[kMaxDescLen];
75 struct 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) {
97 race = (ExpectRace*)internal_alloc(MBlockExpectRace, sizeof(ExpectRace));
107 for (; i < kMaxDescLen - 1 && desc[i]; i++)
108 race->desc[i] = desc[i];
112 race->next = list->next;
113 race->next->prev = race;
117 static ExpectRace *FindRace(ExpectRace *list, uptr addr, uptr size) {
118 for (ExpectRace *race = list->next; race != list; race = race->next) {
119 uptr maxbegin = max(race->addr, addr);
120 uptr minend = min(race->addr + race->size, addr + size);
121 if (maxbegin < minend)
127 static bool CheckContains(ExpectRace *list, uptr addr, uptr size) {
128 ExpectRace *race = FindRace(list, addr, size);
131 DPrintf("Hit expected/benign race: %s addr=%zx:%d %s:%d\n",
132 race->desc, race->addr, (int)race->size, race->file, race->line);
137 static void InitList(ExpectRace *list) {
142 void InitializeDynamicAnnotations() {
143 dyn_ann_ctx = new(dyn_ann_ctx_placeholder) DynamicAnnContext;
144 InitList(&dyn_ann_ctx->expect);
145 InitList(&dyn_ann_ctx->benign);
148 bool IsExpectedReport(uptr addr, uptr size) {
149 Lock lock(&dyn_ann_ctx->mtx);
150 if (CheckContains(&dyn_ann_ctx->expect, addr, size))
152 if (CheckContains(&dyn_ann_ctx->benign, addr, size))
157 static void CollectMatchedBenignRaces(Vector<ExpectRace> *matched,
158 int *unique_count, int *hit_count, int ExpectRace::*counter) {
159 ExpectRace *list = &dyn_ann_ctx->benign;
160 for (ExpectRace *race = list->next; race != list; race = race->next) {
162 if (race->*counter == 0)
164 (*hit_count) += race->*counter;
166 for (; i < matched->Size(); i++) {
167 ExpectRace *race0 = &(*matched)[i];
168 if (race->line == race0->line
169 && internal_strcmp(race->file, race0->file) == 0
170 && internal_strcmp(race->desc, race0->desc) == 0) {
171 race0->*counter += race->*counter;
175 if (i == matched->Size())
176 matched->PushBack(*race);
180 void PrintMatchedBenignRaces() {
181 Lock lock(&dyn_ann_ctx->mtx);
182 int unique_count = 0;
185 Vector<ExpectRace> hit_matched(MBlockScopedBuf);
186 CollectMatchedBenignRaces(&hit_matched, &unique_count, &hit_count,
187 &ExpectRace::hitcount);
188 Vector<ExpectRace> add_matched(MBlockScopedBuf);
189 CollectMatchedBenignRaces(&add_matched, &unique_count, &add_count,
190 &ExpectRace::addcount);
191 if (hit_matched.Size()) {
192 Printf("ThreadSanitizer: Matched %d \"benign\" races (pid=%d):\n",
193 hit_count, (int)internal_getpid());
194 for (uptr i = 0; i < hit_matched.Size(); i++) {
195 Printf("%d %s:%d %s\n",
196 hit_matched[i].hitcount, hit_matched[i].file,
197 hit_matched[i].line, hit_matched[i].desc);
200 if (hit_matched.Size()) {
201 Printf("ThreadSanitizer: Annotated %d \"benign\" races, %d unique"
203 add_count, unique_count, (int)internal_getpid());
204 for (uptr i = 0; i < add_matched.Size(); i++) {
205 Printf("%d %s:%d %s\n",
206 add_matched[i].addcount, add_matched[i].file,
207 add_matched[i].line, add_matched[i].desc);
212 static void ReportMissedExpectedRace(ExpectRace *race) {
213 Printf("==================\n");
214 Printf("WARNING: ThreadSanitizer: missed expected data race\n");
215 Printf(" %s addr=%zx %s:%d\n",
216 race->desc, race->addr, race->file, race->line);
217 Printf("==================\n");
219 } // namespace __tsan
221 using namespace __tsan; // NOLINT
224 void INTERFACE_ATTRIBUTE AnnotateHappensBefore(char *f, int l, uptr addr) {
225 SCOPED_ANNOTATION(AnnotateHappensBefore);
226 Release(thr, pc, addr);
229 void INTERFACE_ATTRIBUTE AnnotateHappensAfter(char *f, int l, uptr addr) {
230 SCOPED_ANNOTATION(AnnotateHappensAfter);
231 Acquire(thr, pc, addr);
234 void INTERFACE_ATTRIBUTE AnnotateCondVarSignal(char *f, int l, uptr cv) {
235 SCOPED_ANNOTATION(AnnotateCondVarSignal);
238 void INTERFACE_ATTRIBUTE AnnotateCondVarSignalAll(char *f, int l, uptr cv) {
239 SCOPED_ANNOTATION(AnnotateCondVarSignalAll);
242 void INTERFACE_ATTRIBUTE AnnotateMutexIsNotPHB(char *f, int l, uptr mu) {
243 SCOPED_ANNOTATION(AnnotateMutexIsNotPHB);
246 void INTERFACE_ATTRIBUTE AnnotateCondVarWait(char *f, int l, uptr cv,
248 SCOPED_ANNOTATION(AnnotateCondVarWait);
251 void INTERFACE_ATTRIBUTE AnnotateRWLockCreate(char *f, int l, uptr m) {
252 SCOPED_ANNOTATION(AnnotateRWLockCreate);
253 MutexCreate(thr, pc, m, true, true, false);
256 void INTERFACE_ATTRIBUTE AnnotateRWLockCreateStatic(char *f, int l, uptr m) {
257 SCOPED_ANNOTATION(AnnotateRWLockCreateStatic);
258 MutexCreate(thr, pc, m, true, true, true);
261 void INTERFACE_ATTRIBUTE AnnotateRWLockDestroy(char *f, int l, uptr m) {
262 SCOPED_ANNOTATION(AnnotateRWLockDestroy);
263 MutexDestroy(thr, pc, m);
266 void INTERFACE_ATTRIBUTE AnnotateRWLockAcquired(char *f, int l, uptr m,
268 SCOPED_ANNOTATION(AnnotateRWLockAcquired);
270 MutexLock(thr, pc, m);
272 MutexReadLock(thr, pc, m);
275 void INTERFACE_ATTRIBUTE AnnotateRWLockReleased(char *f, int l, uptr m,
277 SCOPED_ANNOTATION(AnnotateRWLockReleased);
279 MutexUnlock(thr, pc, m);
281 MutexReadUnlock(thr, pc, m);
284 void INTERFACE_ATTRIBUTE AnnotateTraceMemory(char *f, int l, uptr mem) {
285 SCOPED_ANNOTATION(AnnotateTraceMemory);
288 void INTERFACE_ATTRIBUTE AnnotateFlushState(char *f, int l) {
289 SCOPED_ANNOTATION(AnnotateFlushState);
292 void INTERFACE_ATTRIBUTE AnnotateNewMemory(char *f, int l, uptr mem,
294 SCOPED_ANNOTATION(AnnotateNewMemory);
297 void INTERFACE_ATTRIBUTE AnnotateNoOp(char *f, int l, uptr mem) {
298 SCOPED_ANNOTATION(AnnotateNoOp);
301 void INTERFACE_ATTRIBUTE AnnotateFlushExpectedRaces(char *f, int l) {
302 SCOPED_ANNOTATION(AnnotateFlushExpectedRaces);
303 Lock lock(&dyn_ann_ctx->mtx);
304 while (dyn_ann_ctx->expect.next != &dyn_ann_ctx->expect) {
305 ExpectRace *race = dyn_ann_ctx->expect.next;
306 if (race->hitcount == 0) {
307 ctx->nmissed_expected++;
308 ReportMissedExpectedRace(race);
310 race->prev->next = race->next;
311 race->next->prev = race->prev;
316 void INTERFACE_ATTRIBUTE AnnotateEnableRaceDetection(
317 char *f, int l, int enable) {
318 SCOPED_ANNOTATION(AnnotateEnableRaceDetection);
319 // FIXME: Reconsider this functionality later. It may be irrelevant.
322 void INTERFACE_ATTRIBUTE AnnotateMutexIsUsedAsCondVar(
323 char *f, int l, uptr mu) {
324 SCOPED_ANNOTATION(AnnotateMutexIsUsedAsCondVar);
327 void INTERFACE_ATTRIBUTE AnnotatePCQGet(
328 char *f, int l, uptr pcq) {
329 SCOPED_ANNOTATION(AnnotatePCQGet);
332 void INTERFACE_ATTRIBUTE AnnotatePCQPut(
333 char *f, int l, uptr pcq) {
334 SCOPED_ANNOTATION(AnnotatePCQPut);
337 void INTERFACE_ATTRIBUTE AnnotatePCQDestroy(
338 char *f, int l, uptr pcq) {
339 SCOPED_ANNOTATION(AnnotatePCQDestroy);
342 void INTERFACE_ATTRIBUTE AnnotatePCQCreate(
343 char *f, int l, uptr pcq) {
344 SCOPED_ANNOTATION(AnnotatePCQCreate);
347 void INTERFACE_ATTRIBUTE AnnotateExpectRace(
348 char *f, int l, uptr mem, char *desc) {
349 SCOPED_ANNOTATION(AnnotateExpectRace);
350 Lock lock(&dyn_ann_ctx->mtx);
351 AddExpectRace(&dyn_ann_ctx->expect,
353 DPrintf("Add expected race: %s addr=%zx %s:%d\n", desc, mem, f, l);
356 static void BenignRaceImpl(
357 char *f, int l, uptr mem, uptr size, char *desc) {
358 Lock lock(&dyn_ann_ctx->mtx);
359 AddExpectRace(&dyn_ann_ctx->benign,
360 f, l, mem, size, desc);
361 DPrintf("Add benign race: %s addr=%zx %s:%d\n", desc, mem, f, l);
364 // FIXME: Turn it off later. WTF is benign race?1?? Go talk to Hans Boehm.
365 void INTERFACE_ATTRIBUTE AnnotateBenignRaceSized(
366 char *f, int l, uptr mem, uptr size, char *desc) {
367 SCOPED_ANNOTATION(AnnotateBenignRaceSized);
368 BenignRaceImpl(f, l, mem, size, desc);
371 void INTERFACE_ATTRIBUTE AnnotateBenignRace(
372 char *f, int l, uptr mem, char *desc) {
373 SCOPED_ANNOTATION(AnnotateBenignRace);
374 BenignRaceImpl(f, l, mem, 1, desc);
377 void INTERFACE_ATTRIBUTE AnnotateIgnoreReadsBegin(char *f, int l) {
378 SCOPED_ANNOTATION(AnnotateIgnoreReadsBegin);
379 ThreadIgnoreBegin(thr, pc);
382 void INTERFACE_ATTRIBUTE AnnotateIgnoreReadsEnd(char *f, int l) {
383 SCOPED_ANNOTATION(AnnotateIgnoreReadsEnd);
384 ThreadIgnoreEnd(thr, pc);
387 void INTERFACE_ATTRIBUTE AnnotateIgnoreWritesBegin(char *f, int l) {
388 SCOPED_ANNOTATION(AnnotateIgnoreWritesBegin);
389 ThreadIgnoreBegin(thr, pc);
392 void INTERFACE_ATTRIBUTE AnnotateIgnoreWritesEnd(char *f, int l) {
393 SCOPED_ANNOTATION(AnnotateIgnoreWritesEnd);
394 ThreadIgnoreEnd(thr, pc);
397 void INTERFACE_ATTRIBUTE AnnotateIgnoreSyncBegin(char *f, int l) {
398 SCOPED_ANNOTATION(AnnotateIgnoreSyncBegin);
399 ThreadIgnoreSyncBegin(thr, pc);
402 void INTERFACE_ATTRIBUTE AnnotateIgnoreSyncEnd(char *f, int l) {
403 SCOPED_ANNOTATION(AnnotateIgnoreSyncEnd);
404 ThreadIgnoreSyncEnd(thr, pc);
407 void INTERFACE_ATTRIBUTE AnnotatePublishMemoryRange(
408 char *f, int l, uptr addr, uptr size) {
409 SCOPED_ANNOTATION(AnnotatePublishMemoryRange);
412 void INTERFACE_ATTRIBUTE AnnotateUnpublishMemoryRange(
413 char *f, int l, uptr addr, uptr size) {
414 SCOPED_ANNOTATION(AnnotateUnpublishMemoryRange);
417 void INTERFACE_ATTRIBUTE AnnotateThreadName(
418 char *f, int l, char *name) {
419 SCOPED_ANNOTATION(AnnotateThreadName);
420 ThreadSetName(thr, name);
423 // We deliberately omit the implementation of WTFAnnotateHappensBefore() and
424 // WTFAnnotateHappensAfter(). Those are being used by Webkit to annotate
425 // atomic operations, which should be handled by ThreadSanitizer correctly.
426 void INTERFACE_ATTRIBUTE WTFAnnotateHappensBefore(char *f, int l, uptr addr) {
427 SCOPED_ANNOTATION(AnnotateHappensBefore);
430 void INTERFACE_ATTRIBUTE WTFAnnotateHappensAfter(char *f, int l, uptr addr) {
431 SCOPED_ANNOTATION(AnnotateHappensAfter);
434 void INTERFACE_ATTRIBUTE WTFAnnotateBenignRaceSized(
435 char *f, int l, uptr mem, uptr sz, char *desc) {
436 SCOPED_ANNOTATION(AnnotateBenignRaceSized);
437 BenignRaceImpl(f, l, mem, sz, desc);
440 int INTERFACE_ATTRIBUTE RunningOnValgrind() {
441 return flags()->running_on_valgrind;
444 double __attribute__((weak)) INTERFACE_ATTRIBUTE ValgrindSlowdown(void) {
448 const char INTERFACE_ATTRIBUTE* ThreadSanitizerQuery(const char *query) {
449 if (internal_strcmp(query, "pure_happens_before") == 0)
455 void INTERFACE_ATTRIBUTE
456 AnnotateMemoryIsInitialized(char *f, int l, uptr mem, uptr sz) {}
457 void INTERFACE_ATTRIBUTE
458 AnnotateMemoryIsUninitialized(char *f, int l, uptr mem, uptr sz) {}