tsan_rtl.cc revision 22881ec8c8a3c01f9b993b186040444b0b5caa50
1603c4be006d8c53905d736bf1f19a49f5ce98276Alexey Samsonov//===-- tsan_rtl.cc -------------------------------------------------------===//
27ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany//
37ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany//                     The LLVM Compiler Infrastructure
47ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany//
57ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// This file is distributed under the University of Illinois Open Source
67ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// License. See LICENSE.TXT for details.
77ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany//
87ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany//===----------------------------------------------------------------------===//
97ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany//
107ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// This file is a part of ThreadSanitizer (TSan), a race detector.
117ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany//
127ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// Main file (entry points) for the TSan run-time.
137ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany//===----------------------------------------------------------------------===//
147ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
15fce5bd4cc29fddb5e8f0cb9c12df7c10187a991dDmitry Vyukov#include "sanitizer_common/sanitizer_atomic.h"
160969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov#include "sanitizer_common/sanitizer_common.h"
1716e0075746b21ed866ec3be21ef0d1e46f0efed5Kostya Serebryany#include "sanitizer_common/sanitizer_libc.h"
18848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov#include "sanitizer_common/sanitizer_stackdepot.h"
1947b1634df012507799eb39aa17d4022d748ba67bAlexey Samsonov#include "sanitizer_common/sanitizer_placement_new.h"
208cc1f81b2cc1fa0d4cda4f4635d955aed04c09c8Alexey Samsonov#include "sanitizer_common/sanitizer_symbolizer.h"
217ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_defs.h"
227ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_platform.h"
237ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_rtl.h"
247ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_mman.h"
257ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_suppressions.h"
267ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
27adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukovvolatile int __tsan_resumed = 0;
287ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
297ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyextern "C" void __tsan_resume() {
30adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov  __tsan_resumed = 1;
317ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
327ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
337ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanynamespace __tsan {
347ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
35b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#ifndef TSAN_GO
360a4c906dbc8f150657ddd4f19a7192b779f1d605Alexey SamsonovTHREADLOCAL char cur_thread_placeholder[sizeof(ThreadState)] ALIGNED(64);
37b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#endif
380a4c906dbc8f150657ddd4f19a7192b779f1d605Alexey Samsonovstatic char ctx_placeholder[sizeof(Context)] ALIGNED(64);
397ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
4022881ec8c8a3c01f9b993b186040444b0b5caa50Dmitry Vyukov// Can be overriden by a front-end.
4122881ec8c8a3c01f9b993b186040444b0b5caa50Dmitry Vyukov#ifndef TSAN_GO
4222881ec8c8a3c01f9b993b186040444b0b5caa50Dmitry Vyukovbool WEAK OnFinalize(bool failed) {
4322881ec8c8a3c01f9b993b186040444b0b5caa50Dmitry Vyukov  return failed;
4422881ec8c8a3c01f9b993b186040444b0b5caa50Dmitry Vyukov}
4522881ec8c8a3c01f9b993b186040444b0b5caa50Dmitry Vyukov#endif
4622881ec8c8a3c01f9b993b186040444b0b5caa50Dmitry Vyukov
477ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic Context *ctx;
487ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyContext *CTX() {
497ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return ctx;
507ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
517ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
527ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyContext::Context()
537ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  : initialized()
547ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  , report_mtx(MutexTypeReport, StatMtxReport)
557ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  , nreported()
567ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  , nmissed_expected()
577ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  , thread_mtx(MutexTypeThreads, StatMtxThreads)
587ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  , racy_stacks(MBlockRacyStacks)
59158c6ac3bb46753db217f9c2c73485811a3a1890Dmitry Vyukov  , racy_addresses(MBlockRacyAddresses)
60158c6ac3bb46753db217f9c2c73485811a3a1890Dmitry Vyukov  , fired_suppressions(MBlockRacyAddresses) {
617ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
627ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
637ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// The objects are allocated in TLS, so one may rely on zero-initialization.
64ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry VyukovThreadState::ThreadState(Context *ctx, int tid, int unique_id, u64 epoch,
657ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany                         uptr stk_addr, uptr stk_size,
667ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany                         uptr tls_addr, uptr tls_size)
677ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  : fast_state(tid, epoch)
687ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // Do not touch these, rely on zero initialization,
697ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // they may be accessed before the ctor.
707ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // , fast_ignore_reads()
717ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // , fast_ignore_writes()
727ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // , in_rtl()
737ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  , shadow_stack_pos(&shadow_stack[0])
747ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  , tid(tid)
75ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry Vyukov  , unique_id(unique_id)
767ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  , stk_addr(stk_addr)
777ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  , stk_size(stk_size)
787ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  , tls_addr(tls_addr)
797ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  , tls_size(tls_size) {
807ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
817ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
827ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyThreadContext::ThreadContext(int tid)
837ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  : tid(tid)
847ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  , unique_id()
857dccf3f92a867f917ad19f9a6b37bcf93e64b35bDmitry Vyukov  , os_id()
867ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  , user_id()
877ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  , thr()
887ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  , status(ThreadStatusInvalid)
897ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  , detached()
907ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  , reuse_count()
917ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  , epoch0()
927ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  , epoch1()
939d2ffc2ee08216f8fad9b1bd267d1f112e0d2f01Dmitry Vyukov  , dead_info()
94aecf2e5756c6a0de7c146bef67a6e338c7017d55Dmitry Vyukov  , dead_next()
95aecf2e5756c6a0de7c146bef67a6e338c7017d55Dmitry Vyukov  , name() {
967ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
977ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
9826127735454fddae3495794f38189d57dde6510fDmitry Vyukovstatic void WriteMemoryProfile(char *buf, uptr buf_size, int num) {
9926127735454fddae3495794f38189d57dde6510fDmitry Vyukov  uptr shadow = GetShadowMemoryConsumption();
10026127735454fddae3495794f38189d57dde6510fDmitry Vyukov
10126127735454fddae3495794f38189d57dde6510fDmitry Vyukov  int nthread = 0;
10226127735454fddae3495794f38189d57dde6510fDmitry Vyukov  int nlivethread = 0;
10326127735454fddae3495794f38189d57dde6510fDmitry Vyukov  uptr threadmem = 0;
10426127735454fddae3495794f38189d57dde6510fDmitry Vyukov  {
10526127735454fddae3495794f38189d57dde6510fDmitry Vyukov    Lock l(&ctx->thread_mtx);
10626127735454fddae3495794f38189d57dde6510fDmitry Vyukov    for (unsigned i = 0; i < kMaxTid; i++) {
10726127735454fddae3495794f38189d57dde6510fDmitry Vyukov      ThreadContext *tctx = ctx->threads[i];
10826127735454fddae3495794f38189d57dde6510fDmitry Vyukov      if (tctx == 0)
10926127735454fddae3495794f38189d57dde6510fDmitry Vyukov        continue;
11026127735454fddae3495794f38189d57dde6510fDmitry Vyukov      nthread += 1;
11126127735454fddae3495794f38189d57dde6510fDmitry Vyukov      threadmem += sizeof(ThreadContext);
11226127735454fddae3495794f38189d57dde6510fDmitry Vyukov      if (tctx->status != ThreadStatusRunning)
11326127735454fddae3495794f38189d57dde6510fDmitry Vyukov        continue;
11426127735454fddae3495794f38189d57dde6510fDmitry Vyukov      nlivethread += 1;
11526127735454fddae3495794f38189d57dde6510fDmitry Vyukov      threadmem += sizeof(ThreadState);
11626127735454fddae3495794f38189d57dde6510fDmitry Vyukov    }
11726127735454fddae3495794f38189d57dde6510fDmitry Vyukov  }
11826127735454fddae3495794f38189d57dde6510fDmitry Vyukov
11926127735454fddae3495794f38189d57dde6510fDmitry Vyukov  uptr nsync = 0;
12026127735454fddae3495794f38189d57dde6510fDmitry Vyukov  uptr syncmem = CTX()->synctab.GetMemoryConsumption(&nsync);
12126127735454fddae3495794f38189d57dde6510fDmitry Vyukov
122de08c02aa3007a590bfb7d43f31d5b1a0e7d337cAlexey Samsonov  internal_snprintf(buf, buf_size, "%d: shadow=%zuMB"
123de08c02aa3007a590bfb7d43f31d5b1a0e7d337cAlexey Samsonov                                   " thread=%zuMB(total=%d/live=%d)"
124de08c02aa3007a590bfb7d43f31d5b1a0e7d337cAlexey Samsonov                                   " sync=%zuMB(cnt=%zu)\n",
12526127735454fddae3495794f38189d57dde6510fDmitry Vyukov    num,
12626127735454fddae3495794f38189d57dde6510fDmitry Vyukov    shadow >> 20,
12726127735454fddae3495794f38189d57dde6510fDmitry Vyukov    threadmem >> 20, nthread, nlivethread,
12826127735454fddae3495794f38189d57dde6510fDmitry Vyukov    syncmem >> 20, nsync);
12926127735454fddae3495794f38189d57dde6510fDmitry Vyukov}
13026127735454fddae3495794f38189d57dde6510fDmitry Vyukov
13126127735454fddae3495794f38189d57dde6510fDmitry Vyukovstatic void MemoryProfileThread(void *arg) {
13226127735454fddae3495794f38189d57dde6510fDmitry Vyukov  ScopedInRtl in_rtl;
13326127735454fddae3495794f38189d57dde6510fDmitry Vyukov  fd_t fd = (fd_t)(uptr)arg;
13426127735454fddae3495794f38189d57dde6510fDmitry Vyukov  for (int i = 0; ; i++) {
13514c8bd7250742749e44e306c02a56cf47ad1db82Alexey Samsonov    InternalScopedBuffer<char> buf(4096);
1361dc4cf7e253aefa3ce3bd4a1d349a13647e8b2eaAlexey Samsonov    WriteMemoryProfile(buf.data(), buf.size(), i);
1371dc4cf7e253aefa3ce3bd4a1d349a13647e8b2eaAlexey Samsonov    internal_write(fd, buf.data(), internal_strlen(buf.data()));
1380969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov    SleepForSeconds(1);
13926127735454fddae3495794f38189d57dde6510fDmitry Vyukov  }
14026127735454fddae3495794f38189d57dde6510fDmitry Vyukov}
14126127735454fddae3495794f38189d57dde6510fDmitry Vyukov
14226127735454fddae3495794f38189d57dde6510fDmitry Vyukovstatic void InitializeMemoryProfile() {
14326127735454fddae3495794f38189d57dde6510fDmitry Vyukov  if (flags()->profile_memory == 0 || flags()->profile_memory[0] == 0)
14426127735454fddae3495794f38189d57dde6510fDmitry Vyukov    return;
14514c8bd7250742749e44e306c02a56cf47ad1db82Alexey Samsonov  InternalScopedBuffer<char> filename(4096);
1461dc4cf7e253aefa3ce3bd4a1d349a13647e8b2eaAlexey Samsonov  internal_snprintf(filename.data(), filename.size(), "%s.%d",
14726127735454fddae3495794f38189d57dde6510fDmitry Vyukov      flags()->profile_memory, GetPid());
1481dc4cf7e253aefa3ce3bd4a1d349a13647e8b2eaAlexey Samsonov  fd_t fd = internal_open(filename.data(), true);
14926127735454fddae3495794f38189d57dde6510fDmitry Vyukov  if (fd == kInvalidFd) {
150b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov    Printf("Failed to open memory profile file '%s'\n", &filename[0]);
15126127735454fddae3495794f38189d57dde6510fDmitry Vyukov    Die();
15226127735454fddae3495794f38189d57dde6510fDmitry Vyukov  }
15326127735454fddae3495794f38189d57dde6510fDmitry Vyukov  internal_start_thread(&MemoryProfileThread, (void*)(uptr)fd);
15426127735454fddae3495794f38189d57dde6510fDmitry Vyukov}
15526127735454fddae3495794f38189d57dde6510fDmitry Vyukov
156adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukovstatic void MemoryFlushThread(void *arg) {
157adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov  ScopedInRtl in_rtl;
158adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov  for (int i = 0; ; i++) {
1590969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov    SleepForMillis(flags()->flush_memory_ms);
160adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov    FlushShadowMemory();
161adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov  }
162adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov}
163adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov
164adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukovstatic void InitializeMemoryFlush() {
165adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov  if (flags()->flush_memory_ms == 0)
166adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov    return;
167adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov  if (flags()->flush_memory_ms < 100)
168adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov    flags()->flush_memory_ms = 100;
169adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov  internal_start_thread(&MemoryFlushThread, 0);
170adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov}
171adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov
172a05fcc1e3e045097f2f1a20798cbe038bbb1d6a9Dmitry Vyukovvoid MapShadow(uptr addr, uptr size) {
1736b641c5e63be45a03f96346886d27c4b4135ddafDmitry Vyukov  MmapFixedNoReserve(MemToShadow(addr), size * kShadowMultiplier);
174a05fcc1e3e045097f2f1a20798cbe038bbb1d6a9Dmitry Vyukov}
175a05fcc1e3e045097f2f1a20798cbe038bbb1d6a9Dmitry Vyukov
1766535c31c66569df262791f0b56852c496977c977Dmitry Vyukovvoid MapThreadTrace(uptr addr, uptr size) {
177dae1251f196f9694d428a04f14987b06112ae52cDmitry Vyukov  DPrintf("#0: Mapping trace at %p-%p(0x%zx)\n", addr, addr + size, size);
1786535c31c66569df262791f0b56852c496977c977Dmitry Vyukov  CHECK_GE(addr, kTraceMemBegin);
1796535c31c66569df262791f0b56852c496977c977Dmitry Vyukov  CHECK_LE(addr + size, kTraceMemBegin + kTraceMemSize);
1806535c31c66569df262791f0b56852c496977c977Dmitry Vyukov  if (addr != (uptr)MmapFixedNoReserve(addr, size)) {
1816535c31c66569df262791f0b56852c496977c977Dmitry Vyukov    Printf("FATAL: ThreadSanitizer can not mmap thread trace\n");
1826535c31c66569df262791f0b56852c496977c977Dmitry Vyukov    Die();
1836535c31c66569df262791f0b56852c496977c977Dmitry Vyukov  }
1846535c31c66569df262791f0b56852c496977c977Dmitry Vyukov}
1856535c31c66569df262791f0b56852c496977c977Dmitry Vyukov
1867ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid Initialize(ThreadState *thr) {
1877ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // Thread safe because done before all threads exist.
1887ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  static bool is_initialized = false;
1897ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (is_initialized)
1907ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    return;
1917ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  is_initialized = true;
192591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonov  // Install tool-specific callbacks in sanitizer_common.
193591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonov  SetCheckFailedCallback(TsanCheckFailed);
194591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonov
1957ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  ScopedInRtl in_rtl;
196bbbb20b7212155ebc5b5b4ee1c68c987dcf30320Dmitry Vyukov#ifndef TSAN_GO
1972e87051d136db3150a3ca322d8862f92b0a684bbDmitry Vyukov  InitializeAllocator();
198bbbb20b7212155ebc5b5b4ee1c68c987dcf30320Dmitry Vyukov#endif
1997ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  InitializeInterceptors();
2007ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  const char *env = InitializePlatform();
2017ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  InitializeMutex();
2027ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  InitializeDynamicAnnotations();
2037ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  ctx = new(ctx_placeholder) Context;
204a05fcc1e3e045097f2f1a20798cbe038bbb1d6a9Dmitry Vyukov#ifndef TSAN_GO
2057ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  InitializeShadowMemory();
206a05fcc1e3e045097f2f1a20798cbe038bbb1d6a9Dmitry Vyukov#endif
2077ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  ctx->dead_list_size = 0;
2087ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  ctx->dead_list_head = 0;
2097ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  ctx->dead_list_tail = 0;
2107ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  InitializeFlags(&ctx->flags, env);
211b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov  // Setup correct file descriptor for error reports.
212cec6068bbbbfb84285c0856c196c48170924e215Dmitry Vyukov  if (internal_strcmp(flags()->log_path, "stdout") == 0)
213cec6068bbbbfb84285c0856c196c48170924e215Dmitry Vyukov    __sanitizer_set_report_fd(kStdoutFd);
214cec6068bbbbfb84285c0856c196c48170924e215Dmitry Vyukov  else if (internal_strcmp(flags()->log_path, "stderr") == 0)
215cec6068bbbbfb84285c0856c196c48170924e215Dmitry Vyukov    __sanitizer_set_report_fd(kStderrFd);
216cec6068bbbbfb84285c0856c196c48170924e215Dmitry Vyukov  else
217cec6068bbbbfb84285c0856c196c48170924e215Dmitry Vyukov    __sanitizer_set_report_path(flags()->log_path);
2187ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  InitializeSuppressions();
21985a6dad26739fcd9742eae04b4a539e29889e937Dmitry Vyukov#ifndef TSAN_GO
22068bdcc4db8802c9a6f72d0e684a336ab92a3785bAlexey Samsonov  // Initialize external symbolizer before internal threads are started.
2218cc1f81b2cc1fa0d4cda4f4635d955aed04c09c8Alexey Samsonov  const char *external_symbolizer = flags()->external_symbolizer_path;
2228cc1f81b2cc1fa0d4cda4f4635d955aed04c09c8Alexey Samsonov  if (external_symbolizer != 0 && external_symbolizer[0] != '\0') {
22393b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov    if (!InitializeExternalSymbolizer(external_symbolizer)) {
22493b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov      Printf("Failed to start external symbolizer: '%s'\n",
22593b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov             external_symbolizer);
22693b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov      Die();
22793b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov    }
2288cc1f81b2cc1fa0d4cda4f4635d955aed04c09c8Alexey Samsonov  }
22985a6dad26739fcd9742eae04b4a539e29889e937Dmitry Vyukov#endif
23068bdcc4db8802c9a6f72d0e684a336ab92a3785bAlexey Samsonov  InitializeMemoryProfile();
23168bdcc4db8802c9a6f72d0e684a336ab92a3785bAlexey Samsonov  InitializeMemoryFlush();
2328cc1f81b2cc1fa0d4cda4f4635d955aed04c09c8Alexey Samsonov
2337ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (ctx->flags.verbosity)
234b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov    Printf("***** Running under ThreadSanitizer v2 (pid %d) *****\n",
23567a64dd8259fdbd867633b27f54d584f435f1ce6Alexey Samsonov               GetPid());
2367ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
2377ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // Initialize thread 0.
2387ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  ctx->thread_seq = 0;
2397ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int tid = ThreadCreate(thr, 0, 0, true);
2407ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  CHECK_EQ(tid, 0);
2417dccf3f92a867f917ad19f9a6b37bcf93e64b35bDmitry Vyukov  ThreadStart(thr, tid, GetPid());
2427ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  CHECK_EQ(thr->in_rtl, 1);
2437ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  ctx->initialized = true;
2447ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
245adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov  if (flags()->stop_on_start) {
246b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov    Printf("ThreadSanitizer is suspended at startup (pid %d)."
247adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov           " Call __tsan_resume().\n",
248adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov           GetPid());
249ba5e99668e3030cc5bab357a04271a1bdbac209cAlexey Samsonov    while (__tsan_resumed == 0) {}
2507ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
2517ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
2527ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
2537ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyint Finalize(ThreadState *thr) {
2547ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  ScopedInRtl in_rtl;
2557ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  Context *ctx = __tsan::ctx;
2567ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  bool failed = false;
2577ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
25854e0a9a391616bbd2a4f0fd2d01076291274cb98Dmitry Vyukov  if (flags()->atexit_sleep_ms > 0 && ThreadCount(thr) > 1)
25954e0a9a391616bbd2a4f0fd2d01076291274cb98Dmitry Vyukov    SleepForMillis(flags()->atexit_sleep_ms);
26054e0a9a391616bbd2a4f0fd2d01076291274cb98Dmitry Vyukov
261d0a51c02157e8293ea365ad0d429ef8e73d115deDmitry Vyukov  // Wait for pending reports.
262d0a51c02157e8293ea365ad0d429ef8e73d115deDmitry Vyukov  ctx->report_mtx.Lock();
263d0a51c02157e8293ea365ad0d429ef8e73d115deDmitry Vyukov  ctx->report_mtx.Unlock();
264d0a51c02157e8293ea365ad0d429ef8e73d115deDmitry Vyukov
265bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov#ifndef TSAN_GO
266bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov  if (ctx->flags.verbosity)
267bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov    AllocatorPrintStats();
268bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov#endif
269bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov
2707ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  ThreadFinalize(thr);
2717ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
2727ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (ctx->nreported) {
2737ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    failed = true;
274b3b21231dd9dfeb34f5f302c879f2d11b6312080Dmitry Vyukov#ifndef TSAN_GO
275b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov    Printf("ThreadSanitizer: reported %d warnings\n", ctx->nreported);
276b3b21231dd9dfeb34f5f302c879f2d11b6312080Dmitry Vyukov#else
277b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov    Printf("Found %d data race(s)\n", ctx->nreported);
278b3b21231dd9dfeb34f5f302c879f2d11b6312080Dmitry Vyukov#endif
2797ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
2807ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
2817ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (ctx->nmissed_expected) {
2827ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    failed = true;
283b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov    Printf("ThreadSanitizer: missed %d expected races\n",
2847ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany        ctx->nmissed_expected);
2857ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
2867ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
28722881ec8c8a3c01f9b993b186040444b0b5caa50Dmitry Vyukov#ifndef TSAN_GO
28822881ec8c8a3c01f9b993b186040444b0b5caa50Dmitry Vyukov  failed = OnFinalize(failed);
28922881ec8c8a3c01f9b993b186040444b0b5caa50Dmitry Vyukov#endif
29022881ec8c8a3c01f9b993b186040444b0b5caa50Dmitry Vyukov
29108adb1815b4958df88f904b9780a055b0d387294Dmitry Vyukov  StatAggregate(ctx->stat, thr->stat);
2927ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  StatOutput(ctx->stat);
293b7b6b1cd9df0c954b1f890fcebf373db984923b3Dmitry Vyukov  return failed ? flags()->exitcode : 0;
2947ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
2957ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
2960ab628c61594eb80612e5389d9c33da0e0d70c66Dmitry Vyukov#ifndef TSAN_GO
297848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukovu32 CurrentStackId(ThreadState *thr, uptr pc) {
298848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov  if (thr->shadow_stack_pos == 0)  // May happen during bootstrap.
299848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov    return 0;
300848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov  if (pc) {
301848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov    thr->shadow_stack_pos[0] = pc;
302848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov    thr->shadow_stack_pos++;
303848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov  }
304848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov  u32 id = StackDepotPut(thr->shadow_stack,
305848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov                         thr->shadow_stack_pos - thr->shadow_stack);
306848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov  if (pc)
307848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov    thr->shadow_stack_pos--;
308848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov  return id;
309848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov}
3100ab628c61594eb80612e5389d9c33da0e0d70c66Dmitry Vyukov#endif
311848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov
312b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukovvoid TraceSwitch(ThreadState *thr) {
3139ad7c32720dfa1287f8cfd481e5d583435178caeDmitry Vyukov  thr->nomalloc++;
3147ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  ScopedInRtl in_rtl;
3157ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  Lock l(&thr->trace.mtx);
3160415ac00935795a70d87ae662ccad58ea0704537Dmitry Vyukov  unsigned trace = (thr->fast_state.epoch() / kTracePartSize) % TraceParts();
3177ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TraceHeader *hdr = &thr->trace.headers[trace];
3187ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  hdr->epoch0 = thr->fast_state.epoch();
3197ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  hdr->stack0.ObtainCurrent(thr, 0);
320ad9da372f962495b3487685232d09390be841b1cDmitry Vyukov  hdr->mset0 = thr->mset;
3219ad7c32720dfa1287f8cfd481e5d583435178caeDmitry Vyukov  thr->nomalloc--;
3227ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
3237ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
324385542a2e83a4f37de4232d6c72097c1b7d6d44bDmitry Vyukovuptr TraceTopPC(ThreadState *thr) {
325385542a2e83a4f37de4232d6c72097c1b7d6d44bDmitry Vyukov  Event *events = (Event*)GetThreadTrace(thr->tid);
326d698edc4f74a17048eef3342a9fa42b3ebba802aDmitry Vyukov  uptr pc = events[thr->fast_state.GetTracePos()];
327385542a2e83a4f37de4232d6c72097c1b7d6d44bDmitry Vyukov  return pc;
328385542a2e83a4f37de4232d6c72097c1b7d6d44bDmitry Vyukov}
329385542a2e83a4f37de4232d6c72097c1b7d6d44bDmitry Vyukov
330d698edc4f74a17048eef3342a9fa42b3ebba802aDmitry Vyukovuptr TraceSize() {
331d698edc4f74a17048eef3342a9fa42b3ebba802aDmitry Vyukov  return (uptr)(1ull << (kTracePartSizeBits + flags()->history_size + 1));
332d698edc4f74a17048eef3342a9fa42b3ebba802aDmitry Vyukov}
333d698edc4f74a17048eef3342a9fa42b3ebba802aDmitry Vyukov
3340415ac00935795a70d87ae662ccad58ea0704537Dmitry Vyukovuptr TraceParts() {
3350415ac00935795a70d87ae662ccad58ea0704537Dmitry Vyukov  return TraceSize() / kTracePartSize;
3360415ac00935795a70d87ae662ccad58ea0704537Dmitry Vyukov}
3370415ac00935795a70d87ae662ccad58ea0704537Dmitry Vyukov
338b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#ifndef TSAN_GO
3397ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyextern "C" void __tsan_trace_switch() {
3407ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TraceSwitch(cur_thread());
3417ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
3427ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
3437ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyextern "C" void __tsan_report_race() {
3447ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  ReportRace(cur_thread());
3457ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
346b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#endif
3477ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
3487ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyALWAYS_INLINE
3497ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic Shadow LoadShadow(u64 *p) {
3507ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  u64 raw = atomic_load((atomic_uint64_t*)p, memory_order_relaxed);
3517ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return Shadow(raw);
3527ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
3537ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
3547ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyALWAYS_INLINE
3557ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic void StoreShadow(u64 *sp, u64 s) {
3567ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  atomic_store((atomic_uint64_t*)sp, s, memory_order_relaxed);
3577ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
3587ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
3597ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyALWAYS_INLINE
3607ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic void StoreIfNotYetStored(u64 *sp, u64 *s) {
3617ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  StoreShadow(sp, *s);
3627ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  *s = 0;
3637ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
3647ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
3657ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic inline void HandleRace(ThreadState *thr, u64 *shadow_mem,
3667ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany                              Shadow cur, Shadow old) {
3677ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  thr->racy_state[0] = cur.raw();
3687ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  thr->racy_state[1] = old.raw();
3697ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  thr->racy_shadow_addr = shadow_mem;
370b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#ifndef TSAN_GO
3717ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  HACKY_CALL(__tsan_report_race);
372b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#else
373b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov  ReportRace(thr);
374b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#endif
3757ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
3767ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
3777ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic inline bool BothReads(Shadow s, int kAccessIsWrite) {
3787ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return !kAccessIsWrite && !s.is_write();
3797ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
3807ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
381ed77156ba3c5754b4cfe4ca1d6d5d7a4fdfb7835Dmitry Vyukovstatic inline bool OldIsRWNotWeaker(Shadow old, int kAccessIsWrite) {
3827ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return old.is_write() || !kAccessIsWrite;
3837ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
3847ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
385ed77156ba3c5754b4cfe4ca1d6d5d7a4fdfb7835Dmitry Vyukovstatic inline bool OldIsRWWeakerOrEqual(Shadow old, int kAccessIsWrite) {
3867ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return !old.is_write() || kAccessIsWrite;
3877ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
3887ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
3897ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic inline bool OldIsInSameSynchEpoch(Shadow old, ThreadState *thr) {
3907ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return old.epoch() >= thr->fast_synch_epoch;
3917ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
3927ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
3937ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic inline bool HappensBefore(Shadow old, ThreadState *thr) {
394c8f0a00ede42f83ac79ff63c347ca8ddcda77155Dmitry Vyukov  return thr->clock.get(old.TidWithIgnore()) >= old.epoch();
3957ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
3967ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
3977ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyALWAYS_INLINE
3987ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid MemoryAccessImpl(ThreadState *thr, uptr addr,
399bd9f4963dd50f2fe66ba47a74776dc2665f84d7dDmitry Vyukov    int kAccessSizeLog, bool kAccessIsWrite,
4007ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    u64 *shadow_mem, Shadow cur) {
4017ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  StatInc(thr, StatMop);
4027ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  StatInc(thr, kAccessIsWrite ? StatMopWrite : StatMopRead);
4037ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  StatInc(thr, (StatType)(StatMop1 + kAccessSizeLog));
4047ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
4057ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // This potentially can live in an MMX/SSE scratch register.
4067ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // The required intrinsics are:
4077ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // __m128i _mm_move_epi64(__m128i*);
4087ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // _mm_storel_epi64(u64*, __m128i);
4097ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  u64 store_word = cur.raw();
4107ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
4117ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // scan all the shadow values and dispatch to 4 categories:
4127ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // same, replace, candidate and race (see comments below).
4137ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // we consider only 3 cases regarding access sizes:
4147ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // equal, intersect and not intersect. initially I considered
4157ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // larger and smaller as well, it allowed to replace some
4167ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // 'candidates' with 'same' or 'replace', but I think
4177ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // it's just not worth it (performance- and complexity-wise).
4187ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
4197ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  Shadow old(0);
4207ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (kShadowCnt == 1) {
4217ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    int idx = 0;
4227ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h"
4237ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  } else if (kShadowCnt == 2) {
4247ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    int idx = 0;
4257ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h"
4267ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    idx = 1;
4277ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h"
4287ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  } else if (kShadowCnt == 4) {
4297ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    int idx = 0;
4307ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h"
4317ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    idx = 1;
4327ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h"
4337ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    idx = 2;
4347ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h"
4357ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    idx = 3;
4367ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h"
4377ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  } else if (kShadowCnt == 8) {
4387ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    int idx = 0;
4397ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h"
4407ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    idx = 1;
4417ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h"
4427ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    idx = 2;
4437ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h"
4447ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    idx = 3;
4457ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h"
4467ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    idx = 4;
4477ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h"
4487ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    idx = 5;
4497ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h"
4507ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    idx = 6;
4517ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h"
4527ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    idx = 7;
4537ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h"
4547ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  } else {
4557ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    CHECK(false);
4567ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
4577ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
4587ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // we did not find any races and had already stored
4597ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // the current access info, so we are done
4607ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (LIKELY(store_word == 0))
4617ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    return;
4627ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // choose a random candidate slot and replace it
4637ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  StoreShadow(shadow_mem + (cur.epoch() % kShadowCnt), store_word);
4647ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  StatInc(thr, StatShadowReplace);
4657ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return;
4667ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany RACE:
4677ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  HandleRace(thr, shadow_mem, cur, old);
4687ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return;
4697ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
4707ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
4717ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyALWAYS_INLINE
4727ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid MemoryAccess(ThreadState *thr, uptr pc, uptr addr,
4737ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    int kAccessSizeLog, bool kAccessIsWrite) {
4747ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  u64 *shadow_mem = (u64*)MemToShadow(addr);
47568230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov  DPrintf2("#%d: MemoryAccess: @%p %p size=%d"
476e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov      " is_write=%d shadow_mem=%p {%zx, %zx, %zx, %zx}\n",
4777ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany      (int)thr->fast_state.tid(), (void*)pc, (void*)addr,
4787ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany      (int)(1 << kAccessSizeLog), kAccessIsWrite, shadow_mem,
479e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov      (uptr)shadow_mem[0], (uptr)shadow_mem[1],
480e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov      (uptr)shadow_mem[2], (uptr)shadow_mem[3]);
4817ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#if TSAN_DEBUG
4827ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (!IsAppMem(addr)) {
483b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov    Printf("Access to non app mem %zx\n", addr);
4847ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    DCHECK(IsAppMem(addr));
4857ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
4867ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (!IsShadowMem((uptr)shadow_mem)) {
487b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov    Printf("Bad shadow addr %p (%zx)\n", shadow_mem, addr);
4887ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    DCHECK(IsShadowMem((uptr)shadow_mem));
4897ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
4907ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#endif
4917ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
4927ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  FastState fast_state = thr->fast_state;
4937ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (fast_state.GetIgnoreBit())
4947ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    return;
4957ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  fast_state.IncrementEpoch();
4967ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  thr->fast_state = fast_state;
4977ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  Shadow cur(fast_state);
4987ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  cur.SetAddr0AndSizeLog(addr & 7, kAccessSizeLog);
4997ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  cur.SetWrite(kAccessIsWrite);
5007ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
5017ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // We must not store to the trace if we do not store to the shadow.
5027ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // That is, this call must be moved somewhere below.
503385542a2e83a4f37de4232d6c72097c1b7d6d44bDmitry Vyukov  TraceAddEvent(thr, fast_state, EventTypeMop, pc);
5047ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
505bd9f4963dd50f2fe66ba47a74776dc2665f84d7dDmitry Vyukov  MemoryAccessImpl(thr, addr, kAccessSizeLog, kAccessIsWrite,
5067ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany      shadow_mem, cur);
5077ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
5087ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
5097ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic void MemoryRangeSet(ThreadState *thr, uptr pc, uptr addr, uptr size,
5107ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany                           u64 val) {
5117ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (size == 0)
5127ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    return;
5137ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // FIXME: fix me.
5147ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  uptr offset = addr % kShadowCell;
5157ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (offset) {
5167ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    offset = kShadowCell - offset;
5177ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    if (size <= offset)
5187ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany      return;
5197ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    addr += offset;
5207ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    size -= offset;
5217ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
522aaac6e206453574d0130f2ae8d743f630d0c0a42Dmitry Vyukov  DCHECK_EQ(addr % 8, 0);
523aaac6e206453574d0130f2ae8d743f630d0c0a42Dmitry Vyukov  // If a user passes some insane arguments (memset(0)),
524aaac6e206453574d0130f2ae8d743f630d0c0a42Dmitry Vyukov  // let it just crash as usual.
525aaac6e206453574d0130f2ae8d743f630d0c0a42Dmitry Vyukov  if (!IsAppMem(addr) || !IsAppMem(addr + size - 1))
526aaac6e206453574d0130f2ae8d743f630d0c0a42Dmitry Vyukov    return;
5277ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  (void)thr;
5287ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  (void)pc;
5297ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // Some programs mmap like hundreds of GBs but actually used a small part.
5307ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // So, it's better to report a false positive on the memory
5317ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // then to hang here senselessly.
5329c6c5a26ec1e49f379515d2403b8b206bf2755c3Dmitry Vyukov  const uptr kMaxResetSize = 4ull*1024*1024*1024;
5337ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (size > kMaxResetSize)
5347ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    size = kMaxResetSize;
53526af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov  size = (size + (kShadowCell - 1)) & ~(kShadowCell - 1);
5367ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  u64 *p = (u64*)MemToShadow(addr);
5377ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  CHECK(IsShadowMem((uptr)p));
5387ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  CHECK(IsShadowMem((uptr)(p + size * kShadowCnt / kShadowCell - 1)));
5397ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // FIXME: may overwrite a part outside the region
54026af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov  for (uptr i = 0; i < size * kShadowCnt / kShadowCell;) {
54126af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov    p[i++] = val;
54226af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov    for (uptr j = 1; j < kShadowCnt; j++)
54326af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov      p[i++] = 0;
54426af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov  }
5457ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
5467ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
5477ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid MemoryResetRange(ThreadState *thr, uptr pc, uptr addr, uptr size) {
5487ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  MemoryRangeSet(thr, pc, addr, size, 0);
5497ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
5507ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
5517ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid MemoryRangeFreed(ThreadState *thr, uptr pc, uptr addr, uptr size) {
5527ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  MemoryAccessRange(thr, pc, addr, size, true);
553069ce828e3057819ee34426496ea7080f7cc52f0Dmitry Vyukov  Shadow s(thr->fast_state);
554064c84731c1cf41dcd7195c9380170b9aa6887b6Dmitry Vyukov  s.ClearIgnoreBit();
555069ce828e3057819ee34426496ea7080f7cc52f0Dmitry Vyukov  s.MarkAsFreed();
556069ce828e3057819ee34426496ea7080f7cc52f0Dmitry Vyukov  s.SetWrite(true);
557069ce828e3057819ee34426496ea7080f7cc52f0Dmitry Vyukov  s.SetAddr0AndSizeLog(0, 3);
558069ce828e3057819ee34426496ea7080f7cc52f0Dmitry Vyukov  MemoryRangeSet(thr, pc, addr, size, s.raw());
5597ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
5607ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
56126af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukovvoid MemoryRangeImitateWrite(ThreadState *thr, uptr pc, uptr addr, uptr size) {
56226af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov  Shadow s(thr->fast_state);
563064c84731c1cf41dcd7195c9380170b9aa6887b6Dmitry Vyukov  s.ClearIgnoreBit();
56426af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov  s.SetWrite(true);
56526af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov  s.SetAddr0AndSizeLog(0, 3);
56626af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov  MemoryRangeSet(thr, pc, addr, size, s.raw());
56726af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov}
56826af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov
5696fa4cc3a81713a392b2f3e8e7d6ad411e4b3f421Dmitry VyukovALWAYS_INLINE
5707ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid FuncEntry(ThreadState *thr, uptr pc) {
5717ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  DCHECK_EQ(thr->in_rtl, 0);
5727ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  StatInc(thr, StatFuncEnter);
57325d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov  DPrintf2("#%d: FuncEntry %p\n", (int)thr->fast_state.tid(), (void*)pc);
5747ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  thr->fast_state.IncrementEpoch();
575385542a2e83a4f37de4232d6c72097c1b7d6d44bDmitry Vyukov  TraceAddEvent(thr, thr->fast_state, EventTypeFuncEnter, pc);
5767ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
5777ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // Shadow stack maintenance can be replaced with
5787ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // stack unwinding during trace switch (which presumably must be faster).
579769544eed418993abb8efcb4ea939ed5c93a5ba2Dmitry Vyukov  DCHECK_GE(thr->shadow_stack_pos, &thr->shadow_stack[0]);
58025d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov#ifndef TSAN_GO
581769544eed418993abb8efcb4ea939ed5c93a5ba2Dmitry Vyukov  DCHECK_LT(thr->shadow_stack_pos, &thr->shadow_stack[kShadowStackSize]);
58225d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov#else
58325d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov  if (thr->shadow_stack_pos == thr->shadow_stack_end) {
58425d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov    const int sz = thr->shadow_stack_end - thr->shadow_stack;
58525d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov    const int newsz = 2 * sz;
58625d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov    uptr *newstack = (uptr*)internal_alloc(MBlockShadowStack,
58725d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov        newsz * sizeof(uptr));
58825d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov    internal_memcpy(newstack, thr->shadow_stack, sz * sizeof(uptr));
58925d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov    internal_free(thr->shadow_stack);
59025d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov    thr->shadow_stack = newstack;
59125d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov    thr->shadow_stack_pos = newstack + sz;
59225d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov    thr->shadow_stack_end = newstack + newsz;
59325d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov  }
59425d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov#endif
5957ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  thr->shadow_stack_pos[0] = pc;
5967ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  thr->shadow_stack_pos++;
5977ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
5987ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
5996fa4cc3a81713a392b2f3e8e7d6ad411e4b3f421Dmitry VyukovALWAYS_INLINE
6007ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid FuncExit(ThreadState *thr) {
6017ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  DCHECK_EQ(thr->in_rtl, 0);
6027ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  StatInc(thr, StatFuncExit);
60325d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov  DPrintf2("#%d: FuncExit\n", (int)thr->fast_state.tid());
6047ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  thr->fast_state.IncrementEpoch();
605385542a2e83a4f37de4232d6c72097c1b7d6d44bDmitry Vyukov  TraceAddEvent(thr, thr->fast_state, EventTypeFuncExit, 0);
6067ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
607769544eed418993abb8efcb4ea939ed5c93a5ba2Dmitry Vyukov  DCHECK_GT(thr->shadow_stack_pos, &thr->shadow_stack[0]);
60825d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov#ifndef TSAN_GO
609769544eed418993abb8efcb4ea939ed5c93a5ba2Dmitry Vyukov  DCHECK_LT(thr->shadow_stack_pos, &thr->shadow_stack[kShadowStackSize]);
61025d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov#endif
6117ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  thr->shadow_stack_pos--;
6127ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
6137ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
6147ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid IgnoreCtl(ThreadState *thr, bool write, bool begin) {
6157ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  DPrintf("#%d: IgnoreCtl(%d, %d)\n", thr->tid, write, begin);
6167ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  thr->ignore_reads_and_writes += begin ? 1 : -1;
6177ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  CHECK_GE(thr->ignore_reads_and_writes, 0);
6187ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (thr->ignore_reads_and_writes)
6197ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    thr->fast_state.SetIgnoreBit();
6207ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  else
6217ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    thr->fast_state.ClearIgnoreBit();
6227ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
6237ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
624b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukovbool MD5Hash::operator==(const MD5Hash &other) const {
625b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov  return hash[0] == other.hash[0] && hash[1] == other.hash[1];
626b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov}
627b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov
6287ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#if TSAN_DEBUG
6297ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid build_consistency_debug() {}
6307ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#else
6317ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid build_consistency_release() {}
6327ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#endif
6337ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
6347ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#if TSAN_COLLECT_STATS
6357ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid build_consistency_stats() {}
6367ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#else
6377ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid build_consistency_nostats() {}
6387ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#endif
6397ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
6407ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#if TSAN_SHADOW_COUNT == 1
6417ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid build_consistency_shadow1() {}
6427ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#elif TSAN_SHADOW_COUNT == 2
6437ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid build_consistency_shadow2() {}
6447ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#elif TSAN_SHADOW_COUNT == 4
6457ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid build_consistency_shadow4() {}
6467ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#else
6477ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid build_consistency_shadow8() {}
6487ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#endif
6497ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
6507ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}  // namespace __tsan
6517ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
652b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#ifndef TSAN_GO
6537ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// Must be included in this file to make sure everything is inlined.
6547ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_interface_inl.h"
655b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#endif
656