blob: 58be599ad163008c8b20350f8e4c62d39bac8794 [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"
Kostya Serebryany4ad375f2012-05-10 13:48:04 +000014#include "tsan_interface_ann.h"
15#include "tsan_mutex.h"
16#include "tsan_placement_new.h"
17#include "tsan_report.h"
18#include "tsan_rtl.h"
19#include "tsan_mman.h"
20#include "tsan_flags.h"
21
22#define CALLERPC ((uptr)__builtin_return_address(0))
23
Alexey Samsonov90f96302012-06-04 13:27:49 +000024using namespace __sanitizer; // NOLINT
Kostya Serebryany4ad375f2012-05-10 13:48:04 +000025using 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);
127 if (race == 0)
128 return false;
129 DPrintf("Hit expected/benign race: %s addr=%lx:%d %s:%d\n",
130 race->desc, race->addr, (int)race->size, race->file, race->line);
131 race->hitcount++;
132 return true;
133}
134
135static void InitList(ExpectRace *list) {
136 list->next = list;
137 list->prev = list;
138}
139
140void InitializeDynamicAnnotations() {
141 dyn_ann_ctx = new(dyn_ann_ctx_placeholder) DynamicAnnContext;
142 InitList(&dyn_ann_ctx->expect);
143 InitList(&dyn_ann_ctx->benign);
144}
145
146bool IsExpectedReport(uptr addr, uptr size) {
147 Lock lock(&dyn_ann_ctx->mtx);
148 if (CheckContains(&dyn_ann_ctx->expect, addr, size))
149 return true;
150 if (CheckContains(&dyn_ann_ctx->benign, addr, size))
151 return true;
152 return false;
153}
154
155} // namespace __tsan
156
157using namespace __tsan; // NOLINT
158
159extern "C" {
160void AnnotateHappensBefore(char *f, int l, uptr addr) {
161 SCOPED_ANNOTATION(AnnotateHappensBefore);
162 Release(cur_thread(), CALLERPC, addr);
163}
164
165void AnnotateHappensAfter(char *f, int l, uptr addr) {
166 SCOPED_ANNOTATION(AnnotateHappensAfter);
167 Acquire(cur_thread(), CALLERPC, addr);
168}
169
170void AnnotateCondVarSignal(char *f, int l, uptr cv) {
171 SCOPED_ANNOTATION(AnnotateCondVarSignal);
172}
173
174void AnnotateCondVarSignalAll(char *f, int l, uptr cv) {
175 SCOPED_ANNOTATION(AnnotateCondVarSignalAll);
176}
177
178void AnnotateMutexIsNotPHB(char *f, int l, uptr mu) {
179 SCOPED_ANNOTATION(AnnotateMutexIsNotPHB);
180}
181
182void AnnotateCondVarWait(char *f, int l, uptr cv, uptr lock) {
183 SCOPED_ANNOTATION(AnnotateCondVarWait);
184}
185
186void AnnotateRWLockCreate(char *f, int l, uptr lock) {
187 SCOPED_ANNOTATION(AnnotateRWLockCreate);
188}
189
190void AnnotateRWLockDestroy(char *f, int l, uptr lock) {
191 SCOPED_ANNOTATION(AnnotateRWLockDestroy);
192}
193
194void AnnotateRWLockAcquired(char *f, int l, uptr lock, uptr is_w) {
195 SCOPED_ANNOTATION(AnnotateRWLockAcquired);
196}
197
198void AnnotateRWLockReleased(char *f, int l, uptr lock, uptr is_w) {
199 SCOPED_ANNOTATION(AnnotateRWLockReleased);
200}
201
202void AnnotateTraceMemory(char *f, int l, uptr mem) {
203 SCOPED_ANNOTATION(AnnotateTraceMemory);
204}
205
206void AnnotateFlushState(char *f, int l) {
207 SCOPED_ANNOTATION(AnnotateFlushState);
208}
209
210void AnnotateNewMemory(char *f, int l, uptr mem, uptr size) {
211 SCOPED_ANNOTATION(AnnotateNewMemory);
212}
213
214void AnnotateNoOp(char *f, int l, uptr mem) {
215 SCOPED_ANNOTATION(AnnotateNoOp);
216}
217
218static void ReportMissedExpectedRace(ExpectRace *race) {
219 Printf("==================\n");
220 Printf("WARNING: ThreadSanitizer: missed expected data race\n");
221 Printf(" %s addr=%lx %s:%d\n",
222 race->desc, race->addr, race->file, race->line);
223 Printf("==================\n");
224}
225
226void AnnotateFlushExpectedRaces(char *f, int l) {
227 SCOPED_ANNOTATION(AnnotateFlushExpectedRaces);
228 Lock lock(&dyn_ann_ctx->mtx);
229 while (dyn_ann_ctx->expect.next != &dyn_ann_ctx->expect) {
230 ExpectRace *race = dyn_ann_ctx->expect.next;
231 if (race->hitcount == 0) {
232 CTX()->nmissed_expected++;
233 ReportMissedExpectedRace(race);
234 }
235 race->prev->next = race->next;
236 race->next->prev = race->prev;
237 internal_free(race);
238 }
239}
240
241void AnnotateEnableRaceDetection(char *f, int l, int enable) {
242 SCOPED_ANNOTATION(AnnotateEnableRaceDetection);
243 // FIXME: Reconsider this functionality later. It may be irrelevant.
244}
245
246void AnnotateMutexIsUsedAsCondVar(char *f, int l, uptr mu) {
247 SCOPED_ANNOTATION(AnnotateMutexIsUsedAsCondVar);
248}
249
250void AnnotatePCQGet(char *f, int l, uptr pcq) {
251 SCOPED_ANNOTATION(AnnotatePCQGet);
252}
253
254void AnnotatePCQPut(char *f, int l, uptr pcq) {
255 SCOPED_ANNOTATION(AnnotatePCQPut);
256}
257
258void AnnotatePCQDestroy(char *f, int l, uptr pcq) {
259 SCOPED_ANNOTATION(AnnotatePCQDestroy);
260}
261
262void AnnotatePCQCreate(char *f, int l, uptr pcq) {
263 SCOPED_ANNOTATION(AnnotatePCQCreate);
264}
265
266void AnnotateExpectRace(char *f, int l, uptr mem, char *desc) {
267 SCOPED_ANNOTATION(AnnotateExpectRace);
268 Lock lock(&dyn_ann_ctx->mtx);
269 AddExpectRace(&dyn_ann_ctx->expect,
270 f, l, mem, 1, desc);
271 DPrintf("Add expected race: %s addr=%lx %s:%d\n", desc, mem, f, l);
272}
273
274static void BenignRaceImpl(char *f, int l, uptr mem, uptr size, char *desc) {
275 Lock lock(&dyn_ann_ctx->mtx);
276 AddExpectRace(&dyn_ann_ctx->benign,
277 f, l, mem, size, desc);
278 DPrintf("Add benign race: %s addr=%lx %s:%d\n", desc, mem, f, l);
279}
280
281// FIXME: Turn it off later. WTF is benign race?1?? Go talk to Hans Boehm.
282void AnnotateBenignRaceSized(char *f, int l, uptr mem, uptr size, char *desc) {
283 SCOPED_ANNOTATION(AnnotateBenignRaceSized);
284 BenignRaceImpl(f, l, mem, size, desc);
285}
286
287void AnnotateBenignRace(char *f, int l, uptr mem, char *desc) {
288 SCOPED_ANNOTATION(AnnotateBenignRace);
289 BenignRaceImpl(f, l, mem, 1, desc);
290}
291
292void AnnotateIgnoreReadsBegin(char *f, int l) {
293 SCOPED_ANNOTATION(AnnotateIgnoreReadsBegin);
294 IgnoreCtl(cur_thread(), false, true);
295}
296
297void AnnotateIgnoreReadsEnd(char *f, int l) {
298 SCOPED_ANNOTATION(AnnotateIgnoreReadsEnd);
299 IgnoreCtl(cur_thread(), false, false);
300}
301
302void AnnotateIgnoreWritesBegin(char *f, int l) {
303 SCOPED_ANNOTATION(AnnotateIgnoreWritesBegin);
304 IgnoreCtl(cur_thread(), true, true);
305}
306
307void AnnotateIgnoreWritesEnd(char *f, int l) {
308 SCOPED_ANNOTATION(AnnotateIgnoreWritesEnd);
309 IgnoreCtl(cur_thread(), true, false);
310}
311
312void AnnotatePublishMemoryRange(char *f, int l, uptr addr, uptr size) {
313 SCOPED_ANNOTATION(AnnotatePublishMemoryRange);
314}
315
316void AnnotateUnpublishMemoryRange(char *f, int l, uptr addr, uptr size) {
317 SCOPED_ANNOTATION(AnnotateUnpublishMemoryRange);
318}
319
320void AnnotateThreadName(char *f, int l, char *name) {
321 SCOPED_ANNOTATION(AnnotateThreadName);
322}
323
324void WTFAnnotateHappensBefore(char *f, int l, uptr addr) {
325 SCOPED_ANNOTATION(AnnotateHappensBefore);
326}
327
328void WTFAnnotateHappensAfter(char *f, int l, uptr addr) {
329 SCOPED_ANNOTATION(AnnotateHappensAfter);
330}
331
332void WTFAnnotateBenignRaceSized(char *f, int l, uptr mem, uptr sz, char *desc) {
333 SCOPED_ANNOTATION(AnnotateBenignRaceSized);
334}
335
336int RunningOnValgrind() {
Dmitry Vyukov65c21a52012-05-24 09:24:45 +0000337 return flags()->running_on_valgrind;
Kostya Serebryany4ad375f2012-05-10 13:48:04 +0000338}
339
Dmitry Vyukov352358b2012-05-17 08:31:47 +0000340double __attribute__((weak)) ValgrindSlowdown(void) {
Dmitry Vyukov166b8e52012-05-17 08:04:41 +0000341 return 10.0;
342}
343
Kostya Serebryany4ad375f2012-05-10 13:48:04 +0000344const char *ThreadSanitizerQuery(const char *query) {
345 if (internal_strcmp(query, "pure_happens_before") == 0)
346 return "1";
347 else
348 return "0";
349}
350} // extern "C"