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 = __sanitizer::StackTrace::GetCurrentPc(); \
59 static const int kMaxDescLen
= 128;
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
) {
95 race
= (ExpectRace
*)internal_alloc(MBlockExpectRace
, sizeof(ExpectRace
));
105 for (; i
< kMaxDescLen
- 1 && desc
[i
]; i
++)
106 race
->desc
[i
] = desc
[i
];
110 race
->next
= list
->next
;
111 race
->next
->prev
= race
;
115 static ExpectRace
*FindRace(ExpectRace
*list
, uptr addr
, uptr size
) {
116 for (ExpectRace
*race
= list
->next
; race
!= list
; race
= race
->next
) {
117 uptr maxbegin
= max(race
->addr
, addr
);
118 uptr minend
= min(race
->addr
+ race
->size
, addr
+ size
);
119 if (maxbegin
< minend
)
125 static bool CheckContains(ExpectRace
*list
, uptr addr
, uptr size
) {
126 ExpectRace
*race
= FindRace(list
, addr
, size
);
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
);
135 static void InitList(ExpectRace
*list
) {
140 void InitializeDynamicAnnotations() {
141 dyn_ann_ctx
= new(dyn_ann_ctx_placeholder
) DynamicAnnContext
;
142 InitList(&dyn_ann_ctx
->expect
);
143 InitList(&dyn_ann_ctx
->benign
);
146 bool IsExpectedReport(uptr addr
, uptr size
) {
147 Lock
lock(&dyn_ann_ctx
->mtx
);
148 if (CheckContains(&dyn_ann_ctx
->expect
, addr
, size
))
150 if (CheckContains(&dyn_ann_ctx
->benign
, addr
, size
))
155 static void CollectMatchedBenignRaces(Vector
<ExpectRace
> *matched
,
156 int *unique_count
, int *hit_count
, int ExpectRace::*counter
) {
157 ExpectRace
*list
= &dyn_ann_ctx
->benign
;
158 for (ExpectRace
*race
= list
->next
; race
!= list
; race
= race
->next
) {
160 if (race
->*counter
== 0)
162 (*hit_count
) += race
->*counter
;
164 for (; i
< matched
->Size(); i
++) {
165 ExpectRace
*race0
= &(*matched
)[i
];
166 if (race
->line
== race0
->line
167 && internal_strcmp(race
->file
, race0
->file
) == 0
168 && internal_strcmp(race
->desc
, race0
->desc
) == 0) {
169 race0
->*counter
+= race
->*counter
;
173 if (i
== matched
->Size())
174 matched
->PushBack(*race
);
178 void PrintMatchedBenignRaces() {
179 Lock
lock(&dyn_ann_ctx
->mtx
);
180 int unique_count
= 0;
183 Vector
<ExpectRace
> hit_matched(MBlockScopedBuf
);
184 CollectMatchedBenignRaces(&hit_matched
, &unique_count
, &hit_count
,
185 &ExpectRace::hitcount
);
186 Vector
<ExpectRace
> add_matched(MBlockScopedBuf
);
187 CollectMatchedBenignRaces(&add_matched
, &unique_count
, &add_count
,
188 &ExpectRace::addcount
);
189 if (hit_matched
.Size()) {
190 Printf("ThreadSanitizer: Matched %d \"benign\" races (pid=%d):\n",
191 hit_count
, (int)internal_getpid());
192 for (uptr i
= 0; i
< hit_matched
.Size(); i
++) {
193 Printf("%d %s:%d %s\n",
194 hit_matched
[i
].hitcount
, hit_matched
[i
].file
,
195 hit_matched
[i
].line
, hit_matched
[i
].desc
);
198 if (hit_matched
.Size()) {
199 Printf("ThreadSanitizer: Annotated %d \"benign\" races, %d unique"
201 add_count
, unique_count
, (int)internal_getpid());
202 for (uptr i
= 0; i
< add_matched
.Size(); i
++) {
203 Printf("%d %s:%d %s\n",
204 add_matched
[i
].addcount
, add_matched
[i
].file
,
205 add_matched
[i
].line
, add_matched
[i
].desc
);
210 static void ReportMissedExpectedRace(ExpectRace
*race
) {
211 Printf("==================\n");
212 Printf("WARNING: ThreadSanitizer: missed expected data race\n");
213 Printf(" %s addr=%zx %s:%d\n",
214 race
->desc
, race
->addr
, race
->file
, race
->line
);
215 Printf("==================\n");
217 } // namespace __tsan
219 using namespace __tsan
; // NOLINT
222 void INTERFACE_ATTRIBUTE
AnnotateHappensBefore(char *f
, int l
, uptr addr
) {
223 SCOPED_ANNOTATION(AnnotateHappensBefore
);
224 Release(thr
, pc
, addr
);
227 void INTERFACE_ATTRIBUTE
AnnotateHappensAfter(char *f
, int l
, uptr addr
) {
228 SCOPED_ANNOTATION(AnnotateHappensAfter
);
229 Acquire(thr
, pc
, addr
);
232 void INTERFACE_ATTRIBUTE
AnnotateCondVarSignal(char *f
, int l
, uptr cv
) {
233 SCOPED_ANNOTATION(AnnotateCondVarSignal
);
236 void INTERFACE_ATTRIBUTE
AnnotateCondVarSignalAll(char *f
, int l
, uptr cv
) {
237 SCOPED_ANNOTATION(AnnotateCondVarSignalAll
);
240 void INTERFACE_ATTRIBUTE
AnnotateMutexIsNotPHB(char *f
, int l
, uptr mu
) {
241 SCOPED_ANNOTATION(AnnotateMutexIsNotPHB
);
244 void INTERFACE_ATTRIBUTE
AnnotateCondVarWait(char *f
, int l
, uptr cv
,
246 SCOPED_ANNOTATION(AnnotateCondVarWait
);
249 void INTERFACE_ATTRIBUTE
AnnotateRWLockCreate(char *f
, int l
, uptr m
) {
250 SCOPED_ANNOTATION(AnnotateRWLockCreate
);
251 MutexCreate(thr
, pc
, m
, true, true, false);
254 void INTERFACE_ATTRIBUTE
AnnotateRWLockCreateStatic(char *f
, int l
, uptr m
) {
255 SCOPED_ANNOTATION(AnnotateRWLockCreateStatic
);
256 MutexCreate(thr
, pc
, m
, true, true, true);
259 void INTERFACE_ATTRIBUTE
AnnotateRWLockDestroy(char *f
, int l
, uptr m
) {
260 SCOPED_ANNOTATION(AnnotateRWLockDestroy
);
261 MutexDestroy(thr
, pc
, m
);
264 void INTERFACE_ATTRIBUTE
AnnotateRWLockAcquired(char *f
, int l
, uptr m
,
266 SCOPED_ANNOTATION(AnnotateRWLockAcquired
);
268 MutexLock(thr
, pc
, m
);
270 MutexReadLock(thr
, pc
, m
);
273 void INTERFACE_ATTRIBUTE
AnnotateRWLockReleased(char *f
, int l
, uptr m
,
275 SCOPED_ANNOTATION(AnnotateRWLockReleased
);
277 MutexUnlock(thr
, pc
, m
);
279 MutexReadUnlock(thr
, pc
, m
);
282 void INTERFACE_ATTRIBUTE
AnnotateTraceMemory(char *f
, int l
, uptr mem
) {
283 SCOPED_ANNOTATION(AnnotateTraceMemory
);
286 void INTERFACE_ATTRIBUTE
AnnotateFlushState(char *f
, int l
) {
287 SCOPED_ANNOTATION(AnnotateFlushState
);
290 void INTERFACE_ATTRIBUTE
AnnotateNewMemory(char *f
, int l
, uptr mem
,
292 SCOPED_ANNOTATION(AnnotateNewMemory
);
295 void INTERFACE_ATTRIBUTE
AnnotateNoOp(char *f
, int l
, uptr mem
) {
296 SCOPED_ANNOTATION(AnnotateNoOp
);
299 void INTERFACE_ATTRIBUTE
AnnotateFlushExpectedRaces(char *f
, int l
) {
300 SCOPED_ANNOTATION(AnnotateFlushExpectedRaces
);
301 Lock
lock(&dyn_ann_ctx
->mtx
);
302 while (dyn_ann_ctx
->expect
.next
!= &dyn_ann_ctx
->expect
) {
303 ExpectRace
*race
= dyn_ann_ctx
->expect
.next
;
304 if (race
->hitcount
== 0) {
305 ctx
->nmissed_expected
++;
306 ReportMissedExpectedRace(race
);
308 race
->prev
->next
= race
->next
;
309 race
->next
->prev
= race
->prev
;
314 void INTERFACE_ATTRIBUTE
AnnotateEnableRaceDetection(
315 char *f
, int l
, int enable
) {
316 SCOPED_ANNOTATION(AnnotateEnableRaceDetection
);
317 // FIXME: Reconsider this functionality later. It may be irrelevant.
320 void INTERFACE_ATTRIBUTE
AnnotateMutexIsUsedAsCondVar(
321 char *f
, int l
, uptr mu
) {
322 SCOPED_ANNOTATION(AnnotateMutexIsUsedAsCondVar
);
325 void INTERFACE_ATTRIBUTE
AnnotatePCQGet(
326 char *f
, int l
, uptr pcq
) {
327 SCOPED_ANNOTATION(AnnotatePCQGet
);
330 void INTERFACE_ATTRIBUTE
AnnotatePCQPut(
331 char *f
, int l
, uptr pcq
) {
332 SCOPED_ANNOTATION(AnnotatePCQPut
);
335 void INTERFACE_ATTRIBUTE
AnnotatePCQDestroy(
336 char *f
, int l
, uptr pcq
) {
337 SCOPED_ANNOTATION(AnnotatePCQDestroy
);
340 void INTERFACE_ATTRIBUTE
AnnotatePCQCreate(
341 char *f
, int l
, uptr pcq
) {
342 SCOPED_ANNOTATION(AnnotatePCQCreate
);
345 void INTERFACE_ATTRIBUTE
AnnotateExpectRace(
346 char *f
, int l
, uptr mem
, char *desc
) {
347 SCOPED_ANNOTATION(AnnotateExpectRace
);
348 Lock
lock(&dyn_ann_ctx
->mtx
);
349 AddExpectRace(&dyn_ann_ctx
->expect
,
351 DPrintf("Add expected race: %s addr=%zx %s:%d\n", desc
, mem
, f
, l
);
354 static void BenignRaceImpl(
355 char *f
, int l
, uptr mem
, uptr size
, char *desc
) {
356 Lock
lock(&dyn_ann_ctx
->mtx
);
357 AddExpectRace(&dyn_ann_ctx
->benign
,
358 f
, l
, mem
, size
, desc
);
359 DPrintf("Add benign race: %s addr=%zx %s:%d\n", desc
, mem
, f
, l
);
362 // FIXME: Turn it off later. WTF is benign race?1?? Go talk to Hans Boehm.
363 void INTERFACE_ATTRIBUTE
AnnotateBenignRaceSized(
364 char *f
, int l
, uptr mem
, uptr size
, char *desc
) {
365 SCOPED_ANNOTATION(AnnotateBenignRaceSized
);
366 BenignRaceImpl(f
, l
, mem
, size
, desc
);
369 void INTERFACE_ATTRIBUTE
AnnotateBenignRace(
370 char *f
, int l
, uptr mem
, char *desc
) {
371 SCOPED_ANNOTATION(AnnotateBenignRace
);
372 BenignRaceImpl(f
, l
, mem
, 1, desc
);
375 void INTERFACE_ATTRIBUTE
AnnotateIgnoreReadsBegin(char *f
, int l
) {
376 SCOPED_ANNOTATION(AnnotateIgnoreReadsBegin
);
377 ThreadIgnoreBegin(thr
, pc
);
380 void INTERFACE_ATTRIBUTE
AnnotateIgnoreReadsEnd(char *f
, int l
) {
381 SCOPED_ANNOTATION(AnnotateIgnoreReadsEnd
);
382 ThreadIgnoreEnd(thr
, pc
);
385 void INTERFACE_ATTRIBUTE
AnnotateIgnoreWritesBegin(char *f
, int l
) {
386 SCOPED_ANNOTATION(AnnotateIgnoreWritesBegin
);
387 ThreadIgnoreBegin(thr
, pc
);
390 void INTERFACE_ATTRIBUTE
AnnotateIgnoreWritesEnd(char *f
, int l
) {
391 SCOPED_ANNOTATION(AnnotateIgnoreWritesEnd
);
392 ThreadIgnoreEnd(thr
, pc
);
395 void INTERFACE_ATTRIBUTE
AnnotateIgnoreSyncBegin(char *f
, int l
) {
396 SCOPED_ANNOTATION(AnnotateIgnoreSyncBegin
);
397 ThreadIgnoreSyncBegin(thr
, pc
);
400 void INTERFACE_ATTRIBUTE
AnnotateIgnoreSyncEnd(char *f
, int l
) {
401 SCOPED_ANNOTATION(AnnotateIgnoreSyncEnd
);
402 ThreadIgnoreSyncEnd(thr
, pc
);
405 void INTERFACE_ATTRIBUTE
AnnotatePublishMemoryRange(
406 char *f
, int l
, uptr addr
, uptr size
) {
407 SCOPED_ANNOTATION(AnnotatePublishMemoryRange
);
410 void INTERFACE_ATTRIBUTE
AnnotateUnpublishMemoryRange(
411 char *f
, int l
, uptr addr
, uptr size
) {
412 SCOPED_ANNOTATION(AnnotateUnpublishMemoryRange
);
415 void INTERFACE_ATTRIBUTE
AnnotateThreadName(
416 char *f
, int l
, char *name
) {
417 SCOPED_ANNOTATION(AnnotateThreadName
);
418 ThreadSetName(thr
, name
);
421 // We deliberately omit the implementation of WTFAnnotateHappensBefore() and
422 // WTFAnnotateHappensAfter(). Those are being used by Webkit to annotate
423 // atomic operations, which should be handled by ThreadSanitizer correctly.
424 void INTERFACE_ATTRIBUTE
WTFAnnotateHappensBefore(char *f
, int l
, uptr addr
) {
425 SCOPED_ANNOTATION(AnnotateHappensBefore
);
428 void INTERFACE_ATTRIBUTE
WTFAnnotateHappensAfter(char *f
, int l
, uptr addr
) {
429 SCOPED_ANNOTATION(AnnotateHappensAfter
);
432 void INTERFACE_ATTRIBUTE
WTFAnnotateBenignRaceSized(
433 char *f
, int l
, uptr mem
, uptr sz
, char *desc
) {
434 SCOPED_ANNOTATION(AnnotateBenignRaceSized
);
435 BenignRaceImpl(f
, l
, mem
, sz
, desc
);
438 int INTERFACE_ATTRIBUTE
RunningOnValgrind() {
439 return flags()->running_on_valgrind
;
442 double __attribute__((weak
)) INTERFACE_ATTRIBUTE
ValgrindSlowdown(void) {
446 const char INTERFACE_ATTRIBUTE
* ThreadSanitizerQuery(const char *query
) {
447 if (internal_strcmp(query
, "pure_happens_before") == 0)
453 void INTERFACE_ATTRIBUTE
454 AnnotateMemoryIsInitialized(char *f
, int l
, uptr mem
, uptr sz
) {}