blob: 0877e2a550a955aa36be456584db6e4f98a887de [file] [log] [blame]
Kostya Serebryany4ad375f2012-05-10 13:48:04 +00001//===-- tsan_interface_ann.cc -----------------------------------*- C++ -*-===//
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 "tsan_interface_ann.h"
14#include "tsan_mutex.h"
15#include "tsan_placement_new.h"
16#include "tsan_report.h"
17#include "tsan_rtl.h"
18#include "tsan_mman.h"
19#include "tsan_flags.h"
20
21#define CALLERPC ((uptr)__builtin_return_address(0))
22
23using namespace __tsan; // NOLINT
24
25namespace __tsan {
26
27class ScopedAnnotation {
28 public:
29 ScopedAnnotation(ThreadState *thr, const char *aname, const char *f, int l,
30 uptr pc)
31 : thr_(thr)
32 , in_rtl_(thr->in_rtl) {
33 CHECK_EQ(thr_->in_rtl, 0);
34 FuncEntry(thr_, pc);
35 thr_->in_rtl++;
36 DPrintf("#%d: annotation %s() %s:%d\n", thr_->tid, aname, f, l);
37 }
38
39 ~ScopedAnnotation() {
40 thr_->in_rtl--;
41 CHECK_EQ(in_rtl_, thr_->in_rtl);
42 FuncExit(thr_);
43 }
44 private:
45 ThreadState *const thr_;
46 const int in_rtl_;
47};
48
49#define SCOPED_ANNOTATION(typ) \
50 if (!flags()->enable_annotations) \
51 return; \
52 ThreadState *thr = cur_thread(); \
53 StatInc(thr, StatAnnotation); \
54 StatInc(thr, Stat##typ); \
55 ScopedAnnotation sa(thr, __FUNCTION__, f, l, \
56 (uptr)__builtin_return_address(0)); \
57 const uptr pc = (uptr)&__FUNCTION__; \
58 (void)pc; \
59/**/
60
61static const int kMaxDescLen = 128;
62
63struct ExpectRace {
64 ExpectRace *next;
65 ExpectRace *prev;
66 int hitcount;
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)] ALIGN(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 return;
93 }
94 race = (ExpectRace*)internal_alloc(MBlockExpectRace, sizeof(ExpectRace));
95 race->hitcount = 0;
96 race->addr = addr;
97 race->size = size;
98 race->file = f;
99 race->line = l;
100 race->desc[0] = 0;
101 if (desc) {
102 int i = 0;
103 for (; i < kMaxDescLen - 1 && desc[i]; i++)
104 race->desc[i] = desc[i];
105 race->desc[i] = 0;
106 }
107 race->prev = list;
108 race->next = list->next;
109 race->next->prev = race;
110 list->next = race;
111}
112
113static ExpectRace *FindRace(ExpectRace *list, uptr addr, uptr size) {
114 for (ExpectRace *race = list->next; race != list; race = race->next) {
115 uptr maxbegin = max(race->addr, addr);
116 uptr minend = min(race->addr + race->size, addr + size);
117 if (maxbegin < minend)
118 return race;
119 }
120 return 0;
121}
122
123static bool CheckContains(ExpectRace *list, uptr addr, uptr size) {
124 ExpectRace *race = FindRace(list, addr, size);
125 if (race == 0)
126 return false;
127 DPrintf("Hit expected/benign race: %s addr=%lx:%d %s:%d\n",
128 race->desc, race->addr, (int)race->size, race->file, race->line);
129 race->hitcount++;
130 return true;
131}
132
133static void InitList(ExpectRace *list) {
134 list->next = list;
135 list->prev = list;
136}
137
138void InitializeDynamicAnnotations() {
139 dyn_ann_ctx = new(dyn_ann_ctx_placeholder) DynamicAnnContext;
140 InitList(&dyn_ann_ctx->expect);
141 InitList(&dyn_ann_ctx->benign);
142}
143
144bool IsExpectedReport(uptr addr, uptr size) {
145 Lock lock(&dyn_ann_ctx->mtx);
146 if (CheckContains(&dyn_ann_ctx->expect, addr, size))
147 return true;
148 if (CheckContains(&dyn_ann_ctx->benign, addr, size))
149 return true;
150 return false;
151}
152
153} // namespace __tsan
154
155using namespace __tsan; // NOLINT
156
157extern "C" {
158void AnnotateHappensBefore(char *f, int l, uptr addr) {
159 SCOPED_ANNOTATION(AnnotateHappensBefore);
160 Release(cur_thread(), CALLERPC, addr);
161}
162
163void AnnotateHappensAfter(char *f, int l, uptr addr) {
164 SCOPED_ANNOTATION(AnnotateHappensAfter);
165 Acquire(cur_thread(), CALLERPC, addr);
166}
167
168void AnnotateCondVarSignal(char *f, int l, uptr cv) {
169 SCOPED_ANNOTATION(AnnotateCondVarSignal);
170}
171
172void AnnotateCondVarSignalAll(char *f, int l, uptr cv) {
173 SCOPED_ANNOTATION(AnnotateCondVarSignalAll);
174}
175
176void AnnotateMutexIsNotPHB(char *f, int l, uptr mu) {
177 SCOPED_ANNOTATION(AnnotateMutexIsNotPHB);
178}
179
180void AnnotateCondVarWait(char *f, int l, uptr cv, uptr lock) {
181 SCOPED_ANNOTATION(AnnotateCondVarWait);
182}
183
184void AnnotateRWLockCreate(char *f, int l, uptr lock) {
185 SCOPED_ANNOTATION(AnnotateRWLockCreate);
186}
187
188void AnnotateRWLockDestroy(char *f, int l, uptr lock) {
189 SCOPED_ANNOTATION(AnnotateRWLockDestroy);
190}
191
192void AnnotateRWLockAcquired(char *f, int l, uptr lock, uptr is_w) {
193 SCOPED_ANNOTATION(AnnotateRWLockAcquired);
194}
195
196void AnnotateRWLockReleased(char *f, int l, uptr lock, uptr is_w) {
197 SCOPED_ANNOTATION(AnnotateRWLockReleased);
198}
199
200void AnnotateTraceMemory(char *f, int l, uptr mem) {
201 SCOPED_ANNOTATION(AnnotateTraceMemory);
202}
203
204void AnnotateFlushState(char *f, int l) {
205 SCOPED_ANNOTATION(AnnotateFlushState);
206}
207
208void AnnotateNewMemory(char *f, int l, uptr mem, uptr size) {
209 SCOPED_ANNOTATION(AnnotateNewMemory);
210}
211
212void AnnotateNoOp(char *f, int l, uptr mem) {
213 SCOPED_ANNOTATION(AnnotateNoOp);
214}
215
216static void ReportMissedExpectedRace(ExpectRace *race) {
217 Printf("==================\n");
218 Printf("WARNING: ThreadSanitizer: missed expected data race\n");
219 Printf(" %s addr=%lx %s:%d\n",
220 race->desc, race->addr, race->file, race->line);
221 Printf("==================\n");
222}
223
224void AnnotateFlushExpectedRaces(char *f, int l) {
225 SCOPED_ANNOTATION(AnnotateFlushExpectedRaces);
226 Lock lock(&dyn_ann_ctx->mtx);
227 while (dyn_ann_ctx->expect.next != &dyn_ann_ctx->expect) {
228 ExpectRace *race = dyn_ann_ctx->expect.next;
229 if (race->hitcount == 0) {
230 CTX()->nmissed_expected++;
231 ReportMissedExpectedRace(race);
232 }
233 race->prev->next = race->next;
234 race->next->prev = race->prev;
235 internal_free(race);
236 }
237}
238
239void AnnotateEnableRaceDetection(char *f, int l, int enable) {
240 SCOPED_ANNOTATION(AnnotateEnableRaceDetection);
241 // FIXME: Reconsider this functionality later. It may be irrelevant.
242}
243
244void AnnotateMutexIsUsedAsCondVar(char *f, int l, uptr mu) {
245 SCOPED_ANNOTATION(AnnotateMutexIsUsedAsCondVar);
246}
247
248void AnnotatePCQGet(char *f, int l, uptr pcq) {
249 SCOPED_ANNOTATION(AnnotatePCQGet);
250}
251
252void AnnotatePCQPut(char *f, int l, uptr pcq) {
253 SCOPED_ANNOTATION(AnnotatePCQPut);
254}
255
256void AnnotatePCQDestroy(char *f, int l, uptr pcq) {
257 SCOPED_ANNOTATION(AnnotatePCQDestroy);
258}
259
260void AnnotatePCQCreate(char *f, int l, uptr pcq) {
261 SCOPED_ANNOTATION(AnnotatePCQCreate);
262}
263
264void AnnotateExpectRace(char *f, int l, uptr mem, char *desc) {
265 SCOPED_ANNOTATION(AnnotateExpectRace);
266 Lock lock(&dyn_ann_ctx->mtx);
267 AddExpectRace(&dyn_ann_ctx->expect,
268 f, l, mem, 1, desc);
269 DPrintf("Add expected race: %s addr=%lx %s:%d\n", desc, mem, f, l);
270}
271
272static void BenignRaceImpl(char *f, int l, uptr mem, uptr size, char *desc) {
273 Lock lock(&dyn_ann_ctx->mtx);
274 AddExpectRace(&dyn_ann_ctx->benign,
275 f, l, mem, size, desc);
276 DPrintf("Add benign race: %s addr=%lx %s:%d\n", desc, mem, f, l);
277}
278
279// FIXME: Turn it off later. WTF is benign race?1?? Go talk to Hans Boehm.
280void AnnotateBenignRaceSized(char *f, int l, uptr mem, uptr size, char *desc) {
281 SCOPED_ANNOTATION(AnnotateBenignRaceSized);
282 BenignRaceImpl(f, l, mem, size, desc);
283}
284
285void AnnotateBenignRace(char *f, int l, uptr mem, char *desc) {
286 SCOPED_ANNOTATION(AnnotateBenignRace);
287 BenignRaceImpl(f, l, mem, 1, desc);
288}
289
290void AnnotateIgnoreReadsBegin(char *f, int l) {
291 SCOPED_ANNOTATION(AnnotateIgnoreReadsBegin);
292 IgnoreCtl(cur_thread(), false, true);
293}
294
295void AnnotateIgnoreReadsEnd(char *f, int l) {
296 SCOPED_ANNOTATION(AnnotateIgnoreReadsEnd);
297 IgnoreCtl(cur_thread(), false, false);
298}
299
300void AnnotateIgnoreWritesBegin(char *f, int l) {
301 SCOPED_ANNOTATION(AnnotateIgnoreWritesBegin);
302 IgnoreCtl(cur_thread(), true, true);
303}
304
305void AnnotateIgnoreWritesEnd(char *f, int l) {
306 SCOPED_ANNOTATION(AnnotateIgnoreWritesEnd);
307 IgnoreCtl(cur_thread(), true, false);
308}
309
310void AnnotatePublishMemoryRange(char *f, int l, uptr addr, uptr size) {
311 SCOPED_ANNOTATION(AnnotatePublishMemoryRange);
312}
313
314void AnnotateUnpublishMemoryRange(char *f, int l, uptr addr, uptr size) {
315 SCOPED_ANNOTATION(AnnotateUnpublishMemoryRange);
316}
317
318void AnnotateThreadName(char *f, int l, char *name) {
319 SCOPED_ANNOTATION(AnnotateThreadName);
320}
321
322void WTFAnnotateHappensBefore(char *f, int l, uptr addr) {
323 SCOPED_ANNOTATION(AnnotateHappensBefore);
324}
325
326void WTFAnnotateHappensAfter(char *f, int l, uptr addr) {
327 SCOPED_ANNOTATION(AnnotateHappensAfter);
328}
329
330void WTFAnnotateBenignRaceSized(char *f, int l, uptr mem, uptr sz, char *desc) {
331 SCOPED_ANNOTATION(AnnotateBenignRaceSized);
332}
333
334int RunningOnValgrind() {
335 return 0;
336}
337
Dmitry Vyukov166b8e52012-05-17 08:04:41 +0000338double ValgrindSlowdown(void) {
339 return 10.0;
340}
341
Kostya Serebryany4ad375f2012-05-10 13:48:04 +0000342const char *ThreadSanitizerQuery(const char *query) {
343 if (internal_strcmp(query, "pure_happens_before") == 0)
344 return "1";
345 else
346 return "0";
347}
348} // extern "C"