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_report.h"
20 #include "tsan_mman.h"
21 #include "tsan_flags.h"
22 #include "tsan_platform.h"
24 #define CALLERPC ((uptr)__builtin_return_address(0))
26 using namespace __tsan
;
30 class ScopedAnnotation
{
32 ScopedAnnotation(ThreadState
*thr
, const char *aname
, uptr pc
)
35 DPrintf("#%d: annotation %s()\n", thr_
->tid
, aname
);
40 CheckedMutex::CheckNoLocks();
43 ThreadState
*const thr_
;
46 #define SCOPED_ANNOTATION_RET(typ, ret) \
47 if (!flags()->enable_annotations) \
49 ThreadState *thr = cur_thread(); \
50 const uptr caller_pc = (uptr)__builtin_return_address(0); \
51 ScopedAnnotation sa(thr, __func__, caller_pc); \
52 const uptr pc = StackTrace::GetCurrentPc(); \
55 #define SCOPED_ANNOTATION(typ) SCOPED_ANNOTATION_RET(typ, )
57 static const int kMaxDescLen
= 128;
62 atomic_uintptr_t hitcount
;
63 atomic_uintptr_t addcount
;
68 char desc
[kMaxDescLen
];
71 struct DynamicAnnContext
{
75 DynamicAnnContext() : mtx(MutexTypeAnnotations
) {}
78 static DynamicAnnContext
*dyn_ann_ctx
;
79 static char dyn_ann_ctx_placeholder
[sizeof(DynamicAnnContext
)] ALIGNED(64);
81 static void AddExpectRace(ExpectRace
*list
,
82 char *f
, int l
, uptr addr
, uptr size
, char *desc
) {
83 ExpectRace
*race
= list
->next
;
84 for (; race
!= list
; race
= race
->next
) {
85 if (race
->addr
== addr
&& race
->size
== size
) {
86 atomic_store_relaxed(&race
->addcount
,
87 atomic_load_relaxed(&race
->addcount
) + 1);
91 race
= static_cast<ExpectRace
*>(Alloc(sizeof(ExpectRace
)));
97 atomic_store_relaxed(&race
->hitcount
, 0);
98 atomic_store_relaxed(&race
->addcount
, 1);
101 for (; i
< kMaxDescLen
- 1 && desc
[i
]; i
++)
102 race
->desc
[i
] = desc
[i
];
106 race
->next
= list
->next
;
107 race
->next
->prev
= race
;
111 static ExpectRace
*FindRace(ExpectRace
*list
, uptr addr
, uptr size
) {
112 for (ExpectRace
*race
= list
->next
; race
!= list
; race
= race
->next
) {
113 uptr maxbegin
= max(race
->addr
, addr
);
114 uptr minend
= min(race
->addr
+ race
->size
, addr
+ size
);
115 if (maxbegin
< minend
)
121 static bool CheckContains(ExpectRace
*list
, uptr addr
, uptr size
) {
122 ExpectRace
*race
= FindRace(list
, addr
, size
);
125 DPrintf("Hit expected/benign race: %s addr=%zx:%d %s:%d\n",
126 race
->desc
, race
->addr
, (int)race
->size
, race
->file
, race
->line
);
127 atomic_fetch_add(&race
->hitcount
, 1, memory_order_relaxed
);
131 static void InitList(ExpectRace
*list
) {
136 void InitializeDynamicAnnotations() {
137 dyn_ann_ctx
= new(dyn_ann_ctx_placeholder
) DynamicAnnContext
;
138 InitList(&dyn_ann_ctx
->benign
);
141 bool IsExpectedReport(uptr addr
, uptr size
) {
142 ReadLock
lock(&dyn_ann_ctx
->mtx
);
143 return CheckContains(&dyn_ann_ctx
->benign
, addr
, size
);
145 } // namespace __tsan
147 using namespace __tsan
;
150 void INTERFACE_ATTRIBUTE
AnnotateHappensBefore(char *f
, int l
, uptr addr
) {
151 SCOPED_ANNOTATION(AnnotateHappensBefore
);
152 Release(thr
, pc
, addr
);
155 void INTERFACE_ATTRIBUTE
AnnotateHappensAfter(char *f
, int l
, uptr addr
) {
156 SCOPED_ANNOTATION(AnnotateHappensAfter
);
157 Acquire(thr
, pc
, addr
);
160 void INTERFACE_ATTRIBUTE
AnnotateCondVarSignal(char *f
, int l
, uptr cv
) {
163 void INTERFACE_ATTRIBUTE
AnnotateCondVarSignalAll(char *f
, int l
, uptr cv
) {
166 void INTERFACE_ATTRIBUTE
AnnotateMutexIsNotPHB(char *f
, int l
, uptr mu
) {
169 void INTERFACE_ATTRIBUTE
AnnotateCondVarWait(char *f
, int l
, uptr cv
,
173 void INTERFACE_ATTRIBUTE
AnnotateRWLockCreate(char *f
, int l
, uptr m
) {
174 SCOPED_ANNOTATION(AnnotateRWLockCreate
);
175 MutexCreate(thr
, pc
, m
, MutexFlagWriteReentrant
);
178 void INTERFACE_ATTRIBUTE
AnnotateRWLockCreateStatic(char *f
, int l
, uptr m
) {
179 SCOPED_ANNOTATION(AnnotateRWLockCreateStatic
);
180 MutexCreate(thr
, pc
, m
, MutexFlagWriteReentrant
| MutexFlagLinkerInit
);
183 void INTERFACE_ATTRIBUTE
AnnotateRWLockDestroy(char *f
, int l
, uptr m
) {
184 SCOPED_ANNOTATION(AnnotateRWLockDestroy
);
185 MutexDestroy(thr
, pc
, m
);
188 void INTERFACE_ATTRIBUTE
AnnotateRWLockAcquired(char *f
, int l
, uptr m
,
190 SCOPED_ANNOTATION(AnnotateRWLockAcquired
);
192 MutexPostLock(thr
, pc
, m
, MutexFlagDoPreLockOnPostLock
);
194 MutexPostReadLock(thr
, pc
, m
, MutexFlagDoPreLockOnPostLock
);
197 void INTERFACE_ATTRIBUTE
AnnotateRWLockReleased(char *f
, int l
, uptr m
,
199 SCOPED_ANNOTATION(AnnotateRWLockReleased
);
201 MutexUnlock(thr
, pc
, m
);
203 MutexReadUnlock(thr
, pc
, m
);
206 void INTERFACE_ATTRIBUTE
AnnotateTraceMemory(char *f
, int l
, uptr mem
) {
209 void INTERFACE_ATTRIBUTE
AnnotateFlushState(char *f
, int l
) {
212 void INTERFACE_ATTRIBUTE
AnnotateNewMemory(char *f
, int l
, uptr mem
,
216 void INTERFACE_ATTRIBUTE
AnnotateNoOp(char *f
, int l
, uptr mem
) {
219 void INTERFACE_ATTRIBUTE
AnnotateFlushExpectedRaces(char *f
, int l
) {
222 void INTERFACE_ATTRIBUTE
AnnotateEnableRaceDetection(
223 char *f
, int l
, int enable
) {
226 void INTERFACE_ATTRIBUTE
AnnotateMutexIsUsedAsCondVar(
227 char *f
, int l
, uptr mu
) {
230 void INTERFACE_ATTRIBUTE
AnnotatePCQGet(
231 char *f
, int l
, uptr pcq
) {
234 void INTERFACE_ATTRIBUTE
AnnotatePCQPut(
235 char *f
, int l
, uptr pcq
) {
238 void INTERFACE_ATTRIBUTE
AnnotatePCQDestroy(
239 char *f
, int l
, uptr pcq
) {
242 void INTERFACE_ATTRIBUTE
AnnotatePCQCreate(
243 char *f
, int l
, uptr pcq
) {
246 void INTERFACE_ATTRIBUTE
AnnotateExpectRace(
247 char *f
, int l
, uptr mem
, char *desc
) {
250 static void BenignRaceImpl(char *f
, int l
, uptr mem
, uptr size
, char *desc
) {
251 Lock
lock(&dyn_ann_ctx
->mtx
);
252 AddExpectRace(&dyn_ann_ctx
->benign
,
253 f
, l
, mem
, size
, desc
);
254 DPrintf("Add benign race: %s addr=%zx %s:%d\n", desc
, mem
, f
, l
);
257 void INTERFACE_ATTRIBUTE
AnnotateBenignRaceSized(
258 char *f
, int l
, uptr mem
, uptr size
, char *desc
) {
259 SCOPED_ANNOTATION(AnnotateBenignRaceSized
);
260 BenignRaceImpl(f
, l
, mem
, size
, desc
);
263 void INTERFACE_ATTRIBUTE
AnnotateBenignRace(
264 char *f
, int l
, uptr mem
, char *desc
) {
265 SCOPED_ANNOTATION(AnnotateBenignRace
);
266 BenignRaceImpl(f
, l
, mem
, 1, desc
);
269 void INTERFACE_ATTRIBUTE
AnnotateIgnoreReadsBegin(char *f
, int l
) {
270 SCOPED_ANNOTATION(AnnotateIgnoreReadsBegin
);
271 ThreadIgnoreBegin(thr
, pc
);
274 void INTERFACE_ATTRIBUTE
AnnotateIgnoreReadsEnd(char *f
, int l
) {
275 SCOPED_ANNOTATION(AnnotateIgnoreReadsEnd
);
276 ThreadIgnoreEnd(thr
);
279 void INTERFACE_ATTRIBUTE
AnnotateIgnoreWritesBegin(char *f
, int l
) {
280 SCOPED_ANNOTATION(AnnotateIgnoreWritesBegin
);
281 ThreadIgnoreBegin(thr
, pc
);
284 void INTERFACE_ATTRIBUTE
AnnotateIgnoreWritesEnd(char *f
, int l
) {
285 SCOPED_ANNOTATION(AnnotateIgnoreWritesEnd
);
286 ThreadIgnoreEnd(thr
);
289 void INTERFACE_ATTRIBUTE
AnnotateIgnoreSyncBegin(char *f
, int l
) {
290 SCOPED_ANNOTATION(AnnotateIgnoreSyncBegin
);
291 ThreadIgnoreSyncBegin(thr
, pc
);
294 void INTERFACE_ATTRIBUTE
AnnotateIgnoreSyncEnd(char *f
, int l
) {
295 SCOPED_ANNOTATION(AnnotateIgnoreSyncEnd
);
296 ThreadIgnoreSyncEnd(thr
);
299 void INTERFACE_ATTRIBUTE
AnnotatePublishMemoryRange(
300 char *f
, int l
, uptr addr
, uptr size
) {
303 void INTERFACE_ATTRIBUTE
AnnotateUnpublishMemoryRange(
304 char *f
, int l
, uptr addr
, uptr size
) {
307 void INTERFACE_ATTRIBUTE
AnnotateThreadName(
308 char *f
, int l
, char *name
) {
309 SCOPED_ANNOTATION(AnnotateThreadName
);
310 ThreadSetName(thr
, name
);
313 // We deliberately omit the implementation of WTFAnnotateHappensBefore() and
314 // WTFAnnotateHappensAfter(). Those are being used by Webkit to annotate
315 // atomic operations, which should be handled by ThreadSanitizer correctly.
316 void INTERFACE_ATTRIBUTE
WTFAnnotateHappensBefore(char *f
, int l
, uptr addr
) {
319 void INTERFACE_ATTRIBUTE
WTFAnnotateHappensAfter(char *f
, int l
, uptr addr
) {
322 void INTERFACE_ATTRIBUTE
WTFAnnotateBenignRaceSized(
323 char *f
, int l
, uptr mem
, uptr sz
, char *desc
) {
324 SCOPED_ANNOTATION(AnnotateBenignRaceSized
);
325 BenignRaceImpl(f
, l
, mem
, sz
, desc
);
328 int INTERFACE_ATTRIBUTE
RunningOnValgrind() {
329 return flags()->running_on_valgrind
;
332 double __attribute__((weak
)) INTERFACE_ATTRIBUTE
ValgrindSlowdown(void) {
336 const char INTERFACE_ATTRIBUTE
* ThreadSanitizerQuery(const char *query
) {
337 if (internal_strcmp(query
, "pure_happens_before") == 0)
343 void INTERFACE_ATTRIBUTE
344 AnnotateMemoryIsInitialized(char *f
, int l
, uptr mem
, uptr sz
) {}
345 void INTERFACE_ATTRIBUTE
346 AnnotateMemoryIsUninitialized(char *f
, int l
, uptr mem
, uptr sz
) {}
348 // Note: the parameter is called flagz, because flags is already taken
349 // by the global function that returns flags.
351 void __tsan_mutex_create(void *m
, unsigned flagz
) {
352 SCOPED_ANNOTATION(__tsan_mutex_create
);
353 MutexCreate(thr
, pc
, (uptr
)m
, flagz
& MutexCreationFlagMask
);
357 void __tsan_mutex_destroy(void *m
, unsigned flagz
) {
358 SCOPED_ANNOTATION(__tsan_mutex_destroy
);
359 MutexDestroy(thr
, pc
, (uptr
)m
, flagz
);
363 void __tsan_mutex_pre_lock(void *m
, unsigned flagz
) {
364 SCOPED_ANNOTATION(__tsan_mutex_pre_lock
);
365 if (!(flagz
& MutexFlagTryLock
)) {
366 if (flagz
& MutexFlagReadLock
)
367 MutexPreReadLock(thr
, pc
, (uptr
)m
);
369 MutexPreLock(thr
, pc
, (uptr
)m
);
371 ThreadIgnoreBegin(thr
, 0);
372 ThreadIgnoreSyncBegin(thr
, 0);
376 void __tsan_mutex_post_lock(void *m
, unsigned flagz
, int rec
) {
377 SCOPED_ANNOTATION(__tsan_mutex_post_lock
);
378 ThreadIgnoreSyncEnd(thr
);
379 ThreadIgnoreEnd(thr
);
380 if (!(flagz
& MutexFlagTryLockFailed
)) {
381 if (flagz
& MutexFlagReadLock
)
382 MutexPostReadLock(thr
, pc
, (uptr
)m
, flagz
);
384 MutexPostLock(thr
, pc
, (uptr
)m
, flagz
, rec
);
389 int __tsan_mutex_pre_unlock(void *m
, unsigned flagz
) {
390 SCOPED_ANNOTATION_RET(__tsan_mutex_pre_unlock
, 0);
392 if (flagz
& MutexFlagReadLock
) {
393 CHECK(!(flagz
& MutexFlagRecursiveUnlock
));
394 MutexReadUnlock(thr
, pc
, (uptr
)m
);
396 ret
= MutexUnlock(thr
, pc
, (uptr
)m
, flagz
);
398 ThreadIgnoreBegin(thr
, 0);
399 ThreadIgnoreSyncBegin(thr
, 0);
404 void __tsan_mutex_post_unlock(void *m
, unsigned flagz
) {
405 SCOPED_ANNOTATION(__tsan_mutex_post_unlock
);
406 ThreadIgnoreSyncEnd(thr
);
407 ThreadIgnoreEnd(thr
);
411 void __tsan_mutex_pre_signal(void *addr
, unsigned flagz
) {
412 SCOPED_ANNOTATION(__tsan_mutex_pre_signal
);
413 ThreadIgnoreBegin(thr
, 0);
414 ThreadIgnoreSyncBegin(thr
, 0);
418 void __tsan_mutex_post_signal(void *addr
, unsigned flagz
) {
419 SCOPED_ANNOTATION(__tsan_mutex_post_signal
);
420 ThreadIgnoreSyncEnd(thr
);
421 ThreadIgnoreEnd(thr
);
425 void __tsan_mutex_pre_divert(void *addr
, unsigned flagz
) {
426 SCOPED_ANNOTATION(__tsan_mutex_pre_divert
);
427 // Exit from ignore region started in __tsan_mutex_pre_lock/unlock/signal.
428 ThreadIgnoreSyncEnd(thr
);
429 ThreadIgnoreEnd(thr
);
433 void __tsan_mutex_post_divert(void *addr
, unsigned flagz
) {
434 SCOPED_ANNOTATION(__tsan_mutex_post_divert
);
435 ThreadIgnoreBegin(thr
, 0);
436 ThreadIgnoreSyncBegin(thr
, 0);