blob: a605b6c9d3f0ab85be460b321044d937284a15b8 [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(); \
55 StatInc(thr, StatAnnotation); \
56 StatInc(thr, Stat##typ); \
57 ScopedAnnotation sa(thr, __FUNCTION__, f, l, \
58 (uptr)__builtin_return_address(0)); \
59 const uptr pc = (uptr)&__FUNCTION__; \
60 (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
188void AnnotateRWLockCreate(char *f, int l, uptr lock) {
189 SCOPED_ANNOTATION(AnnotateRWLockCreate);
190}
191
192void AnnotateRWLockDestroy(char *f, int l, uptr lock) {
193 SCOPED_ANNOTATION(AnnotateRWLockDestroy);
194}
195
196void AnnotateRWLockAcquired(char *f, int l, uptr lock, uptr is_w) {
197 SCOPED_ANNOTATION(AnnotateRWLockAcquired);
198}
199
200void AnnotateRWLockReleased(char *f, int l, uptr lock, uptr is_w) {
201 SCOPED_ANNOTATION(AnnotateRWLockReleased);
202}
203
204void AnnotateTraceMemory(char *f, int l, uptr mem) {
205 SCOPED_ANNOTATION(AnnotateTraceMemory);
206}
207
208void AnnotateFlushState(char *f, int l) {
209 SCOPED_ANNOTATION(AnnotateFlushState);
210}
211
212void AnnotateNewMemory(char *f, int l, uptr mem, uptr size) {
213 SCOPED_ANNOTATION(AnnotateNewMemory);
214}
215
216void AnnotateNoOp(char *f, int l, uptr mem) {
217 SCOPED_ANNOTATION(AnnotateNoOp);
218}
219
220static void ReportMissedExpectedRace(ExpectRace *race) {
Alexey Samsonovac4c2902012-06-06 10:13:27 +0000221 TsanPrintf("==================\n");
222 TsanPrintf("WARNING: ThreadSanitizer: missed expected data race\n");
Alexey Samsonov51ae9832012-06-06 13:11:29 +0000223 TsanPrintf(" %s addr=%zx %s:%d\n",
Kostya Serebryany4ad375f2012-05-10 13:48:04 +0000224 race->desc, race->addr, race->file, race->line);
Alexey Samsonovac4c2902012-06-06 10:13:27 +0000225 TsanPrintf("==================\n");
Kostya Serebryany4ad375f2012-05-10 13:48:04 +0000226}
227
228void AnnotateFlushExpectedRaces(char *f, int l) {
229 SCOPED_ANNOTATION(AnnotateFlushExpectedRaces);
230 Lock lock(&dyn_ann_ctx->mtx);
231 while (dyn_ann_ctx->expect.next != &dyn_ann_ctx->expect) {
232 ExpectRace *race = dyn_ann_ctx->expect.next;
233 if (race->hitcount == 0) {
234 CTX()->nmissed_expected++;
235 ReportMissedExpectedRace(race);
236 }
237 race->prev->next = race->next;
238 race->next->prev = race->prev;
239 internal_free(race);
240 }
241}
242
243void AnnotateEnableRaceDetection(char *f, int l, int enable) {
244 SCOPED_ANNOTATION(AnnotateEnableRaceDetection);
245 // FIXME: Reconsider this functionality later. It may be irrelevant.
246}
247
248void AnnotateMutexIsUsedAsCondVar(char *f, int l, uptr mu) {
249 SCOPED_ANNOTATION(AnnotateMutexIsUsedAsCondVar);
250}
251
252void AnnotatePCQGet(char *f, int l, uptr pcq) {
253 SCOPED_ANNOTATION(AnnotatePCQGet);
254}
255
256void AnnotatePCQPut(char *f, int l, uptr pcq) {
257 SCOPED_ANNOTATION(AnnotatePCQPut);
258}
259
260void AnnotatePCQDestroy(char *f, int l, uptr pcq) {
261 SCOPED_ANNOTATION(AnnotatePCQDestroy);
262}
263
264void AnnotatePCQCreate(char *f, int l, uptr pcq) {
265 SCOPED_ANNOTATION(AnnotatePCQCreate);
266}
267
268void AnnotateExpectRace(char *f, int l, uptr mem, char *desc) {
269 SCOPED_ANNOTATION(AnnotateExpectRace);
270 Lock lock(&dyn_ann_ctx->mtx);
271 AddExpectRace(&dyn_ann_ctx->expect,
272 f, l, mem, 1, desc);
Alexey Samsonov51ae9832012-06-06 13:11:29 +0000273 DPrintf("Add expected race: %s addr=%zx %s:%d\n", desc, mem, f, l);
Kostya Serebryany4ad375f2012-05-10 13:48:04 +0000274}
275
276static void BenignRaceImpl(char *f, int l, uptr mem, uptr size, char *desc) {
277 Lock lock(&dyn_ann_ctx->mtx);
278 AddExpectRace(&dyn_ann_ctx->benign,
279 f, l, mem, size, desc);
Alexey Samsonov51ae9832012-06-06 13:11:29 +0000280 DPrintf("Add benign race: %s addr=%zx %s:%d\n", desc, mem, f, l);
Kostya Serebryany4ad375f2012-05-10 13:48:04 +0000281}
282
283// FIXME: Turn it off later. WTF is benign race?1?? Go talk to Hans Boehm.
284void AnnotateBenignRaceSized(char *f, int l, uptr mem, uptr size, char *desc) {
285 SCOPED_ANNOTATION(AnnotateBenignRaceSized);
286 BenignRaceImpl(f, l, mem, size, desc);
287}
288
289void AnnotateBenignRace(char *f, int l, uptr mem, char *desc) {
290 SCOPED_ANNOTATION(AnnotateBenignRace);
291 BenignRaceImpl(f, l, mem, 1, desc);
292}
293
294void AnnotateIgnoreReadsBegin(char *f, int l) {
295 SCOPED_ANNOTATION(AnnotateIgnoreReadsBegin);
296 IgnoreCtl(cur_thread(), false, true);
297}
298
299void AnnotateIgnoreReadsEnd(char *f, int l) {
300 SCOPED_ANNOTATION(AnnotateIgnoreReadsEnd);
301 IgnoreCtl(cur_thread(), false, false);
302}
303
304void AnnotateIgnoreWritesBegin(char *f, int l) {
305 SCOPED_ANNOTATION(AnnotateIgnoreWritesBegin);
306 IgnoreCtl(cur_thread(), true, true);
307}
308
309void AnnotateIgnoreWritesEnd(char *f, int l) {
310 SCOPED_ANNOTATION(AnnotateIgnoreWritesEnd);
311 IgnoreCtl(cur_thread(), true, false);
312}
313
314void AnnotatePublishMemoryRange(char *f, int l, uptr addr, uptr size) {
315 SCOPED_ANNOTATION(AnnotatePublishMemoryRange);
316}
317
318void AnnotateUnpublishMemoryRange(char *f, int l, uptr addr, uptr size) {
319 SCOPED_ANNOTATION(AnnotateUnpublishMemoryRange);
320}
321
322void AnnotateThreadName(char *f, int l, char *name) {
323 SCOPED_ANNOTATION(AnnotateThreadName);
324}
325
326void WTFAnnotateHappensBefore(char *f, int l, uptr addr) {
327 SCOPED_ANNOTATION(AnnotateHappensBefore);
328}
329
330void WTFAnnotateHappensAfter(char *f, int l, uptr addr) {
331 SCOPED_ANNOTATION(AnnotateHappensAfter);
332}
333
334void WTFAnnotateBenignRaceSized(char *f, int l, uptr mem, uptr sz, char *desc) {
335 SCOPED_ANNOTATION(AnnotateBenignRaceSized);
336}
337
338int RunningOnValgrind() {
Dmitry Vyukov65c21a52012-05-24 09:24:45 +0000339 return flags()->running_on_valgrind;
Kostya Serebryany4ad375f2012-05-10 13:48:04 +0000340}
341
Dmitry Vyukov352358b2012-05-17 08:31:47 +0000342double __attribute__((weak)) ValgrindSlowdown(void) {
Dmitry Vyukov166b8e52012-05-17 08:04:41 +0000343 return 10.0;
344}
345
Kostya Serebryany4ad375f2012-05-10 13:48:04 +0000346const char *ThreadSanitizerQuery(const char *query) {
347 if (internal_strcmp(query, "pure_happens_before") == 0)
348 return "1";
349 else
350 return "0";
351}
352} // extern "C"