xref: /freebsd-src/contrib/llvm-project/compiler-rt/lib/tsan/rtl/tsan_interface_ann.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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:
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 
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 
75fe6060f1SDimitry 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 
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 
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 
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 
13168d75effSDimitry Andric static void InitList(ExpectRace *list) {
13268d75effSDimitry Andric   list->next = list;
13368d75effSDimitry Andric   list->prev = list;
13468d75effSDimitry Andric }
13568d75effSDimitry Andric 
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 
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" {
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 
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 
16068d75effSDimitry Andric void INTERFACE_ATTRIBUTE AnnotateCondVarSignal(char *f, int l, uptr cv) {
16168d75effSDimitry Andric }
16268d75effSDimitry Andric 
16368d75effSDimitry Andric void INTERFACE_ATTRIBUTE AnnotateCondVarSignalAll(char *f, int l, uptr cv) {
16468d75effSDimitry Andric }
16568d75effSDimitry Andric 
16668d75effSDimitry Andric void INTERFACE_ATTRIBUTE AnnotateMutexIsNotPHB(char *f, int l, uptr mu) {
16768d75effSDimitry Andric }
16868d75effSDimitry Andric 
16968d75effSDimitry Andric void INTERFACE_ATTRIBUTE AnnotateCondVarWait(char *f, int l, uptr cv,
17068d75effSDimitry Andric                                              uptr lock) {
17168d75effSDimitry Andric }
17268d75effSDimitry Andric 
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 
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 
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 
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 
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 
20668d75effSDimitry Andric void INTERFACE_ATTRIBUTE AnnotateTraceMemory(char *f, int l, uptr mem) {
20768d75effSDimitry Andric }
20868d75effSDimitry Andric 
20968d75effSDimitry Andric void INTERFACE_ATTRIBUTE AnnotateFlushState(char *f, int l) {
21068d75effSDimitry Andric }
21168d75effSDimitry Andric 
21268d75effSDimitry Andric void INTERFACE_ATTRIBUTE AnnotateNewMemory(char *f, int l, uptr mem,
21368d75effSDimitry Andric                                            uptr size) {
21468d75effSDimitry Andric }
21568d75effSDimitry Andric 
21668d75effSDimitry Andric void INTERFACE_ATTRIBUTE AnnotateNoOp(char *f, int l, uptr mem) {
21768d75effSDimitry Andric }
21868d75effSDimitry Andric 
21968d75effSDimitry Andric void INTERFACE_ATTRIBUTE AnnotateFlushExpectedRaces(char *f, int l) {
22068d75effSDimitry Andric }
22168d75effSDimitry Andric 
22268d75effSDimitry Andric void INTERFACE_ATTRIBUTE AnnotateEnableRaceDetection(
22368d75effSDimitry Andric     char *f, int l, int enable) {
22468d75effSDimitry Andric }
22568d75effSDimitry Andric 
22668d75effSDimitry Andric void INTERFACE_ATTRIBUTE AnnotateMutexIsUsedAsCondVar(
22768d75effSDimitry Andric     char *f, int l, uptr mu) {
22868d75effSDimitry Andric }
22968d75effSDimitry Andric 
23068d75effSDimitry Andric void INTERFACE_ATTRIBUTE AnnotatePCQGet(
23168d75effSDimitry Andric     char *f, int l, uptr pcq) {
23268d75effSDimitry Andric }
23368d75effSDimitry Andric 
23468d75effSDimitry Andric void INTERFACE_ATTRIBUTE AnnotatePCQPut(
23568d75effSDimitry Andric     char *f, int l, uptr pcq) {
23668d75effSDimitry Andric }
23768d75effSDimitry Andric 
23868d75effSDimitry Andric void INTERFACE_ATTRIBUTE AnnotatePCQDestroy(
23968d75effSDimitry Andric     char *f, int l, uptr pcq) {
24068d75effSDimitry Andric }
24168d75effSDimitry Andric 
24268d75effSDimitry Andric void INTERFACE_ATTRIBUTE AnnotatePCQCreate(
24368d75effSDimitry Andric     char *f, int l, uptr pcq) {
24468d75effSDimitry Andric }
24568d75effSDimitry Andric 
24668d75effSDimitry Andric void INTERFACE_ATTRIBUTE AnnotateExpectRace(
24768d75effSDimitry Andric     char *f, int l, uptr mem, char *desc) {
24868d75effSDimitry Andric }
24968d75effSDimitry Andric 
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 
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 
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 
26968d75effSDimitry Andric void INTERFACE_ATTRIBUTE AnnotateIgnoreReadsBegin(char *f, int l) {
27068d75effSDimitry Andric   SCOPED_ANNOTATION(AnnotateIgnoreReadsBegin);
27168d75effSDimitry Andric   ThreadIgnoreBegin(thr, pc);
27268d75effSDimitry Andric }
27368d75effSDimitry Andric 
27468d75effSDimitry Andric void INTERFACE_ATTRIBUTE AnnotateIgnoreReadsEnd(char *f, int l) {
27568d75effSDimitry Andric   SCOPED_ANNOTATION(AnnotateIgnoreReadsEnd);
276349cc55cSDimitry Andric   ThreadIgnoreEnd(thr);
27768d75effSDimitry Andric }
27868d75effSDimitry Andric 
27968d75effSDimitry Andric void INTERFACE_ATTRIBUTE AnnotateIgnoreWritesBegin(char *f, int l) {
28068d75effSDimitry Andric   SCOPED_ANNOTATION(AnnotateIgnoreWritesBegin);
28168d75effSDimitry Andric   ThreadIgnoreBegin(thr, pc);
28268d75effSDimitry Andric }
28368d75effSDimitry Andric 
28468d75effSDimitry Andric void INTERFACE_ATTRIBUTE AnnotateIgnoreWritesEnd(char *f, int l) {
28568d75effSDimitry Andric   SCOPED_ANNOTATION(AnnotateIgnoreWritesEnd);
286349cc55cSDimitry Andric   ThreadIgnoreEnd(thr);
28768d75effSDimitry Andric }
28868d75effSDimitry Andric 
28968d75effSDimitry Andric void INTERFACE_ATTRIBUTE AnnotateIgnoreSyncBegin(char *f, int l) {
29068d75effSDimitry Andric   SCOPED_ANNOTATION(AnnotateIgnoreSyncBegin);
29168d75effSDimitry Andric   ThreadIgnoreSyncBegin(thr, pc);
29268d75effSDimitry Andric }
29368d75effSDimitry Andric 
29468d75effSDimitry Andric void INTERFACE_ATTRIBUTE AnnotateIgnoreSyncEnd(char *f, int l) {
29568d75effSDimitry Andric   SCOPED_ANNOTATION(AnnotateIgnoreSyncEnd);
296349cc55cSDimitry Andric   ThreadIgnoreSyncEnd(thr);
29768d75effSDimitry Andric }
29868d75effSDimitry Andric 
29968d75effSDimitry Andric void INTERFACE_ATTRIBUTE AnnotatePublishMemoryRange(
30068d75effSDimitry Andric     char *f, int l, uptr addr, uptr size) {
30168d75effSDimitry Andric }
30268d75effSDimitry Andric 
30368d75effSDimitry Andric void INTERFACE_ATTRIBUTE AnnotateUnpublishMemoryRange(
30468d75effSDimitry Andric     char *f, int l, uptr addr, uptr size) {
30568d75effSDimitry Andric }
30668d75effSDimitry Andric 
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.
31668d75effSDimitry Andric void INTERFACE_ATTRIBUTE WTFAnnotateHappensBefore(char *f, int l, uptr addr) {
31768d75effSDimitry Andric }
31868d75effSDimitry Andric 
31968d75effSDimitry Andric void INTERFACE_ATTRIBUTE WTFAnnotateHappensAfter(char *f, int l, uptr addr) {
32068d75effSDimitry Andric }
32168d75effSDimitry Andric 
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 
32868d75effSDimitry Andric int INTERFACE_ATTRIBUTE RunningOnValgrind() {
32968d75effSDimitry Andric   return flags()->running_on_valgrind;
33068d75effSDimitry Andric }
33168d75effSDimitry Andric 
33268d75effSDimitry Andric double __attribute__((weak)) INTERFACE_ATTRIBUTE ValgrindSlowdown(void) {
33368d75effSDimitry Andric   return 10.0;
33468d75effSDimitry Andric }
33568d75effSDimitry Andric 
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
34468d75effSDimitry Andric AnnotateMemoryIsInitialized(char *f, int l, uptr mem, uptr sz) {}
34568d75effSDimitry Andric void INTERFACE_ATTRIBUTE
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
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
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
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
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
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
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
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
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
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
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 
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
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