xref: /openbsd-src/gnu/llvm/compiler-rt/lib/tsan/rtl/tsan_defs.h (revision 5a38ef86d0b61900239c7913d24a05e7b88a58f0)
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