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