xref: /freebsd/contrib/llvm-project/compiler-rt/lib/tsan/rtl/tsan_defs.h (revision 5e801ac66d24704442eba426ed13c3effb8a34e7)
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 #ifndef TSAN_VECTORIZE
22 #  define TSAN_VECTORIZE __SSE4_2__
23 #endif
24 
25 #if TSAN_VECTORIZE
26 // <emmintrin.h> transitively includes <stdlib.h>,
27 // and it's prohibited to include std headers into tsan runtime.
28 // So we do this dirty trick.
29 #  define _MM_MALLOC_H_INCLUDED
30 #  define __MM_MALLOC_H
31 #  include <emmintrin.h>
32 #  include <smmintrin.h>
33 #  define VECTOR_ALIGNED ALIGNED(16)
34 typedef __m128i m128;
35 #else
36 #  define VECTOR_ALIGNED
37 #endif
38 
39 // Setup defaults for compile definitions.
40 #ifndef TSAN_NO_HISTORY
41 # define TSAN_NO_HISTORY 0
42 #endif
43 
44 #ifndef TSAN_CONTAINS_UBSAN
45 # if CAN_SANITIZE_UB && !SANITIZER_GO
46 #  define TSAN_CONTAINS_UBSAN 1
47 # else
48 #  define TSAN_CONTAINS_UBSAN 0
49 # endif
50 #endif
51 
52 namespace __tsan {
53 
54 constexpr uptr kByteBits = 8;
55 
56 // Thread slot ID.
57 enum class Sid : u8 {};
58 constexpr uptr kThreadSlotCount = 256;
59 constexpr Sid kFreeSid = static_cast<Sid>(255);
60 
61 // Abstract time unit, vector clock element.
62 enum class Epoch : u16 {};
63 constexpr uptr kEpochBits = 14;
64 constexpr Epoch kEpochZero = static_cast<Epoch>(0);
65 constexpr Epoch kEpochOver = static_cast<Epoch>(1 << kEpochBits);
66 
67 const int kClkBits = 42;
68 const unsigned kMaxTidReuse = (1 << (64 - kClkBits)) - 1;
69 
70 struct ClockElem {
71   u64 epoch  : kClkBits;
72   u64 reused : 64 - kClkBits;  // tid reuse count
73 };
74 
75 struct ClockBlock {
76   static const uptr kSize = 512;
77   static const uptr kTableSize = kSize / sizeof(u32);
78   static const uptr kClockCount = kSize / sizeof(ClockElem);
79   static const uptr kRefIdx = kTableSize - 1;
80   static const uptr kBlockIdx = kTableSize - 2;
81 
82   union {
83     u32       table[kTableSize];
84     ClockElem clock[kClockCount];
85   };
86 
87   ClockBlock() {
88   }
89 };
90 
91 const int kTidBits = 13;
92 // Reduce kMaxTid by kClockCount because one slot in ClockBlock table is
93 // occupied by reference counter, so total number of elements we can store
94 // in SyncClock is kClockCount * (kTableSize - 1).
95 const unsigned kMaxTid = (1 << kTidBits) - ClockBlock::kClockCount;
96 #if !SANITIZER_GO
97 const unsigned kMaxTidInClock = kMaxTid * 2;  // This includes msb 'freed' bit.
98 #else
99 const unsigned kMaxTidInClock = kMaxTid;  // Go does not track freed memory.
100 #endif
101 const uptr kShadowStackSize = 64 * 1024;
102 
103 // Count of shadow values in a shadow cell.
104 const uptr kShadowCnt = 4;
105 
106 // That many user bytes are mapped onto a single shadow cell.
107 const uptr kShadowCell = 8;
108 
109 // Single shadow value.
110 typedef u64 RawShadow;
111 const uptr kShadowSize = sizeof(RawShadow);
112 
113 // Shadow memory is kShadowMultiplier times larger than user memory.
114 const uptr kShadowMultiplier = kShadowSize * kShadowCnt / kShadowCell;
115 
116 // That many user bytes are mapped onto a single meta shadow cell.
117 // Must be less or equal to minimal memory allocator alignment.
118 const uptr kMetaShadowCell = 8;
119 
120 // Size of a single meta shadow value (u32).
121 const uptr kMetaShadowSize = 4;
122 
123 // All addresses and PCs are assumed to be compressable to that many bits.
124 const uptr kCompressedAddrBits = 44;
125 
126 #if TSAN_NO_HISTORY
127 const bool kCollectHistory = false;
128 #else
129 const bool kCollectHistory = true;
130 #endif
131 
132 // The following "build consistency" machinery ensures that all source files
133 // are built in the same configuration. Inconsistent builds lead to
134 // hard to debug crashes.
135 #if SANITIZER_DEBUG
136 void build_consistency_debug();
137 #else
138 void build_consistency_release();
139 #endif
140 
141 static inline void USED build_consistency() {
142 #if SANITIZER_DEBUG
143   build_consistency_debug();
144 #else
145   build_consistency_release();
146 #endif
147 }
148 
149 template<typename T>
150 T min(T a, T b) {
151   return a < b ? a : b;
152 }
153 
154 template<typename T>
155 T max(T a, T b) {
156   return a > b ? a : b;
157 }
158 
159 template<typename T>
160 T RoundUp(T p, u64 align) {
161   DCHECK_EQ(align & (align - 1), 0);
162   return (T)(((u64)p + align - 1) & ~(align - 1));
163 }
164 
165 template<typename T>
166 T RoundDown(T p, u64 align) {
167   DCHECK_EQ(align & (align - 1), 0);
168   return (T)((u64)p & ~(align - 1));
169 }
170 
171 // Zeroizes high part, returns 'bits' lsb bits.
172 template<typename T>
173 T GetLsb(T v, int bits) {
174   return (T)((u64)v & ((1ull << bits) - 1));
175 }
176 
177 struct MD5Hash {
178   u64 hash[2];
179   bool operator==(const MD5Hash &other) const;
180 };
181 
182 MD5Hash md5_hash(const void *data, uptr size);
183 
184 struct Processor;
185 struct ThreadState;
186 class ThreadContext;
187 struct Context;
188 struct ReportStack;
189 class ReportDesc;
190 class RegionAlloc;
191 
192 typedef uptr AccessType;
193 
194 enum : AccessType {
195   kAccessWrite = 0,
196   kAccessRead = 1 << 0,
197   kAccessAtomic = 1 << 1,
198   kAccessVptr = 1 << 2,  // read or write of an object virtual table pointer
199   kAccessFree = 1 << 3,  // synthetic memory access during memory freeing
200   kAccessExternalPC = 1 << 4,  // access PC can have kExternalPCBit set
201 };
202 
203 // Descriptor of user's memory block.
204 struct MBlock {
205   u64  siz : 48;
206   u64  tag : 16;
207   StackID stk;
208   Tid tid;
209 };
210 
211 COMPILER_CHECK(sizeof(MBlock) == 16);
212 
213 enum ExternalTag : uptr {
214   kExternalTagNone = 0,
215   kExternalTagSwiftModifyingAccess = 1,
216   kExternalTagFirstUserAvailable = 2,
217   kExternalTagMax = 1024,
218   // Don't set kExternalTagMax over 65,536, since MBlock only stores tags
219   // as 16-bit values, see tsan_defs.h.
220 };
221 
222 enum MutexType {
223   MutexTypeTrace = MutexLastCommon,
224   MutexTypeReport,
225   MutexTypeSyncVar,
226   MutexTypeAnnotations,
227   MutexTypeAtExit,
228   MutexTypeFired,
229   MutexTypeRacy,
230   MutexTypeGlobalProc,
231 };
232 
233 }  // namespace __tsan
234 
235 #endif  // TSAN_DEFS_H
236