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