1 //===-- tsan_interface_ann.cc ---------------------------------------------===//
3 // This file is distributed under the University of Illinois Open Source
4 // License. See LICENSE.TXT for details.
6 //===----------------------------------------------------------------------===//
8 // This file is a part of ThreadSanitizer (TSan), a race detector.
10 //===----------------------------------------------------------------------===//
11 #include "sanitizer_common/sanitizer_libc.h"
12 #include "sanitizer_common/sanitizer_internal_defs.h"
13 #include "sanitizer_common/sanitizer_placement_new.h"
14 #include "sanitizer_common/sanitizer_stacktrace.h"
15 #include "tsan_interface_ann.h"
16 #include "tsan_mutex.h"
17 #include "tsan_report.h"
19 #include "tsan_mman.h"
20 #include "tsan_flags.h"
21 #include "tsan_platform.h"
22 #include "tsan_vector.h"
24 #define CALLERPC ((uptr)__builtin_return_address(0))
26 using namespace __tsan
; // NOLINT
30 class ScopedAnnotation
{
32 ScopedAnnotation(ThreadState
*thr
, const char *aname
, const char *f
, int l
,
36 DPrintf("#%d: annotation %s() %s:%d\n", thr_
->tid
, aname
, f
, l
);
44 ThreadState
*const thr_
;
47 #define SCOPED_ANNOTATION(typ) \
48 if (!flags()->enable_annotations) \
50 ThreadState *thr = cur_thread(); \
51 const uptr caller_pc = (uptr)__builtin_return_address(0); \
52 StatInc(thr, StatAnnotation); \
53 StatInc(thr, Stat##typ); \
54 ScopedAnnotation sa(thr, __func__, f, l, caller_pc); \
55 const uptr pc = StackTrace::GetCurrentPc(); \
59 static const int kMaxDescLen
= 128;
64 atomic_uintptr_t hitcount
;
65 atomic_uintptr_t addcount
;
70 char desc
[kMaxDescLen
];
73 struct DynamicAnnContext
{
79 : mtx(MutexTypeAnnotations
, StatMtxAnnotations
) {
83 static DynamicAnnContext
*dyn_ann_ctx
;
84 static char dyn_ann_ctx_placeholder
[sizeof(DynamicAnnContext
)] ALIGNED(64);
86 static void AddExpectRace(ExpectRace
*list
,
87 char *f
, int l
, uptr addr
, uptr size
, char *desc
) {
88 ExpectRace
*race
= list
->next
;
89 for (; race
!= list
; race
= race
->next
) {
90 if (race
->addr
== addr
&& race
->size
== size
) {
91 atomic_store_relaxed(&race
->addcount
,
92 atomic_load_relaxed(&race
->addcount
) + 1);
96 race
= (ExpectRace
*)internal_alloc(MBlockExpectRace
, sizeof(ExpectRace
));
102 atomic_store_relaxed(&race
->hitcount
, 0);
103 atomic_store_relaxed(&race
->addcount
, 1);
106 for (; i
< kMaxDescLen
- 1 && desc
[i
]; i
++)
107 race
->desc
[i
] = desc
[i
];
111 race
->next
= list
->next
;
112 race
->next
->prev
= race
;
116 static 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
)
126 static bool CheckContains(ExpectRace
*list
, uptr addr
, uptr size
) {
127 ExpectRace
*race
= FindRace(list
, addr
, size
);
130 DPrintf("Hit expected/benign race: %s addr=%zx:%d %s:%d\n",
131 race
->desc
, race
->addr
, (int)race
->size
, race
->file
, race
->line
);
132 atomic_fetch_add(&race
->hitcount
, 1, memory_order_relaxed
);
136 static void InitList(ExpectRace
*list
) {
141 void InitializeDynamicAnnotations() {
142 dyn_ann_ctx
= new(dyn_ann_ctx_placeholder
) DynamicAnnContext
;
143 InitList(&dyn_ann_ctx
->expect
);
144 InitList(&dyn_ann_ctx
->benign
);
147 bool IsExpectedReport(uptr addr
, uptr size
) {
148 ReadLock
lock(&dyn_ann_ctx
->mtx
);
149 if (CheckContains(&dyn_ann_ctx
->expect
, addr
, size
))
151 if (CheckContains(&dyn_ann_ctx
->benign
, addr
, size
))
156 static void CollectMatchedBenignRaces(Vector
<ExpectRace
> *matched
,
157 int *unique_count
, int *hit_count
, atomic_uintptr_t
ExpectRace::*counter
) {
158 ExpectRace
*list
= &dyn_ann_ctx
->benign
;
159 for (ExpectRace
*race
= list
->next
; race
!= list
; race
= race
->next
) {
161 const uptr cnt
= atomic_load_relaxed(&(race
->*counter
));
166 for (; i
< matched
->Size(); i
++) {
167 ExpectRace
*race0
= &(*matched
)[i
];
168 if (race
->line
== race0
->line
169 && internal_strcmp(race
->file
, race0
->file
) == 0
170 && internal_strcmp(race
->desc
, race0
->desc
) == 0) {
171 atomic_fetch_add(&(race0
->*counter
), cnt
, memory_order_relaxed
);
175 if (i
== matched
->Size())
176 matched
->PushBack(*race
);
180 void PrintMatchedBenignRaces() {
181 Lock
lock(&dyn_ann_ctx
->mtx
);
182 int unique_count
= 0;
185 Vector
<ExpectRace
> hit_matched(MBlockScopedBuf
);
186 CollectMatchedBenignRaces(&hit_matched
, &unique_count
, &hit_count
,
187 &ExpectRace::hitcount
);
188 Vector
<ExpectRace
> add_matched(MBlockScopedBuf
);
189 CollectMatchedBenignRaces(&add_matched
, &unique_count
, &add_count
,
190 &ExpectRace::addcount
);
191 if (hit_matched
.Size()) {
192 Printf("ThreadSanitizer: Matched %d \"benign\" races (pid=%d):\n",
193 hit_count
, (int)internal_getpid());
194 for (uptr i
= 0; i
< hit_matched
.Size(); i
++) {
195 Printf("%d %s:%d %s\n",
196 atomic_load_relaxed(&hit_matched
[i
].hitcount
),
197 hit_matched
[i
].file
, hit_matched
[i
].line
, hit_matched
[i
].desc
);
200 if (hit_matched
.Size()) {
201 Printf("ThreadSanitizer: Annotated %d \"benign\" races, %d unique"
203 add_count
, unique_count
, (int)internal_getpid());
204 for (uptr i
= 0; i
< add_matched
.Size(); i
++) {
205 Printf("%d %s:%d %s\n",
206 atomic_load_relaxed(&add_matched
[i
].addcount
),
207 add_matched
[i
].file
, add_matched
[i
].line
, add_matched
[i
].desc
);
212 static void ReportMissedExpectedRace(ExpectRace
*race
) {
213 Printf("==================\n");
214 Printf("WARNING: ThreadSanitizer: missed expected data race\n");
215 Printf(" %s addr=%zx %s:%d\n",
216 race
->desc
, race
->addr
, race
->file
, race
->line
);
217 Printf("==================\n");
219 } // namespace __tsan
221 using namespace __tsan
; // NOLINT
224 void INTERFACE_ATTRIBUTE
AnnotateHappensBefore(char *f
, int l
, uptr addr
) {
225 SCOPED_ANNOTATION(AnnotateHappensBefore
);
226 Release(thr
, pc
, addr
);
229 void INTERFACE_ATTRIBUTE
AnnotateHappensAfter(char *f
, int l
, uptr addr
) {
230 SCOPED_ANNOTATION(AnnotateHappensAfter
);
231 Acquire(thr
, pc
, addr
);
234 void INTERFACE_ATTRIBUTE
AnnotateCondVarSignal(char *f
, int l
, uptr cv
) {
235 SCOPED_ANNOTATION(AnnotateCondVarSignal
);
238 void INTERFACE_ATTRIBUTE
AnnotateCondVarSignalAll(char *f
, int l
, uptr cv
) {
239 SCOPED_ANNOTATION(AnnotateCondVarSignalAll
);
242 void INTERFACE_ATTRIBUTE
AnnotateMutexIsNotPHB(char *f
, int l
, uptr mu
) {
243 SCOPED_ANNOTATION(AnnotateMutexIsNotPHB
);
246 void INTERFACE_ATTRIBUTE
AnnotateCondVarWait(char *f
, int l
, uptr cv
,
248 SCOPED_ANNOTATION(AnnotateCondVarWait
);
251 void INTERFACE_ATTRIBUTE
AnnotateRWLockCreate(char *f
, int l
, uptr m
) {
252 SCOPED_ANNOTATION(AnnotateRWLockCreate
);
253 MutexCreate(thr
, pc
, m
, true, true, false);
256 void INTERFACE_ATTRIBUTE
AnnotateRWLockCreateStatic(char *f
, int l
, uptr m
) {
257 SCOPED_ANNOTATION(AnnotateRWLockCreateStatic
);
258 MutexCreate(thr
, pc
, m
, true, true, true);
261 void INTERFACE_ATTRIBUTE
AnnotateRWLockDestroy(char *f
, int l
, uptr m
) {
262 SCOPED_ANNOTATION(AnnotateRWLockDestroy
);
263 MutexDestroy(thr
, pc
, m
);
266 void INTERFACE_ATTRIBUTE
AnnotateRWLockAcquired(char *f
, int l
, uptr m
,
268 SCOPED_ANNOTATION(AnnotateRWLockAcquired
);
270 MutexLock(thr
, pc
, m
);
272 MutexReadLock(thr
, pc
, m
);
275 void INTERFACE_ATTRIBUTE
AnnotateRWLockReleased(char *f
, int l
, uptr m
,
277 SCOPED_ANNOTATION(AnnotateRWLockReleased
);
279 MutexUnlock(thr
, pc
, m
);
281 MutexReadUnlock(thr
, pc
, m
);
284 void INTERFACE_ATTRIBUTE
AnnotateTraceMemory(char *f
, int l
, uptr mem
) {
285 SCOPED_ANNOTATION(AnnotateTraceMemory
);
288 void INTERFACE_ATTRIBUTE
AnnotateFlushState(char *f
, int l
) {
289 SCOPED_ANNOTATION(AnnotateFlushState
);
292 void INTERFACE_ATTRIBUTE
AnnotateNewMemory(char *f
, int l
, uptr mem
,
294 SCOPED_ANNOTATION(AnnotateNewMemory
);
297 void INTERFACE_ATTRIBUTE
AnnotateNoOp(char *f
, int l
, uptr mem
) {
298 SCOPED_ANNOTATION(AnnotateNoOp
);
301 void INTERFACE_ATTRIBUTE
AnnotateFlushExpectedRaces(char *f
, int l
) {
302 SCOPED_ANNOTATION(AnnotateFlushExpectedRaces
);
303 Lock
lock(&dyn_ann_ctx
->mtx
);
304 while (dyn_ann_ctx
->expect
.next
!= &dyn_ann_ctx
->expect
) {
305 ExpectRace
*race
= dyn_ann_ctx
->expect
.next
;
306 if (atomic_load_relaxed(&race
->hitcount
) == 0) {
307 ctx
->nmissed_expected
++;
308 ReportMissedExpectedRace(race
);
310 race
->prev
->next
= race
->next
;
311 race
->next
->prev
= race
->prev
;
316 void INTERFACE_ATTRIBUTE
AnnotateEnableRaceDetection(
317 char *f
, int l
, int enable
) {
318 SCOPED_ANNOTATION(AnnotateEnableRaceDetection
);
319 // FIXME: Reconsider this functionality later. It may be irrelevant.
322 void INTERFACE_ATTRIBUTE
AnnotateMutexIsUsedAsCondVar(
323 char *f
, int l
, uptr mu
) {
324 SCOPED_ANNOTATION(AnnotateMutexIsUsedAsCondVar
);
327 void INTERFACE_ATTRIBUTE
AnnotatePCQGet(
328 char *f
, int l
, uptr pcq
) {
329 SCOPED_ANNOTATION(AnnotatePCQGet
);
332 void INTERFACE_ATTRIBUTE
AnnotatePCQPut(
333 char *f
, int l
, uptr pcq
) {
334 SCOPED_ANNOTATION(AnnotatePCQPut
);
337 void INTERFACE_ATTRIBUTE
AnnotatePCQDestroy(
338 char *f
, int l
, uptr pcq
) {
339 SCOPED_ANNOTATION(AnnotatePCQDestroy
);
342 void INTERFACE_ATTRIBUTE
AnnotatePCQCreate(
343 char *f
, int l
, uptr pcq
) {
344 SCOPED_ANNOTATION(AnnotatePCQCreate
);
347 void INTERFACE_ATTRIBUTE
AnnotateExpectRace(
348 char *f
, int l
, uptr mem
, char *desc
) {
349 SCOPED_ANNOTATION(AnnotateExpectRace
);
350 Lock
lock(&dyn_ann_ctx
->mtx
);
351 AddExpectRace(&dyn_ann_ctx
->expect
,
353 DPrintf("Add expected race: %s addr=%zx %s:%d\n", desc
, mem
, f
, l
);
356 static void BenignRaceImpl(
357 char *f
, int l
, uptr mem
, uptr size
, char *desc
) {
358 Lock
lock(&dyn_ann_ctx
->mtx
);
359 AddExpectRace(&dyn_ann_ctx
->benign
,
360 f
, l
, mem
, size
, desc
);
361 DPrintf("Add benign race: %s addr=%zx %s:%d\n", desc
, mem
, f
, l
);
364 // FIXME: Turn it off later. WTF is benign race?1?? Go talk to Hans Boehm.
365 void INTERFACE_ATTRIBUTE
AnnotateBenignRaceSized(
366 char *f
, int l
, uptr mem
, uptr size
, char *desc
) {
367 SCOPED_ANNOTATION(AnnotateBenignRaceSized
);
368 BenignRaceImpl(f
, l
, mem
, size
, desc
);
371 void INTERFACE_ATTRIBUTE
AnnotateBenignRace(
372 char *f
, int l
, uptr mem
, char *desc
) {
373 SCOPED_ANNOTATION(AnnotateBenignRace
);
374 BenignRaceImpl(f
, l
, mem
, 1, desc
);
377 void INTERFACE_ATTRIBUTE
AnnotateIgnoreReadsBegin(char *f
, int l
) {
378 SCOPED_ANNOTATION(AnnotateIgnoreReadsBegin
);
379 ThreadIgnoreBegin(thr
, pc
);
382 void INTERFACE_ATTRIBUTE
AnnotateIgnoreReadsEnd(char *f
, int l
) {
383 SCOPED_ANNOTATION(AnnotateIgnoreReadsEnd
);
384 ThreadIgnoreEnd(thr
, pc
);
387 void INTERFACE_ATTRIBUTE
AnnotateIgnoreWritesBegin(char *f
, int l
) {
388 SCOPED_ANNOTATION(AnnotateIgnoreWritesBegin
);
389 ThreadIgnoreBegin(thr
, pc
);
392 void INTERFACE_ATTRIBUTE
AnnotateIgnoreWritesEnd(char *f
, int l
) {
393 SCOPED_ANNOTATION(AnnotateIgnoreWritesEnd
);
394 ThreadIgnoreEnd(thr
, pc
);
397 void INTERFACE_ATTRIBUTE
AnnotateIgnoreSyncBegin(char *f
, int l
) {
398 SCOPED_ANNOTATION(AnnotateIgnoreSyncBegin
);
399 ThreadIgnoreSyncBegin(thr
, pc
);
402 void INTERFACE_ATTRIBUTE
AnnotateIgnoreSyncEnd(char *f
, int l
) {
403 SCOPED_ANNOTATION(AnnotateIgnoreSyncEnd
);
404 ThreadIgnoreSyncEnd(thr
, pc
);
407 void INTERFACE_ATTRIBUTE
AnnotatePublishMemoryRange(
408 char *f
, int l
, uptr addr
, uptr size
) {
409 SCOPED_ANNOTATION(AnnotatePublishMemoryRange
);
412 void INTERFACE_ATTRIBUTE
AnnotateUnpublishMemoryRange(
413 char *f
, int l
, uptr addr
, uptr size
) {
414 SCOPED_ANNOTATION(AnnotateUnpublishMemoryRange
);
417 void INTERFACE_ATTRIBUTE
AnnotateThreadName(
418 char *f
, int l
, char *name
) {
419 SCOPED_ANNOTATION(AnnotateThreadName
);
420 ThreadSetName(thr
, name
);
423 // We deliberately omit the implementation of WTFAnnotateHappensBefore() and
424 // WTFAnnotateHappensAfter(). Those are being used by Webkit to annotate
425 // atomic operations, which should be handled by ThreadSanitizer correctly.
426 void INTERFACE_ATTRIBUTE
WTFAnnotateHappensBefore(char *f
, int l
, uptr addr
) {
427 SCOPED_ANNOTATION(AnnotateHappensBefore
);
430 void INTERFACE_ATTRIBUTE
WTFAnnotateHappensAfter(char *f
, int l
, uptr addr
) {
431 SCOPED_ANNOTATION(AnnotateHappensAfter
);
434 void INTERFACE_ATTRIBUTE
WTFAnnotateBenignRaceSized(
435 char *f
, int l
, uptr mem
, uptr sz
, char *desc
) {
436 SCOPED_ANNOTATION(AnnotateBenignRaceSized
);
437 BenignRaceImpl(f
, l
, mem
, sz
, desc
);
440 int INTERFACE_ATTRIBUTE
RunningOnValgrind() {
441 return flags()->running_on_valgrind
;
444 double __attribute__((weak
)) INTERFACE_ATTRIBUTE
ValgrindSlowdown(void) {
448 const char INTERFACE_ATTRIBUTE
* ThreadSanitizerQuery(const char *query
) {
449 if (internal_strcmp(query
, "pure_happens_before") == 0)
455 void INTERFACE_ATTRIBUTE
456 AnnotateMemoryIsInitialized(char *f
, int l
, uptr mem
, uptr sz
) {}
457 void INTERFACE_ATTRIBUTE
458 AnnotateMemoryIsUninitialized(char *f
, int l
, uptr mem
, uptr sz
) {}