tsan_rtl.h revision 1.2 1 1.1 mrg //===-- tsan_rtl.h ----------------------------------------------*- C++ -*-===//
2 1.1 mrg //
3 1.1 mrg // This file is distributed under the University of Illinois Open Source
4 1.1 mrg // License. See LICENSE.TXT for details.
5 1.1 mrg //
6 1.1 mrg //===----------------------------------------------------------------------===//
7 1.1 mrg //
8 1.1 mrg // This file is a part of ThreadSanitizer (TSan), a race detector.
9 1.1 mrg //
10 1.1 mrg // Main internal TSan header file.
11 1.1 mrg //
12 1.1 mrg // Ground rules:
13 1.1 mrg // - C++ run-time should not be used (static CTORs, RTTI, exceptions, static
14 1.1 mrg // function-scope locals)
15 1.1 mrg // - All functions/classes/etc reside in namespace __tsan, except for those
16 1.1 mrg // declared in tsan_interface.h.
17 1.1 mrg // - Platform-specific files should be used instead of ifdefs (*).
18 1.1 mrg // - No system headers included in header files (*).
19 1.1 mrg // - Platform specific headres included only into platform-specific files (*).
20 1.1 mrg //
21 1.1 mrg // (*) Except when inlining is critical for performance.
22 1.1 mrg //===----------------------------------------------------------------------===//
23 1.1 mrg
24 1.1 mrg #ifndef TSAN_RTL_H
25 1.1 mrg #define TSAN_RTL_H
26 1.1 mrg
27 1.2 mrg #include "sanitizer_common/sanitizer_allocator.h"
28 1.2 mrg #include "sanitizer_common/sanitizer_allocator_internal.h"
29 1.2 mrg #include "sanitizer_common/sanitizer_asm.h"
30 1.1 mrg #include "sanitizer_common/sanitizer_common.h"
31 1.2 mrg #include "sanitizer_common/sanitizer_deadlock_detector_interface.h"
32 1.2 mrg #include "sanitizer_common/sanitizer_libignore.h"
33 1.2 mrg #include "sanitizer_common/sanitizer_suppressions.h"
34 1.2 mrg #include "sanitizer_common/sanitizer_thread_registry.h"
35 1.2 mrg #include "sanitizer_common/sanitizer_vector.h"
36 1.1 mrg #include "tsan_clock.h"
37 1.1 mrg #include "tsan_defs.h"
38 1.1 mrg #include "tsan_flags.h"
39 1.2 mrg #include "tsan_mman.h"
40 1.1 mrg #include "tsan_sync.h"
41 1.1 mrg #include "tsan_trace.h"
42 1.1 mrg #include "tsan_report.h"
43 1.1 mrg #include "tsan_platform.h"
44 1.1 mrg #include "tsan_mutexset.h"
45 1.2 mrg #include "tsan_ignoreset.h"
46 1.2 mrg #include "tsan_stack_trace.h"
47 1.1 mrg
48 1.1 mrg #if SANITIZER_WORDSIZE != 64
49 1.1 mrg # error "ThreadSanitizer is supported only on 64-bit platforms"
50 1.1 mrg #endif
51 1.1 mrg
52 1.1 mrg namespace __tsan {
53 1.1 mrg
54 1.2 mrg #if !SANITIZER_GO
55 1.2 mrg struct MapUnmapCallback;
56 1.2 mrg #if defined(__mips64) || defined(__aarch64__) || defined(__powerpc__)
57 1.2 mrg static const uptr kAllocatorRegionSizeLog = 20;
58 1.2 mrg static const uptr kAllocatorNumRegions =
59 1.2 mrg SANITIZER_MMAP_RANGE_SIZE >> kAllocatorRegionSizeLog;
60 1.2 mrg typedef TwoLevelByteMap<(kAllocatorNumRegions >> 12), 1 << 12,
61 1.2 mrg MapUnmapCallback> ByteMap;
62 1.2 mrg struct AP32 {
63 1.2 mrg static const uptr kSpaceBeg = 0;
64 1.2 mrg static const u64 kSpaceSize = SANITIZER_MMAP_RANGE_SIZE;
65 1.2 mrg static const uptr kMetadataSize = 0;
66 1.2 mrg typedef __sanitizer::CompactSizeClassMap SizeClassMap;
67 1.2 mrg static const uptr kRegionSizeLog = kAllocatorRegionSizeLog;
68 1.2 mrg typedef __tsan::ByteMap ByteMap;
69 1.2 mrg typedef __tsan::MapUnmapCallback MapUnmapCallback;
70 1.2 mrg static const uptr kFlags = 0;
71 1.1 mrg };
72 1.2 mrg typedef SizeClassAllocator32<AP32> PrimaryAllocator;
73 1.1 mrg #else
74 1.2 mrg struct AP64 { // Allocator64 parameters. Deliberately using a short name.
75 1.2 mrg static const uptr kSpaceBeg = Mapping::kHeapMemBeg;
76 1.2 mrg static const uptr kSpaceSize = Mapping::kHeapMemEnd - Mapping::kHeapMemBeg;
77 1.2 mrg static const uptr kMetadataSize = 0;
78 1.2 mrg typedef DefaultSizeClassMap SizeClassMap;
79 1.2 mrg typedef __tsan::MapUnmapCallback MapUnmapCallback;
80 1.2 mrg static const uptr kFlags = 0;
81 1.2 mrg };
82 1.2 mrg typedef SizeClassAllocator64<AP64> PrimaryAllocator;
83 1.1 mrg #endif
84 1.1 mrg typedef SizeClassAllocatorLocalCache<PrimaryAllocator> AllocatorCache;
85 1.2 mrg typedef LargeMmapAllocator<MapUnmapCallback> SecondaryAllocator;
86 1.1 mrg typedef CombinedAllocator<PrimaryAllocator, AllocatorCache,
87 1.1 mrg SecondaryAllocator> Allocator;
88 1.1 mrg Allocator *allocator();
89 1.1 mrg #endif
90 1.1 mrg
91 1.1 mrg void TsanCheckFailed(const char *file, int line, const char *cond,
92 1.1 mrg u64 v1, u64 v2);
93 1.1 mrg
94 1.2 mrg const u64 kShadowRodata = (u64)-1; // .rodata shadow marker
95 1.2 mrg
96 1.1 mrg // FastState (from most significant bit):
97 1.1 mrg // ignore : 1
98 1.1 mrg // tid : kTidBits
99 1.1 mrg // unused : -
100 1.1 mrg // history_size : 3
101 1.2 mrg // epoch : kClkBits
102 1.1 mrg class FastState {
103 1.1 mrg public:
104 1.1 mrg FastState(u64 tid, u64 epoch) {
105 1.1 mrg x_ = tid << kTidShift;
106 1.2 mrg x_ |= epoch;
107 1.1 mrg DCHECK_EQ(tid, this->tid());
108 1.1 mrg DCHECK_EQ(epoch, this->epoch());
109 1.1 mrg DCHECK_EQ(GetIgnoreBit(), false);
110 1.1 mrg }
111 1.1 mrg
112 1.1 mrg explicit FastState(u64 x)
113 1.1 mrg : x_(x) {
114 1.1 mrg }
115 1.1 mrg
116 1.1 mrg u64 raw() const {
117 1.1 mrg return x_;
118 1.1 mrg }
119 1.1 mrg
120 1.1 mrg u64 tid() const {
121 1.1 mrg u64 res = (x_ & ~kIgnoreBit) >> kTidShift;
122 1.1 mrg return res;
123 1.1 mrg }
124 1.1 mrg
125 1.1 mrg u64 TidWithIgnore() const {
126 1.1 mrg u64 res = x_ >> kTidShift;
127 1.1 mrg return res;
128 1.1 mrg }
129 1.1 mrg
130 1.1 mrg u64 epoch() const {
131 1.2 mrg u64 res = x_ & ((1ull << kClkBits) - 1);
132 1.1 mrg return res;
133 1.1 mrg }
134 1.1 mrg
135 1.1 mrg void IncrementEpoch() {
136 1.1 mrg u64 old_epoch = epoch();
137 1.2 mrg x_ += 1;
138 1.1 mrg DCHECK_EQ(old_epoch + 1, epoch());
139 1.1 mrg (void)old_epoch;
140 1.1 mrg }
141 1.1 mrg
142 1.1 mrg void SetIgnoreBit() { x_ |= kIgnoreBit; }
143 1.1 mrg void ClearIgnoreBit() { x_ &= ~kIgnoreBit; }
144 1.1 mrg bool GetIgnoreBit() const { return (s64)x_ < 0; }
145 1.1 mrg
146 1.1 mrg void SetHistorySize(int hs) {
147 1.1 mrg CHECK_GE(hs, 0);
148 1.1 mrg CHECK_LE(hs, 7);
149 1.2 mrg x_ = (x_ & ~(kHistoryMask << kHistoryShift)) | (u64(hs) << kHistoryShift);
150 1.1 mrg }
151 1.1 mrg
152 1.2 mrg ALWAYS_INLINE
153 1.1 mrg int GetHistorySize() const {
154 1.2 mrg return (int)((x_ >> kHistoryShift) & kHistoryMask);
155 1.1 mrg }
156 1.1 mrg
157 1.1 mrg void ClearHistorySize() {
158 1.2 mrg SetHistorySize(0);
159 1.1 mrg }
160 1.1 mrg
161 1.2 mrg ALWAYS_INLINE
162 1.1 mrg u64 GetTracePos() const {
163 1.1 mrg const int hs = GetHistorySize();
164 1.1 mrg // When hs == 0, the trace consists of 2 parts.
165 1.1 mrg const u64 mask = (1ull << (kTracePartSizeBits + hs + 1)) - 1;
166 1.1 mrg return epoch() & mask;
167 1.1 mrg }
168 1.1 mrg
169 1.1 mrg private:
170 1.1 mrg friend class Shadow;
171 1.1 mrg static const int kTidShift = 64 - kTidBits - 1;
172 1.1 mrg static const u64 kIgnoreBit = 1ull << 63;
173 1.1 mrg static const u64 kFreedBit = 1ull << 63;
174 1.2 mrg static const u64 kHistoryShift = kClkBits;
175 1.2 mrg static const u64 kHistoryMask = 7;
176 1.1 mrg u64 x_;
177 1.1 mrg };
178 1.1 mrg
179 1.1 mrg // Shadow (from most significant bit):
180 1.1 mrg // freed : 1
181 1.1 mrg // tid : kTidBits
182 1.1 mrg // is_atomic : 1
183 1.1 mrg // is_read : 1
184 1.1 mrg // size_log : 2
185 1.1 mrg // addr0 : 3
186 1.2 mrg // epoch : kClkBits
187 1.1 mrg class Shadow : public FastState {
188 1.1 mrg public:
189 1.1 mrg explicit Shadow(u64 x)
190 1.1 mrg : FastState(x) {
191 1.1 mrg }
192 1.1 mrg
193 1.1 mrg explicit Shadow(const FastState &s)
194 1.1 mrg : FastState(s.x_) {
195 1.1 mrg ClearHistorySize();
196 1.1 mrg }
197 1.1 mrg
198 1.1 mrg void SetAddr0AndSizeLog(u64 addr0, unsigned kAccessSizeLog) {
199 1.2 mrg DCHECK_EQ((x_ >> kClkBits) & 31, 0);
200 1.1 mrg DCHECK_LE(addr0, 7);
201 1.1 mrg DCHECK_LE(kAccessSizeLog, 3);
202 1.2 mrg x_ |= ((kAccessSizeLog << 3) | addr0) << kClkBits;
203 1.1 mrg DCHECK_EQ(kAccessSizeLog, size_log());
204 1.1 mrg DCHECK_EQ(addr0, this->addr0());
205 1.1 mrg }
206 1.1 mrg
207 1.1 mrg void SetWrite(unsigned kAccessIsWrite) {
208 1.1 mrg DCHECK_EQ(x_ & kReadBit, 0);
209 1.1 mrg if (!kAccessIsWrite)
210 1.1 mrg x_ |= kReadBit;
211 1.1 mrg DCHECK_EQ(kAccessIsWrite, IsWrite());
212 1.1 mrg }
213 1.1 mrg
214 1.1 mrg void SetAtomic(bool kIsAtomic) {
215 1.1 mrg DCHECK(!IsAtomic());
216 1.1 mrg if (kIsAtomic)
217 1.1 mrg x_ |= kAtomicBit;
218 1.1 mrg DCHECK_EQ(IsAtomic(), kIsAtomic);
219 1.1 mrg }
220 1.1 mrg
221 1.1 mrg bool IsAtomic() const {
222 1.1 mrg return x_ & kAtomicBit;
223 1.1 mrg }
224 1.1 mrg
225 1.1 mrg bool IsZero() const {
226 1.1 mrg return x_ == 0;
227 1.1 mrg }
228 1.1 mrg
229 1.1 mrg static inline bool TidsAreEqual(const Shadow s1, const Shadow s2) {
230 1.1 mrg u64 shifted_xor = (s1.x_ ^ s2.x_) >> kTidShift;
231 1.1 mrg DCHECK_EQ(shifted_xor == 0, s1.TidWithIgnore() == s2.TidWithIgnore());
232 1.1 mrg return shifted_xor == 0;
233 1.1 mrg }
234 1.1 mrg
235 1.2 mrg static ALWAYS_INLINE
236 1.2 mrg bool Addr0AndSizeAreEqual(const Shadow s1, const Shadow s2) {
237 1.2 mrg u64 masked_xor = ((s1.x_ ^ s2.x_) >> kClkBits) & 31;
238 1.1 mrg return masked_xor == 0;
239 1.1 mrg }
240 1.1 mrg
241 1.2 mrg static ALWAYS_INLINE bool TwoRangesIntersect(Shadow s1, Shadow s2,
242 1.1 mrg unsigned kS2AccessSize) {
243 1.1 mrg bool res = false;
244 1.1 mrg u64 diff = s1.addr0() - s2.addr0();
245 1.1 mrg if ((s64)diff < 0) { // s1.addr0 < s2.addr0 // NOLINT
246 1.1 mrg // if (s1.addr0() + size1) > s2.addr0()) return true;
247 1.2 mrg if (s1.size() > -diff)
248 1.2 mrg res = true;
249 1.1 mrg } else {
250 1.1 mrg // if (s2.addr0() + kS2AccessSize > s1.addr0()) return true;
251 1.2 mrg if (kS2AccessSize > diff)
252 1.2 mrg res = true;
253 1.1 mrg }
254 1.2 mrg DCHECK_EQ(res, TwoRangesIntersectSlow(s1, s2));
255 1.2 mrg DCHECK_EQ(res, TwoRangesIntersectSlow(s2, s1));
256 1.1 mrg return res;
257 1.1 mrg }
258 1.1 mrg
259 1.2 mrg u64 ALWAYS_INLINE addr0() const { return (x_ >> kClkBits) & 7; }
260 1.2 mrg u64 ALWAYS_INLINE size() const { return 1ull << size_log(); }
261 1.2 mrg bool ALWAYS_INLINE IsWrite() const { return !IsRead(); }
262 1.2 mrg bool ALWAYS_INLINE IsRead() const { return x_ & kReadBit; }
263 1.1 mrg
264 1.1 mrg // The idea behind the freed bit is as follows.
265 1.1 mrg // When the memory is freed (or otherwise unaccessible) we write to the shadow
266 1.1 mrg // values with tid/epoch related to the free and the freed bit set.
267 1.1 mrg // During memory accesses processing the freed bit is considered
268 1.1 mrg // as msb of tid. So any access races with shadow with freed bit set
269 1.1 mrg // (it is as if write from a thread with which we never synchronized before).
270 1.1 mrg // This allows us to detect accesses to freed memory w/o additional
271 1.1 mrg // overheads in memory access processing and at the same time restore
272 1.1 mrg // tid/epoch of free.
273 1.1 mrg void MarkAsFreed() {
274 1.1 mrg x_ |= kFreedBit;
275 1.1 mrg }
276 1.1 mrg
277 1.1 mrg bool IsFreed() const {
278 1.1 mrg return x_ & kFreedBit;
279 1.1 mrg }
280 1.1 mrg
281 1.1 mrg bool GetFreedAndReset() {
282 1.1 mrg bool res = x_ & kFreedBit;
283 1.1 mrg x_ &= ~kFreedBit;
284 1.1 mrg return res;
285 1.1 mrg }
286 1.1 mrg
287 1.2 mrg bool ALWAYS_INLINE IsBothReadsOrAtomic(bool kIsWrite, bool kIsAtomic) const {
288 1.2 mrg bool v = x_ & ((u64(kIsWrite ^ 1) << kReadShift)
289 1.2 mrg | (u64(kIsAtomic) << kAtomicShift));
290 1.1 mrg DCHECK_EQ(v, (!IsWrite() && !kIsWrite) || (IsAtomic() && kIsAtomic));
291 1.1 mrg return v;
292 1.1 mrg }
293 1.1 mrg
294 1.2 mrg bool ALWAYS_INLINE IsRWNotWeaker(bool kIsWrite, bool kIsAtomic) const {
295 1.1 mrg bool v = ((x_ >> kReadShift) & 3)
296 1.1 mrg <= u64((kIsWrite ^ 1) | (kIsAtomic << 1));
297 1.1 mrg DCHECK_EQ(v, (IsAtomic() < kIsAtomic) ||
298 1.1 mrg (IsAtomic() == kIsAtomic && !IsWrite() <= !kIsWrite));
299 1.1 mrg return v;
300 1.1 mrg }
301 1.1 mrg
302 1.2 mrg bool ALWAYS_INLINE IsRWWeakerOrEqual(bool kIsWrite, bool kIsAtomic) const {
303 1.1 mrg bool v = ((x_ >> kReadShift) & 3)
304 1.1 mrg >= u64((kIsWrite ^ 1) | (kIsAtomic << 1));
305 1.1 mrg DCHECK_EQ(v, (IsAtomic() > kIsAtomic) ||
306 1.1 mrg (IsAtomic() == kIsAtomic && !IsWrite() >= !kIsWrite));
307 1.1 mrg return v;
308 1.1 mrg }
309 1.1 mrg
310 1.1 mrg private:
311 1.2 mrg static const u64 kReadShift = 5 + kClkBits;
312 1.1 mrg static const u64 kReadBit = 1ull << kReadShift;
313 1.2 mrg static const u64 kAtomicShift = 6 + kClkBits;
314 1.1 mrg static const u64 kAtomicBit = 1ull << kAtomicShift;
315 1.1 mrg
316 1.2 mrg u64 size_log() const { return (x_ >> (3 + kClkBits)) & 3; }
317 1.1 mrg
318 1.2 mrg static bool TwoRangesIntersectSlow(const Shadow s1, const Shadow s2) {
319 1.1 mrg if (s1.addr0() == s2.addr0()) return true;
320 1.1 mrg if (s1.addr0() < s2.addr0() && s1.addr0() + s1.size() > s2.addr0())
321 1.1 mrg return true;
322 1.1 mrg if (s2.addr0() < s1.addr0() && s2.addr0() + s2.size() > s1.addr0())
323 1.1 mrg return true;
324 1.1 mrg return false;
325 1.1 mrg }
326 1.1 mrg };
327 1.1 mrg
328 1.2 mrg struct ThreadSignalContext;
329 1.2 mrg
330 1.2 mrg struct JmpBuf {
331 1.2 mrg uptr sp;
332 1.2 mrg uptr mangled_sp;
333 1.2 mrg int int_signal_send;
334 1.2 mrg bool in_blocking_func;
335 1.2 mrg uptr in_signal_handler;
336 1.2 mrg uptr *shadow_stack_pos;
337 1.2 mrg };
338 1.2 mrg
339 1.2 mrg // A Processor represents a physical thread, or a P for Go.
340 1.2 mrg // It is used to store internal resources like allocate cache, and does not
341 1.2 mrg // participate in race-detection logic (invisible to end user).
342 1.2 mrg // In C++ it is tied to an OS thread just like ThreadState, however ideally
343 1.2 mrg // it should be tied to a CPU (this way we will have fewer allocator caches).
344 1.2 mrg // In Go it is tied to a P, so there are significantly fewer Processor's than
345 1.2 mrg // ThreadState's (which are tied to Gs).
346 1.2 mrg // A ThreadState must be wired with a Processor to handle events.
347 1.2 mrg struct Processor {
348 1.2 mrg ThreadState *thr; // currently wired thread, or nullptr
349 1.2 mrg #if !SANITIZER_GO
350 1.2 mrg AllocatorCache alloc_cache;
351 1.2 mrg InternalAllocatorCache internal_alloc_cache;
352 1.2 mrg #endif
353 1.2 mrg DenseSlabAllocCache block_cache;
354 1.2 mrg DenseSlabAllocCache sync_cache;
355 1.2 mrg DenseSlabAllocCache clock_cache;
356 1.2 mrg DDPhysicalThread *dd_pt;
357 1.2 mrg };
358 1.2 mrg
359 1.2 mrg #if !SANITIZER_GO
360 1.2 mrg // ScopedGlobalProcessor temporary setups a global processor for the current
361 1.2 mrg // thread, if it does not have one. Intended for interceptors that can run
362 1.2 mrg // at the very thread end, when we already destroyed the thread processor.
363 1.2 mrg struct ScopedGlobalProcessor {
364 1.2 mrg ScopedGlobalProcessor();
365 1.2 mrg ~ScopedGlobalProcessor();
366 1.2 mrg };
367 1.2 mrg #endif
368 1.1 mrg
369 1.1 mrg // This struct is stored in TLS.
370 1.1 mrg struct ThreadState {
371 1.1 mrg FastState fast_state;
372 1.1 mrg // Synch epoch represents the threads's epoch before the last synchronization
373 1.1 mrg // action. It allows to reduce number of shadow state updates.
374 1.1 mrg // For example, fast_synch_epoch=100, last write to addr X was at epoch=150,
375 1.1 mrg // if we are processing write to X from the same thread at epoch=200,
376 1.1 mrg // we do nothing, because both writes happen in the same 'synch epoch'.
377 1.1 mrg // That is, if another memory access does not race with the former write,
378 1.1 mrg // it does not race with the latter as well.
379 1.1 mrg // QUESTION: can we can squeeze this into ThreadState::Fast?
380 1.1 mrg // E.g. ThreadState::Fast is a 44-bit, 32 are taken by synch_epoch and 12 are
381 1.1 mrg // taken by epoch between synchs.
382 1.1 mrg // This way we can save one load from tls.
383 1.1 mrg u64 fast_synch_epoch;
384 1.1 mrg // This is a slow path flag. On fast path, fast_state.GetIgnoreBit() is read.
385 1.1 mrg // We do not distinguish beteween ignoring reads and writes
386 1.1 mrg // for better performance.
387 1.1 mrg int ignore_reads_and_writes;
388 1.2 mrg int ignore_sync;
389 1.2 mrg int suppress_reports;
390 1.2 mrg // Go does not support ignores.
391 1.2 mrg #if !SANITIZER_GO
392 1.2 mrg IgnoreSet mop_ignore_set;
393 1.2 mrg IgnoreSet sync_ignore_set;
394 1.2 mrg #endif
395 1.2 mrg // C/C++ uses fixed size shadow stack embed into Trace.
396 1.2 mrg // Go uses malloc-allocated shadow stack with dynamic size.
397 1.2 mrg uptr *shadow_stack;
398 1.2 mrg uptr *shadow_stack_end;
399 1.1 mrg uptr *shadow_stack_pos;
400 1.1 mrg u64 *racy_shadow_addr;
401 1.1 mrg u64 racy_state[2];
402 1.1 mrg MutexSet mset;
403 1.1 mrg ThreadClock clock;
404 1.2 mrg #if !SANITIZER_GO
405 1.2 mrg Vector<JmpBuf> jmp_bufs;
406 1.2 mrg int ignore_interceptors;
407 1.1 mrg #endif
408 1.2 mrg #if TSAN_COLLECT_STATS
409 1.1 mrg u64 stat[StatCnt];
410 1.2 mrg #endif
411 1.1 mrg const int tid;
412 1.1 mrg const int unique_id;
413 1.1 mrg bool in_symbolizer;
414 1.2 mrg bool in_ignored_lib;
415 1.2 mrg bool is_inited;
416 1.2 mrg bool is_dead;
417 1.1 mrg bool is_freeing;
418 1.2 mrg bool is_vptr_access;
419 1.1 mrg const uptr stk_addr;
420 1.1 mrg const uptr stk_size;
421 1.1 mrg const uptr tls_addr;
422 1.1 mrg const uptr tls_size;
423 1.2 mrg ThreadContext *tctx;
424 1.1 mrg
425 1.2 mrg #if SANITIZER_DEBUG && !SANITIZER_GO
426 1.2 mrg InternalDeadlockDetector internal_deadlock_detector;
427 1.2 mrg #endif
428 1.2 mrg DDLogicalThread *dd_lt;
429 1.2 mrg
430 1.2 mrg // Current wired Processor, or nullptr. Required to handle any events.
431 1.2 mrg Processor *proc1;
432 1.2 mrg #if !SANITIZER_GO
433 1.2 mrg Processor *proc() { return proc1; }
434 1.2 mrg #else
435 1.2 mrg Processor *proc();
436 1.2 mrg #endif
437 1.1 mrg
438 1.2 mrg atomic_uintptr_t in_signal_handler;
439 1.2 mrg ThreadSignalContext *signal_ctx;
440 1.1 mrg
441 1.2 mrg #if !SANITIZER_GO
442 1.1 mrg u32 last_sleep_stack_id;
443 1.1 mrg ThreadClock last_sleep_clock;
444 1.1 mrg #endif
445 1.1 mrg
446 1.1 mrg // Set in regions of runtime that must be signal-safe and fork-safe.
447 1.1 mrg // If set, malloc must not be called.
448 1.1 mrg int nomalloc;
449 1.1 mrg
450 1.2 mrg const ReportDesc *current_report;
451 1.2 mrg
452 1.1 mrg explicit ThreadState(Context *ctx, int tid, int unique_id, u64 epoch,
453 1.2 mrg unsigned reuse_count,
454 1.1 mrg uptr stk_addr, uptr stk_size,
455 1.1 mrg uptr tls_addr, uptr tls_size);
456 1.1 mrg };
457 1.1 mrg
458 1.2 mrg #if !SANITIZER_GO
459 1.2 mrg #if SANITIZER_MAC || SANITIZER_ANDROID
460 1.2 mrg ThreadState *cur_thread();
461 1.2 mrg void cur_thread_finalize();
462 1.2 mrg #else
463 1.2 mrg __attribute__((tls_model("initial-exec")))
464 1.1 mrg extern THREADLOCAL char cur_thread_placeholder[];
465 1.1 mrg INLINE ThreadState *cur_thread() {
466 1.1 mrg return reinterpret_cast<ThreadState *>(&cur_thread_placeholder);
467 1.1 mrg }
468 1.2 mrg INLINE void cur_thread_finalize() { }
469 1.2 mrg #endif // SANITIZER_MAC || SANITIZER_ANDROID
470 1.2 mrg #endif // SANITIZER_GO
471 1.1 mrg
472 1.2 mrg class ThreadContext : public ThreadContextBase {
473 1.2 mrg public:
474 1.2 mrg explicit ThreadContext(int tid);
475 1.2 mrg ~ThreadContext();
476 1.1 mrg ThreadState *thr;
477 1.2 mrg u32 creation_stack_id;
478 1.1 mrg SyncClock sync;
479 1.1 mrg // Epoch at which the thread had started.
480 1.1 mrg // If we see an event from the thread stamped by an older epoch,
481 1.1 mrg // the event is from a dead thread that shared tid with this thread.
482 1.1 mrg u64 epoch0;
483 1.1 mrg u64 epoch1;
484 1.1 mrg
485 1.2 mrg // Override superclass callbacks.
486 1.2 mrg void OnDead() override;
487 1.2 mrg void OnJoined(void *arg) override;
488 1.2 mrg void OnFinished() override;
489 1.2 mrg void OnStarted(void *arg) override;
490 1.2 mrg void OnCreated(void *arg) override;
491 1.2 mrg void OnReset() override;
492 1.2 mrg void OnDetached(void *arg) override;
493 1.1 mrg };
494 1.1 mrg
495 1.1 mrg struct RacyStacks {
496 1.1 mrg MD5Hash hash[2];
497 1.1 mrg bool operator==(const RacyStacks &other) const {
498 1.1 mrg if (hash[0] == other.hash[0] && hash[1] == other.hash[1])
499 1.1 mrg return true;
500 1.1 mrg if (hash[0] == other.hash[1] && hash[1] == other.hash[0])
501 1.1 mrg return true;
502 1.1 mrg return false;
503 1.1 mrg }
504 1.1 mrg };
505 1.1 mrg
506 1.1 mrg struct RacyAddress {
507 1.1 mrg uptr addr_min;
508 1.1 mrg uptr addr_max;
509 1.1 mrg };
510 1.1 mrg
511 1.1 mrg struct FiredSuppression {
512 1.1 mrg ReportType type;
513 1.2 mrg uptr pc_or_addr;
514 1.2 mrg Suppression *supp;
515 1.1 mrg };
516 1.1 mrg
517 1.1 mrg struct Context {
518 1.1 mrg Context();
519 1.1 mrg
520 1.1 mrg bool initialized;
521 1.2 mrg #if !SANITIZER_GO
522 1.2 mrg bool after_multithreaded_fork;
523 1.2 mrg #endif
524 1.1 mrg
525 1.2 mrg MetaMap metamap;
526 1.1 mrg
527 1.1 mrg Mutex report_mtx;
528 1.1 mrg int nreported;
529 1.1 mrg int nmissed_expected;
530 1.2 mrg atomic_uint64_t last_symbolize_time_ns;
531 1.1 mrg
532 1.2 mrg void *background_thread;
533 1.2 mrg atomic_uint32_t stop_background_thread;
534 1.1 mrg
535 1.2 mrg ThreadRegistry *thread_registry;
536 1.2 mrg
537 1.2 mrg Mutex racy_mtx;
538 1.1 mrg Vector<RacyStacks> racy_stacks;
539 1.1 mrg Vector<RacyAddress> racy_addresses;
540 1.2 mrg // Number of fired suppressions may be large enough.
541 1.2 mrg Mutex fired_suppressions_mtx;
542 1.2 mrg InternalMmapVector<FiredSuppression> fired_suppressions;
543 1.2 mrg DDetector *dd;
544 1.2 mrg
545 1.2 mrg ClockAlloc clock_alloc;
546 1.1 mrg
547 1.1 mrg Flags flags;
548 1.1 mrg
549 1.1 mrg u64 stat[StatCnt];
550 1.1 mrg u64 int_alloc_cnt[MBlockTypeCount];
551 1.1 mrg u64 int_alloc_siz[MBlockTypeCount];
552 1.1 mrg };
553 1.1 mrg
554 1.2 mrg extern Context *ctx; // The one and the only global runtime context.
555 1.2 mrg
556 1.2 mrg ALWAYS_INLINE Flags *flags() {
557 1.2 mrg return &ctx->flags;
558 1.2 mrg }
559 1.2 mrg
560 1.2 mrg struct ScopedIgnoreInterceptors {
561 1.2 mrg ScopedIgnoreInterceptors() {
562 1.2 mrg #if !SANITIZER_GO
563 1.2 mrg cur_thread()->ignore_interceptors++;
564 1.2 mrg #endif
565 1.2 mrg }
566 1.2 mrg
567 1.2 mrg ~ScopedIgnoreInterceptors() {
568 1.2 mrg #if !SANITIZER_GO
569 1.2 mrg cur_thread()->ignore_interceptors--;
570 1.2 mrg #endif
571 1.2 mrg }
572 1.1 mrg };
573 1.1 mrg
574 1.2 mrg const char *GetObjectTypeFromTag(uptr tag);
575 1.2 mrg const char *GetReportHeaderFromTag(uptr tag);
576 1.2 mrg uptr TagFromShadowStackFrame(uptr pc);
577 1.2 mrg
578 1.2 mrg class ScopedReportBase {
579 1.1 mrg public:
580 1.2 mrg void AddMemoryAccess(uptr addr, uptr external_tag, Shadow s, StackTrace stack,
581 1.1 mrg const MutexSet *mset);
582 1.2 mrg void AddStack(StackTrace stack, bool suppressable = false);
583 1.2 mrg void AddThread(const ThreadContext *tctx, bool suppressable = false);
584 1.2 mrg void AddThread(int unique_tid, bool suppressable = false);
585 1.2 mrg void AddUniqueTid(int unique_tid);
586 1.1 mrg void AddMutex(const SyncVar *s);
587 1.2 mrg u64 AddMutex(u64 id);
588 1.1 mrg void AddLocation(uptr addr, uptr size);
589 1.1 mrg void AddSleep(u32 stack_id);
590 1.2 mrg void SetCount(int count);
591 1.1 mrg
592 1.1 mrg const ReportDesc *GetReport() const;
593 1.1 mrg
594 1.2 mrg protected:
595 1.2 mrg ScopedReportBase(ReportType typ, uptr tag);
596 1.2 mrg ~ScopedReportBase();
597 1.2 mrg
598 1.1 mrg private:
599 1.1 mrg ReportDesc *rep_;
600 1.2 mrg // Symbolizer makes lots of intercepted calls. If we try to process them,
601 1.2 mrg // at best it will cause deadlocks on internal mutexes.
602 1.2 mrg ScopedIgnoreInterceptors ignore_interceptors_;
603 1.1 mrg
604 1.2 mrg void AddDeadMutex(u64 id);
605 1.1 mrg
606 1.2 mrg ScopedReportBase(const ScopedReportBase &) = delete;
607 1.2 mrg void operator=(const ScopedReportBase &) = delete;
608 1.1 mrg };
609 1.1 mrg
610 1.2 mrg class ScopedReport : public ScopedReportBase {
611 1.2 mrg public:
612 1.2 mrg explicit ScopedReport(ReportType typ, uptr tag = kExternalTagNone);
613 1.2 mrg ~ScopedReport();
614 1.2 mrg
615 1.2 mrg private:
616 1.2 mrg ScopedErrorReportLock lock_;
617 1.2 mrg };
618 1.2 mrg
619 1.2 mrg ThreadContext *IsThreadStackOrTls(uptr addr, bool *is_stack);
620 1.2 mrg void RestoreStack(int tid, const u64 epoch, VarSizeStackTrace *stk,
621 1.2 mrg MutexSet *mset, uptr *tag = nullptr);
622 1.2 mrg
623 1.2 mrg // The stack could look like:
624 1.2 mrg // <start> | <main> | <foo> | tag | <bar>
625 1.2 mrg // This will extract the tag and keep:
626 1.2 mrg // <start> | <main> | <foo> | <bar>
627 1.2 mrg template<typename StackTraceTy>
628 1.2 mrg void ExtractTagFromStack(StackTraceTy *stack, uptr *tag = nullptr) {
629 1.2 mrg if (stack->size < 2) return;
630 1.2 mrg uptr possible_tag_pc = stack->trace[stack->size - 2];
631 1.2 mrg uptr possible_tag = TagFromShadowStackFrame(possible_tag_pc);
632 1.2 mrg if (possible_tag == kExternalTagNone) return;
633 1.2 mrg stack->trace_buffer[stack->size - 2] = stack->trace_buffer[stack->size - 1];
634 1.2 mrg stack->size -= 1;
635 1.2 mrg if (tag) *tag = possible_tag;
636 1.2 mrg }
637 1.2 mrg
638 1.2 mrg template<typename StackTraceTy>
639 1.2 mrg void ObtainCurrentStack(ThreadState *thr, uptr toppc, StackTraceTy *stack,
640 1.2 mrg uptr *tag = nullptr) {
641 1.2 mrg uptr size = thr->shadow_stack_pos - thr->shadow_stack;
642 1.2 mrg uptr start = 0;
643 1.2 mrg if (size + !!toppc > kStackTraceMax) {
644 1.2 mrg start = size + !!toppc - kStackTraceMax;
645 1.2 mrg size = kStackTraceMax - !!toppc;
646 1.2 mrg }
647 1.2 mrg stack->Init(&thr->shadow_stack[start], size, toppc);
648 1.2 mrg ExtractTagFromStack(stack, tag);
649 1.2 mrg }
650 1.2 mrg
651 1.2 mrg #define GET_STACK_TRACE_FATAL(thr, pc) \
652 1.2 mrg VarSizeStackTrace stack; \
653 1.2 mrg ObtainCurrentStack(thr, pc, &stack); \
654 1.2 mrg stack.ReverseOrder();
655 1.1 mrg
656 1.2 mrg #if TSAN_COLLECT_STATS
657 1.1 mrg void StatAggregate(u64 *dst, u64 *src);
658 1.1 mrg void StatOutput(u64 *stat);
659 1.2 mrg #endif
660 1.2 mrg
661 1.2 mrg void ALWAYS_INLINE StatInc(ThreadState *thr, StatType typ, u64 n = 1) {
662 1.2 mrg #if TSAN_COLLECT_STATS
663 1.2 mrg thr->stat[typ] += n;
664 1.2 mrg #endif
665 1.2 mrg }
666 1.2 mrg void ALWAYS_INLINE StatSet(ThreadState *thr, StatType typ, u64 n) {
667 1.2 mrg #if TSAN_COLLECT_STATS
668 1.2 mrg thr->stat[typ] = n;
669 1.2 mrg #endif
670 1.1 mrg }
671 1.1 mrg
672 1.1 mrg void MapShadow(uptr addr, uptr size);
673 1.2 mrg void MapThreadTrace(uptr addr, uptr size, const char *name);
674 1.2 mrg void DontNeedShadowFor(uptr addr, uptr size);
675 1.1 mrg void InitializeShadowMemory();
676 1.1 mrg void InitializeInterceptors();
677 1.2 mrg void InitializeLibIgnore();
678 1.1 mrg void InitializeDynamicAnnotations();
679 1.1 mrg
680 1.2 mrg void ForkBefore(ThreadState *thr, uptr pc);
681 1.2 mrg void ForkParentAfter(ThreadState *thr, uptr pc);
682 1.2 mrg void ForkChildAfter(ThreadState *thr, uptr pc);
683 1.2 mrg
684 1.1 mrg void ReportRace(ThreadState *thr);
685 1.2 mrg bool OutputReport(ThreadState *thr, const ScopedReport &srep);
686 1.2 mrg bool IsFiredSuppression(Context *ctx, ReportType type, StackTrace trace);
687 1.1 mrg bool IsExpectedReport(uptr addr, uptr size);
688 1.2 mrg void PrintMatchedBenignRaces();
689 1.1 mrg
690 1.1 mrg #if defined(TSAN_DEBUG_OUTPUT) && TSAN_DEBUG_OUTPUT >= 1
691 1.1 mrg # define DPrintf Printf
692 1.1 mrg #else
693 1.1 mrg # define DPrintf(...)
694 1.1 mrg #endif
695 1.1 mrg
696 1.1 mrg #if defined(TSAN_DEBUG_OUTPUT) && TSAN_DEBUG_OUTPUT >= 2
697 1.1 mrg # define DPrintf2 Printf
698 1.1 mrg #else
699 1.1 mrg # define DPrintf2(...)
700 1.1 mrg #endif
701 1.1 mrg
702 1.1 mrg u32 CurrentStackId(ThreadState *thr, uptr pc);
703 1.2 mrg ReportStack *SymbolizeStackId(u32 stack_id);
704 1.1 mrg void PrintCurrentStack(ThreadState *thr, uptr pc);
705 1.2 mrg void PrintCurrentStackSlow(uptr pc); // uses libunwind
706 1.1 mrg
707 1.1 mrg void Initialize(ThreadState *thr);
708 1.2 mrg void MaybeSpawnBackgroundThread();
709 1.1 mrg int Finalize(ThreadState *thr);
710 1.1 mrg
711 1.2 mrg void OnUserAlloc(ThreadState *thr, uptr pc, uptr p, uptr sz, bool write);
712 1.2 mrg void OnUserFree(ThreadState *thr, uptr pc, uptr p, bool write);
713 1.1 mrg
714 1.1 mrg void MemoryAccess(ThreadState *thr, uptr pc, uptr addr,
715 1.1 mrg int kAccessSizeLog, bool kAccessIsWrite, bool kIsAtomic);
716 1.1 mrg void MemoryAccessImpl(ThreadState *thr, uptr addr,
717 1.1 mrg int kAccessSizeLog, bool kAccessIsWrite, bool kIsAtomic,
718 1.1 mrg u64 *shadow_mem, Shadow cur);
719 1.1 mrg void MemoryAccessRange(ThreadState *thr, uptr pc, uptr addr,
720 1.1 mrg uptr size, bool is_write);
721 1.1 mrg void MemoryAccessRangeStep(ThreadState *thr, uptr pc, uptr addr,
722 1.1 mrg uptr size, uptr step, bool is_write);
723 1.2 mrg void UnalignedMemoryAccess(ThreadState *thr, uptr pc, uptr addr,
724 1.2 mrg int size, bool kAccessIsWrite, bool kIsAtomic);
725 1.1 mrg
726 1.1 mrg const int kSizeLog1 = 0;
727 1.1 mrg const int kSizeLog2 = 1;
728 1.1 mrg const int kSizeLog4 = 2;
729 1.1 mrg const int kSizeLog8 = 3;
730 1.1 mrg
731 1.2 mrg void ALWAYS_INLINE MemoryRead(ThreadState *thr, uptr pc,
732 1.1 mrg uptr addr, int kAccessSizeLog) {
733 1.1 mrg MemoryAccess(thr, pc, addr, kAccessSizeLog, false, false);
734 1.1 mrg }
735 1.1 mrg
736 1.2 mrg void ALWAYS_INLINE MemoryWrite(ThreadState *thr, uptr pc,
737 1.1 mrg uptr addr, int kAccessSizeLog) {
738 1.1 mrg MemoryAccess(thr, pc, addr, kAccessSizeLog, true, false);
739 1.1 mrg }
740 1.1 mrg
741 1.2 mrg void ALWAYS_INLINE MemoryReadAtomic(ThreadState *thr, uptr pc,
742 1.1 mrg uptr addr, int kAccessSizeLog) {
743 1.1 mrg MemoryAccess(thr, pc, addr, kAccessSizeLog, false, true);
744 1.1 mrg }
745 1.1 mrg
746 1.2 mrg void ALWAYS_INLINE MemoryWriteAtomic(ThreadState *thr, uptr pc,
747 1.1 mrg uptr addr, int kAccessSizeLog) {
748 1.1 mrg MemoryAccess(thr, pc, addr, kAccessSizeLog, true, true);
749 1.1 mrg }
750 1.1 mrg
751 1.1 mrg void MemoryResetRange(ThreadState *thr, uptr pc, uptr addr, uptr size);
752 1.1 mrg void MemoryRangeFreed(ThreadState *thr, uptr pc, uptr addr, uptr size);
753 1.1 mrg void MemoryRangeImitateWrite(ThreadState *thr, uptr pc, uptr addr, uptr size);
754 1.2 mrg
755 1.2 mrg void ThreadIgnoreBegin(ThreadState *thr, uptr pc, bool save_stack = true);
756 1.2 mrg void ThreadIgnoreEnd(ThreadState *thr, uptr pc);
757 1.2 mrg void ThreadIgnoreSyncBegin(ThreadState *thr, uptr pc, bool save_stack = true);
758 1.2 mrg void ThreadIgnoreSyncEnd(ThreadState *thr, uptr pc);
759 1.1 mrg
760 1.1 mrg void FuncEntry(ThreadState *thr, uptr pc);
761 1.1 mrg void FuncExit(ThreadState *thr);
762 1.1 mrg
763 1.1 mrg int ThreadCreate(ThreadState *thr, uptr pc, uptr uid, bool detached);
764 1.2 mrg void ThreadStart(ThreadState *thr, int tid, tid_t os_id, bool workerthread);
765 1.1 mrg void ThreadFinish(ThreadState *thr);
766 1.1 mrg int ThreadTid(ThreadState *thr, uptr pc, uptr uid);
767 1.1 mrg void ThreadJoin(ThreadState *thr, uptr pc, int tid);
768 1.1 mrg void ThreadDetach(ThreadState *thr, uptr pc, int tid);
769 1.1 mrg void ThreadFinalize(ThreadState *thr);
770 1.1 mrg void ThreadSetName(ThreadState *thr, const char *name);
771 1.1 mrg int ThreadCount(ThreadState *thr);
772 1.1 mrg void ProcessPendingSignals(ThreadState *thr);
773 1.1 mrg
774 1.2 mrg Processor *ProcCreate();
775 1.2 mrg void ProcDestroy(Processor *proc);
776 1.2 mrg void ProcWire(Processor *proc, ThreadState *thr);
777 1.2 mrg void ProcUnwire(Processor *proc, ThreadState *thr);
778 1.2 mrg
779 1.2 mrg // Note: the parameter is called flagz, because flags is already taken
780 1.2 mrg // by the global function that returns flags.
781 1.2 mrg void MutexCreate(ThreadState *thr, uptr pc, uptr addr, u32 flagz = 0);
782 1.2 mrg void MutexDestroy(ThreadState *thr, uptr pc, uptr addr, u32 flagz = 0);
783 1.2 mrg void MutexPreLock(ThreadState *thr, uptr pc, uptr addr, u32 flagz = 0);
784 1.2 mrg void MutexPostLock(ThreadState *thr, uptr pc, uptr addr, u32 flagz = 0,
785 1.2 mrg int rec = 1);
786 1.2 mrg int MutexUnlock(ThreadState *thr, uptr pc, uptr addr, u32 flagz = 0);
787 1.2 mrg void MutexPreReadLock(ThreadState *thr, uptr pc, uptr addr, u32 flagz = 0);
788 1.2 mrg void MutexPostReadLock(ThreadState *thr, uptr pc, uptr addr, u32 flagz = 0);
789 1.1 mrg void MutexReadUnlock(ThreadState *thr, uptr pc, uptr addr);
790 1.1 mrg void MutexReadOrWriteUnlock(ThreadState *thr, uptr pc, uptr addr);
791 1.2 mrg void MutexRepair(ThreadState *thr, uptr pc, uptr addr); // call on EOWNERDEAD
792 1.2 mrg void MutexInvalidAccess(ThreadState *thr, uptr pc, uptr addr);
793 1.1 mrg
794 1.1 mrg void Acquire(ThreadState *thr, uptr pc, uptr addr);
795 1.2 mrg // AcquireGlobal synchronizes the current thread with all other threads.
796 1.2 mrg // In terms of happens-before relation, it draws a HB edge from all threads
797 1.2 mrg // (where they happen to execute right now) to the current thread. We use it to
798 1.2 mrg // handle Go finalizers. Namely, finalizer goroutine executes AcquireGlobal
799 1.2 mrg // right before executing finalizers. This provides a coarse, but simple
800 1.2 mrg // approximation of the actual required synchronization.
801 1.1 mrg void AcquireGlobal(ThreadState *thr, uptr pc);
802 1.1 mrg void Release(ThreadState *thr, uptr pc, uptr addr);
803 1.1 mrg void ReleaseStore(ThreadState *thr, uptr pc, uptr addr);
804 1.1 mrg void AfterSleep(ThreadState *thr, uptr pc);
805 1.2 mrg void AcquireImpl(ThreadState *thr, uptr pc, SyncClock *c);
806 1.2 mrg void ReleaseImpl(ThreadState *thr, uptr pc, SyncClock *c);
807 1.2 mrg void ReleaseStoreImpl(ThreadState *thr, uptr pc, SyncClock *c);
808 1.2 mrg void AcquireReleaseImpl(ThreadState *thr, uptr pc, SyncClock *c);
809 1.1 mrg
810 1.1 mrg // The hacky call uses custom calling convention and an assembly thunk.
811 1.1 mrg // It is considerably faster that a normal call for the caller
812 1.1 mrg // if it is not executed (it is intended for slow paths from hot functions).
813 1.1 mrg // The trick is that the call preserves all registers and the compiler
814 1.1 mrg // does not treat it as a call.
815 1.1 mrg // If it does not work for you, use normal call.
816 1.2 mrg #if !SANITIZER_DEBUG && defined(__x86_64__) && !SANITIZER_MAC
817 1.1 mrg // The caller may not create the stack frame for itself at all,
818 1.1 mrg // so we create a reserve stack frame for it (1024b must be enough).
819 1.1 mrg #define HACKY_CALL(f) \
820 1.1 mrg __asm__ __volatile__("sub $1024, %%rsp;" \
821 1.2 mrg CFI_INL_ADJUST_CFA_OFFSET(1024) \
822 1.1 mrg ".hidden " #f "_thunk;" \
823 1.1 mrg "call " #f "_thunk;" \
824 1.1 mrg "add $1024, %%rsp;" \
825 1.2 mrg CFI_INL_ADJUST_CFA_OFFSET(-1024) \
826 1.1 mrg ::: "memory", "cc");
827 1.1 mrg #else
828 1.1 mrg #define HACKY_CALL(f) f()
829 1.1 mrg #endif
830 1.1 mrg
831 1.1 mrg void TraceSwitch(ThreadState *thr);
832 1.1 mrg uptr TraceTopPC(ThreadState *thr);
833 1.1 mrg uptr TraceSize();
834 1.1 mrg uptr TraceParts();
835 1.2 mrg Trace *ThreadTrace(int tid);
836 1.1 mrg
837 1.1 mrg extern "C" void __tsan_trace_switch();
838 1.2 mrg void ALWAYS_INLINE TraceAddEvent(ThreadState *thr, FastState fs,
839 1.1 mrg EventType typ, u64 addr) {
840 1.2 mrg if (!kCollectHistory)
841 1.2 mrg return;
842 1.1 mrg DCHECK_GE((int)typ, 0);
843 1.1 mrg DCHECK_LE((int)typ, 7);
844 1.2 mrg DCHECK_EQ(GetLsb(addr, kEventPCBits), addr);
845 1.1 mrg StatInc(thr, StatEvents);
846 1.1 mrg u64 pos = fs.GetTracePos();
847 1.1 mrg if (UNLIKELY((pos % kTracePartSize) == 0)) {
848 1.2 mrg #if !SANITIZER_GO
849 1.1 mrg HACKY_CALL(__tsan_trace_switch);
850 1.1 mrg #else
851 1.1 mrg TraceSwitch(thr);
852 1.1 mrg #endif
853 1.1 mrg }
854 1.1 mrg Event *trace = (Event*)GetThreadTrace(fs.tid());
855 1.1 mrg Event *evp = &trace[pos];
856 1.2 mrg Event ev = (u64)addr | ((u64)typ << kEventPCBits);
857 1.1 mrg *evp = ev;
858 1.1 mrg }
859 1.1 mrg
860 1.2 mrg #if !SANITIZER_GO
861 1.2 mrg uptr ALWAYS_INLINE HeapEnd() {
862 1.2 mrg return HeapMemEnd() + PrimaryAllocator::AdditionalSize();
863 1.2 mrg }
864 1.2 mrg #endif
865 1.2 mrg
866 1.1 mrg } // namespace __tsan
867 1.1 mrg
868 1.1 mrg #endif // TSAN_RTL_H
869