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