]> git.ipfire.org Git - thirdparty/gcc.git/blame - libsanitizer/tsan/tsan_interface_ann.cc
[libsanitizer] merge from upstream r168514
[thirdparty/gcc.git] / libsanitizer / tsan / tsan_interface_ann.cc
CommitLineData
cd0be65c
WM
1//===-- tsan_interface_ann.cc ---------------------------------------------===//
2//
3// This file is distributed under the University of Illinois Open Source
4// License. See LICENSE.TXT for details.
5//
6//===----------------------------------------------------------------------===//
7//
8// This file is a part of ThreadSanitizer (TSan), a race detector.
9//
10//===----------------------------------------------------------------------===//
11#include "sanitizer_common/sanitizer_libc.h"
12#include "sanitizer_common/sanitizer_placement_new.h"
13#include "tsan_interface_ann.h"
14#include "tsan_mutex.h"
15#include "tsan_report.h"
16#include "tsan_rtl.h"
17#include "tsan_mman.h"
18#include "tsan_flags.h"
19#include "tsan_platform.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 const uptr pc = (uptr)__builtin_return_address(0); \
54 StatInc(thr, StatAnnotation); \
55 StatInc(thr, Stat##typ); \
56 ScopedAnnotation sa(thr, __FUNCTION__, f, l, \
57 (uptr)__builtin_return_address(0)); \
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)] ALIGNED(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 && AlternativeAddress(addr))
126 race = FindRace(list, AlternativeAddress(addr), size);
127 if (race == 0)
128 return false;
129 DPrintf("Hit expected/benign race: %s addr=%zx:%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" {
cd0be65c
WM
160void AnnotateHappensBefore(char *f, int l, uptr addr) {
161 SCOPED_ANNOTATION(AnnotateHappensBefore);
162 Release(cur_thread(), CALLERPC, addr);
163}
164
cd0be65c
WM
165void AnnotateHappensAfter(char *f, int l, uptr addr) {
166 SCOPED_ANNOTATION(AnnotateHappensAfter);
167 Acquire(cur_thread(), CALLERPC, addr);
168}
169
cd0be65c
WM
170void AnnotateCondVarSignal(char *f, int l, uptr cv) {
171 SCOPED_ANNOTATION(AnnotateCondVarSignal);
172}
173
cd0be65c
WM
174void AnnotateCondVarSignalAll(char *f, int l, uptr cv) {
175 SCOPED_ANNOTATION(AnnotateCondVarSignalAll);
176}
177
cd0be65c
WM
178void AnnotateMutexIsNotPHB(char *f, int l, uptr mu) {
179 SCOPED_ANNOTATION(AnnotateMutexIsNotPHB);
180}
181
cd0be65c
WM
182void AnnotateCondVarWait(char *f, int l, uptr cv, uptr lock) {
183 SCOPED_ANNOTATION(AnnotateCondVarWait);
184}
185
cd0be65c
WM
186void AnnotateRWLockCreate(char *f, int l, uptr m) {
187 SCOPED_ANNOTATION(AnnotateRWLockCreate);
188 MutexCreate(thr, pc, m, true, true, false);
189}
190
cd0be65c
WM
191void AnnotateRWLockCreateStatic(char *f, int l, uptr m) {
192 SCOPED_ANNOTATION(AnnotateRWLockCreateStatic);
193 MutexCreate(thr, pc, m, true, true, true);
194}
195
cd0be65c
WM
196void AnnotateRWLockDestroy(char *f, int l, uptr m) {
197 SCOPED_ANNOTATION(AnnotateRWLockDestroy);
198 MutexDestroy(thr, pc, m);
199}
200
cd0be65c
WM
201void AnnotateRWLockAcquired(char *f, int l, uptr m, uptr is_w) {
202 SCOPED_ANNOTATION(AnnotateRWLockAcquired);
203 if (is_w)
204 MutexLock(thr, pc, m);
205 else
206 MutexReadLock(thr, pc, m);
207}
208
cd0be65c
WM
209void AnnotateRWLockReleased(char *f, int l, uptr m, uptr is_w) {
210 SCOPED_ANNOTATION(AnnotateRWLockReleased);
211 if (is_w)
212 MutexUnlock(thr, pc, m);
213 else
214 MutexReadUnlock(thr, pc, m);
215}
216
cd0be65c
WM
217void AnnotateTraceMemory(char *f, int l, uptr mem) {
218 SCOPED_ANNOTATION(AnnotateTraceMemory);
219}
220
cd0be65c
WM
221void AnnotateFlushState(char *f, int l) {
222 SCOPED_ANNOTATION(AnnotateFlushState);
223}
224
cd0be65c
WM
225void AnnotateNewMemory(char *f, int l, uptr mem, uptr size) {
226 SCOPED_ANNOTATION(AnnotateNewMemory);
227}
228
cd0be65c
WM
229void AnnotateNoOp(char *f, int l, uptr mem) {
230 SCOPED_ANNOTATION(AnnotateNoOp);
231}
232
233static void ReportMissedExpectedRace(ExpectRace *race) {
e297eb60
KS
234 Printf("==================\n");
235 Printf("WARNING: ThreadSanitizer: missed expected data race\n");
236 Printf(" %s addr=%zx %s:%d\n",
cd0be65c 237 race->desc, race->addr, race->file, race->line);
e297eb60 238 Printf("==================\n");
cd0be65c
WM
239}
240
cd0be65c
WM
241void AnnotateFlushExpectedRaces(char *f, int l) {
242 SCOPED_ANNOTATION(AnnotateFlushExpectedRaces);
243 Lock lock(&dyn_ann_ctx->mtx);
244 while (dyn_ann_ctx->expect.next != &dyn_ann_ctx->expect) {
245 ExpectRace *race = dyn_ann_ctx->expect.next;
246 if (race->hitcount == 0) {
247 CTX()->nmissed_expected++;
248 ReportMissedExpectedRace(race);
249 }
250 race->prev->next = race->next;
251 race->next->prev = race->prev;
252 internal_free(race);
253 }
254}
255
cd0be65c
WM
256void AnnotateEnableRaceDetection(char *f, int l, int enable) {
257 SCOPED_ANNOTATION(AnnotateEnableRaceDetection);
258 // FIXME: Reconsider this functionality later. It may be irrelevant.
259}
260
cd0be65c
WM
261void AnnotateMutexIsUsedAsCondVar(char *f, int l, uptr mu) {
262 SCOPED_ANNOTATION(AnnotateMutexIsUsedAsCondVar);
263}
264
cd0be65c
WM
265void AnnotatePCQGet(char *f, int l, uptr pcq) {
266 SCOPED_ANNOTATION(AnnotatePCQGet);
267}
268
cd0be65c
WM
269void AnnotatePCQPut(char *f, int l, uptr pcq) {
270 SCOPED_ANNOTATION(AnnotatePCQPut);
271}
272
cd0be65c
WM
273void AnnotatePCQDestroy(char *f, int l, uptr pcq) {
274 SCOPED_ANNOTATION(AnnotatePCQDestroy);
275}
276
cd0be65c
WM
277void AnnotatePCQCreate(char *f, int l, uptr pcq) {
278 SCOPED_ANNOTATION(AnnotatePCQCreate);
279}
280
cd0be65c
WM
281void AnnotateExpectRace(char *f, int l, uptr mem, char *desc) {
282 SCOPED_ANNOTATION(AnnotateExpectRace);
283 Lock lock(&dyn_ann_ctx->mtx);
284 AddExpectRace(&dyn_ann_ctx->expect,
285 f, l, mem, 1, desc);
286 DPrintf("Add expected race: %s addr=%zx %s:%d\n", desc, mem, f, l);
287}
288
289static void BenignRaceImpl(char *f, int l, uptr mem, uptr size, char *desc) {
290 Lock lock(&dyn_ann_ctx->mtx);
291 AddExpectRace(&dyn_ann_ctx->benign,
292 f, l, mem, size, desc);
293 DPrintf("Add benign race: %s addr=%zx %s:%d\n", desc, mem, f, l);
294}
295
296// FIXME: Turn it off later. WTF is benign race?1?? Go talk to Hans Boehm.
cd0be65c
WM
297void AnnotateBenignRaceSized(char *f, int l, uptr mem, uptr size, char *desc) {
298 SCOPED_ANNOTATION(AnnotateBenignRaceSized);
299 BenignRaceImpl(f, l, mem, size, desc);
300}
301
cd0be65c
WM
302void AnnotateBenignRace(char *f, int l, uptr mem, char *desc) {
303 SCOPED_ANNOTATION(AnnotateBenignRace);
304 BenignRaceImpl(f, l, mem, 1, desc);
305}
306
cd0be65c
WM
307void AnnotateIgnoreReadsBegin(char *f, int l) {
308 SCOPED_ANNOTATION(AnnotateIgnoreReadsBegin);
309 IgnoreCtl(cur_thread(), false, true);
310}
311
cd0be65c
WM
312void AnnotateIgnoreReadsEnd(char *f, int l) {
313 SCOPED_ANNOTATION(AnnotateIgnoreReadsEnd);
314 IgnoreCtl(cur_thread(), false, false);
315}
316
cd0be65c
WM
317void AnnotateIgnoreWritesBegin(char *f, int l) {
318 SCOPED_ANNOTATION(AnnotateIgnoreWritesBegin);
319 IgnoreCtl(cur_thread(), true, true);
320}
321
cd0be65c
WM
322void AnnotateIgnoreWritesEnd(char *f, int l) {
323 SCOPED_ANNOTATION(AnnotateIgnoreWritesEnd);
324 IgnoreCtl(cur_thread(), true, false);
325}
326
cd0be65c
WM
327void AnnotatePublishMemoryRange(char *f, int l, uptr addr, uptr size) {
328 SCOPED_ANNOTATION(AnnotatePublishMemoryRange);
329}
330
cd0be65c
WM
331void AnnotateUnpublishMemoryRange(char *f, int l, uptr addr, uptr size) {
332 SCOPED_ANNOTATION(AnnotateUnpublishMemoryRange);
333}
334
cd0be65c
WM
335void AnnotateThreadName(char *f, int l, char *name) {
336 SCOPED_ANNOTATION(AnnotateThreadName);
337}
338
cd0be65c
WM
339void WTFAnnotateHappensBefore(char *f, int l, uptr addr) {
340 SCOPED_ANNOTATION(AnnotateHappensBefore);
341}
342
cd0be65c
WM
343void WTFAnnotateHappensAfter(char *f, int l, uptr addr) {
344 SCOPED_ANNOTATION(AnnotateHappensAfter);
345}
346
cd0be65c
WM
347void WTFAnnotateBenignRaceSized(char *f, int l, uptr mem, uptr sz, char *desc) {
348 SCOPED_ANNOTATION(AnnotateBenignRaceSized);
349}
350
cd0be65c
WM
351int RunningOnValgrind() {
352 return flags()->running_on_valgrind;
353}
354
355double __attribute__((weak)) ValgrindSlowdown(void) {
356 return 10.0;
357}
358
cd0be65c
WM
359const char *ThreadSanitizerQuery(const char *query) {
360 if (internal_strcmp(query, "pure_happens_before") == 0)
361 return "1";
362 else
363 return "0";
364}
365} // extern "C"