tsan_rtl.cc revision 7ed46ff7af911da0dd2067734d1408c6986c6657
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"
26a38e40fde45acccb124f7419ecbe21ef6cfd306bDmitry Vyukov#include "tsan_symbolize.h"
277ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
28adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukovvolatile int __tsan_resumed = 0;
297ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
307ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyextern "C" void __tsan_resume() {
31adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov  __tsan_resumed = 1;
327ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
337ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
347ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanynamespace __tsan {
357ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
36b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#ifndef TSAN_GO
370a4c906dbc8f150657ddd4f19a7192b779f1d605Alexey SamsonovTHREADLOCAL char cur_thread_placeholder[sizeof(ThreadState)] ALIGNED(64);
38b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#endif
390a4c906dbc8f150657ddd4f19a7192b779f1d605Alexey Samsonovstatic char ctx_placeholder[sizeof(Context)] ALIGNED(64);
407ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
4122881ec8c8a3c01f9b993b186040444b0b5caa50Dmitry Vyukov// Can be overriden by a front-end.
427c984ca2fc88e2cd82b30c5b3ef361af2a1f2062Dmitry Vyukovbool CPP_WEAK OnFinalize(bool failed) {
4322881ec8c8a3c01f9b993b186040444b0b5caa50Dmitry Vyukov  return failed;
4422881ec8c8a3c01f9b993b186040444b0b5caa50Dmitry Vyukov}
4522881ec8c8a3c01f9b993b186040444b0b5caa50Dmitry Vyukov
467ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic Context *ctx;
477ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyContext *CTX() {
487ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return ctx;
497ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
507ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
512bbd8bec77c2fdb41c5f5b6cb0d83d22bc576650Alexey Samsonovstatic char thread_registry_placeholder[sizeof(ThreadRegistry)];
522bbd8bec77c2fdb41c5f5b6cb0d83d22bc576650Alexey Samsonov
532bbd8bec77c2fdb41c5f5b6cb0d83d22bc576650Alexey Samsonovstatic ThreadContextBase *CreateThreadContext(u32 tid) {
542bbd8bec77c2fdb41c5f5b6cb0d83d22bc576650Alexey Samsonov  // Map thread trace when context is created.
552bbd8bec77c2fdb41c5f5b6cb0d83d22bc576650Alexey Samsonov  MapThreadTrace(GetThreadTrace(tid), TraceSize() * sizeof(Event));
569743d74426ae43898e4da55e591b09be18f8aa6eDmitry Vyukov  MapThreadTrace(GetThreadTraceHeader(tid), sizeof(Trace));
579743d74426ae43898e4da55e591b09be18f8aa6eDmitry Vyukov  new(ThreadTrace(tid)) Trace();
589743d74426ae43898e4da55e591b09be18f8aa6eDmitry Vyukov  void *mem = internal_alloc(MBlockThreadContex, sizeof(ThreadContext));
592bbd8bec77c2fdb41c5f5b6cb0d83d22bc576650Alexey Samsonov  return new(mem) ThreadContext(tid);
602bbd8bec77c2fdb41c5f5b6cb0d83d22bc576650Alexey Samsonov}
612bbd8bec77c2fdb41c5f5b6cb0d83d22bc576650Alexey Samsonov
622bbd8bec77c2fdb41c5f5b6cb0d83d22bc576650Alexey Samsonov#ifndef TSAN_GO
632bbd8bec77c2fdb41c5f5b6cb0d83d22bc576650Alexey Samsonovstatic const u32 kThreadQuarantineSize = 16;
642bbd8bec77c2fdb41c5f5b6cb0d83d22bc576650Alexey Samsonov#else
652bbd8bec77c2fdb41c5f5b6cb0d83d22bc576650Alexey Samsonovstatic const u32 kThreadQuarantineSize = 64;
662bbd8bec77c2fdb41c5f5b6cb0d83d22bc576650Alexey Samsonov#endif
672bbd8bec77c2fdb41c5f5b6cb0d83d22bc576650Alexey Samsonov
687ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyContext::Context()
697ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  : initialized()
707ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  , report_mtx(MutexTypeReport, StatMtxReport)
717ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  , nreported()
727ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  , nmissed_expected()
732bbd8bec77c2fdb41c5f5b6cb0d83d22bc576650Alexey Samsonov  , thread_registry(new(thread_registry_placeholder) ThreadRegistry(
742bbd8bec77c2fdb41c5f5b6cb0d83d22bc576650Alexey Samsonov      CreateThreadContext, kMaxTid, kThreadQuarantineSize))
757ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  , racy_stacks(MBlockRacyStacks)
76158c6ac3bb46753db217f9c2c73485811a3a1890Dmitry Vyukov  , racy_addresses(MBlockRacyAddresses)
77158c6ac3bb46753db217f9c2c73485811a3a1890Dmitry Vyukov  , fired_suppressions(MBlockRacyAddresses) {
787ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
797ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
807ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// The objects are allocated in TLS, so one may rely on zero-initialization.
81ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry VyukovThreadState::ThreadState(Context *ctx, int tid, int unique_id, u64 epoch,
827ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany                         uptr stk_addr, uptr stk_size,
837ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany                         uptr tls_addr, uptr tls_size)
847ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  : fast_state(tid, epoch)
857ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // Do not touch these, rely on zero initialization,
867ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // they may be accessed before the ctor.
877ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // , fast_ignore_reads()
887ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // , fast_ignore_writes()
897ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // , in_rtl()
907ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  , shadow_stack_pos(&shadow_stack[0])
918b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukov#ifndef TSAN_GO
928b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukov  , jmp_bufs(MBlockJmpBuf)
938b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukov#endif
947ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  , tid(tid)
95ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry Vyukov  , unique_id(unique_id)
967ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  , stk_addr(stk_addr)
977ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  , stk_size(stk_size)
987ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  , tls_addr(tls_addr)
997ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  , tls_size(tls_size) {
1007ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
1017ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
102a38e40fde45acccb124f7419ecbe21ef6cfd306bDmitry Vyukovstatic void MemoryProfiler(Context *ctx, fd_t fd, int i) {
1034bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov  uptr n_threads;
1044bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov  uptr n_running_threads;
1054bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov  ctx->thread_registry->GetNumberOfThreads(&n_threads, &n_running_threads);
106a38e40fde45acccb124f7419ecbe21ef6cfd306bDmitry Vyukov  InternalScopedBuffer<char> buf(4096);
1074bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov  internal_snprintf(buf.data(), buf.size(), "%d: nthr=%d nlive=%d\n",
1084bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov      i, n_threads, n_running_threads);
1094bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov  internal_write(fd, buf.data(), internal_strlen(buf.data()));
1104bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov  WriteMemoryProfile(buf.data(), buf.size());
1114bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov  internal_write(fd, buf.data(), internal_strlen(buf.data()));
1124bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov}
1134bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov
1144bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukovstatic void BackgroundThread(void *arg) {
1154bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov  ScopedInRtl in_rtl;
116a38e40fde45acccb124f7419ecbe21ef6cfd306bDmitry Vyukov  Context *ctx = CTX();
117f63dde3594da0dba4c8039f0cb3a4196a76f1affDmitry Vyukov  const u64 kMs2Ns = 1000 * 1000;
1184bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov
1194bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov  fd_t mprof_fd = kInvalidFd;
1204bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov  if (flags()->profile_memory && flags()->profile_memory[0]) {
1214bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov    InternalScopedBuffer<char> filename(4096);
1224bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov    internal_snprintf(filename.data(), filename.size(), "%s.%d",
1234bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov        flags()->profile_memory, GetPid());
1244bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov    mprof_fd = OpenFile(filename.data(), true);
1254bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov    if (mprof_fd == kInvalidFd) {
1264bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov      Printf("ThreadSanitizer: failed to open memory profile file '%s'\n",
1274bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov          &filename[0]);
1284bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov    }
1294bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov  }
1304bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov
1314bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov  u64 last_flush = NanoTime();
13226127735454fddae3495794f38189d57dde6510fDmitry Vyukov  for (int i = 0; ; i++) {
1330969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov    SleepForSeconds(1);
1344bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov    u64 now = NanoTime();
13526127735454fddae3495794f38189d57dde6510fDmitry Vyukov
136a38e40fde45acccb124f7419ecbe21ef6cfd306bDmitry Vyukov    // Flush memory if requested.
1374bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov    if (flags()->flush_memory_ms) {
138f63dde3594da0dba4c8039f0cb3a4196a76f1affDmitry Vyukov      if (last_flush + flags()->flush_memory_ms * kMs2Ns < now) {
1394bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov        FlushShadowMemory();
1404bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov        last_flush = NanoTime();
1414bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov      }
1424bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov    }
1434bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov
144a38e40fde45acccb124f7419ecbe21ef6cfd306bDmitry Vyukov    // Write memory profile if requested.
1454bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov    if (mprof_fd != kInvalidFd)
146a38e40fde45acccb124f7419ecbe21ef6cfd306bDmitry Vyukov      MemoryProfiler(ctx, mprof_fd, i);
147a38e40fde45acccb124f7419ecbe21ef6cfd306bDmitry Vyukov
148a38e40fde45acccb124f7419ecbe21ef6cfd306bDmitry Vyukov#ifndef TSAN_GO
149f63dde3594da0dba4c8039f0cb3a4196a76f1affDmitry Vyukov    // Flush symbolizer cache if requested.
150f63dde3594da0dba4c8039f0cb3a4196a76f1affDmitry Vyukov    if (flags()->flush_symbolizer_ms > 0) {
151f63dde3594da0dba4c8039f0cb3a4196a76f1affDmitry Vyukov      u64 last = atomic_load(&ctx->last_symbolize_time_ns,
152f63dde3594da0dba4c8039f0cb3a4196a76f1affDmitry Vyukov                             memory_order_relaxed);
153f63dde3594da0dba4c8039f0cb3a4196a76f1affDmitry Vyukov      if (last != 0 && last + flags()->flush_symbolizer_ms * kMs2Ns < now) {
154f63dde3594da0dba4c8039f0cb3a4196a76f1affDmitry Vyukov        Lock l(&ctx->report_mtx);
1557ed46ff7af911da0dd2067734d1408c6986c6657Alexey Samsonov        SpinMutexLock l2(&CommonSanitizerReportMutex);
156f63dde3594da0dba4c8039f0cb3a4196a76f1affDmitry Vyukov        SymbolizeFlush();
157f63dde3594da0dba4c8039f0cb3a4196a76f1affDmitry Vyukov        atomic_store(&ctx->last_symbolize_time_ns, 0, memory_order_relaxed);
158f63dde3594da0dba4c8039f0cb3a4196a76f1affDmitry Vyukov      }
159a38e40fde45acccb124f7419ecbe21ef6cfd306bDmitry Vyukov    }
160a38e40fde45acccb124f7419ecbe21ef6cfd306bDmitry Vyukov#endif
16126127735454fddae3495794f38189d57dde6510fDmitry Vyukov  }
16226127735454fddae3495794f38189d57dde6510fDmitry Vyukov}
16326127735454fddae3495794f38189d57dde6510fDmitry Vyukov
1647ac33ac529ff93a57419f5ddf71b1fde68428577Dmitry Vyukovvoid DontNeedShadowFor(uptr addr, uptr size) {
1657ac33ac529ff93a57419f5ddf71b1fde68428577Dmitry Vyukov  uptr shadow_beg = MemToShadow(addr);
1667ac33ac529ff93a57419f5ddf71b1fde68428577Dmitry Vyukov  uptr shadow_end = MemToShadow(addr + size);
1677ac33ac529ff93a57419f5ddf71b1fde68428577Dmitry Vyukov  FlushUnneededShadowMemory(shadow_beg, shadow_end - shadow_beg);
1687ac33ac529ff93a57419f5ddf71b1fde68428577Dmitry Vyukov}
1697ac33ac529ff93a57419f5ddf71b1fde68428577Dmitry Vyukov
170a05fcc1e3e045097f2f1a20798cbe038bbb1d6a9Dmitry Vyukovvoid MapShadow(uptr addr, uptr size) {
1716b641c5e63be45a03f96346886d27c4b4135ddafDmitry Vyukov  MmapFixedNoReserve(MemToShadow(addr), size * kShadowMultiplier);
172a05fcc1e3e045097f2f1a20798cbe038bbb1d6a9Dmitry Vyukov}
173a05fcc1e3e045097f2f1a20798cbe038bbb1d6a9Dmitry Vyukov
1746535c31c66569df262791f0b56852c496977c977Dmitry Vyukovvoid MapThreadTrace(uptr addr, uptr size) {
175dae1251f196f9694d428a04f14987b06112ae52cDmitry Vyukov  DPrintf("#0: Mapping trace at %p-%p(0x%zx)\n", addr, addr + size, size);
1766535c31c66569df262791f0b56852c496977c977Dmitry Vyukov  CHECK_GE(addr, kTraceMemBegin);
1776535c31c66569df262791f0b56852c496977c977Dmitry Vyukov  CHECK_LE(addr + size, kTraceMemBegin + kTraceMemSize);
1786535c31c66569df262791f0b56852c496977c977Dmitry Vyukov  if (addr != (uptr)MmapFixedNoReserve(addr, size)) {
1796535c31c66569df262791f0b56852c496977c977Dmitry Vyukov    Printf("FATAL: ThreadSanitizer can not mmap thread trace\n");
1806535c31c66569df262791f0b56852c496977c977Dmitry Vyukov    Die();
1816535c31c66569df262791f0b56852c496977c977Dmitry Vyukov  }
1826535c31c66569df262791f0b56852c496977c977Dmitry Vyukov}
1836535c31c66569df262791f0b56852c496977c977Dmitry Vyukov
1847ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid Initialize(ThreadState *thr) {
1857ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // Thread safe because done before all threads exist.
1867ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  static bool is_initialized = false;
1877ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (is_initialized)
1887ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    return;
1897ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  is_initialized = true;
190859778a4e2dffa4024fa3e13b105fd62eca44b1cKostya Serebryany  SanitizerToolName = "ThreadSanitizer";
191591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonov  // Install tool-specific callbacks in sanitizer_common.
192591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonov  SetCheckFailedCallback(TsanCheckFailed);
193591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonov
1947ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  ScopedInRtl in_rtl;
195bbbb20b7212155ebc5b5b4ee1c68c987dcf30320Dmitry Vyukov#ifndef TSAN_GO
1962e87051d136db3150a3ca322d8862f92b0a684bbDmitry Vyukov  InitializeAllocator();
197bbbb20b7212155ebc5b5b4ee1c68c987dcf30320Dmitry Vyukov#endif
1987ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  InitializeInterceptors();
1997ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  const char *env = InitializePlatform();
2007ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  InitializeMutex();
2017ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  InitializeDynamicAnnotations();
2027ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  ctx = new(ctx_placeholder) Context;
203a05fcc1e3e045097f2f1a20798cbe038bbb1d6a9Dmitry Vyukov#ifndef TSAN_GO
2047ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  InitializeShadowMemory();
205a05fcc1e3e045097f2f1a20798cbe038bbb1d6a9Dmitry Vyukov#endif
2067ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  InitializeFlags(&ctx->flags, env);
207b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov  // Setup correct file descriptor for error reports.
208cec6068bbbbfb84285c0856c196c48170924e215Dmitry Vyukov  if (internal_strcmp(flags()->log_path, "stdout") == 0)
209cec6068bbbbfb84285c0856c196c48170924e215Dmitry Vyukov    __sanitizer_set_report_fd(kStdoutFd);
210cec6068bbbbfb84285c0856c196c48170924e215Dmitry Vyukov  else if (internal_strcmp(flags()->log_path, "stderr") == 0)
211cec6068bbbbfb84285c0856c196c48170924e215Dmitry Vyukov    __sanitizer_set_report_fd(kStderrFd);
212cec6068bbbbfb84285c0856c196c48170924e215Dmitry Vyukov  else
213cec6068bbbbfb84285c0856c196c48170924e215Dmitry Vyukov    __sanitizer_set_report_path(flags()->log_path);
2147ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  InitializeSuppressions();
21585a6dad26739fcd9742eae04b4a539e29889e937Dmitry Vyukov#ifndef TSAN_GO
21668bdcc4db8802c9a6f72d0e684a336ab92a3785bAlexey Samsonov  // Initialize external symbolizer before internal threads are started.
2178cc1f81b2cc1fa0d4cda4f4635d955aed04c09c8Alexey Samsonov  const char *external_symbolizer = flags()->external_symbolizer_path;
2188cc1f81b2cc1fa0d4cda4f4635d955aed04c09c8Alexey Samsonov  if (external_symbolizer != 0 && external_symbolizer[0] != '\0') {
21993b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov    if (!InitializeExternalSymbolizer(external_symbolizer)) {
22093b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov      Printf("Failed to start external symbolizer: '%s'\n",
22193b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov             external_symbolizer);
22293b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov      Die();
22393b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov    }
2248cc1f81b2cc1fa0d4cda4f4635d955aed04c09c8Alexey Samsonov  }
22585a6dad26739fcd9742eae04b4a539e29889e937Dmitry Vyukov#endif
2264bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov  internal_start_thread(&BackgroundThread, 0);
2278cc1f81b2cc1fa0d4cda4f4635d955aed04c09c8Alexey Samsonov
2287ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (ctx->flags.verbosity)
229b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov    Printf("***** Running under ThreadSanitizer v2 (pid %d) *****\n",
23067a64dd8259fdbd867633b27f54d584f435f1ce6Alexey Samsonov               GetPid());
2317ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
2327ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // Initialize thread 0.
2337ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int tid = ThreadCreate(thr, 0, 0, true);
2347ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  CHECK_EQ(tid, 0);
2357dccf3f92a867f917ad19f9a6b37bcf93e64b35bDmitry Vyukov  ThreadStart(thr, tid, GetPid());
2367ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  CHECK_EQ(thr->in_rtl, 1);
2377ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  ctx->initialized = true;
2387ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
239adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov  if (flags()->stop_on_start) {
240b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov    Printf("ThreadSanitizer is suspended at startup (pid %d)."
241adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov           " Call __tsan_resume().\n",
242adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov           GetPid());
243ba5e99668e3030cc5bab357a04271a1bdbac209cAlexey Samsonov    while (__tsan_resumed == 0) {}
2447ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
2457ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
2467ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
2477ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyint Finalize(ThreadState *thr) {
2487ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  ScopedInRtl in_rtl;
2497ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  Context *ctx = __tsan::ctx;
2507ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  bool failed = false;
2517ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
25254e0a9a391616bbd2a4f0fd2d01076291274cb98Dmitry Vyukov  if (flags()->atexit_sleep_ms > 0 && ThreadCount(thr) > 1)
25354e0a9a391616bbd2a4f0fd2d01076291274cb98Dmitry Vyukov    SleepForMillis(flags()->atexit_sleep_ms);
25454e0a9a391616bbd2a4f0fd2d01076291274cb98Dmitry Vyukov
255d0a51c02157e8293ea365ad0d429ef8e73d115deDmitry Vyukov  // Wait for pending reports.
256d0a51c02157e8293ea365ad0d429ef8e73d115deDmitry Vyukov  ctx->report_mtx.Lock();
2577ed46ff7af911da0dd2067734d1408c6986c6657Alexey Samsonov  CommonSanitizerReportMutex.Lock();
2587ed46ff7af911da0dd2067734d1408c6986c6657Alexey Samsonov  CommonSanitizerReportMutex.Unlock();
259d0a51c02157e8293ea365ad0d429ef8e73d115deDmitry Vyukov  ctx->report_mtx.Unlock();
260d0a51c02157e8293ea365ad0d429ef8e73d115deDmitry Vyukov
261bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov#ifndef TSAN_GO
262bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov  if (ctx->flags.verbosity)
263bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov    AllocatorPrintStats();
264bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov#endif
265bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov
2667ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  ThreadFinalize(thr);
2677ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
2687ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (ctx->nreported) {
2697ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    failed = true;
270b3b21231dd9dfeb34f5f302c879f2d11b6312080Dmitry Vyukov#ifndef TSAN_GO
271b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov    Printf("ThreadSanitizer: reported %d warnings\n", ctx->nreported);
272b3b21231dd9dfeb34f5f302c879f2d11b6312080Dmitry Vyukov#else
273b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov    Printf("Found %d data race(s)\n", ctx->nreported);
274b3b21231dd9dfeb34f5f302c879f2d11b6312080Dmitry Vyukov#endif
2757ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
2767ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
2777ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (ctx->nmissed_expected) {
2787ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    failed = true;
279b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov    Printf("ThreadSanitizer: missed %d expected races\n",
2807ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany        ctx->nmissed_expected);
2817ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
2827ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
283f754eb501d6bd163fff6747716b7703fe45be4b8Dmitry Vyukov  if (flags()->print_suppressions)
284f754eb501d6bd163fff6747716b7703fe45be4b8Dmitry Vyukov    PrintMatchedSuppressions();
2850fd908cf5a555483633e2d9703932bde18009682Dmitry Vyukov#ifndef TSAN_GO
2860fd908cf5a555483633e2d9703932bde18009682Dmitry Vyukov  if (flags()->print_benign)
2870fd908cf5a555483633e2d9703932bde18009682Dmitry Vyukov    PrintMatchedBenignRaces();
2880fd908cf5a555483633e2d9703932bde18009682Dmitry Vyukov#endif
289f754eb501d6bd163fff6747716b7703fe45be4b8Dmitry Vyukov
29022881ec8c8a3c01f9b993b186040444b0b5caa50Dmitry Vyukov  failed = OnFinalize(failed);
29122881ec8c8a3c01f9b993b186040444b0b5caa50Dmitry Vyukov
29208adb1815b4958df88f904b9780a055b0d387294Dmitry Vyukov  StatAggregate(ctx->stat, thr->stat);
2937ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  StatOutput(ctx->stat);
294b7b6b1cd9df0c954b1f890fcebf373db984923b3Dmitry Vyukov  return failed ? flags()->exitcode : 0;
2957ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
2967ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
2970ab628c61594eb80612e5389d9c33da0e0d70c66Dmitry Vyukov#ifndef TSAN_GO
298848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukovu32 CurrentStackId(ThreadState *thr, uptr pc) {
299848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov  if (thr->shadow_stack_pos == 0)  // May happen during bootstrap.
300848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov    return 0;
301848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov  if (pc) {
302848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov    thr->shadow_stack_pos[0] = pc;
303848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov    thr->shadow_stack_pos++;
304848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov  }
305848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov  u32 id = StackDepotPut(thr->shadow_stack,
306848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov                         thr->shadow_stack_pos - thr->shadow_stack);
307848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov  if (pc)
308848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov    thr->shadow_stack_pos--;
309848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov  return id;
310848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov}
3110ab628c61594eb80612e5389d9c33da0e0d70c66Dmitry Vyukov#endif
312848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov
313b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukovvoid TraceSwitch(ThreadState *thr) {
3149ad7c32720dfa1287f8cfd481e5d583435178caeDmitry Vyukov  thr->nomalloc++;
3157ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  ScopedInRtl in_rtl;
3169743d74426ae43898e4da55e591b09be18f8aa6eDmitry Vyukov  Trace *thr_trace = ThreadTrace(thr->tid);
3179743d74426ae43898e4da55e591b09be18f8aa6eDmitry Vyukov  Lock l(&thr_trace->mtx);
3180415ac00935795a70d87ae662ccad58ea0704537Dmitry Vyukov  unsigned trace = (thr->fast_state.epoch() / kTracePartSize) % TraceParts();
3199743d74426ae43898e4da55e591b09be18f8aa6eDmitry Vyukov  TraceHeader *hdr = &thr_trace->headers[trace];
3207ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  hdr->epoch0 = thr->fast_state.epoch();
3217ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  hdr->stack0.ObtainCurrent(thr, 0);
322ad9da372f962495b3487685232d09390be841b1cDmitry Vyukov  hdr->mset0 = thr->mset;
3239ad7c32720dfa1287f8cfd481e5d583435178caeDmitry Vyukov  thr->nomalloc--;
3247ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
3257ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
3269743d74426ae43898e4da55e591b09be18f8aa6eDmitry VyukovTrace *ThreadTrace(int tid) {
3279743d74426ae43898e4da55e591b09be18f8aa6eDmitry Vyukov  return (Trace*)GetThreadTraceHeader(tid);
3289743d74426ae43898e4da55e591b09be18f8aa6eDmitry Vyukov}
3299743d74426ae43898e4da55e591b09be18f8aa6eDmitry Vyukov
330385542a2e83a4f37de4232d6c72097c1b7d6d44bDmitry Vyukovuptr TraceTopPC(ThreadState *thr) {
331385542a2e83a4f37de4232d6c72097c1b7d6d44bDmitry Vyukov  Event *events = (Event*)GetThreadTrace(thr->tid);
332d698edc4f74a17048eef3342a9fa42b3ebba802aDmitry Vyukov  uptr pc = events[thr->fast_state.GetTracePos()];
333385542a2e83a4f37de4232d6c72097c1b7d6d44bDmitry Vyukov  return pc;
334385542a2e83a4f37de4232d6c72097c1b7d6d44bDmitry Vyukov}
335385542a2e83a4f37de4232d6c72097c1b7d6d44bDmitry Vyukov
336d698edc4f74a17048eef3342a9fa42b3ebba802aDmitry Vyukovuptr TraceSize() {
337d698edc4f74a17048eef3342a9fa42b3ebba802aDmitry Vyukov  return (uptr)(1ull << (kTracePartSizeBits + flags()->history_size + 1));
338d698edc4f74a17048eef3342a9fa42b3ebba802aDmitry Vyukov}
339d698edc4f74a17048eef3342a9fa42b3ebba802aDmitry Vyukov
3400415ac00935795a70d87ae662ccad58ea0704537Dmitry Vyukovuptr TraceParts() {
3410415ac00935795a70d87ae662ccad58ea0704537Dmitry Vyukov  return TraceSize() / kTracePartSize;
3420415ac00935795a70d87ae662ccad58ea0704537Dmitry Vyukov}
3430415ac00935795a70d87ae662ccad58ea0704537Dmitry Vyukov
344b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#ifndef TSAN_GO
3457ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyextern "C" void __tsan_trace_switch() {
3467ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TraceSwitch(cur_thread());
3477ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
3487ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
3497ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyextern "C" void __tsan_report_race() {
3507ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  ReportRace(cur_thread());
3517ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
352b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#endif
3537ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
3547ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyALWAYS_INLINE
35543c36e4b055f348d6076e6da44f9cd3e4399568fTimur IskhodzhanovShadow LoadShadow(u64 *p) {
3567ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  u64 raw = atomic_load((atomic_uint64_t*)p, memory_order_relaxed);
3577ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return Shadow(raw);
3587ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
3597ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
3607ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyALWAYS_INLINE
36143c36e4b055f348d6076e6da44f9cd3e4399568fTimur Iskhodzhanovvoid StoreShadow(u64 *sp, u64 s) {
3627ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  atomic_store((atomic_uint64_t*)sp, s, memory_order_relaxed);
3637ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
3647ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
3657ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyALWAYS_INLINE
36643c36e4b055f348d6076e6da44f9cd3e4399568fTimur Iskhodzhanovvoid StoreIfNotYetStored(u64 *sp, u64 *s) {
3677ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  StoreShadow(sp, *s);
3687ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  *s = 0;
3697ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
3707ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
3717ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic inline void HandleRace(ThreadState *thr, u64 *shadow_mem,
3727ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany                              Shadow cur, Shadow old) {
3737ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  thr->racy_state[0] = cur.raw();
3747ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  thr->racy_state[1] = old.raw();
3757ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  thr->racy_shadow_addr = shadow_mem;
376b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#ifndef TSAN_GO
3777ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  HACKY_CALL(__tsan_report_race);
378b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#else
379b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov  ReportRace(thr);
380b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#endif
3817ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
3827ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
3837ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic inline bool OldIsInSameSynchEpoch(Shadow old, ThreadState *thr) {
3847ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return old.epoch() >= thr->fast_synch_epoch;
3857ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
3867ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
3877ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic inline bool HappensBefore(Shadow old, ThreadState *thr) {
388c8f0a00ede42f83ac79ff63c347ca8ddcda77155Dmitry Vyukov  return thr->clock.get(old.TidWithIgnore()) >= old.epoch();
3897ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
3907ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
391d475aa8578f4a1955cdb3e3159eda8b229f8c021Kostya SerebryanyALWAYS_INLINE USED
3927ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid MemoryAccessImpl(ThreadState *thr, uptr addr,
393334553ec45d8982df45a6f5e656e068142ecde3fDmitry Vyukov    int kAccessSizeLog, bool kAccessIsWrite, bool kIsAtomic,
3947ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    u64 *shadow_mem, Shadow cur) {
3957ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  StatInc(thr, StatMop);
3967ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  StatInc(thr, kAccessIsWrite ? StatMopWrite : StatMopRead);
3977ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  StatInc(thr, (StatType)(StatMop1 + kAccessSizeLog));
3987ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
3997ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // This potentially can live in an MMX/SSE scratch register.
4007ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // The required intrinsics are:
4017ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // __m128i _mm_move_epi64(__m128i*);
4027ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // _mm_storel_epi64(u64*, __m128i);
4037ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  u64 store_word = cur.raw();
4047ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
4057ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // scan all the shadow values and dispatch to 4 categories:
4067ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // same, replace, candidate and race (see comments below).
4077ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // we consider only 3 cases regarding access sizes:
4087ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // equal, intersect and not intersect. initially I considered
4097ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // larger and smaller as well, it allowed to replace some
4107ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // 'candidates' with 'same' or 'replace', but I think
4117ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // it's just not worth it (performance- and complexity-wise).
4127ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
413286c914d37d28df611ae083cac40148cf2622ee7Dmitry Vyukov  Shadow old(0);
4147ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (kShadowCnt == 1) {
4157ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    int idx = 0;
4167ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h"
4177ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  } else if (kShadowCnt == 2) {
4187ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    int idx = 0;
4197ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h"
4207ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    idx = 1;
4217ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h"
4227ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  } else if (kShadowCnt == 4) {
4237ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    int idx = 0;
4247ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h"
4257ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    idx = 1;
4267ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h"
4277ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    idx = 2;
4287ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h"
4297ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    idx = 3;
4307ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h"
4317ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  } else if (kShadowCnt == 8) {
4327ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    int idx = 0;
4337ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h"
4347ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    idx = 1;
4357ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h"
4367ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    idx = 2;
4377ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h"
4387ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    idx = 3;
4397ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h"
4407ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    idx = 4;
4417ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h"
4427ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    idx = 5;
4437ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h"
4447ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    idx = 6;
4457ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h"
4467ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    idx = 7;
4477ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h"
4487ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  } else {
4497ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    CHECK(false);
4507ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
4517ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
4527ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // we did not find any races and had already stored
4537ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // the current access info, so we are done
4547ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (LIKELY(store_word == 0))
4557ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    return;
4567ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // choose a random candidate slot and replace it
4577ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  StoreShadow(shadow_mem + (cur.epoch() % kShadowCnt), store_word);
4587ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  StatInc(thr, StatShadowReplace);
4597ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return;
4607ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany RACE:
4617ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  HandleRace(thr, shadow_mem, cur, old);
4627ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return;
4637ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
4647ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
465d475aa8578f4a1955cdb3e3159eda8b229f8c021Kostya SerebryanyALWAYS_INLINE USED
4667ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid MemoryAccess(ThreadState *thr, uptr pc, uptr addr,
467334553ec45d8982df45a6f5e656e068142ecde3fDmitry Vyukov    int kAccessSizeLog, bool kAccessIsWrite, bool kIsAtomic) {
4687ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  u64 *shadow_mem = (u64*)MemToShadow(addr);
46968230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov  DPrintf2("#%d: MemoryAccess: @%p %p size=%d"
470e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov      " is_write=%d shadow_mem=%p {%zx, %zx, %zx, %zx}\n",
4717ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany      (int)thr->fast_state.tid(), (void*)pc, (void*)addr,
4727ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany      (int)(1 << kAccessSizeLog), kAccessIsWrite, shadow_mem,
473e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov      (uptr)shadow_mem[0], (uptr)shadow_mem[1],
474e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov      (uptr)shadow_mem[2], (uptr)shadow_mem[3]);
4757ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#if TSAN_DEBUG
4767ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (!IsAppMem(addr)) {
477b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov    Printf("Access to non app mem %zx\n", addr);
4787ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    DCHECK(IsAppMem(addr));
4797ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
4807ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (!IsShadowMem((uptr)shadow_mem)) {
481b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov    Printf("Bad shadow addr %p (%zx)\n", shadow_mem, addr);
4827ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    DCHECK(IsShadowMem((uptr)shadow_mem));
4837ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
4847ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#endif
4857ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
48682dbc5195ceedba0e1a9aab92d436614cc4b7ff9Dmitry Vyukov  if (*shadow_mem == kShadowRodata) {
48782dbc5195ceedba0e1a9aab92d436614cc4b7ff9Dmitry Vyukov    // Access to .rodata section, no races here.
48882dbc5195ceedba0e1a9aab92d436614cc4b7ff9Dmitry Vyukov    // Measurements show that it can be 10-20% of all memory accesses.
48982dbc5195ceedba0e1a9aab92d436614cc4b7ff9Dmitry Vyukov    StatInc(thr, StatMop);
49082dbc5195ceedba0e1a9aab92d436614cc4b7ff9Dmitry Vyukov    StatInc(thr, kAccessIsWrite ? StatMopWrite : StatMopRead);
49182dbc5195ceedba0e1a9aab92d436614cc4b7ff9Dmitry Vyukov    StatInc(thr, (StatType)(StatMop1 + kAccessSizeLog));
49282dbc5195ceedba0e1a9aab92d436614cc4b7ff9Dmitry Vyukov    StatInc(thr, StatMopRodata);
49382dbc5195ceedba0e1a9aab92d436614cc4b7ff9Dmitry Vyukov    return;
49482dbc5195ceedba0e1a9aab92d436614cc4b7ff9Dmitry Vyukov  }
49582dbc5195ceedba0e1a9aab92d436614cc4b7ff9Dmitry Vyukov
4967ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  FastState fast_state = thr->fast_state;
4977ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (fast_state.GetIgnoreBit())
4987ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    return;
4997ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  fast_state.IncrementEpoch();
5007ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  thr->fast_state = fast_state;
5017ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  Shadow cur(fast_state);
5027ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  cur.SetAddr0AndSizeLog(addr & 7, kAccessSizeLog);
5037ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  cur.SetWrite(kAccessIsWrite);
504334553ec45d8982df45a6f5e656e068142ecde3fDmitry Vyukov  cur.SetAtomic(kIsAtomic);
5057ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
5067ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // We must not store to the trace if we do not store to the shadow.
5077ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // That is, this call must be moved somewhere below.
508385542a2e83a4f37de4232d6c72097c1b7d6d44bDmitry Vyukov  TraceAddEvent(thr, fast_state, EventTypeMop, pc);
5097ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
510334553ec45d8982df45a6f5e656e068142ecde3fDmitry Vyukov  MemoryAccessImpl(thr, addr, kAccessSizeLog, kAccessIsWrite, kIsAtomic,
5117ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany      shadow_mem, cur);
5127ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
5137ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
5147ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic void MemoryRangeSet(ThreadState *thr, uptr pc, uptr addr, uptr size,
5157ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany                           u64 val) {
51674172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov  (void)thr;
51774172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov  (void)pc;
5187ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (size == 0)
5197ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    return;
5207ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // FIXME: fix me.
5217ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  uptr offset = addr % kShadowCell;
5227ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (offset) {
5237ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    offset = kShadowCell - offset;
5247ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    if (size <= offset)
5257ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany      return;
5267ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    addr += offset;
5277ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    size -= offset;
5287ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
529aaac6e206453574d0130f2ae8d743f630d0c0a42Dmitry Vyukov  DCHECK_EQ(addr % 8, 0);
530aaac6e206453574d0130f2ae8d743f630d0c0a42Dmitry Vyukov  // If a user passes some insane arguments (memset(0)),
531aaac6e206453574d0130f2ae8d743f630d0c0a42Dmitry Vyukov  // let it just crash as usual.
532aaac6e206453574d0130f2ae8d743f630d0c0a42Dmitry Vyukov  if (!IsAppMem(addr) || !IsAppMem(addr + size - 1))
533aaac6e206453574d0130f2ae8d743f630d0c0a42Dmitry Vyukov    return;
53474172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov  // Don't want to touch lots of shadow memory.
53574172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov  // If a program maps 10MB stack, there is no need reset the whole range.
53626af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov  size = (size + (kShadowCell - 1)) & ~(kShadowCell - 1);
53774172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov  if (size < 64*1024) {
53874172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov    u64 *p = (u64*)MemToShadow(addr);
53974172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov    CHECK(IsShadowMem((uptr)p));
54074172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov    CHECK(IsShadowMem((uptr)(p + size * kShadowCnt / kShadowCell - 1)));
54174172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov    // FIXME: may overwrite a part outside the region
54274172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov    for (uptr i = 0; i < size / kShadowCell * kShadowCnt;) {
54374172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov      p[i++] = val;
54474172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov      for (uptr j = 1; j < kShadowCnt; j++)
54574172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov        p[i++] = 0;
54674172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov    }
54774172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov  } else {
54874172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov    // The region is big, reset only beginning and end.
54974172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov    const uptr kPageSize = 4096;
55074172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov    u64 *begin = (u64*)MemToShadow(addr);
55174172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov    u64 *end = begin + size / kShadowCell * kShadowCnt;
55274172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov    u64 *p = begin;
55374172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov    // Set at least first kPageSize/2 to page boundary.
55474172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov    while ((p < begin + kPageSize / kShadowSize / 2) || ((uptr)p % kPageSize)) {
55574172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov      *p++ = val;
55674172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov      for (uptr j = 1; j < kShadowCnt; j++)
55774172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov        *p++ = 0;
55874172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov    }
55974172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov    // Reset middle part.
56074172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov    u64 *p1 = p;
56174172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov    p = RoundDown(end, kPageSize);
56274172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov    UnmapOrDie((void*)p1, (uptr)p - (uptr)p1);
56374172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov    MmapFixedNoReserve((uptr)p1, (uptr)p - (uptr)p1);
56474172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov    // Set the ending.
56574172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov    while (p < end) {
56674172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov      *p++ = val;
56774172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov      for (uptr j = 1; j < kShadowCnt; j++)
56874172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov        *p++ = 0;
56974172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov    }
57026af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov  }
5717ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
5727ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
5737ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid MemoryResetRange(ThreadState *thr, uptr pc, uptr addr, uptr size) {
5747ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  MemoryRangeSet(thr, pc, addr, size, 0);
5757ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
5767ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
5777ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid MemoryRangeFreed(ThreadState *thr, uptr pc, uptr addr, uptr size) {
57874172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov  // Processing more than 1k (4k of shadow) is expensive,
57974172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov  // can cause excessive memory consumption (user does not necessary touch
58074172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov  // the whole range) and most likely unnecessary.
58174172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov  if (size > 1024)
58274172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov    size = 1024;
5833285866e45a8521c56ba6209daf3c9f91f844fd3Dmitry Vyukov  CHECK_EQ(thr->is_freeing, false);
5843285866e45a8521c56ba6209daf3c9f91f844fd3Dmitry Vyukov  thr->is_freeing = true;
5857ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  MemoryAccessRange(thr, pc, addr, size, true);
5863285866e45a8521c56ba6209daf3c9f91f844fd3Dmitry Vyukov  thr->is_freeing = false;
587069ce828e3057819ee34426496ea7080f7cc52f0Dmitry Vyukov  Shadow s(thr->fast_state);
588064c84731c1cf41dcd7195c9380170b9aa6887b6Dmitry Vyukov  s.ClearIgnoreBit();
589069ce828e3057819ee34426496ea7080f7cc52f0Dmitry Vyukov  s.MarkAsFreed();
590069ce828e3057819ee34426496ea7080f7cc52f0Dmitry Vyukov  s.SetWrite(true);
591069ce828e3057819ee34426496ea7080f7cc52f0Dmitry Vyukov  s.SetAddr0AndSizeLog(0, 3);
592069ce828e3057819ee34426496ea7080f7cc52f0Dmitry Vyukov  MemoryRangeSet(thr, pc, addr, size, s.raw());
5937ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
5947ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
59526af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukovvoid MemoryRangeImitateWrite(ThreadState *thr, uptr pc, uptr addr, uptr size) {
59626af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov  Shadow s(thr->fast_state);
597064c84731c1cf41dcd7195c9380170b9aa6887b6Dmitry Vyukov  s.ClearIgnoreBit();
59826af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov  s.SetWrite(true);
59926af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov  s.SetAddr0AndSizeLog(0, 3);
60026af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov  MemoryRangeSet(thr, pc, addr, size, s.raw());
60126af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov}
60226af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov
603d475aa8578f4a1955cdb3e3159eda8b229f8c021Kostya SerebryanyALWAYS_INLINE USED
6047ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid FuncEntry(ThreadState *thr, uptr pc) {
6057ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  DCHECK_EQ(thr->in_rtl, 0);
6067ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  StatInc(thr, StatFuncEnter);
60725d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov  DPrintf2("#%d: FuncEntry %p\n", (int)thr->fast_state.tid(), (void*)pc);
6087ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  thr->fast_state.IncrementEpoch();
609385542a2e83a4f37de4232d6c72097c1b7d6d44bDmitry Vyukov  TraceAddEvent(thr, thr->fast_state, EventTypeFuncEnter, pc);
6107ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
6117ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // Shadow stack maintenance can be replaced with
6127ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // stack unwinding during trace switch (which presumably must be faster).
613769544eed418993abb8efcb4ea939ed5c93a5ba2Dmitry Vyukov  DCHECK_GE(thr->shadow_stack_pos, &thr->shadow_stack[0]);
61425d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov#ifndef TSAN_GO
615769544eed418993abb8efcb4ea939ed5c93a5ba2Dmitry Vyukov  DCHECK_LT(thr->shadow_stack_pos, &thr->shadow_stack[kShadowStackSize]);
61625d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov#else
61725d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov  if (thr->shadow_stack_pos == thr->shadow_stack_end) {
61825d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov    const int sz = thr->shadow_stack_end - thr->shadow_stack;
61925d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov    const int newsz = 2 * sz;
62025d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov    uptr *newstack = (uptr*)internal_alloc(MBlockShadowStack,
62125d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov        newsz * sizeof(uptr));
62225d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov    internal_memcpy(newstack, thr->shadow_stack, sz * sizeof(uptr));
62325d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov    internal_free(thr->shadow_stack);
62425d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov    thr->shadow_stack = newstack;
62525d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov    thr->shadow_stack_pos = newstack + sz;
62625d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov    thr->shadow_stack_end = newstack + newsz;
62725d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov  }
62825d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov#endif
6297ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  thr->shadow_stack_pos[0] = pc;
6307ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  thr->shadow_stack_pos++;
6317ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
6327ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
633d475aa8578f4a1955cdb3e3159eda8b229f8c021Kostya SerebryanyALWAYS_INLINE USED
6347ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid FuncExit(ThreadState *thr) {
6357ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  DCHECK_EQ(thr->in_rtl, 0);
6367ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  StatInc(thr, StatFuncExit);
63725d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov  DPrintf2("#%d: FuncExit\n", (int)thr->fast_state.tid());
6387ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  thr->fast_state.IncrementEpoch();
639385542a2e83a4f37de4232d6c72097c1b7d6d44bDmitry Vyukov  TraceAddEvent(thr, thr->fast_state, EventTypeFuncExit, 0);
6407ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
641769544eed418993abb8efcb4ea939ed5c93a5ba2Dmitry Vyukov  DCHECK_GT(thr->shadow_stack_pos, &thr->shadow_stack[0]);
64225d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov#ifndef TSAN_GO
643769544eed418993abb8efcb4ea939ed5c93a5ba2Dmitry Vyukov  DCHECK_LT(thr->shadow_stack_pos, &thr->shadow_stack[kShadowStackSize]);
64425d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov#endif
6457ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  thr->shadow_stack_pos--;
6467ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
6477ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
6487ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid IgnoreCtl(ThreadState *thr, bool write, bool begin) {
6497ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  DPrintf("#%d: IgnoreCtl(%d, %d)\n", thr->tid, write, begin);
6507ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  thr->ignore_reads_and_writes += begin ? 1 : -1;
6517ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  CHECK_GE(thr->ignore_reads_and_writes, 0);
6527ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (thr->ignore_reads_and_writes)
6537ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    thr->fast_state.SetIgnoreBit();
6547ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  else
6557ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    thr->fast_state.ClearIgnoreBit();
6567ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
6577ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
658b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukovbool MD5Hash::operator==(const MD5Hash &other) const {
659b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov  return hash[0] == other.hash[0] && hash[1] == other.hash[1];
660b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov}
661b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov
6627ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#if TSAN_DEBUG
6637ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid build_consistency_debug() {}
6647ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#else
6657ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid build_consistency_release() {}
6667ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#endif
6677ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
6687ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#if TSAN_COLLECT_STATS
6697ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid build_consistency_stats() {}
6707ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#else
6717ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid build_consistency_nostats() {}
6727ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#endif
6737ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
6747ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#if TSAN_SHADOW_COUNT == 1
6757ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid build_consistency_shadow1() {}
6767ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#elif TSAN_SHADOW_COUNT == 2
6777ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid build_consistency_shadow2() {}
6787ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#elif TSAN_SHADOW_COUNT == 4
6797ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid build_consistency_shadow4() {}
6807ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#else
6817ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid build_consistency_shadow8() {}
6827ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#endif
6837ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
6847ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}  // namespace __tsan
6857ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
686b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#ifndef TSAN_GO
6877ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// Must be included in this file to make sure everything is inlined.
6887ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_interface_inl.h"
689b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#endif
690