blob: 476f5cf6c2e69d0d857c75faa6186e1374204d1e [file] [log] [blame]
Alexey Samsonov3b2f9f42012-06-04 13:55:19 +00001//===-- tsan_interface_ann.cc ---------------------------------------------===//
Kostya Serebryany4ad375f2012-05-10 13:48:04 +00002//
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//===----------------------------------------------------------------------===//
Alexey Samsonov90f96302012-06-04 13:27:49 +000013#include "sanitizer_common/sanitizer_libc.h"
Alexey Samsonov8bd90982012-06-07 09:50:16 +000014#include "sanitizer_common/sanitizer_placement_new.h"
Kostya Serebryany4ad375f2012-05-10 13:48:04 +000015#include "tsan_interface_ann.h"
16#include "tsan_mutex.h"
Kostya Serebryany4ad375f2012-05-10 13:48:04 +000017#include "tsan_report.h"
18#include "tsan_rtl.h"
19#include "tsan_mman.h"
20#include "tsan_flags.h"
Dmitry Vyukovea03fc22012-06-14 21:40:35 +000021#include "tsan_platform.h"
Kostya Serebryany4ad375f2012-05-10 13:48:04 +000022
23#define CALLERPC ((uptr)__builtin_return_address(0))
24
25using namespace __tsan; // NOLINT
26
27namespace __tsan {
28
29class ScopedAnnotation {
30 public:
31 ScopedAnnotation(ThreadState *thr, const char *aname, const char *f, int l,
32 uptr pc)
33 : thr_(thr)
34 , in_rtl_(thr->in_rtl) {
35 CHECK_EQ(thr_->in_rtl, 0);
36 FuncEntry(thr_, pc);
37 thr_->in_rtl++;
38 DPrintf("#%d: annotation %s() %s:%d\n", thr_->tid, aname, f, l);
39 }
40
41 ~ScopedAnnotation() {
42 thr_->in_rtl--;
43 CHECK_EQ(in_rtl_, thr_->in_rtl);
44 FuncExit(thr_);
45 }
46 private:
47 ThreadState *const thr_;
48 const int in_rtl_;
49};
50
51#define SCOPED_ANNOTATION(typ) \
52 if (!flags()->enable_annotations) \
53 return; \
54 ThreadState *thr = cur_thread(); \
Dmitry Vyukov4723e6b2012-08-16 13:29:41 +000055 const uptr pc = (uptr)__builtin_return_address(0); \
Kostya Serebryany4ad375f2012-05-10 13:48:04 +000056 StatInc(thr, StatAnnotation); \
57 StatInc(thr, Stat##typ); \
58 ScopedAnnotation sa(thr, __FUNCTION__, f, l, \
59 (uptr)__builtin_return_address(0)); \
Kostya Serebryany4ad375f2012-05-10 13:48:04 +000060 (void)pc; \
61/**/
62
63static const int kMaxDescLen = 128;
64
65struct ExpectRace {
66 ExpectRace *next;
67 ExpectRace *prev;
68 int hitcount;
69 uptr addr;
70 uptr size;
71 char *file;
72 int line;
73 char desc[kMaxDescLen];
74};
75
76struct DynamicAnnContext {
77 Mutex mtx;
78 ExpectRace expect;
79 ExpectRace benign;
80
81 DynamicAnnContext()
82 : mtx(MutexTypeAnnotations, StatMtxAnnotations) {
83 }
84};
85
86static DynamicAnnContext *dyn_ann_ctx;
Alexey Samsonovef2e2cf2012-06-05 13:50:57 +000087static char dyn_ann_ctx_placeholder[sizeof(DynamicAnnContext)] ALIGNED(64);
Kostya Serebryany4ad375f2012-05-10 13:48:04 +000088
89static void AddExpectRace(ExpectRace *list,
90 char *f, int l, uptr addr, uptr size, char *desc) {
91 ExpectRace *race = list->next;
92 for (; race != list; race = race->next) {
93 if (race->addr == addr && race->size == size)
94 return;
95 }
96 race = (ExpectRace*)internal_alloc(MBlockExpectRace, sizeof(ExpectRace));
97 race->hitcount = 0;
98 race->addr = addr;
99 race->size = size;
100 race->file = f;
101 race->line = l;
102 race->desc[0] = 0;
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;
108 }
109 race->prev = list;
110 race->next = list->next;
111 race->next->prev = race;
112 list->next = race;
113}
114
115static 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;
121 }
122 return 0;
123}
124
125static bool CheckContains(ExpectRace *list, uptr addr, uptr size) {
126 ExpectRace *race = FindRace(list, addr, size);
Dmitry Vyukovea03fc22012-06-14 21:40:35 +0000127 if (race == 0 && AlternativeAddress(addr))
128 race = FindRace(list, AlternativeAddress(addr), size);
Kostya Serebryany4ad375f2012-05-10 13:48:04 +0000129 if (race == 0)
130 return false;
Alexey Samsonov51ae9832012-06-06 13:11:29 +0000131 DPrintf("Hit expected/benign race: %s addr=%zx:%d %s:%d\n",
Kostya Serebryany4ad375f2012-05-10 13:48:04 +0000132 race->desc, race->addr, (int)race->size, race->file, race->line);
133 race->hitcount++;
134 return true;
135}
136
137static void InitList(ExpectRace *list) {
138 list->next = list;
139 list->prev = list;
140}
141
142void InitializeDynamicAnnotations() {
143 dyn_ann_ctx = new(dyn_ann_ctx_placeholder) DynamicAnnContext;
144 InitList(&dyn_ann_ctx->expect);
145 InitList(&dyn_ann_ctx->benign);
146}
147
148bool IsExpectedReport(uptr addr, uptr size) {
149 Lock lock(&dyn_ann_ctx->mtx);
150 if (CheckContains(&dyn_ann_ctx->expect, addr, size))
151 return true;
152 if (CheckContains(&dyn_ann_ctx->benign, addr, size))
153 return true;
154 return false;
155}
156
157} // namespace __tsan
158
159using namespace __tsan; // NOLINT
160
161extern "C" {
162void AnnotateHappensBefore(char *f, int l, uptr addr) {
163 SCOPED_ANNOTATION(AnnotateHappensBefore);
164 Release(cur_thread(), CALLERPC, addr);
165}
166
167void AnnotateHappensAfter(char *f, int l, uptr addr) {
168 SCOPED_ANNOTATION(AnnotateHappensAfter);
169 Acquire(cur_thread(), CALLERPC, addr);
170}
171
172void AnnotateCondVarSignal(char *f, int l, uptr cv) {
173 SCOPED_ANNOTATION(AnnotateCondVarSignal);
174}
175
176void AnnotateCondVarSignalAll(char *f, int l, uptr cv) {
177 SCOPED_ANNOTATION(AnnotateCondVarSignalAll);
178}
179
180void AnnotateMutexIsNotPHB(char *f, int l, uptr mu) {
181 SCOPED_ANNOTATION(AnnotateMutexIsNotPHB);
182}
183
184void AnnotateCondVarWait(char *f, int l, uptr cv, uptr lock) {
185 SCOPED_ANNOTATION(AnnotateCondVarWait);
186}
187
Dmitry Vyukov4723e6b2012-08-16 13:29:41 +0000188void AnnotateRWLockCreate(char *f, int l, uptr m) {
Kostya Serebryany4ad375f2012-05-10 13:48:04 +0000189 SCOPED_ANNOTATION(AnnotateRWLockCreate);
Dmitry Vyukov4723e6b2012-08-16 13:29:41 +0000190 MutexCreate(thr, pc, m, true, true, false);
Kostya Serebryany4ad375f2012-05-10 13:48:04 +0000191}
192
Dmitry Vyukov4723e6b2012-08-16 13:29:41 +0000193void AnnotateRWLockCreateStatic(char *f, int l, uptr m) {
194 SCOPED_ANNOTATION(AnnotateRWLockCreateStatic);
195 MutexCreate(thr, pc, m, true, true, true);
196}
197
198void AnnotateRWLockDestroy(char *f, int l, uptr m) {
Kostya Serebryany4ad375f2012-05-10 13:48:04 +0000199 SCOPED_ANNOTATION(AnnotateRWLockDestroy);
Dmitry Vyukov4723e6b2012-08-16 13:29:41 +0000200 MutexDestroy(thr, pc, m);
Kostya Serebryany4ad375f2012-05-10 13:48:04 +0000201}
202
Dmitry Vyukov4723e6b2012-08-16 13:29:41 +0000203void AnnotateRWLockAcquired(char *f, int l, uptr m, uptr is_w) {
Kostya Serebryany4ad375f2012-05-10 13:48:04 +0000204 SCOPED_ANNOTATION(AnnotateRWLockAcquired);
Dmitry Vyukov4723e6b2012-08-16 13:29:41 +0000205 if (is_w)
206 MutexLock(thr, pc, m);
207 else
208 MutexReadLock(thr, pc, m);
Kostya Serebryany4ad375f2012-05-10 13:48:04 +0000209}
210
Dmitry Vyukov4723e6b2012-08-16 13:29:41 +0000211void AnnotateRWLockReleased(char *f, int l, uptr m, uptr is_w) {
Kostya Serebryany4ad375f2012-05-10 13:48:04 +0000212 SCOPED_ANNOTATION(AnnotateRWLockReleased);
Dmitry Vyukov4723e6b2012-08-16 13:29:41 +0000213 if (is_w)
214 MutexUnlock(thr, pc, m);
215 else
216 MutexReadUnlock(thr, pc, m);
Kostya Serebryany4ad375f2012-05-10 13:48:04 +0000217}
218
219void AnnotateTraceMemory(char *f, int l, uptr mem) {
220 SCOPED_ANNOTATION(AnnotateTraceMemory);
221}
222
223void AnnotateFlushState(char *f, int l) {
224 SCOPED_ANNOTATION(AnnotateFlushState);
225}
226
227void AnnotateNewMemory(char *f, int l, uptr mem, uptr size) {
228 SCOPED_ANNOTATION(AnnotateNewMemory);
229}
230
231void AnnotateNoOp(char *f, int l, uptr mem) {
232 SCOPED_ANNOTATION(AnnotateNoOp);
233}
234
235static void ReportMissedExpectedRace(ExpectRace *race) {
Alexey Samsonovad9d65f2012-11-02 12:17:51 +0000236 Printf("==================\n");
237 Printf("WARNING: ThreadSanitizer: missed expected data race\n");
238 Printf(" %s addr=%zx %s:%d\n",
Kostya Serebryany4ad375f2012-05-10 13:48:04 +0000239 race->desc, race->addr, race->file, race->line);
Alexey Samsonovad9d65f2012-11-02 12:17:51 +0000240 Printf("==================\n");
Kostya Serebryany4ad375f2012-05-10 13:48:04 +0000241}
242
243void AnnotateFlushExpectedRaces(char *f, int l) {
244 SCOPED_ANNOTATION(AnnotateFlushExpectedRaces);
245 Lock lock(&dyn_ann_ctx->mtx);
246 while (dyn_ann_ctx->expect.next != &dyn_ann_ctx->expect) {
247 ExpectRace *race = dyn_ann_ctx->expect.next;
248 if (race->hitcount == 0) {
249 CTX()->nmissed_expected++;
250 ReportMissedExpectedRace(race);
251 }
252 race->prev->next = race->next;
253 race->next->prev = race->prev;
254 internal_free(race);
255 }
256}
257
258void AnnotateEnableRaceDetection(char *f, int l, int enable) {
259 SCOPED_ANNOTATION(AnnotateEnableRaceDetection);
260 // FIXME: Reconsider this functionality later. It may be irrelevant.
261}
262
263void AnnotateMutexIsUsedAsCondVar(char *f, int l, uptr mu) {
264 SCOPED_ANNOTATION(AnnotateMutexIsUsedAsCondVar);
265}
266
267void AnnotatePCQGet(char *f, int l, uptr pcq) {
268 SCOPED_ANNOTATION(AnnotatePCQGet);
269}
270
271void AnnotatePCQPut(char *f, int l, uptr pcq) {
272 SCOPED_ANNOTATION(AnnotatePCQPut);
273}
274
275void AnnotatePCQDestroy(char *f, int l, uptr pcq) {
276 SCOPED_ANNOTATION(AnnotatePCQDestroy);
277}
278
279void AnnotatePCQCreate(char *f, int l, uptr pcq) {
280 SCOPED_ANNOTATION(AnnotatePCQCreate);
281}
282
283void AnnotateExpectRace(char *f, int l, uptr mem, char *desc) {
284 SCOPED_ANNOTATION(AnnotateExpectRace);
285 Lock lock(&dyn_ann_ctx->mtx);
286 AddExpectRace(&dyn_ann_ctx->expect,
287 f, l, mem, 1, desc);
Alexey Samsonov51ae9832012-06-06 13:11:29 +0000288 DPrintf("Add expected race: %s addr=%zx %s:%d\n", desc, mem, f, l);
Kostya Serebryany4ad375f2012-05-10 13:48:04 +0000289}
290
291static void BenignRaceImpl(char *f, int l, uptr mem, uptr size, char *desc) {
292 Lock lock(&dyn_ann_ctx->mtx);
293 AddExpectRace(&dyn_ann_ctx->benign,
294 f, l, mem, size, desc);
Alexey Samsonov51ae9832012-06-06 13:11:29 +0000295 DPrintf("Add benign race: %s addr=%zx %s:%d\n", desc, mem, f, l);
Kostya Serebryany4ad375f2012-05-10 13:48:04 +0000296}
297
298// FIXME: Turn it off later. WTF is benign race?1?? Go talk to Hans Boehm.
299void AnnotateBenignRaceSized(char *f, int l, uptr mem, uptr size, char *desc) {
300 SCOPED_ANNOTATION(AnnotateBenignRaceSized);
301 BenignRaceImpl(f, l, mem, size, desc);
302}
303
304void AnnotateBenignRace(char *f, int l, uptr mem, char *desc) {
305 SCOPED_ANNOTATION(AnnotateBenignRace);
306 BenignRaceImpl(f, l, mem, 1, desc);
307}
308
309void AnnotateIgnoreReadsBegin(char *f, int l) {
310 SCOPED_ANNOTATION(AnnotateIgnoreReadsBegin);
311 IgnoreCtl(cur_thread(), false, true);
312}
313
314void AnnotateIgnoreReadsEnd(char *f, int l) {
315 SCOPED_ANNOTATION(AnnotateIgnoreReadsEnd);
316 IgnoreCtl(cur_thread(), false, false);
317}
318
319void AnnotateIgnoreWritesBegin(char *f, int l) {
320 SCOPED_ANNOTATION(AnnotateIgnoreWritesBegin);
321 IgnoreCtl(cur_thread(), true, true);
322}
323
324void AnnotateIgnoreWritesEnd(char *f, int l) {
325 SCOPED_ANNOTATION(AnnotateIgnoreWritesEnd);
326 IgnoreCtl(cur_thread(), true, false);
327}
328
329void AnnotatePublishMemoryRange(char *f, int l, uptr addr, uptr size) {
330 SCOPED_ANNOTATION(AnnotatePublishMemoryRange);
331}
332
333void AnnotateUnpublishMemoryRange(char *f, int l, uptr addr, uptr size) {
334 SCOPED_ANNOTATION(AnnotateUnpublishMemoryRange);
335}
336
337void AnnotateThreadName(char *f, int l, char *name) {
338 SCOPED_ANNOTATION(AnnotateThreadName);
339}
340
341void WTFAnnotateHappensBefore(char *f, int l, uptr addr) {
342 SCOPED_ANNOTATION(AnnotateHappensBefore);
343}
344
345void WTFAnnotateHappensAfter(char *f, int l, uptr addr) {
346 SCOPED_ANNOTATION(AnnotateHappensAfter);
347}
348
349void WTFAnnotateBenignRaceSized(char *f, int l, uptr mem, uptr sz, char *desc) {
350 SCOPED_ANNOTATION(AnnotateBenignRaceSized);
351}
352
353int RunningOnValgrind() {
Dmitry Vyukov65c21a52012-05-24 09:24:45 +0000354 return flags()->running_on_valgrind;
Kostya Serebryany4ad375f2012-05-10 13:48:04 +0000355}
356
Dmitry Vyukov352358b2012-05-17 08:31:47 +0000357double __attribute__((weak)) ValgrindSlowdown(void) {
Dmitry Vyukov166b8e52012-05-17 08:04:41 +0000358 return 10.0;
359}
360
Kostya Serebryany4ad375f2012-05-10 13:48:04 +0000361const char *ThreadSanitizerQuery(const char *query) {
362 if (internal_strcmp(query, "pure_happens_before") == 0)
363 return "1";
364 else
365 return "0";
366}
367} // extern "C"