1 //===-- tsan_mutexset.h -----------------------------------------*- C++ -*-===// 2 // 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 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file is a part of ThreadSanitizer (TSan), a race detector. 10 // 11 // MutexSet holds the set of mutexes currently held by a thread. 12 //===----------------------------------------------------------------------===// 13 #ifndef TSAN_MUTEXSET_H 14 #define TSAN_MUTEXSET_H 15 16 #include "tsan_defs.h" 17 18 namespace __tsan { 19 20 class MutexSet { 21 public: 22 // Holds limited number of mutexes. 23 // The oldest mutexes are discarded on overflow. 24 static constexpr uptr kMaxSize = 16; 25 struct Desc { 26 uptr addr; 27 StackID stack_id; 28 u32 seq; 29 u32 count; 30 bool write; 31 32 Desc() { internal_memset(this, 0, sizeof(*this)); } 33 Desc(const Desc& other) { *this = other; } 34 Desc& operator=(const MutexSet::Desc& other) { 35 internal_memcpy(this, &other, sizeof(*this)); 36 return *this; 37 } 38 }; 39 40 MutexSet(); 41 void Reset(); 42 void AddAddr(uptr addr, StackID stack_id, bool write); 43 void DelAddr(uptr addr, bool destroy = false); 44 uptr Size() const; 45 Desc Get(uptr i) const; 46 47 private: 48 #if !SANITIZER_GO 49 u32 seq_ = 0; 50 uptr size_ = 0; 51 Desc descs_[kMaxSize]; 52 53 void RemovePos(uptr i); 54 #endif 55 }; 56 57 // MutexSet is too large to live on stack. 58 // DynamicMutexSet can be use used to create local MutexSet's. 59 class DynamicMutexSet { 60 public: 61 DynamicMutexSet(); 62 ~DynamicMutexSet(); 63 MutexSet* operator->() { return ptr_; } 64 operator MutexSet*() { return ptr_; } 65 DynamicMutexSet(const DynamicMutexSet&) = delete; 66 DynamicMutexSet& operator=(const DynamicMutexSet&) = delete; 67 68 private: 69 MutexSet* ptr_; 70 #if SANITIZER_GO 71 MutexSet set_; 72 #endif 73 }; 74 75 // Go does not have mutexes, so do not spend memory and time. 76 // (Go sync.Mutex is actually a semaphore -- can be unlocked 77 // in different goroutine). 78 #if SANITIZER_GO 79 MutexSet::MutexSet() {} 80 void MutexSet::Reset() {} 81 void MutexSet::AddAddr(uptr addr, StackID stack_id, bool write) {} 82 void MutexSet::DelAddr(uptr addr, bool destroy) {} 83 uptr MutexSet::Size() const { return 0; } 84 MutexSet::Desc MutexSet::Get(uptr i) const { return Desc(); } 85 DynamicMutexSet::DynamicMutexSet() : ptr_(&set_) {} 86 DynamicMutexSet::~DynamicMutexSet() {} 87 #endif 88 89 } // namespace __tsan 90 91 #endif // TSAN_MUTEXSET_H 92