blob: 51ebbf2266dd97a3dddf249a25683734eec8dd4a [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"
Dmitry Vyukov01ea6532012-12-04 14:01:21 +000014#include "sanitizer_common/sanitizer_internal_defs.h"
Alexey Samsonov8bd90982012-06-07 09:50:16 +000015#include "sanitizer_common/sanitizer_placement_new.h"
Kostya Serebryany4ad375f2012-05-10 13:48:04 +000016#include "tsan_interface_ann.h"
17#include "tsan_mutex.h"
Kostya Serebryany4ad375f2012-05-10 13:48:04 +000018#include "tsan_report.h"
19#include "tsan_rtl.h"
20#include "tsan_mman.h"
21#include "tsan_flags.h"
Dmitry Vyukovea03fc22012-06-14 21:40:35 +000022#include "tsan_platform.h"
Kostya Serebryany4ad375f2012-05-10 13:48:04 +000023
24#define CALLERPC ((uptr)__builtin_return_address(0))
25
26using namespace __tsan; // NOLINT
27
28namespace __tsan {
29
30class ScopedAnnotation {
31 public:
32 ScopedAnnotation(ThreadState *thr, const char *aname, const char *f, int l,
33 uptr pc)
34 : thr_(thr)
35 , in_rtl_(thr->in_rtl) {
36 CHECK_EQ(thr_->in_rtl, 0);
37 FuncEntry(thr_, pc);
38 thr_->in_rtl++;
39 DPrintf("#%d: annotation %s() %s:%d\n", thr_->tid, aname, f, l);
40 }
41
42 ~ScopedAnnotation() {
43 thr_->in_rtl--;
44 CHECK_EQ(in_rtl_, thr_->in_rtl);
45 FuncExit(thr_);
46 }
47 private:
48 ThreadState *const thr_;
49 const int in_rtl_;
50};
51
52#define SCOPED_ANNOTATION(typ) \
53 if (!flags()->enable_annotations) \
54 return; \
55 ThreadState *thr = cur_thread(); \
Dmitry Vyukov4723e6b2012-08-16 13:29:41 +000056 const uptr pc = (uptr)__builtin_return_address(0); \
Kostya Serebryany4ad375f2012-05-10 13:48:04 +000057 StatInc(thr, StatAnnotation); \
58 StatInc(thr, Stat##typ); \
59 ScopedAnnotation sa(thr, __FUNCTION__, f, l, \
60 (uptr)__builtin_return_address(0)); \
Kostya Serebryany4ad375f2012-05-10 13:48:04 +000061 (void)pc; \
62/**/
63
64static const int kMaxDescLen = 128;
65
66struct ExpectRace {
67 ExpectRace *next;
68 ExpectRace *prev;
69 int hitcount;
70 uptr addr;
71 uptr size;
72 char *file;
73 int line;
74 char desc[kMaxDescLen];
75};
76
77struct DynamicAnnContext {
78 Mutex mtx;
79 ExpectRace expect;
80 ExpectRace benign;
81
82 DynamicAnnContext()
83 : mtx(MutexTypeAnnotations, StatMtxAnnotations) {
84 }
85};
86
87static DynamicAnnContext *dyn_ann_ctx;
Alexey Samsonovef2e2cf2012-06-05 13:50:57 +000088static char dyn_ann_ctx_placeholder[sizeof(DynamicAnnContext)] ALIGNED(64);
Kostya Serebryany4ad375f2012-05-10 13:48:04 +000089
90static void AddExpectRace(ExpectRace *list,
91 char *f, int l, uptr addr, uptr size, char *desc) {
92 ExpectRace *race = list->next;
93 for (; race != list; race = race->next) {
94 if (race->addr == addr && race->size == size)
95 return;
96 }
97 race = (ExpectRace*)internal_alloc(MBlockExpectRace, sizeof(ExpectRace));
98 race->hitcount = 0;
99 race->addr = addr;
100 race->size = size;
101 race->file = f;
102 race->line = l;
103 race->desc[0] = 0;
104 if (desc) {
105 int i = 0;
106 for (; i < kMaxDescLen - 1 && desc[i]; i++)
107 race->desc[i] = desc[i];
108 race->desc[i] = 0;
109 }
110 race->prev = list;
111 race->next = list->next;
112 race->next->prev = race;
113 list->next = race;
114}
115
116static ExpectRace *FindRace(ExpectRace *list, uptr addr, uptr size) {
117 for (ExpectRace *race = list->next; race != list; race = race->next) {
118 uptr maxbegin = max(race->addr, addr);
119 uptr minend = min(race->addr + race->size, addr + size);
120 if (maxbegin < minend)
121 return race;
122 }
123 return 0;
124}
125
126static bool CheckContains(ExpectRace *list, uptr addr, uptr size) {
127 ExpectRace *race = FindRace(list, addr, size);
Dmitry Vyukovea03fc22012-06-14 21:40:35 +0000128 if (race == 0 && AlternativeAddress(addr))
129 race = FindRace(list, AlternativeAddress(addr), size);
Kostya Serebryany4ad375f2012-05-10 13:48:04 +0000130 if (race == 0)
131 return false;
Alexey Samsonov51ae9832012-06-06 13:11:29 +0000132 DPrintf("Hit expected/benign race: %s addr=%zx:%d %s:%d\n",
Kostya Serebryany4ad375f2012-05-10 13:48:04 +0000133 race->desc, race->addr, (int)race->size, race->file, race->line);
134 race->hitcount++;
135 return true;
136}
137
138static void InitList(ExpectRace *list) {
139 list->next = list;
140 list->prev = list;
141}
142
143void InitializeDynamicAnnotations() {
144 dyn_ann_ctx = new(dyn_ann_ctx_placeholder) DynamicAnnContext;
145 InitList(&dyn_ann_ctx->expect);
146 InitList(&dyn_ann_ctx->benign);
147}
148
149bool IsExpectedReport(uptr addr, uptr size) {
150 Lock lock(&dyn_ann_ctx->mtx);
151 if (CheckContains(&dyn_ann_ctx->expect, addr, size))
152 return true;
153 if (CheckContains(&dyn_ann_ctx->benign, addr, size))
154 return true;
155 return false;
156}
157
158} // namespace __tsan
159
160using namespace __tsan; // NOLINT
161
162extern "C" {
Dmitry Vyukov01ea6532012-12-04 14:01:21 +0000163void INTERFACE_ATTRIBUTE AnnotateHappensBefore(char *f, int l, uptr addr) {
Kostya Serebryany4ad375f2012-05-10 13:48:04 +0000164 SCOPED_ANNOTATION(AnnotateHappensBefore);
165 Release(cur_thread(), CALLERPC, addr);
166}
167
Dmitry Vyukov01ea6532012-12-04 14:01:21 +0000168void INTERFACE_ATTRIBUTE AnnotateHappensAfter(char *f, int l, uptr addr) {
Kostya Serebryany4ad375f2012-05-10 13:48:04 +0000169 SCOPED_ANNOTATION(AnnotateHappensAfter);
170 Acquire(cur_thread(), CALLERPC, addr);
171}
172
Dmitry Vyukov01ea6532012-12-04 14:01:21 +0000173void INTERFACE_ATTRIBUTE AnnotateCondVarSignal(char *f, int l, uptr cv) {
Kostya Serebryany4ad375f2012-05-10 13:48:04 +0000174 SCOPED_ANNOTATION(AnnotateCondVarSignal);
175}
176
Dmitry Vyukov01ea6532012-12-04 14:01:21 +0000177void INTERFACE_ATTRIBUTE AnnotateCondVarSignalAll(char *f, int l, uptr cv) {
Kostya Serebryany4ad375f2012-05-10 13:48:04 +0000178 SCOPED_ANNOTATION(AnnotateCondVarSignalAll);
179}
180
Dmitry Vyukov01ea6532012-12-04 14:01:21 +0000181void INTERFACE_ATTRIBUTE AnnotateMutexIsNotPHB(char *f, int l, uptr mu) {
Kostya Serebryany4ad375f2012-05-10 13:48:04 +0000182 SCOPED_ANNOTATION(AnnotateMutexIsNotPHB);
183}
184
Dmitry Vyukov01ea6532012-12-04 14:01:21 +0000185void INTERFACE_ATTRIBUTE AnnotateCondVarWait(char *f, int l, uptr cv,
186 uptr lock) {
Kostya Serebryany4ad375f2012-05-10 13:48:04 +0000187 SCOPED_ANNOTATION(AnnotateCondVarWait);
188}
189
Dmitry Vyukov01ea6532012-12-04 14:01:21 +0000190void INTERFACE_ATTRIBUTE AnnotateRWLockCreate(char *f, int l, uptr m) {
Kostya Serebryany4ad375f2012-05-10 13:48:04 +0000191 SCOPED_ANNOTATION(AnnotateRWLockCreate);
Dmitry Vyukov4723e6b2012-08-16 13:29:41 +0000192 MutexCreate(thr, pc, m, true, true, false);
Kostya Serebryany4ad375f2012-05-10 13:48:04 +0000193}
194
Dmitry Vyukov01ea6532012-12-04 14:01:21 +0000195void INTERFACE_ATTRIBUTE AnnotateRWLockCreateStatic(char *f, int l, uptr m) {
Dmitry Vyukov4723e6b2012-08-16 13:29:41 +0000196 SCOPED_ANNOTATION(AnnotateRWLockCreateStatic);
197 MutexCreate(thr, pc, m, true, true, true);
198}
199
Dmitry Vyukov01ea6532012-12-04 14:01:21 +0000200void INTERFACE_ATTRIBUTE AnnotateRWLockDestroy(char *f, int l, uptr m) {
Kostya Serebryany4ad375f2012-05-10 13:48:04 +0000201 SCOPED_ANNOTATION(AnnotateRWLockDestroy);
Dmitry Vyukov4723e6b2012-08-16 13:29:41 +0000202 MutexDestroy(thr, pc, m);
Kostya Serebryany4ad375f2012-05-10 13:48:04 +0000203}
204
Dmitry Vyukov01ea6532012-12-04 14:01:21 +0000205void INTERFACE_ATTRIBUTE AnnotateRWLockAcquired(char *f, int l, uptr m,
206 uptr is_w) {
Kostya Serebryany4ad375f2012-05-10 13:48:04 +0000207 SCOPED_ANNOTATION(AnnotateRWLockAcquired);
Dmitry Vyukov4723e6b2012-08-16 13:29:41 +0000208 if (is_w)
209 MutexLock(thr, pc, m);
210 else
211 MutexReadLock(thr, pc, m);
Kostya Serebryany4ad375f2012-05-10 13:48:04 +0000212}
213
Dmitry Vyukov01ea6532012-12-04 14:01:21 +0000214void INTERFACE_ATTRIBUTE AnnotateRWLockReleased(char *f, int l, uptr m,
215 uptr is_w) {
Kostya Serebryany4ad375f2012-05-10 13:48:04 +0000216 SCOPED_ANNOTATION(AnnotateRWLockReleased);
Dmitry Vyukov4723e6b2012-08-16 13:29:41 +0000217 if (is_w)
218 MutexUnlock(thr, pc, m);
219 else
220 MutexReadUnlock(thr, pc, m);
Kostya Serebryany4ad375f2012-05-10 13:48:04 +0000221}
222
Dmitry Vyukov01ea6532012-12-04 14:01:21 +0000223void INTERFACE_ATTRIBUTE AnnotateTraceMemory(char *f, int l, uptr mem) {
Kostya Serebryany4ad375f2012-05-10 13:48:04 +0000224 SCOPED_ANNOTATION(AnnotateTraceMemory);
225}
226
Dmitry Vyukov01ea6532012-12-04 14:01:21 +0000227void INTERFACE_ATTRIBUTE AnnotateFlushState(char *f, int l) {
Kostya Serebryany4ad375f2012-05-10 13:48:04 +0000228 SCOPED_ANNOTATION(AnnotateFlushState);
229}
230
Dmitry Vyukov01ea6532012-12-04 14:01:21 +0000231void INTERFACE_ATTRIBUTE AnnotateNewMemory(char *f, int l, uptr mem,
232 uptr size) {
Kostya Serebryany4ad375f2012-05-10 13:48:04 +0000233 SCOPED_ANNOTATION(AnnotateNewMemory);
234}
235
Dmitry Vyukov01ea6532012-12-04 14:01:21 +0000236void INTERFACE_ATTRIBUTE AnnotateNoOp(char *f, int l, uptr mem) {
Kostya Serebryany4ad375f2012-05-10 13:48:04 +0000237 SCOPED_ANNOTATION(AnnotateNoOp);
238}
239
240static void ReportMissedExpectedRace(ExpectRace *race) {
Alexey Samsonovad9d65f2012-11-02 12:17:51 +0000241 Printf("==================\n");
242 Printf("WARNING: ThreadSanitizer: missed expected data race\n");
243 Printf(" %s addr=%zx %s:%d\n",
Kostya Serebryany4ad375f2012-05-10 13:48:04 +0000244 race->desc, race->addr, race->file, race->line);
Alexey Samsonovad9d65f2012-11-02 12:17:51 +0000245 Printf("==================\n");
Kostya Serebryany4ad375f2012-05-10 13:48:04 +0000246}
247
Dmitry Vyukov01ea6532012-12-04 14:01:21 +0000248void INTERFACE_ATTRIBUTE AnnotateFlushExpectedRaces(char *f, int l) {
Kostya Serebryany4ad375f2012-05-10 13:48:04 +0000249 SCOPED_ANNOTATION(AnnotateFlushExpectedRaces);
250 Lock lock(&dyn_ann_ctx->mtx);
251 while (dyn_ann_ctx->expect.next != &dyn_ann_ctx->expect) {
252 ExpectRace *race = dyn_ann_ctx->expect.next;
253 if (race->hitcount == 0) {
254 CTX()->nmissed_expected++;
255 ReportMissedExpectedRace(race);
256 }
257 race->prev->next = race->next;
258 race->next->prev = race->prev;
259 internal_free(race);
260 }
261}
262
Dmitry Vyukov01ea6532012-12-04 14:01:21 +0000263void INTERFACE_ATTRIBUTE AnnotateEnableRaceDetection(
264 char *f, int l, int enable) {
Kostya Serebryany4ad375f2012-05-10 13:48:04 +0000265 SCOPED_ANNOTATION(AnnotateEnableRaceDetection);
266 // FIXME: Reconsider this functionality later. It may be irrelevant.
267}
268
Dmitry Vyukov01ea6532012-12-04 14:01:21 +0000269void INTERFACE_ATTRIBUTE AnnotateMutexIsUsedAsCondVar(
270 char *f, int l, uptr mu) {
Kostya Serebryany4ad375f2012-05-10 13:48:04 +0000271 SCOPED_ANNOTATION(AnnotateMutexIsUsedAsCondVar);
272}
273
Dmitry Vyukov01ea6532012-12-04 14:01:21 +0000274void INTERFACE_ATTRIBUTE AnnotatePCQGet(
275 char *f, int l, uptr pcq) {
Kostya Serebryany4ad375f2012-05-10 13:48:04 +0000276 SCOPED_ANNOTATION(AnnotatePCQGet);
277}
278
Dmitry Vyukov01ea6532012-12-04 14:01:21 +0000279void INTERFACE_ATTRIBUTE AnnotatePCQPut(
280 char *f, int l, uptr pcq) {
Kostya Serebryany4ad375f2012-05-10 13:48:04 +0000281 SCOPED_ANNOTATION(AnnotatePCQPut);
282}
283
Dmitry Vyukov01ea6532012-12-04 14:01:21 +0000284void INTERFACE_ATTRIBUTE AnnotatePCQDestroy(
285 char *f, int l, uptr pcq) {
Kostya Serebryany4ad375f2012-05-10 13:48:04 +0000286 SCOPED_ANNOTATION(AnnotatePCQDestroy);
287}
288
Dmitry Vyukov01ea6532012-12-04 14:01:21 +0000289void INTERFACE_ATTRIBUTE AnnotatePCQCreate(
290 char *f, int l, uptr pcq) {
Kostya Serebryany4ad375f2012-05-10 13:48:04 +0000291 SCOPED_ANNOTATION(AnnotatePCQCreate);
292}
293
Dmitry Vyukov01ea6532012-12-04 14:01:21 +0000294void INTERFACE_ATTRIBUTE AnnotateExpectRace(
295 char *f, int l, uptr mem, char *desc) {
Kostya Serebryany4ad375f2012-05-10 13:48:04 +0000296 SCOPED_ANNOTATION(AnnotateExpectRace);
297 Lock lock(&dyn_ann_ctx->mtx);
298 AddExpectRace(&dyn_ann_ctx->expect,
299 f, l, mem, 1, desc);
Alexey Samsonov51ae9832012-06-06 13:11:29 +0000300 DPrintf("Add expected race: %s addr=%zx %s:%d\n", desc, mem, f, l);
Kostya Serebryany4ad375f2012-05-10 13:48:04 +0000301}
302
Dmitry Vyukov01ea6532012-12-04 14:01:21 +0000303static void BenignRaceImpl(
304 char *f, int l, uptr mem, uptr size, char *desc) {
Kostya Serebryany4ad375f2012-05-10 13:48:04 +0000305 Lock lock(&dyn_ann_ctx->mtx);
306 AddExpectRace(&dyn_ann_ctx->benign,
307 f, l, mem, size, desc);
Alexey Samsonov51ae9832012-06-06 13:11:29 +0000308 DPrintf("Add benign race: %s addr=%zx %s:%d\n", desc, mem, f, l);
Kostya Serebryany4ad375f2012-05-10 13:48:04 +0000309}
310
311// FIXME: Turn it off later. WTF is benign race?1?? Go talk to Hans Boehm.
Dmitry Vyukov01ea6532012-12-04 14:01:21 +0000312void INTERFACE_ATTRIBUTE AnnotateBenignRaceSized(
313 char *f, int l, uptr mem, uptr size, char *desc) {
Kostya Serebryany4ad375f2012-05-10 13:48:04 +0000314 SCOPED_ANNOTATION(AnnotateBenignRaceSized);
315 BenignRaceImpl(f, l, mem, size, desc);
316}
317
Dmitry Vyukov01ea6532012-12-04 14:01:21 +0000318void INTERFACE_ATTRIBUTE AnnotateBenignRace(
319 char *f, int l, uptr mem, char *desc) {
Kostya Serebryany4ad375f2012-05-10 13:48:04 +0000320 SCOPED_ANNOTATION(AnnotateBenignRace);
321 BenignRaceImpl(f, l, mem, 1, desc);
322}
323
Dmitry Vyukov01ea6532012-12-04 14:01:21 +0000324void INTERFACE_ATTRIBUTE AnnotateIgnoreReadsBegin(char *f, int l) {
Kostya Serebryany4ad375f2012-05-10 13:48:04 +0000325 SCOPED_ANNOTATION(AnnotateIgnoreReadsBegin);
326 IgnoreCtl(cur_thread(), false, true);
327}
328
Dmitry Vyukov01ea6532012-12-04 14:01:21 +0000329void INTERFACE_ATTRIBUTE AnnotateIgnoreReadsEnd(char *f, int l) {
Kostya Serebryany4ad375f2012-05-10 13:48:04 +0000330 SCOPED_ANNOTATION(AnnotateIgnoreReadsEnd);
331 IgnoreCtl(cur_thread(), false, false);
332}
333
Dmitry Vyukov01ea6532012-12-04 14:01:21 +0000334void INTERFACE_ATTRIBUTE AnnotateIgnoreWritesBegin(char *f, int l) {
Kostya Serebryany4ad375f2012-05-10 13:48:04 +0000335 SCOPED_ANNOTATION(AnnotateIgnoreWritesBegin);
336 IgnoreCtl(cur_thread(), true, true);
337}
338
Dmitry Vyukov01ea6532012-12-04 14:01:21 +0000339void INTERFACE_ATTRIBUTE AnnotateIgnoreWritesEnd(char *f, int l) {
Kostya Serebryany4ad375f2012-05-10 13:48:04 +0000340 SCOPED_ANNOTATION(AnnotateIgnoreWritesEnd);
Dmitry Vyukov1b469932012-12-04 15:46:05 +0000341 IgnoreCtl(thr, true, false);
Kostya Serebryany4ad375f2012-05-10 13:48:04 +0000342}
343
Dmitry Vyukov01ea6532012-12-04 14:01:21 +0000344void INTERFACE_ATTRIBUTE AnnotatePublishMemoryRange(
345 char *f, int l, uptr addr, uptr size) {
Kostya Serebryany4ad375f2012-05-10 13:48:04 +0000346 SCOPED_ANNOTATION(AnnotatePublishMemoryRange);
347}
348
Dmitry Vyukov01ea6532012-12-04 14:01:21 +0000349void INTERFACE_ATTRIBUTE AnnotateUnpublishMemoryRange(
350 char *f, int l, uptr addr, uptr size) {
Kostya Serebryany4ad375f2012-05-10 13:48:04 +0000351 SCOPED_ANNOTATION(AnnotateUnpublishMemoryRange);
352}
353
Dmitry Vyukov01ea6532012-12-04 14:01:21 +0000354void INTERFACE_ATTRIBUTE AnnotateThreadName(
355 char *f, int l, char *name) {
Kostya Serebryany4ad375f2012-05-10 13:48:04 +0000356 SCOPED_ANNOTATION(AnnotateThreadName);
Dmitry Vyukov1b469932012-12-04 15:46:05 +0000357 ThreadSetName(thr, name);
Kostya Serebryany4ad375f2012-05-10 13:48:04 +0000358}
359
Dmitry Vyukov01ea6532012-12-04 14:01:21 +0000360void INTERFACE_ATTRIBUTE WTFAnnotateHappensBefore(char *f, int l, uptr addr) {
Kostya Serebryany4ad375f2012-05-10 13:48:04 +0000361 SCOPED_ANNOTATION(AnnotateHappensBefore);
362}
363
Dmitry Vyukov01ea6532012-12-04 14:01:21 +0000364void INTERFACE_ATTRIBUTE WTFAnnotateHappensAfter(char *f, int l, uptr addr) {
Kostya Serebryany4ad375f2012-05-10 13:48:04 +0000365 SCOPED_ANNOTATION(AnnotateHappensAfter);
366}
367
Dmitry Vyukov01ea6532012-12-04 14:01:21 +0000368void INTERFACE_ATTRIBUTE WTFAnnotateBenignRaceSized(
369 char *f, int l, uptr mem, uptr sz, char *desc) {
Kostya Serebryany4ad375f2012-05-10 13:48:04 +0000370 SCOPED_ANNOTATION(AnnotateBenignRaceSized);
371}
372
Dmitry Vyukov01ea6532012-12-04 14:01:21 +0000373int INTERFACE_ATTRIBUTE RunningOnValgrind() {
Dmitry Vyukov65c21a52012-05-24 09:24:45 +0000374 return flags()->running_on_valgrind;
Kostya Serebryany4ad375f2012-05-10 13:48:04 +0000375}
376
Dmitry Vyukov01ea6532012-12-04 14:01:21 +0000377double __attribute__((weak)) INTERFACE_ATTRIBUTE ValgrindSlowdown(void) {
Dmitry Vyukov166b8e52012-05-17 08:04:41 +0000378 return 10.0;
379}
380
Dmitry Vyukov01ea6532012-12-04 14:01:21 +0000381const char INTERFACE_ATTRIBUTE* ThreadSanitizerQuery(const char *query) {
Kostya Serebryany4ad375f2012-05-10 13:48:04 +0000382 if (internal_strcmp(query, "pure_happens_before") == 0)
383 return "1";
384 else
385 return "0";
386}
387} // extern "C"