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