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