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