tsan_interface_ann.cc revision 2d1fdb26e458c4ddc04155c1d421bced3ba90cd0
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.
11//
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"
25
26#define CALLERPC ((uptr)__builtin_return_address(0))
27
28using namespace __tsan;  // NOLINT
29
30namespace __tsan {
31
32class ScopedAnnotation {
33 public:
34  ScopedAnnotation(ThreadState *thr, const char *aname, const char *f, int l,
35                   uptr pc)
36      : thr_(thr) {
37    FuncEntry(thr_, pc);
38    DPrintf("#%d: annotation %s() %s:%d\n", thr_->tid, aname, f, l);
39  }
40
41  ~ScopedAnnotation() {
42    FuncExit(thr_);
43  }
44 private:
45  ThreadState *const thr_;
46};
47
48#define SCOPED_ANNOTATION(typ) \
49    if (!flags()->enable_annotations) \
50      return; \
51    ThreadState *thr = cur_thread(); \
52    const uptr caller_pc = (uptr)__builtin_return_address(0); \
53    StatInc(thr, StatAnnotation); \
54    StatInc(thr, Stat##typ); \
55    ScopedAnnotation sa(thr, __func__, f, l, caller_pc); \
56    const uptr pc = __sanitizer::StackTrace::GetCurrentPc(); \
57    (void)pc; \
58/**/
59
60static const int kMaxDescLen = 128;
61
62struct ExpectRace {
63  ExpectRace *next;
64  ExpectRace *prev;
65  int hitcount;
66  int addcount;
67  uptr addr;
68  uptr size;
69  char *file;
70  int line;
71  char desc[kMaxDescLen];
72};
73
74struct DynamicAnnContext {
75  Mutex mtx;
76  ExpectRace expect;
77  ExpectRace benign;
78
79  DynamicAnnContext()
80    : mtx(MutexTypeAnnotations, StatMtxAnnotations) {
81  }
82};
83
84static DynamicAnnContext *dyn_ann_ctx;
85static char dyn_ann_ctx_placeholder[sizeof(DynamicAnnContext)] ALIGNED(64);
86
87static void AddExpectRace(ExpectRace *list,
88    char *f, int l, uptr addr, uptr size, char *desc) {
89  ExpectRace *race = list->next;
90  for (; race != list; race = race->next) {
91    if (race->addr == addr && race->size == size) {
92      race->addcount++;
93      return;
94    }
95  }
96  race = (ExpectRace*)internal_alloc(MBlockExpectRace, sizeof(ExpectRace));
97  race->addr = addr;
98  race->size = size;
99  race->file = f;
100  race->line = l;
101  race->desc[0] = 0;
102  race->hitcount = 0;
103  race->addcount = 1;
104  if (desc) {
105    int i = 0;
106    for (; i < kMaxDescLen - 1 && desc[i]; i++)
107      race->desc[i] = desc[i];
108    race->desc[i] = 0;
109  }
110  race->prev = list;
111  race->next = list->next;
112  race->next->prev = race;
113  list->next = race;
114}
115
116static ExpectRace *FindRace(ExpectRace *list, uptr addr, uptr size) {
117  for (ExpectRace *race = list->next; race != list; race = race->next) {
118    uptr maxbegin = max(race->addr, addr);
119    uptr minend = min(race->addr + race->size, addr + size);
120    if (maxbegin < minend)
121      return race;
122  }
123  return 0;
124}
125
126static bool CheckContains(ExpectRace *list, uptr addr, uptr size) {
127  ExpectRace *race = FindRace(list, addr, size);
128  if (race == 0 && AlternativeAddress(addr))
129    race = FindRace(list, AlternativeAddress(addr), size);
130  if (race == 0)
131    return false;
132  DPrintf("Hit expected/benign race: %s addr=%zx:%d %s:%d\n",
133      race->desc, race->addr, (int)race->size, race->file, race->line);
134  race->hitcount++;
135  return true;
136}
137
138static void InitList(ExpectRace *list) {
139  list->next = list;
140  list->prev = list;
141}
142
143void InitializeDynamicAnnotations() {
144  dyn_ann_ctx = new(dyn_ann_ctx_placeholder) DynamicAnnContext;
145  InitList(&dyn_ann_ctx->expect);
146  InitList(&dyn_ann_ctx->benign);
147}
148
149bool IsExpectedReport(uptr addr, uptr size) {
150  Lock lock(&dyn_ann_ctx->mtx);
151  if (CheckContains(&dyn_ann_ctx->expect, addr, size))
152    return true;
153  if (CheckContains(&dyn_ann_ctx->benign, addr, size))
154    return true;
155  return false;
156}
157
158static void CollectMatchedBenignRaces(Vector<ExpectRace> *matched,
159    int *unique_count, int *hit_count, int ExpectRace::*counter) {
160  ExpectRace *list = &dyn_ann_ctx->benign;
161  for (ExpectRace *race = list->next; race != list; race = race->next) {
162    (*unique_count)++;
163    if (race->*counter == 0)
164      continue;
165    (*hit_count) += race->*counter;
166    uptr i = 0;
167    for (; i < matched->Size(); i++) {
168      ExpectRace *race0 = &(*matched)[i];
169      if (race->line == race0->line
170          && internal_strcmp(race->file, race0->file) == 0
171          && internal_strcmp(race->desc, race0->desc) == 0) {
172        race0->*counter += race->*counter;
173        break;
174      }
175    }
176    if (i == matched->Size())
177      matched->PushBack(*race);
178  }
179}
180
181void PrintMatchedBenignRaces() {
182  Lock lock(&dyn_ann_ctx->mtx);
183  int unique_count = 0;
184  int hit_count = 0;
185  int add_count = 0;
186  Vector<ExpectRace> hit_matched(MBlockScopedBuf);
187  CollectMatchedBenignRaces(&hit_matched, &unique_count, &hit_count,
188      &ExpectRace::hitcount);
189  Vector<ExpectRace> add_matched(MBlockScopedBuf);
190  CollectMatchedBenignRaces(&add_matched, &unique_count, &add_count,
191      &ExpectRace::addcount);
192  if (hit_matched.Size()) {
193    Printf("ThreadSanitizer: Matched %d \"benign\" races (pid=%d):\n",
194        hit_count, (int)internal_getpid());
195    for (uptr i = 0; i < hit_matched.Size(); i++) {
196      Printf("%d %s:%d %s\n",
197          hit_matched[i].hitcount, hit_matched[i].file,
198          hit_matched[i].line, hit_matched[i].desc);
199    }
200  }
201  if (hit_matched.Size()) {
202    Printf("ThreadSanitizer: Annotated %d \"benign\" races, %d unique"
203           " (pid=%d):\n",
204        add_count, unique_count, (int)internal_getpid());
205    for (uptr i = 0; i < add_matched.Size(); i++) {
206      Printf("%d %s:%d %s\n",
207          add_matched[i].addcount, add_matched[i].file,
208          add_matched[i].line, add_matched[i].desc);
209    }
210  }
211}
212
213static void ReportMissedExpectedRace(ExpectRace *race) {
214  Printf("==================\n");
215  Printf("WARNING: ThreadSanitizer: missed expected data race\n");
216  Printf("  %s addr=%zx %s:%d\n",
217      race->desc, race->addr, race->file, race->line);
218  Printf("==================\n");
219}
220}  // namespace __tsan
221
222using namespace __tsan;  // NOLINT
223
224extern "C" {
225void INTERFACE_ATTRIBUTE AnnotateHappensBefore(char *f, int l, uptr addr) {
226  SCOPED_ANNOTATION(AnnotateHappensBefore);
227  Release(thr, pc, addr);
228}
229
230void INTERFACE_ATTRIBUTE AnnotateHappensAfter(char *f, int l, uptr addr) {
231  SCOPED_ANNOTATION(AnnotateHappensAfter);
232  Acquire(thr, pc, addr);
233}
234
235void INTERFACE_ATTRIBUTE AnnotateCondVarSignal(char *f, int l, uptr cv) {
236  SCOPED_ANNOTATION(AnnotateCondVarSignal);
237}
238
239void INTERFACE_ATTRIBUTE AnnotateCondVarSignalAll(char *f, int l, uptr cv) {
240  SCOPED_ANNOTATION(AnnotateCondVarSignalAll);
241}
242
243void INTERFACE_ATTRIBUTE AnnotateMutexIsNotPHB(char *f, int l, uptr mu) {
244  SCOPED_ANNOTATION(AnnotateMutexIsNotPHB);
245}
246
247void INTERFACE_ATTRIBUTE AnnotateCondVarWait(char *f, int l, uptr cv,
248                                             uptr lock) {
249  SCOPED_ANNOTATION(AnnotateCondVarWait);
250}
251
252void INTERFACE_ATTRIBUTE AnnotateRWLockCreate(char *f, int l, uptr m) {
253  SCOPED_ANNOTATION(AnnotateRWLockCreate);
254  MutexCreate(thr, pc, m, true, true, false);
255}
256
257void INTERFACE_ATTRIBUTE AnnotateRWLockCreateStatic(char *f, int l, uptr m) {
258  SCOPED_ANNOTATION(AnnotateRWLockCreateStatic);
259  MutexCreate(thr, pc, m, true, true, true);
260}
261
262void INTERFACE_ATTRIBUTE AnnotateRWLockDestroy(char *f, int l, uptr m) {
263  SCOPED_ANNOTATION(AnnotateRWLockDestroy);
264  MutexDestroy(thr, pc, m);
265}
266
267void INTERFACE_ATTRIBUTE AnnotateRWLockAcquired(char *f, int l, uptr m,
268                                                uptr is_w) {
269  SCOPED_ANNOTATION(AnnotateRWLockAcquired);
270  if (is_w)
271    MutexLock(thr, pc, m);
272  else
273    MutexReadLock(thr, pc, m);
274}
275
276void INTERFACE_ATTRIBUTE AnnotateRWLockReleased(char *f, int l, uptr m,
277                                                uptr is_w) {
278  SCOPED_ANNOTATION(AnnotateRWLockReleased);
279  if (is_w)
280    MutexUnlock(thr, pc, m);
281  else
282    MutexReadUnlock(thr, pc, m);
283}
284
285void INTERFACE_ATTRIBUTE AnnotateTraceMemory(char *f, int l, uptr mem) {
286  SCOPED_ANNOTATION(AnnotateTraceMemory);
287}
288
289void INTERFACE_ATTRIBUTE AnnotateFlushState(char *f, int l) {
290  SCOPED_ANNOTATION(AnnotateFlushState);
291}
292
293void INTERFACE_ATTRIBUTE AnnotateNewMemory(char *f, int l, uptr mem,
294                                           uptr size) {
295  SCOPED_ANNOTATION(AnnotateNewMemory);
296}
297
298void INTERFACE_ATTRIBUTE AnnotateNoOp(char *f, int l, uptr mem) {
299  SCOPED_ANNOTATION(AnnotateNoOp);
300}
301
302void INTERFACE_ATTRIBUTE AnnotateFlushExpectedRaces(char *f, int l) {
303  SCOPED_ANNOTATION(AnnotateFlushExpectedRaces);
304  Lock lock(&dyn_ann_ctx->mtx);
305  while (dyn_ann_ctx->expect.next != &dyn_ann_ctx->expect) {
306    ExpectRace *race = dyn_ann_ctx->expect.next;
307    if (race->hitcount == 0) {
308      ctx->nmissed_expected++;
309      ReportMissedExpectedRace(race);
310    }
311    race->prev->next = race->next;
312    race->next->prev = race->prev;
313    internal_free(race);
314  }
315}
316
317void INTERFACE_ATTRIBUTE AnnotateEnableRaceDetection(
318    char *f, int l, int enable) {
319  SCOPED_ANNOTATION(AnnotateEnableRaceDetection);
320  // FIXME: Reconsider this functionality later. It may be irrelevant.
321}
322
323void INTERFACE_ATTRIBUTE AnnotateMutexIsUsedAsCondVar(
324    char *f, int l, uptr mu) {
325  SCOPED_ANNOTATION(AnnotateMutexIsUsedAsCondVar);
326}
327
328void INTERFACE_ATTRIBUTE AnnotatePCQGet(
329    char *f, int l, uptr pcq) {
330  SCOPED_ANNOTATION(AnnotatePCQGet);
331}
332
333void INTERFACE_ATTRIBUTE AnnotatePCQPut(
334    char *f, int l, uptr pcq) {
335  SCOPED_ANNOTATION(AnnotatePCQPut);
336}
337
338void INTERFACE_ATTRIBUTE AnnotatePCQDestroy(
339    char *f, int l, uptr pcq) {
340  SCOPED_ANNOTATION(AnnotatePCQDestroy);
341}
342
343void INTERFACE_ATTRIBUTE AnnotatePCQCreate(
344    char *f, int l, uptr pcq) {
345  SCOPED_ANNOTATION(AnnotatePCQCreate);
346}
347
348void INTERFACE_ATTRIBUTE AnnotateExpectRace(
349    char *f, int l, uptr mem, char *desc) {
350  SCOPED_ANNOTATION(AnnotateExpectRace);
351  Lock lock(&dyn_ann_ctx->mtx);
352  AddExpectRace(&dyn_ann_ctx->expect,
353                f, l, mem, 1, desc);
354  DPrintf("Add expected race: %s addr=%zx %s:%d\n", desc, mem, f, l);
355}
356
357static void BenignRaceImpl(
358    char *f, int l, uptr mem, uptr size, char *desc) {
359  Lock lock(&dyn_ann_ctx->mtx);
360  AddExpectRace(&dyn_ann_ctx->benign,
361                f, l, mem, size, desc);
362  DPrintf("Add benign race: %s addr=%zx %s:%d\n", desc, mem, f, l);
363}
364
365// FIXME: Turn it off later. WTF is benign race?1?? Go talk to Hans Boehm.
366void INTERFACE_ATTRIBUTE AnnotateBenignRaceSized(
367    char *f, int l, uptr mem, uptr size, char *desc) {
368  SCOPED_ANNOTATION(AnnotateBenignRaceSized);
369  BenignRaceImpl(f, l, mem, size, desc);
370}
371
372void INTERFACE_ATTRIBUTE AnnotateBenignRace(
373    char *f, int l, uptr mem, char *desc) {
374  SCOPED_ANNOTATION(AnnotateBenignRace);
375  BenignRaceImpl(f, l, mem, 1, desc);
376}
377
378void INTERFACE_ATTRIBUTE AnnotateIgnoreReadsBegin(char *f, int l) {
379  SCOPED_ANNOTATION(AnnotateIgnoreReadsBegin);
380  ThreadIgnoreBegin(thr, pc);
381}
382
383void INTERFACE_ATTRIBUTE AnnotateIgnoreReadsEnd(char *f, int l) {
384  SCOPED_ANNOTATION(AnnotateIgnoreReadsEnd);
385  ThreadIgnoreEnd(thr, pc);
386}
387
388void INTERFACE_ATTRIBUTE AnnotateIgnoreWritesBegin(char *f, int l) {
389  SCOPED_ANNOTATION(AnnotateIgnoreWritesBegin);
390  ThreadIgnoreBegin(thr, pc);
391}
392
393void INTERFACE_ATTRIBUTE AnnotateIgnoreWritesEnd(char *f, int l) {
394  SCOPED_ANNOTATION(AnnotateIgnoreWritesEnd);
395  ThreadIgnoreEnd(thr, pc);
396}
397
398void INTERFACE_ATTRIBUTE AnnotateIgnoreSyncBegin(char *f, int l) {
399  SCOPED_ANNOTATION(AnnotateIgnoreSyncBegin);
400  ThreadIgnoreSyncBegin(thr, pc);
401}
402
403void INTERFACE_ATTRIBUTE AnnotateIgnoreSyncEnd(char *f, int l) {
404  SCOPED_ANNOTATION(AnnotateIgnoreSyncEnd);
405  ThreadIgnoreSyncEnd(thr, pc);
406}
407
408void INTERFACE_ATTRIBUTE AnnotatePublishMemoryRange(
409    char *f, int l, uptr addr, uptr size) {
410  SCOPED_ANNOTATION(AnnotatePublishMemoryRange);
411}
412
413void INTERFACE_ATTRIBUTE AnnotateUnpublishMemoryRange(
414    char *f, int l, uptr addr, uptr size) {
415  SCOPED_ANNOTATION(AnnotateUnpublishMemoryRange);
416}
417
418void INTERFACE_ATTRIBUTE AnnotateThreadName(
419    char *f, int l, char *name) {
420  SCOPED_ANNOTATION(AnnotateThreadName);
421  ThreadSetName(thr, name);
422}
423
424// We deliberately omit the implementation of WTFAnnotateHappensBefore() and
425// WTFAnnotateHappensAfter(). Those are being used by Webkit to annotate
426// atomic operations, which should be handled by ThreadSanitizer correctly.
427void INTERFACE_ATTRIBUTE WTFAnnotateHappensBefore(char *f, int l, uptr addr) {
428  SCOPED_ANNOTATION(AnnotateHappensBefore);
429}
430
431void INTERFACE_ATTRIBUTE WTFAnnotateHappensAfter(char *f, int l, uptr addr) {
432  SCOPED_ANNOTATION(AnnotateHappensAfter);
433}
434
435void INTERFACE_ATTRIBUTE WTFAnnotateBenignRaceSized(
436    char *f, int l, uptr mem, uptr sz, char *desc) {
437  SCOPED_ANNOTATION(AnnotateBenignRaceSized);
438  BenignRaceImpl(f, l, mem, sz, desc);
439}
440
441int INTERFACE_ATTRIBUTE RunningOnValgrind() {
442  return flags()->running_on_valgrind;
443}
444
445double __attribute__((weak)) INTERFACE_ATTRIBUTE ValgrindSlowdown(void) {
446  return 10.0;
447}
448
449const char INTERFACE_ATTRIBUTE* ThreadSanitizerQuery(const char *query) {
450  if (internal_strcmp(query, "pure_happens_before") == 0)
451    return "1";
452  else
453    return "0";
454}
455
456void INTERFACE_ATTRIBUTE
457AnnotateMemoryIsInitialized(char *f, int l, uptr mem, uptr sz) {}
458}  // extern "C"
459