tsan_rtl.cc revision 68230a12bbd22c9402dd8f9af027fcb2e119f978
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
407ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic Context *ctx;
417ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyContext *CTX() {
427ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return ctx;
437ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
447ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
457ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyContext::Context()
467ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  : initialized()
477ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  , report_mtx(MutexTypeReport, StatMtxReport)
487ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  , nreported()
497ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  , nmissed_expected()
507ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  , thread_mtx(MutexTypeThreads, StatMtxThreads)
517ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  , racy_stacks(MBlockRacyStacks)
52158c6ac3bb46753db217f9c2c73485811a3a1890Dmitry Vyukov  , racy_addresses(MBlockRacyAddresses)
53158c6ac3bb46753db217f9c2c73485811a3a1890Dmitry Vyukov  , fired_suppressions(MBlockRacyAddresses) {
547ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
557ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
567ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// The objects are allocated in TLS, so one may rely on zero-initialization.
57ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry VyukovThreadState::ThreadState(Context *ctx, int tid, int unique_id, u64 epoch,
587ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany                         uptr stk_addr, uptr stk_size,
597ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany                         uptr tls_addr, uptr tls_size)
607ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  : fast_state(tid, epoch)
617ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // Do not touch these, rely on zero initialization,
627ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // they may be accessed before the ctor.
637ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // , fast_ignore_reads()
647ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // , fast_ignore_writes()
657ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // , in_rtl()
667ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  , shadow_stack_pos(&shadow_stack[0])
677ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  , tid(tid)
68ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry Vyukov  , unique_id(unique_id)
697ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  , stk_addr(stk_addr)
707ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  , stk_size(stk_size)
717ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  , tls_addr(tls_addr)
727ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  , tls_size(tls_size) {
737ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
747ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
757ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyThreadContext::ThreadContext(int tid)
767ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  : tid(tid)
777ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  , unique_id()
787dccf3f92a867f917ad19f9a6b37bcf93e64b35bDmitry Vyukov  , os_id()
797ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  , user_id()
807ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  , thr()
817ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  , status(ThreadStatusInvalid)
827ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  , detached()
837ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  , reuse_count()
847ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  , epoch0()
857ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  , epoch1()
869d2ffc2ee08216f8fad9b1bd267d1f112e0d2f01Dmitry Vyukov  , dead_info()
87aecf2e5756c6a0de7c146bef67a6e338c7017d55Dmitry Vyukov  , dead_next()
88aecf2e5756c6a0de7c146bef67a6e338c7017d55Dmitry Vyukov  , name() {
897ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
907ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
9126127735454fddae3495794f38189d57dde6510fDmitry Vyukovstatic void WriteMemoryProfile(char *buf, uptr buf_size, int num) {
9226127735454fddae3495794f38189d57dde6510fDmitry Vyukov  uptr shadow = GetShadowMemoryConsumption();
9326127735454fddae3495794f38189d57dde6510fDmitry Vyukov
9426127735454fddae3495794f38189d57dde6510fDmitry Vyukov  int nthread = 0;
9526127735454fddae3495794f38189d57dde6510fDmitry Vyukov  int nlivethread = 0;
9626127735454fddae3495794f38189d57dde6510fDmitry Vyukov  uptr threadmem = 0;
9726127735454fddae3495794f38189d57dde6510fDmitry Vyukov  {
9826127735454fddae3495794f38189d57dde6510fDmitry Vyukov    Lock l(&ctx->thread_mtx);
9926127735454fddae3495794f38189d57dde6510fDmitry Vyukov    for (unsigned i = 0; i < kMaxTid; i++) {
10026127735454fddae3495794f38189d57dde6510fDmitry Vyukov      ThreadContext *tctx = ctx->threads[i];
10126127735454fddae3495794f38189d57dde6510fDmitry Vyukov      if (tctx == 0)
10226127735454fddae3495794f38189d57dde6510fDmitry Vyukov        continue;
10326127735454fddae3495794f38189d57dde6510fDmitry Vyukov      nthread += 1;
10426127735454fddae3495794f38189d57dde6510fDmitry Vyukov      threadmem += sizeof(ThreadContext);
10526127735454fddae3495794f38189d57dde6510fDmitry Vyukov      if (tctx->status != ThreadStatusRunning)
10626127735454fddae3495794f38189d57dde6510fDmitry Vyukov        continue;
10726127735454fddae3495794f38189d57dde6510fDmitry Vyukov      nlivethread += 1;
10826127735454fddae3495794f38189d57dde6510fDmitry Vyukov      threadmem += sizeof(ThreadState);
10926127735454fddae3495794f38189d57dde6510fDmitry Vyukov    }
11026127735454fddae3495794f38189d57dde6510fDmitry Vyukov  }
11126127735454fddae3495794f38189d57dde6510fDmitry Vyukov
11226127735454fddae3495794f38189d57dde6510fDmitry Vyukov  uptr nsync = 0;
11326127735454fddae3495794f38189d57dde6510fDmitry Vyukov  uptr syncmem = CTX()->synctab.GetMemoryConsumption(&nsync);
11426127735454fddae3495794f38189d57dde6510fDmitry Vyukov
115de08c02aa3007a590bfb7d43f31d5b1a0e7d337cAlexey Samsonov  internal_snprintf(buf, buf_size, "%d: shadow=%zuMB"
116de08c02aa3007a590bfb7d43f31d5b1a0e7d337cAlexey Samsonov                                   " thread=%zuMB(total=%d/live=%d)"
117de08c02aa3007a590bfb7d43f31d5b1a0e7d337cAlexey Samsonov                                   " sync=%zuMB(cnt=%zu)\n",
11826127735454fddae3495794f38189d57dde6510fDmitry Vyukov    num,
11926127735454fddae3495794f38189d57dde6510fDmitry Vyukov    shadow >> 20,
12026127735454fddae3495794f38189d57dde6510fDmitry Vyukov    threadmem >> 20, nthread, nlivethread,
12126127735454fddae3495794f38189d57dde6510fDmitry Vyukov    syncmem >> 20, nsync);
12226127735454fddae3495794f38189d57dde6510fDmitry Vyukov}
12326127735454fddae3495794f38189d57dde6510fDmitry Vyukov
12426127735454fddae3495794f38189d57dde6510fDmitry Vyukovstatic void MemoryProfileThread(void *arg) {
12526127735454fddae3495794f38189d57dde6510fDmitry Vyukov  ScopedInRtl in_rtl;
12626127735454fddae3495794f38189d57dde6510fDmitry Vyukov  fd_t fd = (fd_t)(uptr)arg;
12726127735454fddae3495794f38189d57dde6510fDmitry Vyukov  for (int i = 0; ; i++) {
12814c8bd7250742749e44e306c02a56cf47ad1db82Alexey Samsonov    InternalScopedBuffer<char> buf(4096);
1291dc4cf7e253aefa3ce3bd4a1d349a13647e8b2eaAlexey Samsonov    WriteMemoryProfile(buf.data(), buf.size(), i);
1301dc4cf7e253aefa3ce3bd4a1d349a13647e8b2eaAlexey Samsonov    internal_write(fd, buf.data(), internal_strlen(buf.data()));
1310969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov    SleepForSeconds(1);
13226127735454fddae3495794f38189d57dde6510fDmitry Vyukov  }
13326127735454fddae3495794f38189d57dde6510fDmitry Vyukov}
13426127735454fddae3495794f38189d57dde6510fDmitry Vyukov
13526127735454fddae3495794f38189d57dde6510fDmitry Vyukovstatic void InitializeMemoryProfile() {
13626127735454fddae3495794f38189d57dde6510fDmitry Vyukov  if (flags()->profile_memory == 0 || flags()->profile_memory[0] == 0)
13726127735454fddae3495794f38189d57dde6510fDmitry Vyukov    return;
13814c8bd7250742749e44e306c02a56cf47ad1db82Alexey Samsonov  InternalScopedBuffer<char> filename(4096);
1391dc4cf7e253aefa3ce3bd4a1d349a13647e8b2eaAlexey Samsonov  internal_snprintf(filename.data(), filename.size(), "%s.%d",
14026127735454fddae3495794f38189d57dde6510fDmitry Vyukov      flags()->profile_memory, GetPid());
1411dc4cf7e253aefa3ce3bd4a1d349a13647e8b2eaAlexey Samsonov  fd_t fd = internal_open(filename.data(), true);
14226127735454fddae3495794f38189d57dde6510fDmitry Vyukov  if (fd == kInvalidFd) {
143b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov    Printf("Failed to open memory profile file '%s'\n", &filename[0]);
14426127735454fddae3495794f38189d57dde6510fDmitry Vyukov    Die();
14526127735454fddae3495794f38189d57dde6510fDmitry Vyukov  }
14626127735454fddae3495794f38189d57dde6510fDmitry Vyukov  internal_start_thread(&MemoryProfileThread, (void*)(uptr)fd);
14726127735454fddae3495794f38189d57dde6510fDmitry Vyukov}
14826127735454fddae3495794f38189d57dde6510fDmitry Vyukov
149adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukovstatic void MemoryFlushThread(void *arg) {
150adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov  ScopedInRtl in_rtl;
151adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov  for (int i = 0; ; i++) {
1520969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov    SleepForMillis(flags()->flush_memory_ms);
153adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov    FlushShadowMemory();
154adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov  }
155adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov}
156adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov
157adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukovstatic void InitializeMemoryFlush() {
158adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov  if (flags()->flush_memory_ms == 0)
159adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov    return;
160adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov  if (flags()->flush_memory_ms < 100)
161adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov    flags()->flush_memory_ms = 100;
162adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov  internal_start_thread(&MemoryFlushThread, 0);
163adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov}
164adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov
165a05fcc1e3e045097f2f1a20798cbe038bbb1d6a9Dmitry Vyukovvoid MapShadow(uptr addr, uptr size) {
1666b641c5e63be45a03f96346886d27c4b4135ddafDmitry Vyukov  MmapFixedNoReserve(MemToShadow(addr), size * kShadowMultiplier);
167a05fcc1e3e045097f2f1a20798cbe038bbb1d6a9Dmitry Vyukov}
168a05fcc1e3e045097f2f1a20798cbe038bbb1d6a9Dmitry Vyukov
1697ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid Initialize(ThreadState *thr) {
1707ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // Thread safe because done before all threads exist.
1717ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  static bool is_initialized = false;
1727ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (is_initialized)
1737ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    return;
1747ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  is_initialized = true;
175591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonov  // Install tool-specific callbacks in sanitizer_common.
176591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonov  SetCheckFailedCallback(TsanCheckFailed);
177591616d323d73b7ea7cd8fea4eec46cedccda27eAlexey Samsonov
1787ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  ScopedInRtl in_rtl;
179bbbb20b7212155ebc5b5b4ee1c68c987dcf30320Dmitry Vyukov#ifndef TSAN_GO
1802e87051d136db3150a3ca322d8862f92b0a684bbDmitry Vyukov  InitializeAllocator();
181bbbb20b7212155ebc5b5b4ee1c68c987dcf30320Dmitry Vyukov#endif
1827ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  InitializeInterceptors();
1837ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  const char *env = InitializePlatform();
1847ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  InitializeMutex();
1857ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  InitializeDynamicAnnotations();
1867ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  ctx = new(ctx_placeholder) Context;
187a05fcc1e3e045097f2f1a20798cbe038bbb1d6a9Dmitry Vyukov#ifndef TSAN_GO
1887ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  InitializeShadowMemory();
189a05fcc1e3e045097f2f1a20798cbe038bbb1d6a9Dmitry Vyukov#endif
1907ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  ctx->dead_list_size = 0;
1917ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  ctx->dead_list_head = 0;
1927ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  ctx->dead_list_tail = 0;
1937ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  InitializeFlags(&ctx->flags, env);
194b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov  // Setup correct file descriptor for error reports.
195cec6068bbbbfb84285c0856c196c48170924e215Dmitry Vyukov  if (internal_strcmp(flags()->log_path, "stdout") == 0)
196cec6068bbbbfb84285c0856c196c48170924e215Dmitry Vyukov    __sanitizer_set_report_fd(kStdoutFd);
197cec6068bbbbfb84285c0856c196c48170924e215Dmitry Vyukov  else if (internal_strcmp(flags()->log_path, "stderr") == 0)
198cec6068bbbbfb84285c0856c196c48170924e215Dmitry Vyukov    __sanitizer_set_report_fd(kStderrFd);
199cec6068bbbbfb84285c0856c196c48170924e215Dmitry Vyukov  else
200cec6068bbbbfb84285c0856c196c48170924e215Dmitry Vyukov    __sanitizer_set_report_path(flags()->log_path);
2017ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  InitializeSuppressions();
20285a6dad26739fcd9742eae04b4a539e29889e937Dmitry Vyukov#ifndef TSAN_GO
20368bdcc4db8802c9a6f72d0e684a336ab92a3785bAlexey Samsonov  // Initialize external symbolizer before internal threads are started.
2048cc1f81b2cc1fa0d4cda4f4635d955aed04c09c8Alexey Samsonov  const char *external_symbolizer = flags()->external_symbolizer_path;
2058cc1f81b2cc1fa0d4cda4f4635d955aed04c09c8Alexey Samsonov  if (external_symbolizer != 0 && external_symbolizer[0] != '\0') {
20693b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov    if (!InitializeExternalSymbolizer(external_symbolizer)) {
20793b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov      Printf("Failed to start external symbolizer: '%s'\n",
20893b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov             external_symbolizer);
20993b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov      Die();
21093b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov    }
2118cc1f81b2cc1fa0d4cda4f4635d955aed04c09c8Alexey Samsonov  }
21285a6dad26739fcd9742eae04b4a539e29889e937Dmitry Vyukov#endif
21368bdcc4db8802c9a6f72d0e684a336ab92a3785bAlexey Samsonov  InitializeMemoryProfile();
21468bdcc4db8802c9a6f72d0e684a336ab92a3785bAlexey Samsonov  InitializeMemoryFlush();
2158cc1f81b2cc1fa0d4cda4f4635d955aed04c09c8Alexey Samsonov
2167ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (ctx->flags.verbosity)
217b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov    Printf("***** Running under ThreadSanitizer v2 (pid %d) *****\n",
21867a64dd8259fdbd867633b27f54d584f435f1ce6Alexey Samsonov               GetPid());
2197ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
2207ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // Initialize thread 0.
2217ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  ctx->thread_seq = 0;
2227ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int tid = ThreadCreate(thr, 0, 0, true);
2237ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  CHECK_EQ(tid, 0);
2247dccf3f92a867f917ad19f9a6b37bcf93e64b35bDmitry Vyukov  ThreadStart(thr, tid, GetPid());
2257ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  CHECK_EQ(thr->in_rtl, 1);
2267ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  ctx->initialized = true;
2277ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
228adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov  if (flags()->stop_on_start) {
229b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov    Printf("ThreadSanitizer is suspended at startup (pid %d)."
230adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov           " Call __tsan_resume().\n",
231adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov           GetPid());
232adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov    while (__tsan_resumed == 0);
2337ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
2347ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
2357ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
2367ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyint Finalize(ThreadState *thr) {
2377ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  ScopedInRtl in_rtl;
2387ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  Context *ctx = __tsan::ctx;
2397ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  bool failed = false;
2407ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
24154e0a9a391616bbd2a4f0fd2d01076291274cb98Dmitry Vyukov  if (flags()->atexit_sleep_ms > 0 && ThreadCount(thr) > 1)
24254e0a9a391616bbd2a4f0fd2d01076291274cb98Dmitry Vyukov    SleepForMillis(flags()->atexit_sleep_ms);
24354e0a9a391616bbd2a4f0fd2d01076291274cb98Dmitry Vyukov
244d0a51c02157e8293ea365ad0d429ef8e73d115deDmitry Vyukov  // Wait for pending reports.
245d0a51c02157e8293ea365ad0d429ef8e73d115deDmitry Vyukov  ctx->report_mtx.Lock();
246d0a51c02157e8293ea365ad0d429ef8e73d115deDmitry Vyukov  ctx->report_mtx.Unlock();
247d0a51c02157e8293ea365ad0d429ef8e73d115deDmitry Vyukov
2487ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  ThreadFinalize(thr);
2497ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
2507ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (ctx->nreported) {
2517ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    failed = true;
252b3b21231dd9dfeb34f5f302c879f2d11b6312080Dmitry Vyukov#ifndef TSAN_GO
253b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov    Printf("ThreadSanitizer: reported %d warnings\n", ctx->nreported);
254b3b21231dd9dfeb34f5f302c879f2d11b6312080Dmitry Vyukov#else
255b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov    Printf("Found %d data race(s)\n", ctx->nreported);
256b3b21231dd9dfeb34f5f302c879f2d11b6312080Dmitry Vyukov#endif
2577ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
2587ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
2597ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (ctx->nmissed_expected) {
2607ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    failed = true;
261b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov    Printf("ThreadSanitizer: missed %d expected races\n",
2627ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany        ctx->nmissed_expected);
2637ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
2647ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
26508adb1815b4958df88f904b9780a055b0d387294Dmitry Vyukov  StatAggregate(ctx->stat, thr->stat);
2667ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  StatOutput(ctx->stat);
267b7b6b1cd9df0c954b1f890fcebf373db984923b3Dmitry Vyukov  return failed ? flags()->exitcode : 0;
2687ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
2697ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
2700ab628c61594eb80612e5389d9c33da0e0d70c66Dmitry Vyukov#ifndef TSAN_GO
271848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukovu32 CurrentStackId(ThreadState *thr, uptr pc) {
272848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov  if (thr->shadow_stack_pos == 0)  // May happen during bootstrap.
273848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov    return 0;
274848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov  if (pc) {
275848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov    thr->shadow_stack_pos[0] = pc;
276848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov    thr->shadow_stack_pos++;
277848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov  }
278848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov  u32 id = StackDepotPut(thr->shadow_stack,
279848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov                         thr->shadow_stack_pos - thr->shadow_stack);
280848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov  if (pc)
281848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov    thr->shadow_stack_pos--;
282848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov  return id;
283848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov}
2840ab628c61594eb80612e5389d9c33da0e0d70c66Dmitry Vyukov#endif
285848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov
286b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukovvoid TraceSwitch(ThreadState *thr) {
2879ad7c32720dfa1287f8cfd481e5d583435178caeDmitry Vyukov  thr->nomalloc++;
2887ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  ScopedInRtl in_rtl;
2897ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  Lock l(&thr->trace.mtx);
2900415ac00935795a70d87ae662ccad58ea0704537Dmitry Vyukov  unsigned trace = (thr->fast_state.epoch() / kTracePartSize) % TraceParts();
2917ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TraceHeader *hdr = &thr->trace.headers[trace];
2927ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  hdr->epoch0 = thr->fast_state.epoch();
2937ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  hdr->stack0.ObtainCurrent(thr, 0);
294ad9da372f962495b3487685232d09390be841b1cDmitry Vyukov  hdr->mset0 = thr->mset;
2959ad7c32720dfa1287f8cfd481e5d583435178caeDmitry Vyukov  thr->nomalloc--;
2967ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
2977ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
298385542a2e83a4f37de4232d6c72097c1b7d6d44bDmitry Vyukovuptr TraceTopPC(ThreadState *thr) {
299385542a2e83a4f37de4232d6c72097c1b7d6d44bDmitry Vyukov  Event *events = (Event*)GetThreadTrace(thr->tid);
300d698edc4f74a17048eef3342a9fa42b3ebba802aDmitry Vyukov  uptr pc = events[thr->fast_state.GetTracePos()];
301385542a2e83a4f37de4232d6c72097c1b7d6d44bDmitry Vyukov  return pc;
302385542a2e83a4f37de4232d6c72097c1b7d6d44bDmitry Vyukov}
303385542a2e83a4f37de4232d6c72097c1b7d6d44bDmitry Vyukov
304d698edc4f74a17048eef3342a9fa42b3ebba802aDmitry Vyukovuptr TraceSize() {
305d698edc4f74a17048eef3342a9fa42b3ebba802aDmitry Vyukov  return (uptr)(1ull << (kTracePartSizeBits + flags()->history_size + 1));
306d698edc4f74a17048eef3342a9fa42b3ebba802aDmitry Vyukov}
307d698edc4f74a17048eef3342a9fa42b3ebba802aDmitry Vyukov
3080415ac00935795a70d87ae662ccad58ea0704537Dmitry Vyukovuptr TraceParts() {
3090415ac00935795a70d87ae662ccad58ea0704537Dmitry Vyukov  return TraceSize() / kTracePartSize;
3100415ac00935795a70d87ae662ccad58ea0704537Dmitry Vyukov}
3110415ac00935795a70d87ae662ccad58ea0704537Dmitry Vyukov
312b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#ifndef TSAN_GO
3137ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyextern "C" void __tsan_trace_switch() {
3147ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TraceSwitch(cur_thread());
3157ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
3167ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
3177ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyextern "C" void __tsan_report_race() {
3187ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  ReportRace(cur_thread());
3197ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
320b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#endif
3217ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
3227ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyALWAYS_INLINE
3237ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic Shadow LoadShadow(u64 *p) {
3247ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  u64 raw = atomic_load((atomic_uint64_t*)p, memory_order_relaxed);
3257ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return Shadow(raw);
3267ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
3277ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
3287ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyALWAYS_INLINE
3297ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic void StoreShadow(u64 *sp, u64 s) {
3307ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  atomic_store((atomic_uint64_t*)sp, s, memory_order_relaxed);
3317ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
3327ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
3337ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyALWAYS_INLINE
3347ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic void StoreIfNotYetStored(u64 *sp, u64 *s) {
3357ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  StoreShadow(sp, *s);
3367ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  *s = 0;
3377ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
3387ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
3397ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic inline void HandleRace(ThreadState *thr, u64 *shadow_mem,
3407ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany                              Shadow cur, Shadow old) {
3417ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  thr->racy_state[0] = cur.raw();
3427ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  thr->racy_state[1] = old.raw();
3437ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  thr->racy_shadow_addr = shadow_mem;
344b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#ifndef TSAN_GO
3457ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  HACKY_CALL(__tsan_report_race);
346b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#else
347b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov  ReportRace(thr);
348b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#endif
3497ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
3507ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
3517ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic inline bool BothReads(Shadow s, int kAccessIsWrite) {
3527ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return !kAccessIsWrite && !s.is_write();
3537ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
3547ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
355ed77156ba3c5754b4cfe4ca1d6d5d7a4fdfb7835Dmitry Vyukovstatic inline bool OldIsRWNotWeaker(Shadow old, int kAccessIsWrite) {
3567ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return old.is_write() || !kAccessIsWrite;
3577ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
3587ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
359ed77156ba3c5754b4cfe4ca1d6d5d7a4fdfb7835Dmitry Vyukovstatic inline bool OldIsRWWeakerOrEqual(Shadow old, int kAccessIsWrite) {
3607ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return !old.is_write() || kAccessIsWrite;
3617ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
3627ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
3637ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic inline bool OldIsInSameSynchEpoch(Shadow old, ThreadState *thr) {
3647ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return old.epoch() >= thr->fast_synch_epoch;
3657ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
3667ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
3677ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic inline bool HappensBefore(Shadow old, ThreadState *thr) {
368c8f0a00ede42f83ac79ff63c347ca8ddcda77155Dmitry Vyukov  return thr->clock.get(old.TidWithIgnore()) >= old.epoch();
3697ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
3707ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
3717ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyALWAYS_INLINE
3727ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid MemoryAccessImpl(ThreadState *thr, uptr addr,
373bd9f4963dd50f2fe66ba47a74776dc2665f84d7dDmitry Vyukov    int kAccessSizeLog, bool kAccessIsWrite,
3747ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    u64 *shadow_mem, Shadow cur) {
3757ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  StatInc(thr, StatMop);
3767ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  StatInc(thr, kAccessIsWrite ? StatMopWrite : StatMopRead);
3777ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  StatInc(thr, (StatType)(StatMop1 + kAccessSizeLog));
3787ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
3797ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // This potentially can live in an MMX/SSE scratch register.
3807ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // The required intrinsics are:
3817ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // __m128i _mm_move_epi64(__m128i*);
3827ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // _mm_storel_epi64(u64*, __m128i);
3837ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  u64 store_word = cur.raw();
3847ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
3857ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // scan all the shadow values and dispatch to 4 categories:
3867ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // same, replace, candidate and race (see comments below).
3877ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // we consider only 3 cases regarding access sizes:
3887ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // equal, intersect and not intersect. initially I considered
3897ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // larger and smaller as well, it allowed to replace some
3907ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // 'candidates' with 'same' or 'replace', but I think
3917ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // it's just not worth it (performance- and complexity-wise).
3927ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
3937ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  Shadow old(0);
3947ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (kShadowCnt == 1) {
3957ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    int idx = 0;
3967ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h"
3977ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  } else if (kShadowCnt == 2) {
3987ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    int idx = 0;
3997ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h"
4007ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    idx = 1;
4017ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h"
4027ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  } else if (kShadowCnt == 4) {
4037ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    int idx = 0;
4047ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h"
4057ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    idx = 1;
4067ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h"
4077ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    idx = 2;
4087ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h"
4097ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    idx = 3;
4107ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h"
4117ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  } else if (kShadowCnt == 8) {
4127ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    int idx = 0;
4137ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h"
4147ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    idx = 1;
4157ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h"
4167ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    idx = 2;
4177ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h"
4187ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    idx = 3;
4197ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h"
4207ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    idx = 4;
4217ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h"
4227ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    idx = 5;
4237ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h"
4247ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    idx = 6;
4257ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h"
4267ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    idx = 7;
4277ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h"
4287ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  } else {
4297ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    CHECK(false);
4307ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
4317ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
4327ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // we did not find any races and had already stored
4337ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // the current access info, so we are done
4347ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (LIKELY(store_word == 0))
4357ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    return;
4367ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // choose a random candidate slot and replace it
4377ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  StoreShadow(shadow_mem + (cur.epoch() % kShadowCnt), store_word);
4387ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  StatInc(thr, StatShadowReplace);
4397ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return;
4407ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany RACE:
4417ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  HandleRace(thr, shadow_mem, cur, old);
4427ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return;
4437ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
4447ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
4457ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyALWAYS_INLINE
4467ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid MemoryAccess(ThreadState *thr, uptr pc, uptr addr,
4477ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    int kAccessSizeLog, bool kAccessIsWrite) {
4487ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  u64 *shadow_mem = (u64*)MemToShadow(addr);
44968230a12bbd22c9402dd8f9af027fcb2e119f978Dmitry Vyukov  DPrintf2("#%d: MemoryAccess: @%p %p size=%d"
450e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov      " is_write=%d shadow_mem=%p {%zx, %zx, %zx, %zx}\n",
4517ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany      (int)thr->fast_state.tid(), (void*)pc, (void*)addr,
4527ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany      (int)(1 << kAccessSizeLog), kAccessIsWrite, shadow_mem,
453e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov      (uptr)shadow_mem[0], (uptr)shadow_mem[1],
454e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov      (uptr)shadow_mem[2], (uptr)shadow_mem[3]);
4557ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#if TSAN_DEBUG
4567ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (!IsAppMem(addr)) {
457b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov    Printf("Access to non app mem %zx\n", addr);
4587ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    DCHECK(IsAppMem(addr));
4597ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
4607ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (!IsShadowMem((uptr)shadow_mem)) {
461b1fe3021eca0843e37878d224ee7f32e32f40d99Alexey Samsonov    Printf("Bad shadow addr %p (%zx)\n", shadow_mem, addr);
4627ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    DCHECK(IsShadowMem((uptr)shadow_mem));
4637ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
4647ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#endif
4657ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
4667ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  FastState fast_state = thr->fast_state;
4677ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (fast_state.GetIgnoreBit())
4687ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    return;
4697ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  fast_state.IncrementEpoch();
4707ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  thr->fast_state = fast_state;
4717ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  Shadow cur(fast_state);
4727ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  cur.SetAddr0AndSizeLog(addr & 7, kAccessSizeLog);
4737ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  cur.SetWrite(kAccessIsWrite);
4747ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
4757ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // We must not store to the trace if we do not store to the shadow.
4767ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // That is, this call must be moved somewhere below.
477385542a2e83a4f37de4232d6c72097c1b7d6d44bDmitry Vyukov  TraceAddEvent(thr, fast_state, EventTypeMop, pc);
4787ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
479bd9f4963dd50f2fe66ba47a74776dc2665f84d7dDmitry Vyukov  MemoryAccessImpl(thr, addr, kAccessSizeLog, kAccessIsWrite,
4807ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany      shadow_mem, cur);
4817ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
4827ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
4837ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic void MemoryRangeSet(ThreadState *thr, uptr pc, uptr addr, uptr size,
4847ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany                           u64 val) {
4857ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (size == 0)
4867ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    return;
4877ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // FIXME: fix me.
4887ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  uptr offset = addr % kShadowCell;
4897ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (offset) {
4907ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    offset = kShadowCell - offset;
4917ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    if (size <= offset)
4927ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany      return;
4937ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    addr += offset;
4947ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    size -= offset;
4957ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
496aaac6e206453574d0130f2ae8d743f630d0c0a42Dmitry Vyukov  DCHECK_EQ(addr % 8, 0);
497aaac6e206453574d0130f2ae8d743f630d0c0a42Dmitry Vyukov  // If a user passes some insane arguments (memset(0)),
498aaac6e206453574d0130f2ae8d743f630d0c0a42Dmitry Vyukov  // let it just crash as usual.
499aaac6e206453574d0130f2ae8d743f630d0c0a42Dmitry Vyukov  if (!IsAppMem(addr) || !IsAppMem(addr + size - 1))
500aaac6e206453574d0130f2ae8d743f630d0c0a42Dmitry Vyukov    return;
5017ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  (void)thr;
5027ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  (void)pc;
5037ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // Some programs mmap like hundreds of GBs but actually used a small part.
5047ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // So, it's better to report a false positive on the memory
5057ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // then to hang here senselessly.
5069c6c5a26ec1e49f379515d2403b8b206bf2755c3Dmitry Vyukov  const uptr kMaxResetSize = 4ull*1024*1024*1024;
5077ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (size > kMaxResetSize)
5087ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    size = kMaxResetSize;
50926af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov  size = (size + (kShadowCell - 1)) & ~(kShadowCell - 1);
5107ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  u64 *p = (u64*)MemToShadow(addr);
5117ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  CHECK(IsShadowMem((uptr)p));
5127ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  CHECK(IsShadowMem((uptr)(p + size * kShadowCnt / kShadowCell - 1)));
5137ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // FIXME: may overwrite a part outside the region
51426af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov  for (uptr i = 0; i < size * kShadowCnt / kShadowCell;) {
51526af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov    p[i++] = val;
51626af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov    for (uptr j = 1; j < kShadowCnt; j++)
51726af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov      p[i++] = 0;
51826af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov  }
5197ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
5207ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
5217ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid MemoryResetRange(ThreadState *thr, uptr pc, uptr addr, uptr size) {
5227ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  MemoryRangeSet(thr, pc, addr, size, 0);
5237ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
5247ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
5257ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid MemoryRangeFreed(ThreadState *thr, uptr pc, uptr addr, uptr size) {
5267ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  MemoryAccessRange(thr, pc, addr, size, true);
527069ce828e3057819ee34426496ea7080f7cc52f0Dmitry Vyukov  Shadow s(thr->fast_state);
528064c84731c1cf41dcd7195c9380170b9aa6887b6Dmitry Vyukov  s.ClearIgnoreBit();
529069ce828e3057819ee34426496ea7080f7cc52f0Dmitry Vyukov  s.MarkAsFreed();
530069ce828e3057819ee34426496ea7080f7cc52f0Dmitry Vyukov  s.SetWrite(true);
531069ce828e3057819ee34426496ea7080f7cc52f0Dmitry Vyukov  s.SetAddr0AndSizeLog(0, 3);
532069ce828e3057819ee34426496ea7080f7cc52f0Dmitry Vyukov  MemoryRangeSet(thr, pc, addr, size, s.raw());
5337ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
5347ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
53526af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukovvoid MemoryRangeImitateWrite(ThreadState *thr, uptr pc, uptr addr, uptr size) {
53626af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov  Shadow s(thr->fast_state);
537064c84731c1cf41dcd7195c9380170b9aa6887b6Dmitry Vyukov  s.ClearIgnoreBit();
53826af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov  s.SetWrite(true);
53926af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov  s.SetAddr0AndSizeLog(0, 3);
54026af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov  MemoryRangeSet(thr, pc, addr, size, s.raw());
54126af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov}
54226af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov
5436fa4cc3a81713a392b2f3e8e7d6ad411e4b3f421Dmitry VyukovALWAYS_INLINE
5447ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid FuncEntry(ThreadState *thr, uptr pc) {
5457ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  DCHECK_EQ(thr->in_rtl, 0);
5467ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  StatInc(thr, StatFuncEnter);
54725d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov  DPrintf2("#%d: FuncEntry %p\n", (int)thr->fast_state.tid(), (void*)pc);
5487ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  thr->fast_state.IncrementEpoch();
549385542a2e83a4f37de4232d6c72097c1b7d6d44bDmitry Vyukov  TraceAddEvent(thr, thr->fast_state, EventTypeFuncEnter, pc);
5507ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
5517ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // Shadow stack maintenance can be replaced with
5527ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // stack unwinding during trace switch (which presumably must be faster).
553769544eed418993abb8efcb4ea939ed5c93a5ba2Dmitry Vyukov  DCHECK_GE(thr->shadow_stack_pos, &thr->shadow_stack[0]);
55425d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov#ifndef TSAN_GO
555769544eed418993abb8efcb4ea939ed5c93a5ba2Dmitry Vyukov  DCHECK_LT(thr->shadow_stack_pos, &thr->shadow_stack[kShadowStackSize]);
55625d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov#else
55725d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov  if (thr->shadow_stack_pos == thr->shadow_stack_end) {
55825d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov    const int sz = thr->shadow_stack_end - thr->shadow_stack;
55925d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov    const int newsz = 2 * sz;
56025d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov    uptr *newstack = (uptr*)internal_alloc(MBlockShadowStack,
56125d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov        newsz * sizeof(uptr));
56225d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov    internal_memcpy(newstack, thr->shadow_stack, sz * sizeof(uptr));
56325d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov    internal_free(thr->shadow_stack);
56425d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov    thr->shadow_stack = newstack;
56525d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov    thr->shadow_stack_pos = newstack + sz;
56625d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov    thr->shadow_stack_end = newstack + newsz;
56725d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov  }
56825d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov#endif
5697ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  thr->shadow_stack_pos[0] = pc;
5707ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  thr->shadow_stack_pos++;
5717ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
5727ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
5736fa4cc3a81713a392b2f3e8e7d6ad411e4b3f421Dmitry VyukovALWAYS_INLINE
5747ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid FuncExit(ThreadState *thr) {
5757ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  DCHECK_EQ(thr->in_rtl, 0);
5767ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  StatInc(thr, StatFuncExit);
57725d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov  DPrintf2("#%d: FuncExit\n", (int)thr->fast_state.tid());
5787ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  thr->fast_state.IncrementEpoch();
579385542a2e83a4f37de4232d6c72097c1b7d6d44bDmitry Vyukov  TraceAddEvent(thr, thr->fast_state, EventTypeFuncExit, 0);
5807ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
581769544eed418993abb8efcb4ea939ed5c93a5ba2Dmitry Vyukov  DCHECK_GT(thr->shadow_stack_pos, &thr->shadow_stack[0]);
58225d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov#ifndef TSAN_GO
583769544eed418993abb8efcb4ea939ed5c93a5ba2Dmitry Vyukov  DCHECK_LT(thr->shadow_stack_pos, &thr->shadow_stack[kShadowStackSize]);
58425d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov#endif
5857ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  thr->shadow_stack_pos--;
5867ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
5877ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
5887ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid IgnoreCtl(ThreadState *thr, bool write, bool begin) {
5897ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  DPrintf("#%d: IgnoreCtl(%d, %d)\n", thr->tid, write, begin);
5907ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  thr->ignore_reads_and_writes += begin ? 1 : -1;
5917ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  CHECK_GE(thr->ignore_reads_and_writes, 0);
5927ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (thr->ignore_reads_and_writes)
5937ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    thr->fast_state.SetIgnoreBit();
5947ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  else
5957ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    thr->fast_state.ClearIgnoreBit();
5967ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
5977ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
598b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukovbool MD5Hash::operator==(const MD5Hash &other) const {
599b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov  return hash[0] == other.hash[0] && hash[1] == other.hash[1];
600b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov}
601b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov
6027ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#if TSAN_DEBUG
6037ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid build_consistency_debug() {}
6047ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#else
6057ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid build_consistency_release() {}
6067ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#endif
6077ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
6087ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#if TSAN_COLLECT_STATS
6097ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid build_consistency_stats() {}
6107ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#else
6117ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid build_consistency_nostats() {}
6127ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#endif
6137ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
6147ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#if TSAN_SHADOW_COUNT == 1
6157ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid build_consistency_shadow1() {}
6167ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#elif TSAN_SHADOW_COUNT == 2
6177ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid build_consistency_shadow2() {}
6187ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#elif TSAN_SHADOW_COUNT == 4
6197ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid build_consistency_shadow4() {}
6207ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#else
6217ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid build_consistency_shadow8() {}
6227ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#endif
6237ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
6247ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}  // namespace __tsan
6257ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
626b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#ifndef TSAN_GO
6277ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// Must be included in this file to make sure everything is inlined.
6287ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_interface_inl.h"
629b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#endif
630