1 //===-- tsan_interface_ann.cpp --------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This file is a part of ThreadSanitizer (TSan), a race detector.
11 //===----------------------------------------------------------------------===//
12 #include "sanitizer_common/sanitizer_libc.h"
13 #include "sanitizer_common/sanitizer_internal_defs.h"
14 #include "sanitizer_common/sanitizer_placement_new.h"
15 #include "sanitizer_common/sanitizer_stacktrace.h"
16 #include "sanitizer_common/sanitizer_vector.h"
17 #include "tsan_interface_ann.h"
18 #include "tsan_mutex.h"
19 #include "tsan_report.h"
21 #include "tsan_mman.h"
22 #include "tsan_flags.h"
23 #include "tsan_platform.h"
25 #define CALLERPC ((uptr)__builtin_return_address(0))
27 using namespace __tsan
;
31 class ScopedAnnotation
{
33 ScopedAnnotation(ThreadState
*thr
, const char *aname
, uptr pc
)
36 DPrintf("#%d: annotation %s()\n", thr_
->tid
, aname
);
44 ThreadState
*const thr_
;
47 #define SCOPED_ANNOTATION_RET(typ, ret) \
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__, caller_pc); \
55 const uptr pc = StackTrace::GetCurrentPc(); \
59 #define SCOPED_ANNOTATION(typ) SCOPED_ANNOTATION_RET(typ, )
61 static const int kMaxDescLen
= 128;
66 atomic_uintptr_t hitcount
;
67 atomic_uintptr_t addcount
;
72 char desc
[kMaxDescLen
];
75 struct DynamicAnnContext
{
81 : mtx(MutexTypeAnnotations
, StatMtxAnnotations
) {
85 static DynamicAnnContext
*dyn_ann_ctx
;
86 static char dyn_ann_ctx_placeholder
[sizeof(DynamicAnnContext
)] ALIGNED(64);
88 static 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 atomic_store_relaxed(&race
->addcount
,
94 atomic_load_relaxed(&race
->addcount
) + 1);
98 race
= (ExpectRace
*)internal_alloc(MBlockExpectRace
, sizeof(ExpectRace
));
104 atomic_store_relaxed(&race
->hitcount
, 0);
105 atomic_store_relaxed(&race
->addcount
, 1);
108 for (; i
< kMaxDescLen
- 1 && desc
[i
]; i
++)
109 race
->desc
[i
] = desc
[i
];
113 race
->next
= list
->next
;
114 race
->next
->prev
= race
;
118 static ExpectRace
*FindRace(ExpectRace
*list
, uptr addr
, uptr size
) {
119 for (ExpectRace
*race
= list
->next
; race
!= list
; race
= race
->next
) {
120 uptr maxbegin
= max(race
->addr
, addr
);
121 uptr minend
= min(race
->addr
+ race
->size
, addr
+ size
);
122 if (maxbegin
< minend
)
128 static bool CheckContains(ExpectRace
*list
, uptr addr
, uptr size
) {
129 ExpectRace
*race
= FindRace(list
, addr
, size
);
132 DPrintf("Hit expected/benign race: %s addr=%zx:%d %s:%d\n",
133 race
->desc
, race
->addr
, (int)race
->size
, race
->file
, race
->line
);
134 atomic_fetch_add(&race
->hitcount
, 1, memory_order_relaxed
);
138 static void InitList(ExpectRace
*list
) {
143 void InitializeDynamicAnnotations() {
144 dyn_ann_ctx
= new(dyn_ann_ctx_placeholder
) DynamicAnnContext
;
145 InitList(&dyn_ann_ctx
->expect
);
146 InitList(&dyn_ann_ctx
->benign
);
149 bool IsExpectedReport(uptr addr
, uptr size
) {
150 ReadLock
lock(&dyn_ann_ctx
->mtx
);
151 if (CheckContains(&dyn_ann_ctx
->expect
, addr
, size
))
153 if (CheckContains(&dyn_ann_ctx
->benign
, addr
, size
))
158 static void CollectMatchedBenignRaces(Vector
<ExpectRace
> *matched
,
159 int *unique_count
, int *hit_count
, atomic_uintptr_t
ExpectRace::*counter
) {
160 ExpectRace
*list
= &dyn_ann_ctx
->benign
;
161 for (ExpectRace
*race
= list
->next
; race
!= list
; race
= race
->next
) {
163 const uptr cnt
= atomic_load_relaxed(&(race
->*counter
));
168 for (; i
< matched
->Size(); i
++) {
169 ExpectRace
*race0
= &(*matched
)[i
];
170 if (race
->line
== race0
->line
171 && internal_strcmp(race
->file
, race0
->file
) == 0
172 && internal_strcmp(race
->desc
, race0
->desc
) == 0) {
173 atomic_fetch_add(&(race0
->*counter
), cnt
, memory_order_relaxed
);
177 if (i
== matched
->Size())
178 matched
->PushBack(*race
);
182 void PrintMatchedBenignRaces() {
183 Lock
lock(&dyn_ann_ctx
->mtx
);
184 int unique_count
= 0;
187 Vector
<ExpectRace
> hit_matched
;
188 CollectMatchedBenignRaces(&hit_matched
, &unique_count
, &hit_count
,
189 &ExpectRace::hitcount
);
190 Vector
<ExpectRace
> add_matched
;
191 CollectMatchedBenignRaces(&add_matched
, &unique_count
, &add_count
,
192 &ExpectRace::addcount
);
193 if (hit_matched
.Size()) {
194 Printf("ThreadSanitizer: Matched %d \"benign\" races (pid=%d):\n",
195 hit_count
, (int)internal_getpid());
196 for (uptr i
= 0; i
< hit_matched
.Size(); i
++) {
197 Printf("%d %s:%d %s\n",
198 atomic_load_relaxed(&hit_matched
[i
].hitcount
),
199 hit_matched
[i
].file
, hit_matched
[i
].line
, hit_matched
[i
].desc
);
202 if (hit_matched
.Size()) {
203 Printf("ThreadSanitizer: Annotated %d \"benign\" races, %d unique"
205 add_count
, unique_count
, (int)internal_getpid());
206 for (uptr i
= 0; i
< add_matched
.Size(); i
++) {
207 Printf("%d %s:%d %s\n",
208 atomic_load_relaxed(&add_matched
[i
].addcount
),
209 add_matched
[i
].file
, add_matched
[i
].line
, add_matched
[i
].desc
);
214 static void ReportMissedExpectedRace(ExpectRace
*race
) {
215 Printf("==================\n");
216 Printf("WARNING: ThreadSanitizer: missed expected data race\n");
217 Printf(" %s addr=%zx %s:%d\n",
218 race
->desc
, race
->addr
, race
->file
, race
->line
);
219 Printf("==================\n");
221 } // namespace __tsan
223 using namespace __tsan
;
226 void INTERFACE_ATTRIBUTE
AnnotateHappensBefore(char *f
, int l
, uptr addr
) {
227 SCOPED_ANNOTATION(AnnotateHappensBefore
);
228 Release(thr
, pc
, addr
);
231 void INTERFACE_ATTRIBUTE
AnnotateHappensAfter(char *f
, int l
, uptr addr
) {
232 SCOPED_ANNOTATION(AnnotateHappensAfter
);
233 Acquire(thr
, pc
, addr
);
236 void INTERFACE_ATTRIBUTE
AnnotateCondVarSignal(char *f
, int l
, uptr cv
) {
237 SCOPED_ANNOTATION(AnnotateCondVarSignal
);
240 void INTERFACE_ATTRIBUTE
AnnotateCondVarSignalAll(char *f
, int l
, uptr cv
) {
241 SCOPED_ANNOTATION(AnnotateCondVarSignalAll
);
244 void INTERFACE_ATTRIBUTE
AnnotateMutexIsNotPHB(char *f
, int l
, uptr mu
) {
245 SCOPED_ANNOTATION(AnnotateMutexIsNotPHB
);
248 void INTERFACE_ATTRIBUTE
AnnotateCondVarWait(char *f
, int l
, uptr cv
,
250 SCOPED_ANNOTATION(AnnotateCondVarWait
);
253 void INTERFACE_ATTRIBUTE
AnnotateRWLockCreate(char *f
, int l
, uptr m
) {
254 SCOPED_ANNOTATION(AnnotateRWLockCreate
);
255 MutexCreate(thr
, pc
, m
, MutexFlagWriteReentrant
);
258 void INTERFACE_ATTRIBUTE
AnnotateRWLockCreateStatic(char *f
, int l
, uptr m
) {
259 SCOPED_ANNOTATION(AnnotateRWLockCreateStatic
);
260 MutexCreate(thr
, pc
, m
, MutexFlagWriteReentrant
| MutexFlagLinkerInit
);
263 void INTERFACE_ATTRIBUTE
AnnotateRWLockDestroy(char *f
, int l
, uptr m
) {
264 SCOPED_ANNOTATION(AnnotateRWLockDestroy
);
265 MutexDestroy(thr
, pc
, m
);
268 void INTERFACE_ATTRIBUTE
AnnotateRWLockAcquired(char *f
, int l
, uptr m
,
270 SCOPED_ANNOTATION(AnnotateRWLockAcquired
);
272 MutexPostLock(thr
, pc
, m
, MutexFlagDoPreLockOnPostLock
);
274 MutexPostReadLock(thr
, pc
, m
, MutexFlagDoPreLockOnPostLock
);
277 void INTERFACE_ATTRIBUTE
AnnotateRWLockReleased(char *f
, int l
, uptr m
,
279 SCOPED_ANNOTATION(AnnotateRWLockReleased
);
281 MutexUnlock(thr
, pc
, m
);
283 MutexReadUnlock(thr
, pc
, m
);
286 void INTERFACE_ATTRIBUTE
AnnotateTraceMemory(char *f
, int l
, uptr mem
) {
287 SCOPED_ANNOTATION(AnnotateTraceMemory
);
290 void INTERFACE_ATTRIBUTE
AnnotateFlushState(char *f
, int l
) {
291 SCOPED_ANNOTATION(AnnotateFlushState
);
294 void INTERFACE_ATTRIBUTE
AnnotateNewMemory(char *f
, int l
, uptr mem
,
296 SCOPED_ANNOTATION(AnnotateNewMemory
);
299 void INTERFACE_ATTRIBUTE
AnnotateNoOp(char *f
, int l
, uptr mem
) {
300 SCOPED_ANNOTATION(AnnotateNoOp
);
303 void INTERFACE_ATTRIBUTE
AnnotateFlushExpectedRaces(char *f
, int l
) {
304 SCOPED_ANNOTATION(AnnotateFlushExpectedRaces
);
305 Lock
lock(&dyn_ann_ctx
->mtx
);
306 while (dyn_ann_ctx
->expect
.next
!= &dyn_ann_ctx
->expect
) {
307 ExpectRace
*race
= dyn_ann_ctx
->expect
.next
;
308 if (atomic_load_relaxed(&race
->hitcount
) == 0) {
309 ctx
->nmissed_expected
++;
310 ReportMissedExpectedRace(race
);
312 race
->prev
->next
= race
->next
;
313 race
->next
->prev
= race
->prev
;
318 void INTERFACE_ATTRIBUTE
AnnotateEnableRaceDetection(
319 char *f
, int l
, int enable
) {
320 SCOPED_ANNOTATION(AnnotateEnableRaceDetection
);
321 // FIXME: Reconsider this functionality later. It may be irrelevant.
324 void INTERFACE_ATTRIBUTE
AnnotateMutexIsUsedAsCondVar(
325 char *f
, int l
, uptr mu
) {
326 SCOPED_ANNOTATION(AnnotateMutexIsUsedAsCondVar
);
329 void INTERFACE_ATTRIBUTE
AnnotatePCQGet(
330 char *f
, int l
, uptr pcq
) {
331 SCOPED_ANNOTATION(AnnotatePCQGet
);
334 void INTERFACE_ATTRIBUTE
AnnotatePCQPut(
335 char *f
, int l
, uptr pcq
) {
336 SCOPED_ANNOTATION(AnnotatePCQPut
);
339 void INTERFACE_ATTRIBUTE
AnnotatePCQDestroy(
340 char *f
, int l
, uptr pcq
) {
341 SCOPED_ANNOTATION(AnnotatePCQDestroy
);
344 void INTERFACE_ATTRIBUTE
AnnotatePCQCreate(
345 char *f
, int l
, uptr pcq
) {
346 SCOPED_ANNOTATION(AnnotatePCQCreate
);
349 void INTERFACE_ATTRIBUTE
AnnotateExpectRace(
350 char *f
, int l
, uptr mem
, char *desc
) {
351 SCOPED_ANNOTATION(AnnotateExpectRace
);
352 Lock
lock(&dyn_ann_ctx
->mtx
);
353 AddExpectRace(&dyn_ann_ctx
->expect
,
355 DPrintf("Add expected race: %s addr=%zx %s:%d\n", desc
, mem
, f
, l
);
358 static void BenignRaceImpl(
359 char *f
, int l
, uptr mem
, uptr size
, char *desc
) {
360 Lock
lock(&dyn_ann_ctx
->mtx
);
361 AddExpectRace(&dyn_ann_ctx
->benign
,
362 f
, l
, mem
, size
, desc
);
363 DPrintf("Add benign race: %s addr=%zx %s:%d\n", desc
, mem
, f
, l
);
366 // FIXME: Turn it off later. WTF is benign race?1?? Go talk to Hans Boehm.
367 void INTERFACE_ATTRIBUTE
AnnotateBenignRaceSized(
368 char *f
, int l
, uptr mem
, uptr size
, char *desc
) {
369 SCOPED_ANNOTATION(AnnotateBenignRaceSized
);
370 BenignRaceImpl(f
, l
, mem
, size
, desc
);
373 void INTERFACE_ATTRIBUTE
AnnotateBenignRace(
374 char *f
, int l
, uptr mem
, char *desc
) {
375 SCOPED_ANNOTATION(AnnotateBenignRace
);
376 BenignRaceImpl(f
, l
, mem
, 1, desc
);
379 void INTERFACE_ATTRIBUTE
AnnotateIgnoreReadsBegin(char *f
, int l
) {
380 SCOPED_ANNOTATION(AnnotateIgnoreReadsBegin
);
381 ThreadIgnoreBegin(thr
, pc
);
384 void INTERFACE_ATTRIBUTE
AnnotateIgnoreReadsEnd(char *f
, int l
) {
385 SCOPED_ANNOTATION(AnnotateIgnoreReadsEnd
);
386 ThreadIgnoreEnd(thr
, pc
);
389 void INTERFACE_ATTRIBUTE
AnnotateIgnoreWritesBegin(char *f
, int l
) {
390 SCOPED_ANNOTATION(AnnotateIgnoreWritesBegin
);
391 ThreadIgnoreBegin(thr
, pc
);
394 void INTERFACE_ATTRIBUTE
AnnotateIgnoreWritesEnd(char *f
, int l
) {
395 SCOPED_ANNOTATION(AnnotateIgnoreWritesEnd
);
396 ThreadIgnoreEnd(thr
, pc
);
399 void INTERFACE_ATTRIBUTE
AnnotateIgnoreSyncBegin(char *f
, int l
) {
400 SCOPED_ANNOTATION(AnnotateIgnoreSyncBegin
);
401 ThreadIgnoreSyncBegin(thr
, pc
);
404 void INTERFACE_ATTRIBUTE
AnnotateIgnoreSyncEnd(char *f
, int l
) {
405 SCOPED_ANNOTATION(AnnotateIgnoreSyncEnd
);
406 ThreadIgnoreSyncEnd(thr
, pc
);
409 void INTERFACE_ATTRIBUTE
AnnotatePublishMemoryRange(
410 char *f
, int l
, uptr addr
, uptr size
) {
411 SCOPED_ANNOTATION(AnnotatePublishMemoryRange
);
414 void INTERFACE_ATTRIBUTE
AnnotateUnpublishMemoryRange(
415 char *f
, int l
, uptr addr
, uptr size
) {
416 SCOPED_ANNOTATION(AnnotateUnpublishMemoryRange
);
419 void INTERFACE_ATTRIBUTE
AnnotateThreadName(
420 char *f
, int l
, char *name
) {
421 SCOPED_ANNOTATION(AnnotateThreadName
);
422 ThreadSetName(thr
, name
);
425 // We deliberately omit the implementation of WTFAnnotateHappensBefore() and
426 // WTFAnnotateHappensAfter(). Those are being used by Webkit to annotate
427 // atomic operations, which should be handled by ThreadSanitizer correctly.
428 void INTERFACE_ATTRIBUTE
WTFAnnotateHappensBefore(char *f
, int l
, uptr addr
) {
429 SCOPED_ANNOTATION(AnnotateHappensBefore
);
432 void INTERFACE_ATTRIBUTE
WTFAnnotateHappensAfter(char *f
, int l
, uptr addr
) {
433 SCOPED_ANNOTATION(AnnotateHappensAfter
);
436 void INTERFACE_ATTRIBUTE
WTFAnnotateBenignRaceSized(
437 char *f
, int l
, uptr mem
, uptr sz
, char *desc
) {
438 SCOPED_ANNOTATION(AnnotateBenignRaceSized
);
439 BenignRaceImpl(f
, l
, mem
, sz
, desc
);
442 int INTERFACE_ATTRIBUTE
RunningOnValgrind() {
443 return flags()->running_on_valgrind
;
446 double __attribute__((weak
)) INTERFACE_ATTRIBUTE
ValgrindSlowdown(void) {
450 const char INTERFACE_ATTRIBUTE
* ThreadSanitizerQuery(const char *query
) {
451 if (internal_strcmp(query
, "pure_happens_before") == 0)
457 void INTERFACE_ATTRIBUTE
458 AnnotateMemoryIsInitialized(char *f
, int l
, uptr mem
, uptr sz
) {}
459 void INTERFACE_ATTRIBUTE
460 AnnotateMemoryIsUninitialized(char *f
, int l
, uptr mem
, uptr sz
) {}
462 // Note: the parameter is called flagz, because flags is already taken
463 // by the global function that returns flags.
465 void __tsan_mutex_create(void *m
, unsigned flagz
) {
466 SCOPED_ANNOTATION(__tsan_mutex_create
);
467 MutexCreate(thr
, pc
, (uptr
)m
, flagz
& MutexCreationFlagMask
);
471 void __tsan_mutex_destroy(void *m
, unsigned flagz
) {
472 SCOPED_ANNOTATION(__tsan_mutex_destroy
);
473 MutexDestroy(thr
, pc
, (uptr
)m
, flagz
);
477 void __tsan_mutex_pre_lock(void *m
, unsigned flagz
) {
478 SCOPED_ANNOTATION(__tsan_mutex_pre_lock
);
479 if (!(flagz
& MutexFlagTryLock
)) {
480 if (flagz
& MutexFlagReadLock
)
481 MutexPreReadLock(thr
, pc
, (uptr
)m
);
483 MutexPreLock(thr
, pc
, (uptr
)m
);
485 ThreadIgnoreBegin(thr
, pc
, /*save_stack=*/false);
486 ThreadIgnoreSyncBegin(thr
, pc
, /*save_stack=*/false);
490 void __tsan_mutex_post_lock(void *m
, unsigned flagz
, int rec
) {
491 SCOPED_ANNOTATION(__tsan_mutex_post_lock
);
492 ThreadIgnoreSyncEnd(thr
, pc
);
493 ThreadIgnoreEnd(thr
, pc
);
494 if (!(flagz
& MutexFlagTryLockFailed
)) {
495 if (flagz
& MutexFlagReadLock
)
496 MutexPostReadLock(thr
, pc
, (uptr
)m
, flagz
);
498 MutexPostLock(thr
, pc
, (uptr
)m
, flagz
, rec
);
503 int __tsan_mutex_pre_unlock(void *m
, unsigned flagz
) {
504 SCOPED_ANNOTATION_RET(__tsan_mutex_pre_unlock
, 0);
506 if (flagz
& MutexFlagReadLock
) {
507 CHECK(!(flagz
& MutexFlagRecursiveUnlock
));
508 MutexReadUnlock(thr
, pc
, (uptr
)m
);
510 ret
= MutexUnlock(thr
, pc
, (uptr
)m
, flagz
);
512 ThreadIgnoreBegin(thr
, pc
, /*save_stack=*/false);
513 ThreadIgnoreSyncBegin(thr
, pc
, /*save_stack=*/false);
518 void __tsan_mutex_post_unlock(void *m
, unsigned flagz
) {
519 SCOPED_ANNOTATION(__tsan_mutex_post_unlock
);
520 ThreadIgnoreSyncEnd(thr
, pc
);
521 ThreadIgnoreEnd(thr
, pc
);
525 void __tsan_mutex_pre_signal(void *addr
, unsigned flagz
) {
526 SCOPED_ANNOTATION(__tsan_mutex_pre_signal
);
527 ThreadIgnoreBegin(thr
, pc
, /*save_stack=*/false);
528 ThreadIgnoreSyncBegin(thr
, pc
, /*save_stack=*/false);
532 void __tsan_mutex_post_signal(void *addr
, unsigned flagz
) {
533 SCOPED_ANNOTATION(__tsan_mutex_post_signal
);
534 ThreadIgnoreSyncEnd(thr
, pc
);
535 ThreadIgnoreEnd(thr
, pc
);
539 void __tsan_mutex_pre_divert(void *addr
, unsigned flagz
) {
540 SCOPED_ANNOTATION(__tsan_mutex_pre_divert
);
541 // Exit from ignore region started in __tsan_mutex_pre_lock/unlock/signal.
542 ThreadIgnoreSyncEnd(thr
, pc
);
543 ThreadIgnoreEnd(thr
, pc
);
547 void __tsan_mutex_post_divert(void *addr
, unsigned flagz
) {
548 SCOPED_ANNOTATION(__tsan_mutex_post_divert
);
549 ThreadIgnoreBegin(thr
, pc
, /*save_stack=*/false);
550 ThreadIgnoreSyncBegin(thr
, pc
, /*save_stack=*/false);