1 //===-- tsan_defs.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 //===----------------------------------------------------------------------===// 12 13 #ifndef TSAN_DEFS_H 14 #define TSAN_DEFS_H 15 16 #include "sanitizer_common/sanitizer_internal_defs.h" 17 #include "sanitizer_common/sanitizer_libc.h" 18 #include "sanitizer_common/sanitizer_mutex.h" 19 #include "ubsan/ubsan_platform.h" 20 21 // Setup defaults for compile definitions. 22 #ifndef TSAN_NO_HISTORY 23 # define TSAN_NO_HISTORY 0 24 #endif 25 26 #ifndef TSAN_CONTAINS_UBSAN 27 # if CAN_SANITIZE_UB && !SANITIZER_GO 28 # define TSAN_CONTAINS_UBSAN 1 29 # else 30 # define TSAN_CONTAINS_UBSAN 0 31 # endif 32 #endif 33 34 namespace __tsan { 35 36 const int kClkBits = 42; 37 const unsigned kMaxTidReuse = (1 << (64 - kClkBits)) - 1; 38 39 struct ClockElem { 40 u64 epoch : kClkBits; 41 u64 reused : 64 - kClkBits; // tid reuse count 42 }; 43 44 struct ClockBlock { 45 static const uptr kSize = 512; 46 static const uptr kTableSize = kSize / sizeof(u32); 47 static const uptr kClockCount = kSize / sizeof(ClockElem); 48 static const uptr kRefIdx = kTableSize - 1; 49 static const uptr kBlockIdx = kTableSize - 2; 50 51 union { 52 u32 table[kTableSize]; 53 ClockElem clock[kClockCount]; 54 }; 55 56 ClockBlock() { 57 } 58 }; 59 60 const int kTidBits = 13; 61 // Reduce kMaxTid by kClockCount because one slot in ClockBlock table is 62 // occupied by reference counter, so total number of elements we can store 63 // in SyncClock is kClockCount * (kTableSize - 1). 64 const unsigned kMaxTid = (1 << kTidBits) - ClockBlock::kClockCount; 65 #if !SANITIZER_GO 66 const unsigned kMaxTidInClock = kMaxTid * 2; // This includes msb 'freed' bit. 67 #else 68 const unsigned kMaxTidInClock = kMaxTid; // Go does not track freed memory. 69 #endif 70 const uptr kShadowStackSize = 64 * 1024; 71 72 // Count of shadow values in a shadow cell. 73 const uptr kShadowCnt = 4; 74 75 // That many user bytes are mapped onto a single shadow cell. 76 const uptr kShadowCell = 8; 77 78 // Size of a single shadow value (u64). 79 const uptr kShadowSize = 8; 80 81 // Shadow memory is kShadowMultiplier times larger than user memory. 82 const uptr kShadowMultiplier = kShadowSize * kShadowCnt / kShadowCell; 83 84 // That many user bytes are mapped onto a single meta shadow cell. 85 // Must be less or equal to minimal memory allocator alignment. 86 const uptr kMetaShadowCell = 8; 87 88 // Size of a single meta shadow value (u32). 89 const uptr kMetaShadowSize = 4; 90 91 #if TSAN_NO_HISTORY 92 const bool kCollectHistory = false; 93 #else 94 const bool kCollectHistory = true; 95 #endif 96 97 // The following "build consistency" machinery ensures that all source files 98 // are built in the same configuration. Inconsistent builds lead to 99 // hard to debug crashes. 100 #if SANITIZER_DEBUG 101 void build_consistency_debug(); 102 #else 103 void build_consistency_release(); 104 #endif 105 106 static inline void USED build_consistency() { 107 #if SANITIZER_DEBUG 108 build_consistency_debug(); 109 #else 110 build_consistency_release(); 111 #endif 112 } 113 114 template<typename T> 115 T min(T a, T b) { 116 return a < b ? a : b; 117 } 118 119 template<typename T> 120 T max(T a, T b) { 121 return a > b ? a : b; 122 } 123 124 template<typename T> 125 T RoundUp(T p, u64 align) { 126 DCHECK_EQ(align & (align - 1), 0); 127 return (T)(((u64)p + align - 1) & ~(align - 1)); 128 } 129 130 template<typename T> 131 T RoundDown(T p, u64 align) { 132 DCHECK_EQ(align & (align - 1), 0); 133 return (T)((u64)p & ~(align - 1)); 134 } 135 136 // Zeroizes high part, returns 'bits' lsb bits. 137 template<typename T> 138 T GetLsb(T v, int bits) { 139 return (T)((u64)v & ((1ull << bits) - 1)); 140 } 141 142 struct MD5Hash { 143 u64 hash[2]; 144 bool operator==(const MD5Hash &other) const; 145 }; 146 147 MD5Hash md5_hash(const void *data, uptr size); 148 149 struct Processor; 150 struct ThreadState; 151 class ThreadContext; 152 struct Context; 153 struct ReportStack; 154 class ReportDesc; 155 class RegionAlloc; 156 157 // Descriptor of user's memory block. 158 struct MBlock { 159 u64 siz : 48; 160 u64 tag : 16; 161 u32 stk; 162 u16 tid; 163 }; 164 165 COMPILER_CHECK(sizeof(MBlock) == 16); 166 167 enum ExternalTag : uptr { 168 kExternalTagNone = 0, 169 kExternalTagSwiftModifyingAccess = 1, 170 kExternalTagFirstUserAvailable = 2, 171 kExternalTagMax = 1024, 172 // Don't set kExternalTagMax over 65,536, since MBlock only stores tags 173 // as 16-bit values, see tsan_defs.h. 174 }; 175 176 enum MutexType { 177 MutexTypeTrace = MutexLastCommon, 178 MutexTypeReport, 179 MutexTypeSyncVar, 180 MutexTypeAnnotations, 181 MutexTypeAtExit, 182 MutexTypeFired, 183 MutexTypeRacy, 184 MutexTypeGlobalProc, 185 }; 186 187 } // namespace __tsan 188 189 #endif // TSAN_DEFS_H 190