168d75effSDimitry Andric //===-- tsan_interface_ann.cpp --------------------------------------------===//
268d75effSDimitry Andric //
368d75effSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
468d75effSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
568d75effSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
668d75effSDimitry Andric //
768d75effSDimitry Andric //===----------------------------------------------------------------------===//
868d75effSDimitry Andric //
968d75effSDimitry Andric // This file is a part of ThreadSanitizer (TSan), a race detector.
1068d75effSDimitry Andric //
1168d75effSDimitry Andric //===----------------------------------------------------------------------===//
1268d75effSDimitry Andric #include "sanitizer_common/sanitizer_libc.h"
1368d75effSDimitry Andric #include "sanitizer_common/sanitizer_internal_defs.h"
1468d75effSDimitry Andric #include "sanitizer_common/sanitizer_placement_new.h"
1568d75effSDimitry Andric #include "sanitizer_common/sanitizer_stacktrace.h"
1668d75effSDimitry Andric #include "sanitizer_common/sanitizer_vector.h"
1768d75effSDimitry Andric #include "tsan_interface_ann.h"
1868d75effSDimitry Andric #include "tsan_report.h"
1968d75effSDimitry Andric #include "tsan_rtl.h"
2068d75effSDimitry Andric #include "tsan_mman.h"
2168d75effSDimitry Andric #include "tsan_flags.h"
2268d75effSDimitry Andric #include "tsan_platform.h"
2368d75effSDimitry Andric
2468d75effSDimitry Andric #define CALLERPC ((uptr)__builtin_return_address(0))
2568d75effSDimitry Andric
2668d75effSDimitry Andric using namespace __tsan;
2768d75effSDimitry Andric
2868d75effSDimitry Andric namespace __tsan {
2968d75effSDimitry Andric
3068d75effSDimitry Andric class ScopedAnnotation {
3168d75effSDimitry Andric public:
ScopedAnnotation(ThreadState * thr,const char * aname,uptr pc)3268d75effSDimitry Andric ScopedAnnotation(ThreadState *thr, const char *aname, uptr pc)
3368d75effSDimitry Andric : thr_(thr) {
3468d75effSDimitry Andric FuncEntry(thr_, pc);
3568d75effSDimitry Andric DPrintf("#%d: annotation %s()\n", thr_->tid, aname);
3668d75effSDimitry Andric }
3768d75effSDimitry Andric
~ScopedAnnotation()3868d75effSDimitry Andric ~ScopedAnnotation() {
3968d75effSDimitry Andric FuncExit(thr_);
40fe6060f1SDimitry Andric CheckedMutex::CheckNoLocks();
4168d75effSDimitry Andric }
4268d75effSDimitry Andric private:
4368d75effSDimitry Andric ThreadState *const thr_;
4468d75effSDimitry Andric };
4568d75effSDimitry Andric
4668d75effSDimitry Andric #define SCOPED_ANNOTATION_RET(typ, ret) \
4768d75effSDimitry Andric if (!flags()->enable_annotations) \
4868d75effSDimitry Andric return ret; \
4968d75effSDimitry Andric ThreadState *thr = cur_thread(); \
5068d75effSDimitry Andric const uptr caller_pc = (uptr)__builtin_return_address(0); \
5168d75effSDimitry Andric ScopedAnnotation sa(thr, __func__, caller_pc); \
5268d75effSDimitry Andric const uptr pc = StackTrace::GetCurrentPc(); \
53349cc55cSDimitry Andric (void)pc;
5468d75effSDimitry Andric
5568d75effSDimitry Andric #define SCOPED_ANNOTATION(typ) SCOPED_ANNOTATION_RET(typ, )
5668d75effSDimitry Andric
5768d75effSDimitry Andric static const int kMaxDescLen = 128;
5868d75effSDimitry Andric
5968d75effSDimitry Andric struct ExpectRace {
6068d75effSDimitry Andric ExpectRace *next;
6168d75effSDimitry Andric ExpectRace *prev;
6268d75effSDimitry Andric atomic_uintptr_t hitcount;
6368d75effSDimitry Andric atomic_uintptr_t addcount;
6468d75effSDimitry Andric uptr addr;
6568d75effSDimitry Andric uptr size;
6668d75effSDimitry Andric char *file;
6768d75effSDimitry Andric int line;
6868d75effSDimitry Andric char desc[kMaxDescLen];
6968d75effSDimitry Andric };
7068d75effSDimitry Andric
7168d75effSDimitry Andric struct DynamicAnnContext {
7268d75effSDimitry Andric Mutex mtx;
7368d75effSDimitry Andric ExpectRace benign;
7468d75effSDimitry Andric
DynamicAnnContext__tsan::DynamicAnnContext75fe6060f1SDimitry Andric DynamicAnnContext() : mtx(MutexTypeAnnotations) {}
7668d75effSDimitry Andric };
7768d75effSDimitry Andric
7868d75effSDimitry Andric static DynamicAnnContext *dyn_ann_ctx;
79*0fca6ea1SDimitry Andric alignas(64) static char dyn_ann_ctx_placeholder[sizeof(DynamicAnnContext)];
8068d75effSDimitry Andric
AddExpectRace(ExpectRace * list,char * f,int l,uptr addr,uptr size,char * desc)8168d75effSDimitry Andric static void AddExpectRace(ExpectRace *list,
8268d75effSDimitry Andric char *f, int l, uptr addr, uptr size, char *desc) {
8368d75effSDimitry Andric ExpectRace *race = list->next;
8468d75effSDimitry Andric for (; race != list; race = race->next) {
8568d75effSDimitry Andric if (race->addr == addr && race->size == size) {
8668d75effSDimitry Andric atomic_store_relaxed(&race->addcount,
8768d75effSDimitry Andric atomic_load_relaxed(&race->addcount) + 1);
8868d75effSDimitry Andric return;
8968d75effSDimitry Andric }
9068d75effSDimitry Andric }
91349cc55cSDimitry Andric race = static_cast<ExpectRace *>(Alloc(sizeof(ExpectRace)));
9268d75effSDimitry Andric race->addr = addr;
9368d75effSDimitry Andric race->size = size;
9468d75effSDimitry Andric race->file = f;
9568d75effSDimitry Andric race->line = l;
9668d75effSDimitry Andric race->desc[0] = 0;
9768d75effSDimitry Andric atomic_store_relaxed(&race->hitcount, 0);
9868d75effSDimitry Andric atomic_store_relaxed(&race->addcount, 1);
9968d75effSDimitry Andric if (desc) {
10068d75effSDimitry Andric int i = 0;
10168d75effSDimitry Andric for (; i < kMaxDescLen - 1 && desc[i]; i++)
10268d75effSDimitry Andric race->desc[i] = desc[i];
10368d75effSDimitry Andric race->desc[i] = 0;
10468d75effSDimitry Andric }
10568d75effSDimitry Andric race->prev = list;
10668d75effSDimitry Andric race->next = list->next;
10768d75effSDimitry Andric race->next->prev = race;
10868d75effSDimitry Andric list->next = race;
10968d75effSDimitry Andric }
11068d75effSDimitry Andric
FindRace(ExpectRace * list,uptr addr,uptr size)11168d75effSDimitry Andric static ExpectRace *FindRace(ExpectRace *list, uptr addr, uptr size) {
11268d75effSDimitry Andric for (ExpectRace *race = list->next; race != list; race = race->next) {
11368d75effSDimitry Andric uptr maxbegin = max(race->addr, addr);
11468d75effSDimitry Andric uptr minend = min(race->addr + race->size, addr + size);
11568d75effSDimitry Andric if (maxbegin < minend)
11668d75effSDimitry Andric return race;
11768d75effSDimitry Andric }
11868d75effSDimitry Andric return 0;
11968d75effSDimitry Andric }
12068d75effSDimitry Andric
CheckContains(ExpectRace * list,uptr addr,uptr size)12168d75effSDimitry Andric static bool CheckContains(ExpectRace *list, uptr addr, uptr size) {
12268d75effSDimitry Andric ExpectRace *race = FindRace(list, addr, size);
12368d75effSDimitry Andric if (race == 0)
12468d75effSDimitry Andric return false;
12568d75effSDimitry Andric DPrintf("Hit expected/benign race: %s addr=%zx:%d %s:%d\n",
12668d75effSDimitry Andric race->desc, race->addr, (int)race->size, race->file, race->line);
12768d75effSDimitry Andric atomic_fetch_add(&race->hitcount, 1, memory_order_relaxed);
12868d75effSDimitry Andric return true;
12968d75effSDimitry Andric }
13068d75effSDimitry Andric
InitList(ExpectRace * list)13168d75effSDimitry Andric static void InitList(ExpectRace *list) {
13268d75effSDimitry Andric list->next = list;
13368d75effSDimitry Andric list->prev = list;
13468d75effSDimitry Andric }
13568d75effSDimitry Andric
InitializeDynamicAnnotations()13668d75effSDimitry Andric void InitializeDynamicAnnotations() {
13768d75effSDimitry Andric dyn_ann_ctx = new(dyn_ann_ctx_placeholder) DynamicAnnContext;
13868d75effSDimitry Andric InitList(&dyn_ann_ctx->benign);
13968d75effSDimitry Andric }
14068d75effSDimitry Andric
IsExpectedReport(uptr addr,uptr size)14168d75effSDimitry Andric bool IsExpectedReport(uptr addr, uptr size) {
14268d75effSDimitry Andric ReadLock lock(&dyn_ann_ctx->mtx);
143349cc55cSDimitry Andric return CheckContains(&dyn_ann_ctx->benign, addr, size);
14468d75effSDimitry Andric }
14568d75effSDimitry Andric } // namespace __tsan
14668d75effSDimitry Andric
14768d75effSDimitry Andric using namespace __tsan;
14868d75effSDimitry Andric
14968d75effSDimitry Andric extern "C" {
AnnotateHappensBefore(char * f,int l,uptr addr)15068d75effSDimitry Andric void INTERFACE_ATTRIBUTE AnnotateHappensBefore(char *f, int l, uptr addr) {
15168d75effSDimitry Andric SCOPED_ANNOTATION(AnnotateHappensBefore);
15268d75effSDimitry Andric Release(thr, pc, addr);
15368d75effSDimitry Andric }
15468d75effSDimitry Andric
AnnotateHappensAfter(char * f,int l,uptr addr)15568d75effSDimitry Andric void INTERFACE_ATTRIBUTE AnnotateHappensAfter(char *f, int l, uptr addr) {
15668d75effSDimitry Andric SCOPED_ANNOTATION(AnnotateHappensAfter);
15768d75effSDimitry Andric Acquire(thr, pc, addr);
15868d75effSDimitry Andric }
15968d75effSDimitry Andric
AnnotateCondVarSignal(char * f,int l,uptr cv)16068d75effSDimitry Andric void INTERFACE_ATTRIBUTE AnnotateCondVarSignal(char *f, int l, uptr cv) {
16168d75effSDimitry Andric }
16268d75effSDimitry Andric
AnnotateCondVarSignalAll(char * f,int l,uptr cv)16368d75effSDimitry Andric void INTERFACE_ATTRIBUTE AnnotateCondVarSignalAll(char *f, int l, uptr cv) {
16468d75effSDimitry Andric }
16568d75effSDimitry Andric
AnnotateMutexIsNotPHB(char * f,int l,uptr mu)16668d75effSDimitry Andric void INTERFACE_ATTRIBUTE AnnotateMutexIsNotPHB(char *f, int l, uptr mu) {
16768d75effSDimitry Andric }
16868d75effSDimitry Andric
AnnotateCondVarWait(char * f,int l,uptr cv,uptr lock)16968d75effSDimitry Andric void INTERFACE_ATTRIBUTE AnnotateCondVarWait(char *f, int l, uptr cv,
17068d75effSDimitry Andric uptr lock) {
17168d75effSDimitry Andric }
17268d75effSDimitry Andric
AnnotateRWLockCreate(char * f,int l,uptr m)17368d75effSDimitry Andric void INTERFACE_ATTRIBUTE AnnotateRWLockCreate(char *f, int l, uptr m) {
17468d75effSDimitry Andric SCOPED_ANNOTATION(AnnotateRWLockCreate);
17568d75effSDimitry Andric MutexCreate(thr, pc, m, MutexFlagWriteReentrant);
17668d75effSDimitry Andric }
17768d75effSDimitry Andric
AnnotateRWLockCreateStatic(char * f,int l,uptr m)17868d75effSDimitry Andric void INTERFACE_ATTRIBUTE AnnotateRWLockCreateStatic(char *f, int l, uptr m) {
17968d75effSDimitry Andric SCOPED_ANNOTATION(AnnotateRWLockCreateStatic);
18068d75effSDimitry Andric MutexCreate(thr, pc, m, MutexFlagWriteReentrant | MutexFlagLinkerInit);
18168d75effSDimitry Andric }
18268d75effSDimitry Andric
AnnotateRWLockDestroy(char * f,int l,uptr m)18368d75effSDimitry Andric void INTERFACE_ATTRIBUTE AnnotateRWLockDestroy(char *f, int l, uptr m) {
18468d75effSDimitry Andric SCOPED_ANNOTATION(AnnotateRWLockDestroy);
18568d75effSDimitry Andric MutexDestroy(thr, pc, m);
18668d75effSDimitry Andric }
18768d75effSDimitry Andric
AnnotateRWLockAcquired(char * f,int l,uptr m,uptr is_w)18868d75effSDimitry Andric void INTERFACE_ATTRIBUTE AnnotateRWLockAcquired(char *f, int l, uptr m,
18968d75effSDimitry Andric uptr is_w) {
19068d75effSDimitry Andric SCOPED_ANNOTATION(AnnotateRWLockAcquired);
19168d75effSDimitry Andric if (is_w)
19268d75effSDimitry Andric MutexPostLock(thr, pc, m, MutexFlagDoPreLockOnPostLock);
19368d75effSDimitry Andric else
19468d75effSDimitry Andric MutexPostReadLock(thr, pc, m, MutexFlagDoPreLockOnPostLock);
19568d75effSDimitry Andric }
19668d75effSDimitry Andric
AnnotateRWLockReleased(char * f,int l,uptr m,uptr is_w)19768d75effSDimitry Andric void INTERFACE_ATTRIBUTE AnnotateRWLockReleased(char *f, int l, uptr m,
19868d75effSDimitry Andric uptr is_w) {
19968d75effSDimitry Andric SCOPED_ANNOTATION(AnnotateRWLockReleased);
20068d75effSDimitry Andric if (is_w)
20168d75effSDimitry Andric MutexUnlock(thr, pc, m);
20268d75effSDimitry Andric else
20368d75effSDimitry Andric MutexReadUnlock(thr, pc, m);
20468d75effSDimitry Andric }
20568d75effSDimitry Andric
AnnotateTraceMemory(char * f,int l,uptr mem)20668d75effSDimitry Andric void INTERFACE_ATTRIBUTE AnnotateTraceMemory(char *f, int l, uptr mem) {
20768d75effSDimitry Andric }
20868d75effSDimitry Andric
AnnotateFlushState(char * f,int l)20968d75effSDimitry Andric void INTERFACE_ATTRIBUTE AnnotateFlushState(char *f, int l) {
21068d75effSDimitry Andric }
21168d75effSDimitry Andric
AnnotateNewMemory(char * f,int l,uptr mem,uptr size)21268d75effSDimitry Andric void INTERFACE_ATTRIBUTE AnnotateNewMemory(char *f, int l, uptr mem,
21368d75effSDimitry Andric uptr size) {
21468d75effSDimitry Andric }
21568d75effSDimitry Andric
AnnotateNoOp(char * f,int l,uptr mem)21668d75effSDimitry Andric void INTERFACE_ATTRIBUTE AnnotateNoOp(char *f, int l, uptr mem) {
21768d75effSDimitry Andric }
21868d75effSDimitry Andric
AnnotateFlushExpectedRaces(char * f,int l)21968d75effSDimitry Andric void INTERFACE_ATTRIBUTE AnnotateFlushExpectedRaces(char *f, int l) {
22068d75effSDimitry Andric }
22168d75effSDimitry Andric
AnnotateEnableRaceDetection(char * f,int l,int enable)22268d75effSDimitry Andric void INTERFACE_ATTRIBUTE AnnotateEnableRaceDetection(
22368d75effSDimitry Andric char *f, int l, int enable) {
22468d75effSDimitry Andric }
22568d75effSDimitry Andric
AnnotateMutexIsUsedAsCondVar(char * f,int l,uptr mu)22668d75effSDimitry Andric void INTERFACE_ATTRIBUTE AnnotateMutexIsUsedAsCondVar(
22768d75effSDimitry Andric char *f, int l, uptr mu) {
22868d75effSDimitry Andric }
22968d75effSDimitry Andric
AnnotatePCQGet(char * f,int l,uptr pcq)23068d75effSDimitry Andric void INTERFACE_ATTRIBUTE AnnotatePCQGet(
23168d75effSDimitry Andric char *f, int l, uptr pcq) {
23268d75effSDimitry Andric }
23368d75effSDimitry Andric
AnnotatePCQPut(char * f,int l,uptr pcq)23468d75effSDimitry Andric void INTERFACE_ATTRIBUTE AnnotatePCQPut(
23568d75effSDimitry Andric char *f, int l, uptr pcq) {
23668d75effSDimitry Andric }
23768d75effSDimitry Andric
AnnotatePCQDestroy(char * f,int l,uptr pcq)23868d75effSDimitry Andric void INTERFACE_ATTRIBUTE AnnotatePCQDestroy(
23968d75effSDimitry Andric char *f, int l, uptr pcq) {
24068d75effSDimitry Andric }
24168d75effSDimitry Andric
AnnotatePCQCreate(char * f,int l,uptr pcq)24268d75effSDimitry Andric void INTERFACE_ATTRIBUTE AnnotatePCQCreate(
24368d75effSDimitry Andric char *f, int l, uptr pcq) {
24468d75effSDimitry Andric }
24568d75effSDimitry Andric
AnnotateExpectRace(char * f,int l,uptr mem,char * desc)24668d75effSDimitry Andric void INTERFACE_ATTRIBUTE AnnotateExpectRace(
24768d75effSDimitry Andric char *f, int l, uptr mem, char *desc) {
24868d75effSDimitry Andric }
24968d75effSDimitry Andric
BenignRaceImpl(char * f,int l,uptr mem,uptr size,char * desc)250349cc55cSDimitry Andric static void BenignRaceImpl(char *f, int l, uptr mem, uptr size, char *desc) {
25168d75effSDimitry Andric Lock lock(&dyn_ann_ctx->mtx);
25268d75effSDimitry Andric AddExpectRace(&dyn_ann_ctx->benign,
25368d75effSDimitry Andric f, l, mem, size, desc);
25468d75effSDimitry Andric DPrintf("Add benign race: %s addr=%zx %s:%d\n", desc, mem, f, l);
25568d75effSDimitry Andric }
25668d75effSDimitry Andric
AnnotateBenignRaceSized(char * f,int l,uptr mem,uptr size,char * desc)25768d75effSDimitry Andric void INTERFACE_ATTRIBUTE AnnotateBenignRaceSized(
25868d75effSDimitry Andric char *f, int l, uptr mem, uptr size, char *desc) {
25968d75effSDimitry Andric SCOPED_ANNOTATION(AnnotateBenignRaceSized);
26068d75effSDimitry Andric BenignRaceImpl(f, l, mem, size, desc);
26168d75effSDimitry Andric }
26268d75effSDimitry Andric
AnnotateBenignRace(char * f,int l,uptr mem,char * desc)26368d75effSDimitry Andric void INTERFACE_ATTRIBUTE AnnotateBenignRace(
26468d75effSDimitry Andric char *f, int l, uptr mem, char *desc) {
26568d75effSDimitry Andric SCOPED_ANNOTATION(AnnotateBenignRace);
26668d75effSDimitry Andric BenignRaceImpl(f, l, mem, 1, desc);
26768d75effSDimitry Andric }
26868d75effSDimitry Andric
AnnotateIgnoreReadsBegin(char * f,int l)26968d75effSDimitry Andric void INTERFACE_ATTRIBUTE AnnotateIgnoreReadsBegin(char *f, int l) {
27068d75effSDimitry Andric SCOPED_ANNOTATION(AnnotateIgnoreReadsBegin);
27168d75effSDimitry Andric ThreadIgnoreBegin(thr, pc);
27268d75effSDimitry Andric }
27368d75effSDimitry Andric
AnnotateIgnoreReadsEnd(char * f,int l)27468d75effSDimitry Andric void INTERFACE_ATTRIBUTE AnnotateIgnoreReadsEnd(char *f, int l) {
27568d75effSDimitry Andric SCOPED_ANNOTATION(AnnotateIgnoreReadsEnd);
276349cc55cSDimitry Andric ThreadIgnoreEnd(thr);
27768d75effSDimitry Andric }
27868d75effSDimitry Andric
AnnotateIgnoreWritesBegin(char * f,int l)27968d75effSDimitry Andric void INTERFACE_ATTRIBUTE AnnotateIgnoreWritesBegin(char *f, int l) {
28068d75effSDimitry Andric SCOPED_ANNOTATION(AnnotateIgnoreWritesBegin);
28168d75effSDimitry Andric ThreadIgnoreBegin(thr, pc);
28268d75effSDimitry Andric }
28368d75effSDimitry Andric
AnnotateIgnoreWritesEnd(char * f,int l)28468d75effSDimitry Andric void INTERFACE_ATTRIBUTE AnnotateIgnoreWritesEnd(char *f, int l) {
28568d75effSDimitry Andric SCOPED_ANNOTATION(AnnotateIgnoreWritesEnd);
286349cc55cSDimitry Andric ThreadIgnoreEnd(thr);
28768d75effSDimitry Andric }
28868d75effSDimitry Andric
AnnotateIgnoreSyncBegin(char * f,int l)28968d75effSDimitry Andric void INTERFACE_ATTRIBUTE AnnotateIgnoreSyncBegin(char *f, int l) {
29068d75effSDimitry Andric SCOPED_ANNOTATION(AnnotateIgnoreSyncBegin);
29168d75effSDimitry Andric ThreadIgnoreSyncBegin(thr, pc);
29268d75effSDimitry Andric }
29368d75effSDimitry Andric
AnnotateIgnoreSyncEnd(char * f,int l)29468d75effSDimitry Andric void INTERFACE_ATTRIBUTE AnnotateIgnoreSyncEnd(char *f, int l) {
29568d75effSDimitry Andric SCOPED_ANNOTATION(AnnotateIgnoreSyncEnd);
296349cc55cSDimitry Andric ThreadIgnoreSyncEnd(thr);
29768d75effSDimitry Andric }
29868d75effSDimitry Andric
AnnotatePublishMemoryRange(char * f,int l,uptr addr,uptr size)29968d75effSDimitry Andric void INTERFACE_ATTRIBUTE AnnotatePublishMemoryRange(
30068d75effSDimitry Andric char *f, int l, uptr addr, uptr size) {
30168d75effSDimitry Andric }
30268d75effSDimitry Andric
AnnotateUnpublishMemoryRange(char * f,int l,uptr addr,uptr size)30368d75effSDimitry Andric void INTERFACE_ATTRIBUTE AnnotateUnpublishMemoryRange(
30468d75effSDimitry Andric char *f, int l, uptr addr, uptr size) {
30568d75effSDimitry Andric }
30668d75effSDimitry Andric
AnnotateThreadName(char * f,int l,char * name)30768d75effSDimitry Andric void INTERFACE_ATTRIBUTE AnnotateThreadName(
30868d75effSDimitry Andric char *f, int l, char *name) {
30968d75effSDimitry Andric SCOPED_ANNOTATION(AnnotateThreadName);
31068d75effSDimitry Andric ThreadSetName(thr, name);
31168d75effSDimitry Andric }
31268d75effSDimitry Andric
31368d75effSDimitry Andric // We deliberately omit the implementation of WTFAnnotateHappensBefore() and
31468d75effSDimitry Andric // WTFAnnotateHappensAfter(). Those are being used by Webkit to annotate
31568d75effSDimitry Andric // atomic operations, which should be handled by ThreadSanitizer correctly.
WTFAnnotateHappensBefore(char * f,int l,uptr addr)31668d75effSDimitry Andric void INTERFACE_ATTRIBUTE WTFAnnotateHappensBefore(char *f, int l, uptr addr) {
31768d75effSDimitry Andric }
31868d75effSDimitry Andric
WTFAnnotateHappensAfter(char * f,int l,uptr addr)31968d75effSDimitry Andric void INTERFACE_ATTRIBUTE WTFAnnotateHappensAfter(char *f, int l, uptr addr) {
32068d75effSDimitry Andric }
32168d75effSDimitry Andric
WTFAnnotateBenignRaceSized(char * f,int l,uptr mem,uptr sz,char * desc)32268d75effSDimitry Andric void INTERFACE_ATTRIBUTE WTFAnnotateBenignRaceSized(
32368d75effSDimitry Andric char *f, int l, uptr mem, uptr sz, char *desc) {
32468d75effSDimitry Andric SCOPED_ANNOTATION(AnnotateBenignRaceSized);
32568d75effSDimitry Andric BenignRaceImpl(f, l, mem, sz, desc);
32668d75effSDimitry Andric }
32768d75effSDimitry Andric
RunningOnValgrind()32868d75effSDimitry Andric int INTERFACE_ATTRIBUTE RunningOnValgrind() {
32968d75effSDimitry Andric return flags()->running_on_valgrind;
33068d75effSDimitry Andric }
33168d75effSDimitry Andric
ValgrindSlowdown(void)33268d75effSDimitry Andric double __attribute__((weak)) INTERFACE_ATTRIBUTE ValgrindSlowdown(void) {
33368d75effSDimitry Andric return 10.0;
33468d75effSDimitry Andric }
33568d75effSDimitry Andric
ThreadSanitizerQuery(const char * query)33668d75effSDimitry Andric const char INTERFACE_ATTRIBUTE* ThreadSanitizerQuery(const char *query) {
33768d75effSDimitry Andric if (internal_strcmp(query, "pure_happens_before") == 0)
33868d75effSDimitry Andric return "1";
33968d75effSDimitry Andric else
34068d75effSDimitry Andric return "0";
34168d75effSDimitry Andric }
34268d75effSDimitry Andric
34368d75effSDimitry Andric void INTERFACE_ATTRIBUTE
AnnotateMemoryIsInitialized(char * f,int l,uptr mem,uptr sz)34468d75effSDimitry Andric AnnotateMemoryIsInitialized(char *f, int l, uptr mem, uptr sz) {}
34568d75effSDimitry Andric void INTERFACE_ATTRIBUTE
AnnotateMemoryIsUninitialized(char * f,int l,uptr mem,uptr sz)34668d75effSDimitry Andric AnnotateMemoryIsUninitialized(char *f, int l, uptr mem, uptr sz) {}
34768d75effSDimitry Andric
34868d75effSDimitry Andric // Note: the parameter is called flagz, because flags is already taken
34968d75effSDimitry Andric // by the global function that returns flags.
35068d75effSDimitry Andric INTERFACE_ATTRIBUTE
__tsan_mutex_create(void * m,unsigned flagz)35168d75effSDimitry Andric void __tsan_mutex_create(void *m, unsigned flagz) {
35268d75effSDimitry Andric SCOPED_ANNOTATION(__tsan_mutex_create);
35368d75effSDimitry Andric MutexCreate(thr, pc, (uptr)m, flagz & MutexCreationFlagMask);
35468d75effSDimitry Andric }
35568d75effSDimitry Andric
35668d75effSDimitry Andric INTERFACE_ATTRIBUTE
__tsan_mutex_destroy(void * m,unsigned flagz)35768d75effSDimitry Andric void __tsan_mutex_destroy(void *m, unsigned flagz) {
35868d75effSDimitry Andric SCOPED_ANNOTATION(__tsan_mutex_destroy);
35968d75effSDimitry Andric MutexDestroy(thr, pc, (uptr)m, flagz);
36068d75effSDimitry Andric }
36168d75effSDimitry Andric
36268d75effSDimitry Andric INTERFACE_ATTRIBUTE
__tsan_mutex_pre_lock(void * m,unsigned flagz)36368d75effSDimitry Andric void __tsan_mutex_pre_lock(void *m, unsigned flagz) {
36468d75effSDimitry Andric SCOPED_ANNOTATION(__tsan_mutex_pre_lock);
36568d75effSDimitry Andric if (!(flagz & MutexFlagTryLock)) {
36668d75effSDimitry Andric if (flagz & MutexFlagReadLock)
36768d75effSDimitry Andric MutexPreReadLock(thr, pc, (uptr)m);
36868d75effSDimitry Andric else
36968d75effSDimitry Andric MutexPreLock(thr, pc, (uptr)m);
37068d75effSDimitry Andric }
371349cc55cSDimitry Andric ThreadIgnoreBegin(thr, 0);
372349cc55cSDimitry Andric ThreadIgnoreSyncBegin(thr, 0);
37368d75effSDimitry Andric }
37468d75effSDimitry Andric
37568d75effSDimitry Andric INTERFACE_ATTRIBUTE
__tsan_mutex_post_lock(void * m,unsigned flagz,int rec)37668d75effSDimitry Andric void __tsan_mutex_post_lock(void *m, unsigned flagz, int rec) {
37768d75effSDimitry Andric SCOPED_ANNOTATION(__tsan_mutex_post_lock);
378349cc55cSDimitry Andric ThreadIgnoreSyncEnd(thr);
379349cc55cSDimitry Andric ThreadIgnoreEnd(thr);
38068d75effSDimitry Andric if (!(flagz & MutexFlagTryLockFailed)) {
38168d75effSDimitry Andric if (flagz & MutexFlagReadLock)
38268d75effSDimitry Andric MutexPostReadLock(thr, pc, (uptr)m, flagz);
38368d75effSDimitry Andric else
38468d75effSDimitry Andric MutexPostLock(thr, pc, (uptr)m, flagz, rec);
38568d75effSDimitry Andric }
38668d75effSDimitry Andric }
38768d75effSDimitry Andric
38868d75effSDimitry Andric INTERFACE_ATTRIBUTE
__tsan_mutex_pre_unlock(void * m,unsigned flagz)38968d75effSDimitry Andric int __tsan_mutex_pre_unlock(void *m, unsigned flagz) {
39068d75effSDimitry Andric SCOPED_ANNOTATION_RET(__tsan_mutex_pre_unlock, 0);
39168d75effSDimitry Andric int ret = 0;
39268d75effSDimitry Andric if (flagz & MutexFlagReadLock) {
39368d75effSDimitry Andric CHECK(!(flagz & MutexFlagRecursiveUnlock));
39468d75effSDimitry Andric MutexReadUnlock(thr, pc, (uptr)m);
39568d75effSDimitry Andric } else {
39668d75effSDimitry Andric ret = MutexUnlock(thr, pc, (uptr)m, flagz);
39768d75effSDimitry Andric }
398349cc55cSDimitry Andric ThreadIgnoreBegin(thr, 0);
399349cc55cSDimitry Andric ThreadIgnoreSyncBegin(thr, 0);
40068d75effSDimitry Andric return ret;
40168d75effSDimitry Andric }
40268d75effSDimitry Andric
40368d75effSDimitry Andric INTERFACE_ATTRIBUTE
__tsan_mutex_post_unlock(void * m,unsigned flagz)40468d75effSDimitry Andric void __tsan_mutex_post_unlock(void *m, unsigned flagz) {
40568d75effSDimitry Andric SCOPED_ANNOTATION(__tsan_mutex_post_unlock);
406349cc55cSDimitry Andric ThreadIgnoreSyncEnd(thr);
407349cc55cSDimitry Andric ThreadIgnoreEnd(thr);
40868d75effSDimitry Andric }
40968d75effSDimitry Andric
41068d75effSDimitry Andric INTERFACE_ATTRIBUTE
__tsan_mutex_pre_signal(void * addr,unsigned flagz)41168d75effSDimitry Andric void __tsan_mutex_pre_signal(void *addr, unsigned flagz) {
41268d75effSDimitry Andric SCOPED_ANNOTATION(__tsan_mutex_pre_signal);
413349cc55cSDimitry Andric ThreadIgnoreBegin(thr, 0);
414349cc55cSDimitry Andric ThreadIgnoreSyncBegin(thr, 0);
41568d75effSDimitry Andric }
41668d75effSDimitry Andric
41768d75effSDimitry Andric INTERFACE_ATTRIBUTE
__tsan_mutex_post_signal(void * addr,unsigned flagz)41868d75effSDimitry Andric void __tsan_mutex_post_signal(void *addr, unsigned flagz) {
41968d75effSDimitry Andric SCOPED_ANNOTATION(__tsan_mutex_post_signal);
420349cc55cSDimitry Andric ThreadIgnoreSyncEnd(thr);
421349cc55cSDimitry Andric ThreadIgnoreEnd(thr);
42268d75effSDimitry Andric }
42368d75effSDimitry Andric
42468d75effSDimitry Andric INTERFACE_ATTRIBUTE
__tsan_mutex_pre_divert(void * addr,unsigned flagz)42568d75effSDimitry Andric void __tsan_mutex_pre_divert(void *addr, unsigned flagz) {
42668d75effSDimitry Andric SCOPED_ANNOTATION(__tsan_mutex_pre_divert);
42768d75effSDimitry Andric // Exit from ignore region started in __tsan_mutex_pre_lock/unlock/signal.
428349cc55cSDimitry Andric ThreadIgnoreSyncEnd(thr);
429349cc55cSDimitry Andric ThreadIgnoreEnd(thr);
43068d75effSDimitry Andric }
43168d75effSDimitry Andric
43268d75effSDimitry Andric INTERFACE_ATTRIBUTE
__tsan_mutex_post_divert(void * addr,unsigned flagz)43368d75effSDimitry Andric void __tsan_mutex_post_divert(void *addr, unsigned flagz) {
43468d75effSDimitry Andric SCOPED_ANNOTATION(__tsan_mutex_post_divert);
435349cc55cSDimitry Andric ThreadIgnoreBegin(thr, 0);
436349cc55cSDimitry Andric ThreadIgnoreSyncBegin(thr, 0);
43768d75effSDimitry Andric }
4385f757f3fSDimitry Andric
ReportMutexHeldWrongContext(ThreadState * thr,uptr pc)4395f757f3fSDimitry Andric static void ReportMutexHeldWrongContext(ThreadState *thr, uptr pc) {
4405f757f3fSDimitry Andric ThreadRegistryLock l(&ctx->thread_registry);
4415f757f3fSDimitry Andric ScopedReport rep(ReportTypeMutexHeldWrongContext);
4425f757f3fSDimitry Andric for (uptr i = 0; i < thr->mset.Size(); ++i) {
4435f757f3fSDimitry Andric MutexSet::Desc desc = thr->mset.Get(i);
4445f757f3fSDimitry Andric rep.AddMutex(desc.addr, desc.stack_id);
4455f757f3fSDimitry Andric }
4465f757f3fSDimitry Andric VarSizeStackTrace trace;
4475f757f3fSDimitry Andric ObtainCurrentStack(thr, pc, &trace);
4485f757f3fSDimitry Andric rep.AddStack(trace, true);
4495f757f3fSDimitry Andric OutputReport(thr, rep);
4505f757f3fSDimitry Andric }
4515f757f3fSDimitry Andric
4525f757f3fSDimitry Andric INTERFACE_ATTRIBUTE
__tsan_check_no_mutexes_held()4535f757f3fSDimitry Andric void __tsan_check_no_mutexes_held() {
4545f757f3fSDimitry Andric SCOPED_ANNOTATION(__tsan_check_no_mutexes_held);
4555f757f3fSDimitry Andric if (thr->mset.Size() == 0) {
4565f757f3fSDimitry Andric return;
4575f757f3fSDimitry Andric }
4585f757f3fSDimitry Andric ReportMutexHeldWrongContext(thr, pc);
4595f757f3fSDimitry Andric }
46068d75effSDimitry Andric } // extern "C"
461