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