1 //===-- tsan_sync.h ---------------------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file is a part of ThreadSanitizer (TSan), a race detector. 11 // 12 //===----------------------------------------------------------------------===// 13 #ifndef TSAN_SYNC_H 14 #define TSAN_SYNC_H 15 16 #include "sanitizer_common/sanitizer_atomic.h" 17 #include "sanitizer_common/sanitizer_common.h" 18 #include "tsan_clock.h" 19 #include "tsan_defs.h" 20 #include "tsan_mutex.h" 21 22 namespace __tsan { 23 24 class SlabCache; 25 26 class StackTrace { 27 public: 28 StackTrace(); 29 // Initialized the object in "static mode", 30 // in this mode it never calls malloc/free but uses the provided buffer. 31 StackTrace(uptr *buf, uptr cnt); 32 ~StackTrace(); 33 void Reset(); 34 35 void Init(const uptr *pcs, uptr cnt); 36 void ObtainCurrent(ThreadState *thr, uptr toppc); 37 bool IsEmpty() const; 38 uptr Size() const; 39 uptr Get(uptr i) const; 40 const uptr *Begin() const; 41 void CopyFrom(const StackTrace& other); 42 43 private: 44 uptr n_; 45 uptr *s_; 46 const uptr c_; 47 48 StackTrace(const StackTrace&); 49 void operator = (const StackTrace&); 50 }; 51 52 struct SyncVar { 53 explicit SyncVar(uptr addr, u64 uid); 54 55 static const int kInvalidTid = -1; 56 57 Mutex mtx; 58 uptr addr; 59 const u64 uid; // Globally unique id. 60 SyncClock clock; 61 SyncClock read_clock; // Used for rw mutexes only. 62 u32 creation_stack_id; 63 int owner_tid; // Set only by exclusive owners. 64 u64 last_lock; 65 int recursion; 66 bool is_rw; 67 bool is_recursive; 68 bool is_broken; 69 bool is_linker_init; 70 SyncVar *next; // In SyncTab hashtable. 71 72 uptr GetMemoryConsumption(); 73 u64 GetId() const { 74 // 47 lsb is addr, then 14 bits is low part of uid, then 3 zero bits. 75 return GetLsb((u64)addr | (uid << 47), 61); 76 } 77 bool CheckId(u64 uid) const { 78 CHECK_EQ(uid, GetLsb(uid, 14)); 79 return GetLsb(this->uid, 14) == uid; 80 } 81 static uptr SplitId(u64 id, u64 *uid) { 82 *uid = id >> 47; 83 return (uptr)GetLsb(id, 47); 84 } 85 }; 86 87 class SyncTab { 88 public: 89 SyncTab(); 90 ~SyncTab(); 91 92 SyncVar* GetOrCreateAndLock(ThreadState *thr, uptr pc, 93 uptr addr, bool write_lock); 94 SyncVar* GetIfExistsAndLock(uptr addr, bool write_lock); 95 96 // If the SyncVar does not exist, returns 0. 97 SyncVar* GetAndRemove(ThreadState *thr, uptr pc, uptr addr); 98 99 SyncVar* Create(ThreadState *thr, uptr pc, uptr addr); 100 101 uptr GetMemoryConsumption(uptr *nsync); 102 103 private: 104 struct Part { 105 Mutex mtx; 106 SyncVar *val; 107 char pad[kCacheLineSize - sizeof(Mutex) - sizeof(SyncVar*)]; // NOLINT 108 Part(); 109 }; 110 111 // FIXME: Implement something more sane. 112 static const int kPartCount = 1009; 113 Part tab_[kPartCount]; 114 atomic_uint64_t uid_gen_; 115 116 int PartIdx(uptr addr); 117 118 SyncVar* GetAndLock(ThreadState *thr, uptr pc, 119 uptr addr, bool write_lock, bool create); 120 121 SyncTab(const SyncTab&); // Not implemented. 122 void operator = (const SyncTab&); // Not implemented. 123 }; 124 125 } // namespace __tsan 126 127 #endif // TSAN_SYNC_H 128