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"
27cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar#include "ubsan/ubsan_init.h"
287ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
296a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines#ifdef __SSE3__
306a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines// <emmintrin.h> transitively includes <stdlib.h>,
316a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines// and it's prohibited to include std headers into tsan runtime.
326a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines// So we do this dirty trick.
336a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines#define _MM_MALLOC_H_INCLUDED
346a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines#define __MM_MALLOC_H
356a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines#include <emmintrin.h>
366a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hinestypedef __m128i m128;
376a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines#endif
386a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines
39adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukovvolatile int __tsan_resumed = 0;
407ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
417ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyextern "C" void __tsan_resume() {
42adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov  __tsan_resumed = 1;
437ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
447ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
457ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanynamespace __tsan {
467ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
473d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar#if !defined(SANITIZER_GO) && !SANITIZER_MAC
480a4c906dbc8f150657ddd4f19a7192b779f1d605Alexey SamsonovTHREADLOCAL char cur_thread_placeholder[sizeof(ThreadState)] ALIGNED(64);
49b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#endif
500a4c906dbc8f150657ddd4f19a7192b779f1d605Alexey Samsonovstatic char ctx_placeholder[sizeof(Context)] ALIGNED(64);
512d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesContext *ctx;
527ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
5322881ec8c8a3c01f9b993b186040444b0b5caa50Dmitry Vyukov// Can be overriden by a front-end.
546a135be19fa0cc594fd61f9caf3c0be2b7f1466eDmitry Vyukov#ifdef TSAN_EXTERNAL_HOOKS
556a135be19fa0cc594fd61f9caf3c0be2b7f1466eDmitry Vyukovbool OnFinalize(bool failed);
562d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid OnInitialize();
576a135be19fa0cc594fd61f9caf3c0be2b7f1466eDmitry Vyukov#else
583d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga NainarSANITIZER_WEAK_CXX_DEFAULT_IMPL
593d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainarbool OnFinalize(bool failed) {
6022881ec8c8a3c01f9b993b186040444b0b5caa50Dmitry Vyukov  return failed;
6122881ec8c8a3c01f9b993b186040444b0b5caa50Dmitry Vyukov}
623d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga NainarSANITIZER_WEAK_CXX_DEFAULT_IMPL
633d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainarvoid OnInitialize() {}
646a135be19fa0cc594fd61f9caf3c0be2b7f1466eDmitry Vyukov#endif
6522881ec8c8a3c01f9b993b186040444b0b5caa50Dmitry Vyukov
662bbd8bec77c2fdb41c5f5b6cb0d83d22bc576650Alexey Samsonovstatic char thread_registry_placeholder[sizeof(ThreadRegistry)];
672bbd8bec77c2fdb41c5f5b6cb0d83d22bc576650Alexey Samsonov
682bbd8bec77c2fdb41c5f5b6cb0d83d22bc576650Alexey Samsonovstatic ThreadContextBase *CreateThreadContext(u32 tid) {
692bbd8bec77c2fdb41c5f5b6cb0d83d22bc576650Alexey Samsonov  // Map thread trace when context is created.
70cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  char name[50];
71cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  internal_snprintf(name, sizeof(name), "trace %u", tid);
72cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  MapThreadTrace(GetThreadTrace(tid), TraceSize() * sizeof(Event), name);
7386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  const uptr hdr = GetThreadTraceHeader(tid);
74cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  internal_snprintf(name, sizeof(name), "trace header %u", tid);
75cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  MapThreadTrace(hdr, sizeof(Trace), name);
7686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  new((void*)hdr) Trace();
7786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  // We are going to use only a small part of the trace with the default
7886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  // value of history_size. However, the constructor writes to the whole trace.
7986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  // Unmap the unused part.
8086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  uptr hdr_end = hdr + sizeof(Trace);
8186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  hdr_end -= sizeof(TraceHeader) * (kTraceParts - TraceParts());
8286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  hdr_end = RoundUp(hdr_end, GetPageSizeCached());
8386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  if (hdr_end < hdr + sizeof(Trace))
8486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    UnmapOrDie((void*)hdr_end, hdr + sizeof(Trace) - hdr_end);
859743d74426ae43898e4da55e591b09be18f8aa6eDmitry Vyukov  void *mem = internal_alloc(MBlockThreadContex, sizeof(ThreadContext));
862bbd8bec77c2fdb41c5f5b6cb0d83d22bc576650Alexey Samsonov  return new(mem) ThreadContext(tid);
872bbd8bec77c2fdb41c5f5b6cb0d83d22bc576650Alexey Samsonov}
882bbd8bec77c2fdb41c5f5b6cb0d83d22bc576650Alexey Samsonov
8986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#ifndef SANITIZER_GO
902bbd8bec77c2fdb41c5f5b6cb0d83d22bc576650Alexey Samsonovstatic const u32 kThreadQuarantineSize = 16;
912bbd8bec77c2fdb41c5f5b6cb0d83d22bc576650Alexey Samsonov#else
922bbd8bec77c2fdb41c5f5b6cb0d83d22bc576650Alexey Samsonovstatic const u32 kThreadQuarantineSize = 64;
932bbd8bec77c2fdb41c5f5b6cb0d83d22bc576650Alexey Samsonov#endif
942bbd8bec77c2fdb41c5f5b6cb0d83d22bc576650Alexey Samsonov
957ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyContext::Context()
967ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  : initialized()
977ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  , report_mtx(MutexTypeReport, StatMtxReport)
987ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  , nreported()
997ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  , nmissed_expected()
1002bbd8bec77c2fdb41c5f5b6cb0d83d22bc576650Alexey Samsonov  , thread_registry(new(thread_registry_placeholder) ThreadRegistry(
1012d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      CreateThreadContext, kMaxTid, kThreadQuarantineSize, kMaxTidReuse))
1023d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar  , racy_mtx(MutexTypeRacy, StatMtxRacy)
1037ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  , racy_stacks(MBlockRacyStacks)
104158c6ac3bb46753db217f9c2c73485811a3a1890Dmitry Vyukov  , racy_addresses(MBlockRacyAddresses)
1053d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar  , fired_suppressions_mtx(MutexTypeFired, StatMtxFired)
1060a05e5fa28a7424f8146549057c53b4590f3a251Alexey Samsonov  , fired_suppressions(8) {
1077ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
1087ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
1097ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// The objects are allocated in TLS, so one may rely on zero-initialization.
110ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry VyukovThreadState::ThreadState(Context *ctx, int tid, int unique_id, u64 epoch,
1112d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                         unsigned reuse_count,
1127ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany                         uptr stk_addr, uptr stk_size,
1137ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany                         uptr tls_addr, uptr tls_size)
1147ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  : fast_state(tid, epoch)
1157ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // Do not touch these, rely on zero initialization,
1167ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // they may be accessed before the ctor.
117dc563c0efbba5aec49b20a4d74e020feb75d7e8aDmitry Vyukov  // , ignore_reads_and_writes()
1182d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  // , ignore_interceptors()
1192d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  , clock(tid, reuse_count)
12086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#ifndef SANITIZER_GO
1218b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukov  , jmp_bufs(MBlockJmpBuf)
1228b30c254a63a7421dd81d13dee086a54c4ca134bDmitry Vyukov#endif
1237ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  , tid(tid)
124ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry Vyukov  , unique_id(unique_id)
1257ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  , stk_addr(stk_addr)
1267ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  , stk_size(stk_size)
1277ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  , tls_addr(tls_addr)
1282d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  , tls_size(tls_size)
12986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#ifndef SANITIZER_GO
1302d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  , last_sleep_clock(tid)
1312d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
1322d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines{
1337ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
1347ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
13586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#ifndef SANITIZER_GO
136a38e40fde45acccb124f7419ecbe21ef6cfd306bDmitry Vyukovstatic void MemoryProfiler(Context *ctx, fd_t fd, int i) {
1374bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov  uptr n_threads;
1384bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov  uptr n_running_threads;
1394bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov  ctx->thread_registry->GetNumberOfThreads(&n_threads, &n_running_threads);
140a38e40fde45acccb124f7419ecbe21ef6cfd306bDmitry Vyukov  InternalScopedBuffer<char> buf(4096);
1416a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  WriteMemoryProfile(buf.data(), buf.size(), n_threads, n_running_threads);
142259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar  WriteToFile(fd, buf.data(), internal_strlen(buf.data()));
1434bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov}
1444bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov
1454bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukovstatic void BackgroundThread(void *arg) {
1462d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  // This is a non-initialized non-user thread, nothing to see here.
1472d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  // We don't use ScopedIgnoreInterceptors, because we want ignores to be
1482d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  // enabled even when the thread function exits (e.g. during pthread thread
1492d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  // shutdown code).
1502d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  cur_thread()->ignore_interceptors++;
151f63dde3594da0dba4c8039f0cb3a4196a76f1affDmitry Vyukov  const u64 kMs2Ns = 1000 * 1000;
1524bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov
1534bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov  fd_t mprof_fd = kInvalidFd;
1544bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov  if (flags()->profile_memory && flags()->profile_memory[0]) {
1556a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines    if (internal_strcmp(flags()->profile_memory, "stdout") == 0) {
1566a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines      mprof_fd = 1;
1576a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines    } else if (internal_strcmp(flags()->profile_memory, "stderr") == 0) {
1586a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines      mprof_fd = 2;
1599578a3ecfc35a264ede1135033398e2a77a6cad6Peter Collingbourne    } else {
16086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      InternalScopedString filename(kMaxPathLength);
16186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      filename.append("%s.%d", flags()->profile_memory, (int)internal_getpid());
162259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar      fd_t fd = OpenFile(filename.data(), WrOnly);
163259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar      if (fd == kInvalidFd) {
1646a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines        Printf("ThreadSanitizer: failed to open memory profile file '%s'\n",
1656a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines            &filename[0]);
1666a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines      } else {
167259f7063e3e4c4b94dded1e90ab0a943d0fa737bPirama Arumuga Nainar        mprof_fd = fd;
1686a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines      }
1694bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov    }
1704bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov  }
1714bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov
1724bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov  u64 last_flush = NanoTime();
17392b54796149a8b5995fa49c43f43b709b83c5644Dmitry Vyukov  uptr last_rss = 0;
1742d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  for (int i = 0;
1752d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      atomic_load(&ctx->stop_background_thread, memory_order_relaxed) == 0;
1762d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      i++) {
1772d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    SleepForMillis(100);
1784bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov    u64 now = NanoTime();
17926127735454fddae3495794f38189d57dde6510fDmitry Vyukov
180a38e40fde45acccb124f7419ecbe21ef6cfd306bDmitry Vyukov    // Flush memory if requested.
18192b54796149a8b5995fa49c43f43b709b83c5644Dmitry Vyukov    if (flags()->flush_memory_ms > 0) {
182f63dde3594da0dba4c8039f0cb3a4196a76f1affDmitry Vyukov      if (last_flush + flags()->flush_memory_ms * kMs2Ns < now) {
1836d1862363c88c183b0ed7740fca876342cf0474bStephen Hines        VPrintf(1, "ThreadSanitizer: periodic memory flush\n");
1844bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov        FlushShadowMemory();
1854bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov        last_flush = NanoTime();
1864bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov      }
1874bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov    }
1886a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines    // GetRSS can be expensive on huge programs, so don't do it every 100ms.
1896d1862363c88c183b0ed7740fca876342cf0474bStephen Hines    if (flags()->memory_limit_mb > 0) {
19092b54796149a8b5995fa49c43f43b709b83c5644Dmitry Vyukov      uptr rss = GetRSS();
19192b54796149a8b5995fa49c43f43b709b83c5644Dmitry Vyukov      uptr limit = uptr(flags()->memory_limit_mb) << 20;
1926d1862363c88c183b0ed7740fca876342cf0474bStephen Hines      VPrintf(1, "ThreadSanitizer: memory flush check"
1936d1862363c88c183b0ed7740fca876342cf0474bStephen Hines                 " RSS=%llu LAST=%llu LIMIT=%llu\n",
1946d1862363c88c183b0ed7740fca876342cf0474bStephen Hines              (u64)rss >> 20, (u64)last_rss >> 20, (u64)limit >> 20);
19592b54796149a8b5995fa49c43f43b709b83c5644Dmitry Vyukov      if (2 * rss > limit + last_rss) {
1966d1862363c88c183b0ed7740fca876342cf0474bStephen Hines        VPrintf(1, "ThreadSanitizer: flushing memory due to RSS\n");
19792b54796149a8b5995fa49c43f43b709b83c5644Dmitry Vyukov        FlushShadowMemory();
19892b54796149a8b5995fa49c43f43b709b83c5644Dmitry Vyukov        rss = GetRSS();
1996d1862363c88c183b0ed7740fca876342cf0474bStephen Hines        VPrintf(1, "ThreadSanitizer: memory flushed RSS=%llu\n", (u64)rss>>20);
20092b54796149a8b5995fa49c43f43b709b83c5644Dmitry Vyukov      }
20192b54796149a8b5995fa49c43f43b709b83c5644Dmitry Vyukov      last_rss = rss;
20292b54796149a8b5995fa49c43f43b709b83c5644Dmitry Vyukov    }
2034bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov
204a38e40fde45acccb124f7419ecbe21ef6cfd306bDmitry Vyukov    // Write memory profile if requested.
2054bebe7bab966c82f0a8952f797ed3d490624dc62Dmitry Vyukov    if (mprof_fd != kInvalidFd)
206a38e40fde45acccb124f7419ecbe21ef6cfd306bDmitry Vyukov      MemoryProfiler(ctx, mprof_fd, i);
207a38e40fde45acccb124f7419ecbe21ef6cfd306bDmitry Vyukov
208f63dde3594da0dba4c8039f0cb3a4196a76f1affDmitry Vyukov    // Flush symbolizer cache if requested.
209f63dde3594da0dba4c8039f0cb3a4196a76f1affDmitry Vyukov    if (flags()->flush_symbolizer_ms > 0) {
210f63dde3594da0dba4c8039f0cb3a4196a76f1affDmitry Vyukov      u64 last = atomic_load(&ctx->last_symbolize_time_ns,
211f63dde3594da0dba4c8039f0cb3a4196a76f1affDmitry Vyukov                             memory_order_relaxed);
212f63dde3594da0dba4c8039f0cb3a4196a76f1affDmitry Vyukov      if (last != 0 && last + flags()->flush_symbolizer_ms * kMs2Ns < now) {
213f63dde3594da0dba4c8039f0cb3a4196a76f1affDmitry Vyukov        Lock l(&ctx->report_mtx);
2147ed46ff7af911da0dd2067734d1408c6986c6657Alexey Samsonov        SpinMutexLock l2(&CommonSanitizerReportMutex);
215f63dde3594da0dba4c8039f0cb3a4196a76f1affDmitry Vyukov        SymbolizeFlush();
216f63dde3594da0dba4c8039f0cb3a4196a76f1affDmitry Vyukov        atomic_store(&ctx->last_symbolize_time_ns, 0, memory_order_relaxed);
217f63dde3594da0dba4c8039f0cb3a4196a76f1affDmitry Vyukov      }
218a38e40fde45acccb124f7419ecbe21ef6cfd306bDmitry Vyukov    }
21926127735454fddae3495794f38189d57dde6510fDmitry Vyukov  }
22026127735454fddae3495794f38189d57dde6510fDmitry Vyukov}
22126127735454fddae3495794f38189d57dde6510fDmitry Vyukov
2222d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesstatic void StartBackgroundThread() {
2232d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  ctx->background_thread = internal_start_thread(&BackgroundThread, 0);
2242d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
2252d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
22686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#ifndef __mips__
2272d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesstatic void StopBackgroundThread() {
2282d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  atomic_store(&ctx->stop_background_thread, 1, memory_order_relaxed);
2292d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  internal_join_thread(ctx->background_thread);
2302d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  ctx->background_thread = 0;
2312d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
2322d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
23386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#endif
2342d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
2357ac33ac529ff93a57419f5ddf71b1fde68428577Dmitry Vyukovvoid DontNeedShadowFor(uptr addr, uptr size) {
2367ac33ac529ff93a57419f5ddf71b1fde68428577Dmitry Vyukov  uptr shadow_beg = MemToShadow(addr);
2377ac33ac529ff93a57419f5ddf71b1fde68428577Dmitry Vyukov  uptr shadow_end = MemToShadow(addr + size);
2387ac33ac529ff93a57419f5ddf71b1fde68428577Dmitry Vyukov  FlushUnneededShadowMemory(shadow_beg, shadow_end - shadow_beg);
2397ac33ac529ff93a57419f5ddf71b1fde68428577Dmitry Vyukov}
2407ac33ac529ff93a57419f5ddf71b1fde68428577Dmitry Vyukov
241a05fcc1e3e045097f2f1a20798cbe038bbb1d6a9Dmitry Vyukovvoid MapShadow(uptr addr, uptr size) {
2422d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  // Global data is not 64K aligned, but there are no adjacent mappings,
2432d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  // so we can get away with unaligned mapping.
2442d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  // CHECK_EQ(addr, addr & ~((64 << 10) - 1));  // windows wants 64K alignment
245cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  MmapFixedNoReserve(MemToShadow(addr), size * kShadowMultiplier, "shadow");
2466a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines
2476a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  // Meta shadow is 2:1, so tread carefully.
2486a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  static bool data_mapped = false;
2496a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  static uptr mapped_meta_end = 0;
2506a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  uptr meta_begin = (uptr)MemToMeta(addr);
2516a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  uptr meta_end = (uptr)MemToMeta(addr + size);
2526a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  meta_begin = RoundDownTo(meta_begin, 64 << 10);
2536a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  meta_end = RoundUpTo(meta_end, 64 << 10);
2546a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  if (!data_mapped) {
2556a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines    // First call maps data+bss.
2566a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines    data_mapped = true;
257cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar    MmapFixedNoReserve(meta_begin, meta_end - meta_begin, "meta shadow");
2586a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  } else {
2596a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines    // Mapping continous heap.
2606a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines    // Windows wants 64K alignment.
2616a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines    meta_begin = RoundDownTo(meta_begin, 64 << 10);
2626a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines    meta_end = RoundUpTo(meta_end, 64 << 10);
2636a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines    if (meta_end <= mapped_meta_end)
2646a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines      return;
2656a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines    if (meta_begin < mapped_meta_end)
2666a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines      meta_begin = mapped_meta_end;
267cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar    MmapFixedNoReserve(meta_begin, meta_end - meta_begin, "meta shadow");
2686a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines    mapped_meta_end = meta_end;
2696a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  }
2706a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  VPrintf(2, "mapped meta shadow for (%p-%p) at (%p-%p)\n",
2716a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines      addr, addr+size, meta_begin, meta_end);
272a05fcc1e3e045097f2f1a20798cbe038bbb1d6a9Dmitry Vyukov}
273a05fcc1e3e045097f2f1a20798cbe038bbb1d6a9Dmitry Vyukov
274cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainarvoid MapThreadTrace(uptr addr, uptr size, const char *name) {
275dae1251f196f9694d428a04f14987b06112ae52cDmitry Vyukov  DPrintf("#0: Mapping trace at %p-%p(0x%zx)\n", addr, addr + size, size);
2763d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar  CHECK_GE(addr, TraceMemBeg());
2773d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar  CHECK_LE(addr + size, TraceMemEnd());
2782d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  CHECK_EQ(addr, addr & ~((64 << 10) - 1));  // windows wants 64K alignment
279cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  uptr addr1 = (uptr)MmapFixedNoReserve(addr, size, name);
28001a7ce809bf7cc627d73c045c70bcca9891f632cDmitry Vyukov  if (addr1 != addr) {
28101a7ce809bf7cc627d73c045c70bcca9891f632cDmitry Vyukov    Printf("FATAL: ThreadSanitizer can not mmap thread trace (%p/%p->%p)\n",
28201a7ce809bf7cc627d73c045c70bcca9891f632cDmitry Vyukov        addr, size, addr1);
2836535c31c66569df262791f0b56852c496977c977Dmitry Vyukov    Die();
2846535c31c66569df262791f0b56852c496977c977Dmitry Vyukov  }
2856535c31c66569df262791f0b56852c496977c977Dmitry Vyukov}
2866535c31c66569df262791f0b56852c496977c977Dmitry Vyukov
2876d1862363c88c183b0ed7740fca876342cf0474bStephen Hinesstatic void CheckShadowMapping() {
2883d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar  uptr beg, end;
2893d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar  for (int i = 0; GetUserRegion(i, &beg, &end); i++) {
2906d1862363c88c183b0ed7740fca876342cf0474bStephen Hines    VPrintf(3, "checking shadow region %p-%p\n", beg, end);
2916d1862363c88c183b0ed7740fca876342cf0474bStephen Hines    for (uptr p0 = beg; p0 <= end; p0 += (end - beg) / 4) {
2926d1862363c88c183b0ed7740fca876342cf0474bStephen Hines      for (int x = -1; x <= 1; x++) {
2936d1862363c88c183b0ed7740fca876342cf0474bStephen Hines        const uptr p = p0 + x;
2946d1862363c88c183b0ed7740fca876342cf0474bStephen Hines        if (p < beg || p >= end)
2956d1862363c88c183b0ed7740fca876342cf0474bStephen Hines          continue;
2966d1862363c88c183b0ed7740fca876342cf0474bStephen Hines        const uptr s = MemToShadow(p);
29786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines        const uptr m = (uptr)MemToMeta(p);
29886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines        VPrintf(3, "  checking pointer %p: shadow=%p meta=%p\n", p, s, m);
2996d1862363c88c183b0ed7740fca876342cf0474bStephen Hines        CHECK(IsAppMem(p));
3006d1862363c88c183b0ed7740fca876342cf0474bStephen Hines        CHECK(IsShadowMem(s));
3016d1862363c88c183b0ed7740fca876342cf0474bStephen Hines        CHECK_EQ(p & ~(kShadowCell - 1), ShadowToMem(s));
3026d1862363c88c183b0ed7740fca876342cf0474bStephen Hines        CHECK(IsMetaMem(m));
3036d1862363c88c183b0ed7740fca876342cf0474bStephen Hines      }
3046d1862363c88c183b0ed7740fca876342cf0474bStephen Hines    }
3056d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  }
3066d1862363c88c183b0ed7740fca876342cf0474bStephen Hines}
3076d1862363c88c183b0ed7740fca876342cf0474bStephen Hines
3087ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid Initialize(ThreadState *thr) {
3097ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // Thread safe because done before all threads exist.
3107ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  static bool is_initialized = false;
3117ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (is_initialized)
3127ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    return;
3137ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  is_initialized = true;
3142d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  // We are not ready to handle interceptors yet.
3152d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  ScopedIgnoreInterceptors ignore;
316859778a4e2dffa4024fa3e13b105fd62eca44b1cKostya Serebryany  SanitizerToolName = "ThreadSanitizer";
317591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonov  // Install tool-specific callbacks in sanitizer_common.
318591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonov  SetCheckFailedCallback(TsanCheckFailed);
319591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonov
3206d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  ctx = new(ctx_placeholder) Context;
3216d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  const char *options = GetEnv(kTsanOptionsEnv);
322cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  CacheBinaryName();
3233d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar  InitializeFlags(&ctx->flags, options);
3243d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar  InitializePlatformEarly();
32586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#ifndef SANITIZER_GO
3263d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar  // Re-exec ourselves if we need to set additional env or command line args.
3273d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar  MaybeReexec();
3283d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar
3292e87051d136db3150a3ca322d8862f92b0a684bbDmitry Vyukov  InitializeAllocator();
3303d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar  ReplaceSystemMalloc();
331bbbb20b7212155ebc5b5b4ee1c68c987dcf30320Dmitry Vyukov#endif
3327ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  InitializeInterceptors();
3336d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  CheckShadowMapping();
3346d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  InitializePlatform();
3357ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  InitializeMutex();
3367ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  InitializeDynamicAnnotations();
33786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#ifndef SANITIZER_GO
3387ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  InitializeShadowMemory();
339a05fcc1e3e045097f2f1a20798cbe038bbb1d6a9Dmitry Vyukov#endif
340b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov  // Setup correct file descriptor for error reports.
3416d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  __sanitizer_set_report_path(common_flags()->log_path);
3427ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  InitializeSuppressions();
34386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#ifndef SANITIZER_GO
3444af0f21c0c98950df1136dbec8824a029ed5bb8eDmitry Vyukov  InitializeLibIgnore();
3456d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  Symbolizer::GetOrInit()->AddHooks(EnterSymbolizer, ExitSymbolizer);
34686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  // On MIPS, TSan initialization is run before
34786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  // __pthread_initialize_minimal_internal() is finished, so we can not spawn
34886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  // new threads.
34986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#ifndef __mips__
3502d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  StartBackgroundThread();
3512d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  SetSandboxingCallback(StopBackgroundThread);
3522d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
35386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#endif
3546d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  if (common_flags()->detect_deadlocks)
3552d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    ctx->dd = DDetector::Create(flags());
3568cc1f81b2cc1fa0d4cda4f4635d955aed04c09c8Alexey Samsonov
3576d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  VPrintf(1, "***** Running under ThreadSanitizer v2 (pid %d) *****\n",
3586d1862363c88c183b0ed7740fca876342cf0474bStephen Hines          (int)internal_getpid());
3597ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
3607ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // Initialize thread 0.
3617ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int tid = ThreadCreate(thr, 0, 0, true);
3627ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  CHECK_EQ(tid, 0);
3630b694fcab9b2f33bdd6691cbea4e80a5c27191b1Peter Collingbourne  ThreadStart(thr, tid, internal_getpid());
364cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar#if TSAN_CONTAINS_UBSAN
365cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar  __ubsan::InitAsPlugin();
366cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar#endif
3677ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  ctx->initialized = true;
3687ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
369adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov  if (flags()->stop_on_start) {
370b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov    Printf("ThreadSanitizer is suspended at startup (pid %d)."
371adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov           " Call __tsan_resume().\n",
3720b694fcab9b2f33bdd6691cbea4e80a5c27191b1Peter Collingbourne           (int)internal_getpid());
373ba5e99668e3030cc5bab357a04271a1bdbac209cAlexey Samsonov    while (__tsan_resumed == 0) {}
3747ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
3752d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
3762d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  OnInitialize();
3777ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
3787ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
3797ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyint Finalize(ThreadState *thr) {
3807ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  bool failed = false;
3817ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
38254e0a9a391616bbd2a4f0fd2d01076291274cb98Dmitry Vyukov  if (flags()->atexit_sleep_ms > 0 && ThreadCount(thr) > 1)
38354e0a9a391616bbd2a4f0fd2d01076291274cb98Dmitry Vyukov    SleepForMillis(flags()->atexit_sleep_ms);
38454e0a9a391616bbd2a4f0fd2d01076291274cb98Dmitry Vyukov
385d0a51c02157e8293ea365ad0d429ef8e73d115deDmitry Vyukov  // Wait for pending reports.
386d0a51c02157e8293ea365ad0d429ef8e73d115deDmitry Vyukov  ctx->report_mtx.Lock();
3877ed46ff7af911da0dd2067734d1408c6986c6657Alexey Samsonov  CommonSanitizerReportMutex.Lock();
3887ed46ff7af911da0dd2067734d1408c6986c6657Alexey Samsonov  CommonSanitizerReportMutex.Unlock();
389d0a51c02157e8293ea365ad0d429ef8e73d115deDmitry Vyukov  ctx->report_mtx.Unlock();
390d0a51c02157e8293ea365ad0d429ef8e73d115deDmitry Vyukov
39186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#ifndef SANITIZER_GO
39286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  if (Verbosity()) AllocatorPrintStats();
393bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov#endif
394bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov
3957ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  ThreadFinalize(thr);
3967ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
3977ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (ctx->nreported) {
3987ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    failed = true;
39986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#ifndef SANITIZER_GO
400b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov    Printf("ThreadSanitizer: reported %d warnings\n", ctx->nreported);
401b3b21231dd9dfeb34f5f302c879f2d11b6312080Dmitry Vyukov#else
402b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov    Printf("Found %d data race(s)\n", ctx->nreported);
403b3b21231dd9dfeb34f5f302c879f2d11b6312080Dmitry Vyukov#endif
4047ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
4057ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
4067ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (ctx->nmissed_expected) {
4077ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    failed = true;
408b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov    Printf("ThreadSanitizer: missed %d expected races\n",
4097ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany        ctx->nmissed_expected);
4107ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
4117ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
4126d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  if (common_flags()->print_suppressions)
413f754eb501d6bd163fff6747716b7703fe45be4b8Dmitry Vyukov    PrintMatchedSuppressions();
41486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#ifndef SANITIZER_GO
4150fd908cf5a555483633e2d9703932bde18009682Dmitry Vyukov  if (flags()->print_benign)
4160fd908cf5a555483633e2d9703932bde18009682Dmitry Vyukov    PrintMatchedBenignRaces();
4170fd908cf5a555483633e2d9703932bde18009682Dmitry Vyukov#endif
418f754eb501d6bd163fff6747716b7703fe45be4b8Dmitry Vyukov
41922881ec8c8a3c01f9b993b186040444b0b5caa50Dmitry Vyukov  failed = OnFinalize(failed);
42022881ec8c8a3c01f9b993b186040444b0b5caa50Dmitry Vyukov
42186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#if TSAN_COLLECT_STATS
42208adb1815b4958df88f904b9780a055b0d387294Dmitry Vyukov  StatAggregate(ctx->stat, thr->stat);
4237ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  StatOutput(ctx->stat);
42486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#endif
42586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
4263d763c0d3700e73b3aead8e65e04ec28efc56138Pirama Arumuga Nainar  return failed ? common_flags()->exitcode : 0;
4277ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
4287ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
42986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#ifndef SANITIZER_GO
4302d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid ForkBefore(ThreadState *thr, uptr pc) {
4312d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  ctx->thread_registry->Lock();
4322d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  ctx->report_mtx.Lock();
4332d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
4342d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
4352d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid ForkParentAfter(ThreadState *thr, uptr pc) {
4362d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  ctx->report_mtx.Unlock();
4372d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  ctx->thread_registry->Unlock();
4382d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
4392d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
4402d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid ForkChildAfter(ThreadState *thr, uptr pc) {
4412d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  ctx->report_mtx.Unlock();
4422d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  ctx->thread_registry->Unlock();
4432d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
4442d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  uptr nthread = 0;
4452d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  ctx->thread_registry->GetNumberOfThreads(0, 0, &nthread /* alive threads */);
4462d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  VPrintf(1, "ThreadSanitizer: forked new process with pid %d,"
4472d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      " parent had %d threads\n", (int)internal_getpid(), (int)nthread);
4482d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  if (nthread == 1) {
44986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    StartBackgroundThread();
4502d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  } else {
4512d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    // We've just forked a multi-threaded process. We cannot reasonably function
4522d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    // after that (some mutexes may be locked before fork). So just enable
4532d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    // ignores for everything in the hope that we will exec soon.
4542d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    ctx->after_multithreaded_fork = true;
4552d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    thr->ignore_interceptors++;
4562d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    ThreadIgnoreBegin(thr, pc);
4572d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    ThreadIgnoreSyncBegin(thr, pc);
4582d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  }
4592d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
4602d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
4612d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
46286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#ifdef SANITIZER_GO
4636a211c5814e25d6745a5058cc0e499e5235d3821Stephen HinesNOINLINE
4646a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hinesvoid GrowShadowStack(ThreadState *thr) {
4656a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  const int sz = thr->shadow_stack_end - thr->shadow_stack;
4666a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  const int newsz = 2 * sz;
4676a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  uptr *newstack = (uptr*)internal_alloc(MBlockShadowStack,
4686a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines      newsz * sizeof(uptr));
4696a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  internal_memcpy(newstack, thr->shadow_stack, sz * sizeof(uptr));
4706a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  internal_free(thr->shadow_stack);
4716a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  thr->shadow_stack = newstack;
4726a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  thr->shadow_stack_pos = newstack + sz;
4736a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  thr->shadow_stack_end = newstack + newsz;
4746a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines}
4756a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines#endif
4766a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines
477848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukovu32 CurrentStackId(ThreadState *thr, uptr pc) {
4787c9150579ed0278492f51cc8434b1d63a44b9bd1Pirama Arumuga Nainar  if (!thr->is_inited)  // May happen during bootstrap.
479848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov    return 0;
4806a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  if (pc != 0) {
48186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#ifndef SANITIZER_GO
4826a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines    DCHECK_LT(thr->shadow_stack_pos, thr->shadow_stack_end);
4836a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines#else
4846a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines    if (thr->shadow_stack_pos == thr->shadow_stack_end)
4856a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines      GrowShadowStack(thr);
4866a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines#endif
487848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov    thr->shadow_stack_pos[0] = pc;
488848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov    thr->shadow_stack_pos++;
489848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov  }
4906d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  u32 id = StackDepotPut(
4916d1862363c88c183b0ed7740fca876342cf0474bStephen Hines      StackTrace(thr->shadow_stack, thr->shadow_stack_pos - thr->shadow_stack));
4926a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  if (pc != 0)
493848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov    thr->shadow_stack_pos--;
494848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov  return id;
495848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov}
496848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov
497b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukovvoid TraceSwitch(ThreadState *thr) {
4989ad7c32720dfa1287f8cfd481e5d583435178caeDmitry Vyukov  thr->nomalloc++;
4999743d74426ae43898e4da55e591b09be18f8aa6eDmitry Vyukov  Trace *thr_trace = ThreadTrace(thr->tid);
5009743d74426ae43898e4da55e591b09be18f8aa6eDmitry Vyukov  Lock l(&thr_trace->mtx);
5010415ac00935795a70d87ae662ccad58ea0704537Dmitry Vyukov  unsigned trace = (thr->fast_state.epoch() / kTracePartSize) % TraceParts();
5029743d74426ae43898e4da55e591b09be18f8aa6eDmitry Vyukov  TraceHeader *hdr = &thr_trace->headers[trace];
5037ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  hdr->epoch0 = thr->fast_state.epoch();
5046d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  ObtainCurrentStack(thr, 0, &hdr->stack0);
505ad9da372f962495b3487685232d09390be841b1cDmitry Vyukov  hdr->mset0 = thr->mset;
5069ad7c32720dfa1287f8cfd481e5d583435178caeDmitry Vyukov  thr->nomalloc--;
5077ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
5087ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
5099743d74426ae43898e4da55e591b09be18f8aa6eDmitry VyukovTrace *ThreadTrace(int tid) {
5109743d74426ae43898e4da55e591b09be18f8aa6eDmitry Vyukov  return (Trace*)GetThreadTraceHeader(tid);
5119743d74426ae43898e4da55e591b09be18f8aa6eDmitry Vyukov}
5129743d74426ae43898e4da55e591b09be18f8aa6eDmitry Vyukov
513385542a2e83a4f37de4232d6c72097c1b7d6d44bDmitry Vyukovuptr TraceTopPC(ThreadState *thr) {
514385542a2e83a4f37de4232d6c72097c1b7d6d44bDmitry Vyukov  Event *events = (Event*)GetThreadTrace(thr->tid);
515d698edc4f74a17048eef3342a9fa42b3ebba802aDmitry Vyukov  uptr pc = events[thr->fast_state.GetTracePos()];
516385542a2e83a4f37de4232d6c72097c1b7d6d44bDmitry Vyukov  return pc;
517385542a2e83a4f37de4232d6c72097c1b7d6d44bDmitry Vyukov}
518385542a2e83a4f37de4232d6c72097c1b7d6d44bDmitry Vyukov
519d698edc4f74a17048eef3342a9fa42b3ebba802aDmitry Vyukovuptr TraceSize() {
520d698edc4f74a17048eef3342a9fa42b3ebba802aDmitry Vyukov  return (uptr)(1ull << (kTracePartSizeBits + flags()->history_size + 1));
521d698edc4f74a17048eef3342a9fa42b3ebba802aDmitry Vyukov}
522d698edc4f74a17048eef3342a9fa42b3ebba802aDmitry Vyukov
5230415ac00935795a70d87ae662ccad58ea0704537Dmitry Vyukovuptr TraceParts() {
5240415ac00935795a70d87ae662ccad58ea0704537Dmitry Vyukov  return TraceSize() / kTracePartSize;
5250415ac00935795a70d87ae662ccad58ea0704537Dmitry Vyukov}
5260415ac00935795a70d87ae662ccad58ea0704537Dmitry Vyukov
52786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#ifndef SANITIZER_GO
5287ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyextern "C" void __tsan_trace_switch() {
5297ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TraceSwitch(cur_thread());
5307ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
5317ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
5327ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyextern "C" void __tsan_report_race() {
5337ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  ReportRace(cur_thread());
5347ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
535b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#endif
5367ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
5377ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyALWAYS_INLINE
53843c36e4b055f348d6076e6da44f9cd3e4399568fTimur IskhodzhanovShadow LoadShadow(u64 *p) {
5397ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  u64 raw = atomic_load((atomic_uint64_t*)p, memory_order_relaxed);
5407ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return Shadow(raw);
5417ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
5427ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
5437ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyALWAYS_INLINE
54443c36e4b055f348d6076e6da44f9cd3e4399568fTimur Iskhodzhanovvoid StoreShadow(u64 *sp, u64 s) {
5457ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  atomic_store((atomic_uint64_t*)sp, s, memory_order_relaxed);
5467ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
5477ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
5487ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyALWAYS_INLINE
54943c36e4b055f348d6076e6da44f9cd3e4399568fTimur Iskhodzhanovvoid StoreIfNotYetStored(u64 *sp, u64 *s) {
5507ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  StoreShadow(sp, *s);
5517ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  *s = 0;
5527ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
5537ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
5546a211c5814e25d6745a5058cc0e499e5235d3821Stephen HinesALWAYS_INLINE
5556a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hinesvoid HandleRace(ThreadState *thr, u64 *shadow_mem,
5567ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany                              Shadow cur, Shadow old) {
5577ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  thr->racy_state[0] = cur.raw();
5587ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  thr->racy_state[1] = old.raw();
5597ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  thr->racy_shadow_addr = shadow_mem;
56086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#ifndef SANITIZER_GO
5617ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  HACKY_CALL(__tsan_report_race);
562b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#else
563b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov  ReportRace(thr);
564b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#endif
5657ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
5667ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
5677ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic inline bool HappensBefore(Shadow old, ThreadState *thr) {
568c8f0a00ede42f83ac79ff63c347ca8ddcda77155Dmitry Vyukov  return thr->clock.get(old.TidWithIgnore()) >= old.epoch();
5697ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
5707ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
5716a211c5814e25d6745a5058cc0e499e5235d3821Stephen HinesALWAYS_INLINE
5726a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hinesvoid MemoryAccessImpl1(ThreadState *thr, uptr addr,
573334553ec45d8982df45a6f5e656e068142ecde3fDmitry Vyukov    int kAccessSizeLog, bool kAccessIsWrite, bool kIsAtomic,
5747ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    u64 *shadow_mem, Shadow cur) {
5757ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  StatInc(thr, StatMop);
5767ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  StatInc(thr, kAccessIsWrite ? StatMopWrite : StatMopRead);
5777ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  StatInc(thr, (StatType)(StatMop1 + kAccessSizeLog));
5787ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
5797ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // This potentially can live in an MMX/SSE scratch register.
5807ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // The required intrinsics are:
5817ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // __m128i _mm_move_epi64(__m128i*);
5827ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // _mm_storel_epi64(u64*, __m128i);
5837ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  u64 store_word = cur.raw();
5847ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
5857ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // scan all the shadow values and dispatch to 4 categories:
5867ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // same, replace, candidate and race (see comments below).
5877ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // we consider only 3 cases regarding access sizes:
5887ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // equal, intersect and not intersect. initially I considered
5897ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // larger and smaller as well, it allowed to replace some
5907ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // 'candidates' with 'same' or 'replace', but I think
5917ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // it's just not worth it (performance- and complexity-wise).
5927ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
593286c914d37d28df611ae083cac40148cf2622ee7Dmitry Vyukov  Shadow old(0);
59486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
59586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  // It release mode we manually unroll the loop,
59686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  // because empirically gcc generates better code this way.
59786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  // However, we can't afford unrolling in debug mode, because the function
59886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  // consumes almost 4K of stack. Gtest gives only 4K of stack to death test
59986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  // threads, which is not enough for the unrolled loop.
60086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#if SANITIZER_DEBUG
60186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  for (int idx = 0; idx < 4; idx++) {
6027ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h"
60386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  }
60486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#else
60586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  int idx = 0;
6067ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h"
60786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  idx = 1;
6087ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h"
60986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  idx = 2;
6107ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h"
61186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  idx = 3;
6127ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h"
61386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#endif
6147ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
6157ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // we did not find any races and had already stored
6167ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // the current access info, so we are done
6177ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (LIKELY(store_word == 0))
6187ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    return;
6197ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // choose a random candidate slot and replace it
6207ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  StoreShadow(shadow_mem + (cur.epoch() % kShadowCnt), store_word);
6217ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  StatInc(thr, StatShadowReplace);
6227ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return;
6237ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany RACE:
6247ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  HandleRace(thr, shadow_mem, cur, old);
6257ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return;
6267ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
6277ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
6288ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukovvoid UnalignedMemoryAccess(ThreadState *thr, uptr pc, uptr addr,
6298ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov    int size, bool kAccessIsWrite, bool kIsAtomic) {
6308ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov  while (size) {
6318ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov    int size1 = 1;
6328ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov    int kAccessSizeLog = kSizeLog1;
6336d1862363c88c183b0ed7740fca876342cf0474bStephen Hines    if (size >= 8 && (addr & ~7) == ((addr + 7) & ~7)) {
6348ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov      size1 = 8;
6358ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov      kAccessSizeLog = kSizeLog8;
6366d1862363c88c183b0ed7740fca876342cf0474bStephen Hines    } else if (size >= 4 && (addr & ~7) == ((addr + 3) & ~7)) {
6378ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov      size1 = 4;
6388ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov      kAccessSizeLog = kSizeLog4;
6396d1862363c88c183b0ed7740fca876342cf0474bStephen Hines    } else if (size >= 2 && (addr & ~7) == ((addr + 1) & ~7)) {
6408ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov      size1 = 2;
6418ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov      kAccessSizeLog = kSizeLog2;
6428ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov    }
6438ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov    MemoryAccess(thr, pc, addr, kAccessSizeLog, kAccessIsWrite, kIsAtomic);
6448ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov    addr += size1;
6458ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov    size -= size1;
6468ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov  }
6478ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov}
6488ecd0e5d9f389d18653892851c6ffb2f235de4b7Dmitry Vyukov
6496a211c5814e25d6745a5058cc0e499e5235d3821Stephen HinesALWAYS_INLINE
6506a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hinesbool ContainsSameAccessSlow(u64 *s, u64 a, u64 sync_epoch, bool is_write) {
6516a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  Shadow cur(a);
6526a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  for (uptr i = 0; i < kShadowCnt; i++) {
6536a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines    Shadow old(LoadShadow(&s[i]));
6546a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines    if (Shadow::Addr0AndSizeAreEqual(cur, old) &&
6556a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines        old.TidWithIgnore() == cur.TidWithIgnore() &&
6566a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines        old.epoch() > sync_epoch &&
6576a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines        old.IsAtomic() == cur.IsAtomic() &&
6586a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines        old.IsRead() <= cur.IsRead())
6596a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines      return true;
6606a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  }
6616a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  return false;
6626a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines}
6636a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines
66486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#if defined(__SSE3__)
6656a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines#define SHUF(v0, v1, i0, i1, i2, i3) _mm_castps_si128(_mm_shuffle_ps( \
6666a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines    _mm_castsi128_ps(v0), _mm_castsi128_ps(v1), \
6676a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines    (i0)*1 + (i1)*4 + (i2)*16 + (i3)*64))
6686a211c5814e25d6745a5058cc0e499e5235d3821Stephen HinesALWAYS_INLINE
6696a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hinesbool ContainsSameAccessFast(u64 *s, u64 a, u64 sync_epoch, bool is_write) {
6706a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  // This is an optimized version of ContainsSameAccessSlow.
6716a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  // load current access into access[0:63]
6726a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  const m128 access     = _mm_cvtsi64_si128(a);
6736a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  // duplicate high part of access in addr0:
6746a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  // addr0[0:31]        = access[32:63]
6756a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  // addr0[32:63]       = access[32:63]
6766a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  // addr0[64:95]       = access[32:63]
6776a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  // addr0[96:127]      = access[32:63]
6786a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  const m128 addr0      = SHUF(access, access, 1, 1, 1, 1);
6796a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  // load 4 shadow slots
6806a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  const m128 shadow0    = _mm_load_si128((__m128i*)s);
6816a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  const m128 shadow1    = _mm_load_si128((__m128i*)s + 1);
6826a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  // load high parts of 4 shadow slots into addr_vect:
6836a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  // addr_vect[0:31]    = shadow0[32:63]
6846a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  // addr_vect[32:63]   = shadow0[96:127]
6856a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  // addr_vect[64:95]   = shadow1[32:63]
6866a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  // addr_vect[96:127]  = shadow1[96:127]
6876a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  m128 addr_vect        = SHUF(shadow0, shadow1, 1, 3, 1, 3);
6886a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  if (!is_write) {
6896a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines    // set IsRead bit in addr_vect
6906a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines    const m128 rw_mask1 = _mm_cvtsi64_si128(1<<15);
6916a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines    const m128 rw_mask  = SHUF(rw_mask1, rw_mask1, 0, 0, 0, 0);
6926a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines    addr_vect           = _mm_or_si128(addr_vect, rw_mask);
6936a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  }
6946a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  // addr0 == addr_vect?
6956a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  const m128 addr_res   = _mm_cmpeq_epi32(addr0, addr_vect);
6966a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  // epoch1[0:63]       = sync_epoch
6976a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  const m128 epoch1     = _mm_cvtsi64_si128(sync_epoch);
6986a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  // epoch[0:31]        = sync_epoch[0:31]
6996a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  // epoch[32:63]       = sync_epoch[0:31]
7006a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  // epoch[64:95]       = sync_epoch[0:31]
7016a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  // epoch[96:127]      = sync_epoch[0:31]
7026a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  const m128 epoch      = SHUF(epoch1, epoch1, 0, 0, 0, 0);
7036a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  // load low parts of shadow cell epochs into epoch_vect:
7046a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  // epoch_vect[0:31]   = shadow0[0:31]
7056a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  // epoch_vect[32:63]  = shadow0[64:95]
7066a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  // epoch_vect[64:95]  = shadow1[0:31]
7076a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  // epoch_vect[96:127] = shadow1[64:95]
7086a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  const m128 epoch_vect = SHUF(shadow0, shadow1, 0, 2, 0, 2);
7096a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  // epoch_vect >= sync_epoch?
7106a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  const m128 epoch_res  = _mm_cmpgt_epi32(epoch_vect, epoch);
7116a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  // addr_res & epoch_res
7126a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  const m128 res        = _mm_and_si128(addr_res, epoch_res);
7136a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  // mask[0] = res[7]
7146a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  // mask[1] = res[15]
7156a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  // ...
7166a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  // mask[15] = res[127]
7176a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  const int mask        = _mm_movemask_epi8(res);
7186a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  return mask != 0;
7196a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines}
7206a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines#endif
7216a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines
7226a211c5814e25d6745a5058cc0e499e5235d3821Stephen HinesALWAYS_INLINE
7236a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hinesbool ContainsSameAccess(u64 *s, u64 a, u64 sync_epoch, bool is_write) {
72486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#if defined(__SSE3__)
7256a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  bool res = ContainsSameAccessFast(s, a, sync_epoch, is_write);
7266d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  // NOTE: this check can fail if the shadow is concurrently mutated
72786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  // by other threads. But it still can be useful if you modify
72886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  // ContainsSameAccessFast and want to ensure that it's not completely broken.
72986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  // DCHECK_EQ(res, ContainsSameAccessSlow(s, a, sync_epoch, is_write));
7306a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  return res;
7316a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines#else
7326a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  return ContainsSameAccessSlow(s, a, sync_epoch, is_write);
7336a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines#endif
7346a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines}
7356a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines
736d475aa8578f4a1955cdb3e3159eda8b229f8c021Kostya SerebryanyALWAYS_INLINE USED
7377ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid MemoryAccess(ThreadState *thr, uptr pc, uptr addr,
738334553ec45d8982df45a6f5e656e068142ecde3fDmitry Vyukov    int kAccessSizeLog, bool kAccessIsWrite, bool kIsAtomic) {
7397ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  u64 *shadow_mem = (u64*)MemToShadow(addr);
74068230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov  DPrintf2("#%d: MemoryAccess: @%p %p size=%d"
741e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov      " is_write=%d shadow_mem=%p {%zx, %zx, %zx, %zx}\n",
7427ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany      (int)thr->fast_state.tid(), (void*)pc, (void*)addr,
7437ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany      (int)(1 << kAccessSizeLog), kAccessIsWrite, shadow_mem,
744e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov      (uptr)shadow_mem[0], (uptr)shadow_mem[1],
745e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov      (uptr)shadow_mem[2], (uptr)shadow_mem[3]);
74686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#if SANITIZER_DEBUG
7477ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (!IsAppMem(addr)) {
748b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov    Printf("Access to non app mem %zx\n", addr);
7497ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    DCHECK(IsAppMem(addr));
7507ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
7517ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (!IsShadowMem((uptr)shadow_mem)) {
752b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov    Printf("Bad shadow addr %p (%zx)\n", shadow_mem, addr);
7537ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    DCHECK(IsShadowMem((uptr)shadow_mem));
7547ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
7557ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#endif
7567ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
7576a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  if (kCppMode && *shadow_mem == kShadowRodata) {
75882dbc5195ceedba0e1a9aab92d436614cc4b7ff9Dmitry Vyukov    // Access to .rodata section, no races here.
75982dbc5195ceedba0e1a9aab92d436614cc4b7ff9Dmitry Vyukov    // Measurements show that it can be 10-20% of all memory accesses.
76082dbc5195ceedba0e1a9aab92d436614cc4b7ff9Dmitry Vyukov    StatInc(thr, StatMop);
76182dbc5195ceedba0e1a9aab92d436614cc4b7ff9Dmitry Vyukov    StatInc(thr, kAccessIsWrite ? StatMopWrite : StatMopRead);
76282dbc5195ceedba0e1a9aab92d436614cc4b7ff9Dmitry Vyukov    StatInc(thr, (StatType)(StatMop1 + kAccessSizeLog));
76382dbc5195ceedba0e1a9aab92d436614cc4b7ff9Dmitry Vyukov    StatInc(thr, StatMopRodata);
76482dbc5195ceedba0e1a9aab92d436614cc4b7ff9Dmitry Vyukov    return;
76582dbc5195ceedba0e1a9aab92d436614cc4b7ff9Dmitry Vyukov  }
76682dbc5195ceedba0e1a9aab92d436614cc4b7ff9Dmitry Vyukov
7677ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  FastState fast_state = thr->fast_state;
7686a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  if (fast_state.GetIgnoreBit()) {
7696a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines    StatInc(thr, StatMop);
7706a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines    StatInc(thr, kAccessIsWrite ? StatMopWrite : StatMopRead);
7716a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines    StatInc(thr, (StatType)(StatMop1 + kAccessSizeLog));
7726a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines    StatInc(thr, StatMopIgnored);
7737ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    return;
7742d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  }
7752d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
7767ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  Shadow cur(fast_state);
7777ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  cur.SetAddr0AndSizeLog(addr & 7, kAccessSizeLog);
7787ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  cur.SetWrite(kAccessIsWrite);
779334553ec45d8982df45a6f5e656e068142ecde3fDmitry Vyukov  cur.SetAtomic(kIsAtomic);
7807ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
7816a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  if (LIKELY(ContainsSameAccess(shadow_mem, cur.raw(),
7826a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines      thr->fast_synch_epoch, kAccessIsWrite))) {
7836a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines    StatInc(thr, StatMop);
7846a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines    StatInc(thr, kAccessIsWrite ? StatMopWrite : StatMopRead);
7856a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines    StatInc(thr, (StatType)(StatMop1 + kAccessSizeLog));
7866a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines    StatInc(thr, StatMopSame);
7876a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines    return;
7886a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  }
7896a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines
7906a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  if (kCollectHistory) {
7916a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines    fast_state.IncrementEpoch();
7926a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines    thr->fast_state = fast_state;
7936a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines    TraceAddEvent(thr, fast_state, EventTypeMop, pc);
7946a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines    cur.IncrementEpoch();
7956a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  }
7966a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines
7976a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  MemoryAccessImpl1(thr, addr, kAccessSizeLog, kAccessIsWrite, kIsAtomic,
7986a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines      shadow_mem, cur);
7996a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines}
8006a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines
8016a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines// Called by MemoryAccessRange in tsan_rtl_thread.cc
8026a211c5814e25d6745a5058cc0e499e5235d3821Stephen HinesALWAYS_INLINE USED
8036a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hinesvoid MemoryAccessImpl(ThreadState *thr, uptr addr,
8046a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines    int kAccessSizeLog, bool kAccessIsWrite, bool kIsAtomic,
8056a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines    u64 *shadow_mem, Shadow cur) {
8066a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  if (LIKELY(ContainsSameAccess(shadow_mem, cur.raw(),
8076a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines      thr->fast_synch_epoch, kAccessIsWrite))) {
8086a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines    StatInc(thr, StatMop);
8096a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines    StatInc(thr, kAccessIsWrite ? StatMopWrite : StatMopRead);
8106a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines    StatInc(thr, (StatType)(StatMop1 + kAccessSizeLog));
8116a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines    StatInc(thr, StatMopSame);
8126a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines    return;
8136a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  }
8146a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines
8156a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  MemoryAccessImpl1(thr, addr, kAccessSizeLog, kAccessIsWrite, kIsAtomic,
8167ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany      shadow_mem, cur);
8177ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
8187ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
8197ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic void MemoryRangeSet(ThreadState *thr, uptr pc, uptr addr, uptr size,
8207ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany                           u64 val) {
82174172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov  (void)thr;
82274172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov  (void)pc;
8237ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (size == 0)
8247ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    return;
8257ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // FIXME: fix me.
8267ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  uptr offset = addr % kShadowCell;
8277ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (offset) {
8287ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    offset = kShadowCell - offset;
8297ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    if (size <= offset)
8307ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany      return;
8317ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    addr += offset;
8327ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    size -= offset;
8337ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
834aaac6e206453574d0130f2ae8d743f630d0c0a42Dmitry Vyukov  DCHECK_EQ(addr % 8, 0);
835aaac6e206453574d0130f2ae8d743f630d0c0a42Dmitry Vyukov  // If a user passes some insane arguments (memset(0)),
836aaac6e206453574d0130f2ae8d743f630d0c0a42Dmitry Vyukov  // let it just crash as usual.
837aaac6e206453574d0130f2ae8d743f630d0c0a42Dmitry Vyukov  if (!IsAppMem(addr) || !IsAppMem(addr + size - 1))
838aaac6e206453574d0130f2ae8d743f630d0c0a42Dmitry Vyukov    return;
83974172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov  // Don't want to touch lots of shadow memory.
84074172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov  // If a program maps 10MB stack, there is no need reset the whole range.
84126af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov  size = (size + (kShadowCell - 1)) & ~(kShadowCell - 1);
8429c4d7a4e5fc1b49757ac733fec72c5e89948fefbDmitry Vyukov  // UnmapOrDie/MmapFixedNoReserve does not work on Windows,
8439c4d7a4e5fc1b49757ac733fec72c5e89948fefbDmitry Vyukov  // so we do it only for C/C++.
8442d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  if (kGoMode || size < common_flags()->clear_shadow_mmap_threshold) {
84574172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov    u64 *p = (u64*)MemToShadow(addr);
84674172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov    CHECK(IsShadowMem((uptr)p));
84774172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov    CHECK(IsShadowMem((uptr)(p + size * kShadowCnt / kShadowCell - 1)));
84874172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov    // FIXME: may overwrite a part outside the region
84974172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov    for (uptr i = 0; i < size / kShadowCell * kShadowCnt;) {
85074172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov      p[i++] = val;
85174172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov      for (uptr j = 1; j < kShadowCnt; j++)
85274172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov        p[i++] = 0;
85374172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov    }
85474172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov  } else {
85574172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov    // The region is big, reset only beginning and end.
85686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    const uptr kPageSize = GetPageSizeCached();
85774172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov    u64 *begin = (u64*)MemToShadow(addr);
85874172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov    u64 *end = begin + size / kShadowCell * kShadowCnt;
85974172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov    u64 *p = begin;
86074172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov    // Set at least first kPageSize/2 to page boundary.
86174172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov    while ((p < begin + kPageSize / kShadowSize / 2) || ((uptr)p % kPageSize)) {
86274172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov      *p++ = val;
86374172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov      for (uptr j = 1; j < kShadowCnt; j++)
86474172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov        *p++ = 0;
86574172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov    }
86674172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov    // Reset middle part.
86774172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov    u64 *p1 = p;
86874172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov    p = RoundDown(end, kPageSize);
86974172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov    UnmapOrDie((void*)p1, (uptr)p - (uptr)p1);
87074172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov    MmapFixedNoReserve((uptr)p1, (uptr)p - (uptr)p1);
87174172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov    // Set the ending.
87274172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov    while (p < end) {
87374172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov      *p++ = val;
87474172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov      for (uptr j = 1; j < kShadowCnt; j++)
87574172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov        *p++ = 0;
87674172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov    }
87726af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov  }
8787ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
8797ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
8807ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid MemoryResetRange(ThreadState *thr, uptr pc, uptr addr, uptr size) {
8817ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  MemoryRangeSet(thr, pc, addr, size, 0);
8827ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
8837ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
8847ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid MemoryRangeFreed(ThreadState *thr, uptr pc, uptr addr, uptr size) {
88574172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov  // Processing more than 1k (4k of shadow) is expensive,
88674172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov  // can cause excessive memory consumption (user does not necessary touch
88774172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov  // the whole range) and most likely unnecessary.
88874172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov  if (size > 1024)
88974172de3ce25bf52d9d3918c94216f2eef5956e2Dmitry Vyukov    size = 1024;
8903285866e45a8521c56ba6209daf3c9f91f844fd3Dmitry Vyukov  CHECK_EQ(thr->is_freeing, false);
8913285866e45a8521c56ba6209daf3c9f91f844fd3Dmitry Vyukov  thr->is_freeing = true;
8927ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  MemoryAccessRange(thr, pc, addr, size, true);
8933285866e45a8521c56ba6209daf3c9f91f844fd3Dmitry Vyukov  thr->is_freeing = false;
8942d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  if (kCollectHistory) {
8952d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    thr->fast_state.IncrementEpoch();
8962d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    TraceAddEvent(thr, thr->fast_state, EventTypeMop, pc);
8972d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  }
898069ce828e3057819ee34426496ea7080f7cc52f0Dmitry Vyukov  Shadow s(thr->fast_state);
899064c84731c1cf41dcd7195c9380170b9aa6887b6Dmitry Vyukov  s.ClearIgnoreBit();
900069ce828e3057819ee34426496ea7080f7cc52f0Dmitry Vyukov  s.MarkAsFreed();
901069ce828e3057819ee34426496ea7080f7cc52f0Dmitry Vyukov  s.SetWrite(true);
902069ce828e3057819ee34426496ea7080f7cc52f0Dmitry Vyukov  s.SetAddr0AndSizeLog(0, 3);
903069ce828e3057819ee34426496ea7080f7cc52f0Dmitry Vyukov  MemoryRangeSet(thr, pc, addr, size, s.raw());
9047ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
9057ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
90626af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukovvoid MemoryRangeImitateWrite(ThreadState *thr, uptr pc, uptr addr, uptr size) {
9072d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  if (kCollectHistory) {
9082d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    thr->fast_state.IncrementEpoch();
9092d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    TraceAddEvent(thr, thr->fast_state, EventTypeMop, pc);
9102d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  }
91126af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov  Shadow s(thr->fast_state);
912064c84731c1cf41dcd7195c9380170b9aa6887b6Dmitry Vyukov  s.ClearIgnoreBit();
91326af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov  s.SetWrite(true);
91426af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov  s.SetAddr0AndSizeLog(0, 3);
91526af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov  MemoryRangeSet(thr, pc, addr, size, s.raw());
91626af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov}
91726af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov
918d475aa8578f4a1955cdb3e3159eda8b229f8c021Kostya SerebryanyALWAYS_INLINE USED
9197ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid FuncEntry(ThreadState *thr, uptr pc) {
9207ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  StatInc(thr, StatFuncEnter);
92125d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov  DPrintf2("#%d: FuncEntry %p\n", (int)thr->fast_state.tid(), (void*)pc);
9222d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  if (kCollectHistory) {
9232d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    thr->fast_state.IncrementEpoch();
9242d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    TraceAddEvent(thr, thr->fast_state, EventTypeFuncEnter, pc);
9252d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  }
9267ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
9277ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // Shadow stack maintenance can be replaced with
9287ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // stack unwinding during trace switch (which presumably must be faster).
92901a7ce809bf7cc627d73c045c70bcca9891f632cDmitry Vyukov  DCHECK_GE(thr->shadow_stack_pos, thr->shadow_stack);
93086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#ifndef SANITIZER_GO
93101a7ce809bf7cc627d73c045c70bcca9891f632cDmitry Vyukov  DCHECK_LT(thr->shadow_stack_pos, thr->shadow_stack_end);
93225d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov#else
9336a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines  if (thr->shadow_stack_pos == thr->shadow_stack_end)
9346a211c5814e25d6745a5058cc0e499e5235d3821Stephen Hines    GrowShadowStack(thr);
93525d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov#endif
9367ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  thr->shadow_stack_pos[0] = pc;
9377ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  thr->shadow_stack_pos++;
9387ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
9397ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
940d475aa8578f4a1955cdb3e3159eda8b229f8c021Kostya SerebryanyALWAYS_INLINE USED
9417ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid FuncExit(ThreadState *thr) {
9427ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  StatInc(thr, StatFuncExit);
94325d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov  DPrintf2("#%d: FuncExit\n", (int)thr->fast_state.tid());
9442d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  if (kCollectHistory) {
9452d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    thr->fast_state.IncrementEpoch();
9462d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    TraceAddEvent(thr, thr->fast_state, EventTypeFuncExit, 0);
9472d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  }
9487ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
94901a7ce809bf7cc627d73c045c70bcca9891f632cDmitry Vyukov  DCHECK_GT(thr->shadow_stack_pos, thr->shadow_stack);
95086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#ifndef SANITIZER_GO
95101a7ce809bf7cc627d73c045c70bcca9891f632cDmitry Vyukov  DCHECK_LT(thr->shadow_stack_pos, thr->shadow_stack_end);
95225d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov#endif
9537ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  thr->shadow_stack_pos--;
9547ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
9557ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
9562d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid ThreadIgnoreBegin(ThreadState *thr, uptr pc) {
957652f78a41de2887aedc1b0314b58bb6b622c80caDmitry Vyukov  DPrintf("#%d: ThreadIgnoreBegin\n", thr->tid);
958652f78a41de2887aedc1b0314b58bb6b622c80caDmitry Vyukov  thr->ignore_reads_and_writes++;
959e1ddbf9a458e81125a03fea721997565124294aeDmitry Vyukov  CHECK_GT(thr->ignore_reads_and_writes, 0);
960652f78a41de2887aedc1b0314b58bb6b622c80caDmitry Vyukov  thr->fast_state.SetIgnoreBit();
96186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#ifndef SANITIZER_GO
9622d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  if (!ctx->after_multithreaded_fork)
9632d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    thr->mop_ignore_set.Add(CurrentStackId(thr, pc));
9642d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
965652f78a41de2887aedc1b0314b58bb6b622c80caDmitry Vyukov}
966652f78a41de2887aedc1b0314b58bb6b622c80caDmitry Vyukov
9672d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid ThreadIgnoreEnd(ThreadState *thr, uptr pc) {
968652f78a41de2887aedc1b0314b58bb6b622c80caDmitry Vyukov  DPrintf("#%d: ThreadIgnoreEnd\n", thr->tid);
969652f78a41de2887aedc1b0314b58bb6b622c80caDmitry Vyukov  thr->ignore_reads_and_writes--;
970652f78a41de2887aedc1b0314b58bb6b622c80caDmitry Vyukov  CHECK_GE(thr->ignore_reads_and_writes, 0);
9712d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  if (thr->ignore_reads_and_writes == 0) {
9727ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    thr->fast_state.ClearIgnoreBit();
97386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#ifndef SANITIZER_GO
9742d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    thr->mop_ignore_set.Reset();
9752d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
9762d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  }
9777ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
9787ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
9792d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid ThreadIgnoreSyncBegin(ThreadState *thr, uptr pc) {
980e1ddbf9a458e81125a03fea721997565124294aeDmitry Vyukov  DPrintf("#%d: ThreadIgnoreSyncBegin\n", thr->tid);
981e1ddbf9a458e81125a03fea721997565124294aeDmitry Vyukov  thr->ignore_sync++;
982e1ddbf9a458e81125a03fea721997565124294aeDmitry Vyukov  CHECK_GT(thr->ignore_sync, 0);
98386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#ifndef SANITIZER_GO
9842d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  if (!ctx->after_multithreaded_fork)
9852d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    thr->sync_ignore_set.Add(CurrentStackId(thr, pc));
9862d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
987e1ddbf9a458e81125a03fea721997565124294aeDmitry Vyukov}
988e1ddbf9a458e81125a03fea721997565124294aeDmitry Vyukov
9892d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid ThreadIgnoreSyncEnd(ThreadState *thr, uptr pc) {
990e1ddbf9a458e81125a03fea721997565124294aeDmitry Vyukov  DPrintf("#%d: ThreadIgnoreSyncEnd\n", thr->tid);
991e1ddbf9a458e81125a03fea721997565124294aeDmitry Vyukov  thr->ignore_sync--;
992e1ddbf9a458e81125a03fea721997565124294aeDmitry Vyukov  CHECK_GE(thr->ignore_sync, 0);
99386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#ifndef SANITIZER_GO
9942d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  if (thr->ignore_sync == 0)
9952d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    thr->sync_ignore_set.Reset();
9962d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
997e1ddbf9a458e81125a03fea721997565124294aeDmitry Vyukov}
998e1ddbf9a458e81125a03fea721997565124294aeDmitry Vyukov
999b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukovbool MD5Hash::operator==(const MD5Hash &other) const {
1000b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov  return hash[0] == other.hash[0] && hash[1] == other.hash[1];
1001b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov}
1002b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov
100386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#if SANITIZER_DEBUG
10047ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid build_consistency_debug() {}
10057ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#else
10067ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid build_consistency_release() {}
10077ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#endif
10087ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
10097ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#if TSAN_COLLECT_STATS
10107ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid build_consistency_stats() {}
10117ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#else
10127ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid build_consistency_nostats() {}
10137ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#endif
10147ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
10157ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}  // namespace __tsan
10167ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
101786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#ifndef SANITIZER_GO
10187ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// Must be included in this file to make sure everything is inlined.
10197ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_interface_inl.h"
1020b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#endif
1021