tsan_rtl.cc revision 848531192777acecf79747dc7c1ffeedf5c1da9f
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"
207ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_defs.h"
217ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_platform.h"
227ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_rtl.h"
237ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_mman.h"
247ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_suppressions.h"
257ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
26adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukovvolatile int __tsan_resumed = 0;
277ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
287ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyextern "C" void __tsan_resume() {
29adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov  __tsan_resumed = 1;
307ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
317ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
327ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanynamespace __tsan {
337ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
34b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#ifndef TSAN_GO
350a4c906dbc8f150657ddd4f19a7192b779f1d605Alexey SamsonovTHREADLOCAL char cur_thread_placeholder[sizeof(ThreadState)] ALIGNED(64);
36b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#endif
370a4c906dbc8f150657ddd4f19a7192b779f1d605Alexey Samsonovstatic char ctx_placeholder[sizeof(Context)] ALIGNED(64);
387ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
397ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic Context *ctx;
407ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyContext *CTX() {
417ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return ctx;
427ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
437ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
447ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyContext::Context()
457ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  : initialized()
467ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  , report_mtx(MutexTypeReport, StatMtxReport)
477ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  , nreported()
487ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  , nmissed_expected()
497ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  , thread_mtx(MutexTypeThreads, StatMtxThreads)
507ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  , racy_stacks(MBlockRacyStacks)
517ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  , racy_addresses(MBlockRacyAddresses) {
527ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
537ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
547ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// The objects are allocated in TLS, so one may rely on zero-initialization.
55ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry VyukovThreadState::ThreadState(Context *ctx, int tid, int unique_id, u64 epoch,
567ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany                         uptr stk_addr, uptr stk_size,
577ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany                         uptr tls_addr, uptr tls_size)
587ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  : fast_state(tid, epoch)
597ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // Do not touch these, rely on zero initialization,
607ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // they may be accessed before the ctor.
617ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // , fast_ignore_reads()
627ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // , fast_ignore_writes()
637ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // , in_rtl()
647ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  , shadow_stack_pos(&shadow_stack[0])
657ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  , tid(tid)
66ff35f1d82b4f145b3477ef27a7a2e7b63c486988Dmitry Vyukov  , unique_id(unique_id)
677ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  , stk_addr(stk_addr)
687ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  , stk_size(stk_size)
697ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  , tls_addr(tls_addr)
707ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  , tls_size(tls_size) {
717ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
727ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
737ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyThreadContext::ThreadContext(int tid)
747ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  : tid(tid)
757ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  , unique_id()
767ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  , user_id()
777ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  , thr()
787ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  , status(ThreadStatusInvalid)
797ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  , detached()
807ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  , reuse_count()
817ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  , epoch0()
827ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  , epoch1()
839d2ffc2ee08216f8fad9b1bd267d1f112e0d2f01Dmitry Vyukov  , dead_info()
847ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  , dead_next() {
857ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
867ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
8726127735454fddae3495794f38189d57dde6510fDmitry Vyukovstatic void WriteMemoryProfile(char *buf, uptr buf_size, int num) {
8826127735454fddae3495794f38189d57dde6510fDmitry Vyukov  uptr shadow = GetShadowMemoryConsumption();
8926127735454fddae3495794f38189d57dde6510fDmitry Vyukov
9026127735454fddae3495794f38189d57dde6510fDmitry Vyukov  int nthread = 0;
9126127735454fddae3495794f38189d57dde6510fDmitry Vyukov  int nlivethread = 0;
9226127735454fddae3495794f38189d57dde6510fDmitry Vyukov  uptr threadmem = 0;
9326127735454fddae3495794f38189d57dde6510fDmitry Vyukov  {
9426127735454fddae3495794f38189d57dde6510fDmitry Vyukov    Lock l(&ctx->thread_mtx);
9526127735454fddae3495794f38189d57dde6510fDmitry Vyukov    for (unsigned i = 0; i < kMaxTid; i++) {
9626127735454fddae3495794f38189d57dde6510fDmitry Vyukov      ThreadContext *tctx = ctx->threads[i];
9726127735454fddae3495794f38189d57dde6510fDmitry Vyukov      if (tctx == 0)
9826127735454fddae3495794f38189d57dde6510fDmitry Vyukov        continue;
9926127735454fddae3495794f38189d57dde6510fDmitry Vyukov      nthread += 1;
10026127735454fddae3495794f38189d57dde6510fDmitry Vyukov      threadmem += sizeof(ThreadContext);
10126127735454fddae3495794f38189d57dde6510fDmitry Vyukov      if (tctx->status != ThreadStatusRunning)
10226127735454fddae3495794f38189d57dde6510fDmitry Vyukov        continue;
10326127735454fddae3495794f38189d57dde6510fDmitry Vyukov      nlivethread += 1;
10426127735454fddae3495794f38189d57dde6510fDmitry Vyukov      threadmem += sizeof(ThreadState);
10526127735454fddae3495794f38189d57dde6510fDmitry Vyukov    }
10626127735454fddae3495794f38189d57dde6510fDmitry Vyukov  }
10726127735454fddae3495794f38189d57dde6510fDmitry Vyukov
10826127735454fddae3495794f38189d57dde6510fDmitry Vyukov  uptr nsync = 0;
10926127735454fddae3495794f38189d57dde6510fDmitry Vyukov  uptr syncmem = CTX()->synctab.GetMemoryConsumption(&nsync);
11026127735454fddae3495794f38189d57dde6510fDmitry Vyukov
111de08c02aa3007a590bfb7d43f31d5b1a0e7d337cAlexey Samsonov  internal_snprintf(buf, buf_size, "%d: shadow=%zuMB"
112de08c02aa3007a590bfb7d43f31d5b1a0e7d337cAlexey Samsonov                                   " thread=%zuMB(total=%d/live=%d)"
113de08c02aa3007a590bfb7d43f31d5b1a0e7d337cAlexey Samsonov                                   " sync=%zuMB(cnt=%zu)\n",
11426127735454fddae3495794f38189d57dde6510fDmitry Vyukov    num,
11526127735454fddae3495794f38189d57dde6510fDmitry Vyukov    shadow >> 20,
11626127735454fddae3495794f38189d57dde6510fDmitry Vyukov    threadmem >> 20, nthread, nlivethread,
11726127735454fddae3495794f38189d57dde6510fDmitry Vyukov    syncmem >> 20, nsync);
11826127735454fddae3495794f38189d57dde6510fDmitry Vyukov}
11926127735454fddae3495794f38189d57dde6510fDmitry Vyukov
12026127735454fddae3495794f38189d57dde6510fDmitry Vyukovstatic void MemoryProfileThread(void *arg) {
12126127735454fddae3495794f38189d57dde6510fDmitry Vyukov  ScopedInRtl in_rtl;
12226127735454fddae3495794f38189d57dde6510fDmitry Vyukov  fd_t fd = (fd_t)(uptr)arg;
12326127735454fddae3495794f38189d57dde6510fDmitry Vyukov  for (int i = 0; ; i++) {
12414c8bd7250742749e44e306c02a56cf47ad1db82Alexey Samsonov    InternalScopedBuffer<char> buf(4096);
12514c8bd7250742749e44e306c02a56cf47ad1db82Alexey Samsonov    WriteMemoryProfile(buf, buf.size(), i);
12614c8bd7250742749e44e306c02a56cf47ad1db82Alexey Samsonov    internal_write(fd, buf, internal_strlen(buf));
1270969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov    SleepForSeconds(1);
12826127735454fddae3495794f38189d57dde6510fDmitry Vyukov  }
12926127735454fddae3495794f38189d57dde6510fDmitry Vyukov}
13026127735454fddae3495794f38189d57dde6510fDmitry Vyukov
13126127735454fddae3495794f38189d57dde6510fDmitry Vyukovstatic void InitializeMemoryProfile() {
13226127735454fddae3495794f38189d57dde6510fDmitry Vyukov  if (flags()->profile_memory == 0 || flags()->profile_memory[0] == 0)
13326127735454fddae3495794f38189d57dde6510fDmitry Vyukov    return;
13414c8bd7250742749e44e306c02a56cf47ad1db82Alexey Samsonov  InternalScopedBuffer<char> filename(4096);
13514c8bd7250742749e44e306c02a56cf47ad1db82Alexey Samsonov  internal_snprintf(filename, filename.size(), "%s.%d",
13626127735454fddae3495794f38189d57dde6510fDmitry Vyukov      flags()->profile_memory, GetPid());
13714c8bd7250742749e44e306c02a56cf47ad1db82Alexey Samsonov  fd_t fd = internal_open(filename, true);
13826127735454fddae3495794f38189d57dde6510fDmitry Vyukov  if (fd == kInvalidFd) {
13967a64dd8259fdbd867633b27f54d584f435f1ce6Alexey Samsonov    TsanPrintf("Failed to open memory profile file '%s'\n", &filename[0]);
14026127735454fddae3495794f38189d57dde6510fDmitry Vyukov    Die();
14126127735454fddae3495794f38189d57dde6510fDmitry Vyukov  }
14226127735454fddae3495794f38189d57dde6510fDmitry Vyukov  internal_start_thread(&MemoryProfileThread, (void*)(uptr)fd);
14326127735454fddae3495794f38189d57dde6510fDmitry Vyukov}
14426127735454fddae3495794f38189d57dde6510fDmitry Vyukov
145adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukovstatic void MemoryFlushThread(void *arg) {
146adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov  ScopedInRtl in_rtl;
147adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov  for (int i = 0; ; i++) {
1480969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov    SleepForMillis(flags()->flush_memory_ms);
149adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov    FlushShadowMemory();
150adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov  }
151adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov}
152adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov
153adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukovstatic void InitializeMemoryFlush() {
154adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov  if (flags()->flush_memory_ms == 0)
155adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov    return;
156adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov  if (flags()->flush_memory_ms < 100)
157adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov    flags()->flush_memory_ms = 100;
158adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov  internal_start_thread(&MemoryFlushThread, 0);
159adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov}
160adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov
1617ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid Initialize(ThreadState *thr) {
1627ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // Thread safe because done before all threads exist.
1637ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  static bool is_initialized = false;
1647ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (is_initialized)
1657ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    return;
1667ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  is_initialized = true;
1677ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  ScopedInRtl in_rtl;
168bbbb20b7212155ebc5b5b4ee1c68c987dcf30320Dmitry Vyukov#ifndef TSAN_GO
1692e87051d136db3150a3ca322d8862f92b0a684bbDmitry Vyukov  InitializeAllocator();
170bbbb20b7212155ebc5b5b4ee1c68c987dcf30320Dmitry Vyukov#endif
1717ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  InitializeInterceptors();
1727ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  const char *env = InitializePlatform();
1737ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  InitializeMutex();
1747ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  InitializeDynamicAnnotations();
1757ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  ctx = new(ctx_placeholder) Context;
1767ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  InitializeShadowMemory();
1777ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  ctx->dead_list_size = 0;
1787ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  ctx->dead_list_head = 0;
1797ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  ctx->dead_list_tail = 0;
1807ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  InitializeFlags(&ctx->flags, env);
1817ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  InitializeSuppressions();
18226127735454fddae3495794f38189d57dde6510fDmitry Vyukov  InitializeMemoryProfile();
183adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov  InitializeMemoryFlush();
1847ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
1857ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (ctx->flags.verbosity)
18667a64dd8259fdbd867633b27f54d584f435f1ce6Alexey Samsonov    TsanPrintf("***** Running under ThreadSanitizer v2 (pid %d) *****\n",
18767a64dd8259fdbd867633b27f54d584f435f1ce6Alexey Samsonov               GetPid());
1887ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
1897ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // Initialize thread 0.
1907ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  ctx->thread_seq = 0;
1917ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  int tid = ThreadCreate(thr, 0, 0, true);
1927ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  CHECK_EQ(tid, 0);
1937ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  ThreadStart(thr, tid);
1947ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  CHECK_EQ(thr->in_rtl, 1);
1957ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  ctx->initialized = true;
1967ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
197adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov  if (flags()->stop_on_start) {
19867a64dd8259fdbd867633b27f54d584f435f1ce6Alexey Samsonov    TsanPrintf("ThreadSanitizer is suspended at startup (pid %d)."
199adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov           " Call __tsan_resume().\n",
200adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov           GetPid());
201adfb65039646774f0f063b538f8fb0aec021f42bDmitry Vyukov    while (__tsan_resumed == 0);
2027ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
2037ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
2047ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
2057ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyint Finalize(ThreadState *thr) {
2067ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  ScopedInRtl in_rtl;
2077ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  Context *ctx = __tsan::ctx;
2087ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  bool failed = false;
2097ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
2107ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  ThreadFinalize(thr);
2117ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
2127ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (ctx->nreported) {
2137ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    failed = true;
21467a64dd8259fdbd867633b27f54d584f435f1ce6Alexey Samsonov    TsanPrintf("ThreadSanitizer: reported %d warnings\n", ctx->nreported);
2157ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
2167ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
2177ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (ctx->nmissed_expected) {
2187ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    failed = true;
21967a64dd8259fdbd867633b27f54d584f435f1ce6Alexey Samsonov    TsanPrintf("ThreadSanitizer: missed %d expected races\n",
2207ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany        ctx->nmissed_expected);
2217ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
2227ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
2237ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  StatOutput(ctx->stat);
224b7b6b1cd9df0c954b1f890fcebf373db984923b3Dmitry Vyukov  return failed ? flags()->exitcode : 0;
2257ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
2267ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
227848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukovu32 CurrentStackId(ThreadState *thr, uptr pc) {
228848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov  if (thr->shadow_stack_pos == 0)  // May happen during bootstrap.
229848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov    return 0;
230848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov  if (pc) {
231848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov    thr->shadow_stack_pos[0] = pc;
232848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov    thr->shadow_stack_pos++;
233848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov  }
234848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov  u32 id = StackDepotPut(thr->shadow_stack,
235848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov                         thr->shadow_stack_pos - thr->shadow_stack);
236848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov  if (pc)
237848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov    thr->shadow_stack_pos--;
238848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov  return id;
239848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov}
240848531192777acecf79747dc7c1ffeedf5c1da9fDmitry Vyukov
241b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukovvoid TraceSwitch(ThreadState *thr) {
2429ad7c32720dfa1287f8cfd481e5d583435178caeDmitry Vyukov  thr->nomalloc++;
2437ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  ScopedInRtl in_rtl;
2447ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  Lock l(&thr->trace.mtx);
2457ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  unsigned trace = (thr->fast_state.epoch() / kTracePartSize) % kTraceParts;
2467ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TraceHeader *hdr = &thr->trace.headers[trace];
2477ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  hdr->epoch0 = thr->fast_state.epoch();
2487ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  hdr->stack0.ObtainCurrent(thr, 0);
2499ad7c32720dfa1287f8cfd481e5d583435178caeDmitry Vyukov  thr->nomalloc--;
2507ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
2517ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
252b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#ifndef TSAN_GO
2537ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyextern "C" void __tsan_trace_switch() {
2547ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TraceSwitch(cur_thread());
2557ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
2567ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
2577ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyextern "C" void __tsan_report_race() {
2587ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  ReportRace(cur_thread());
2597ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
260b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#endif
2617ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
2627ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyALWAYS_INLINE
2637ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic Shadow LoadShadow(u64 *p) {
2647ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  u64 raw = atomic_load((atomic_uint64_t*)p, memory_order_relaxed);
2657ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return Shadow(raw);
2667ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
2677ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
2687ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyALWAYS_INLINE
2697ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic void StoreShadow(u64 *sp, u64 s) {
2707ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  atomic_store((atomic_uint64_t*)sp, s, memory_order_relaxed);
2717ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
2727ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
2737ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyALWAYS_INLINE
2747ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic void StoreIfNotYetStored(u64 *sp, u64 *s) {
2757ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  StoreShadow(sp, *s);
2767ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  *s = 0;
2777ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
2787ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
2797ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic inline void HandleRace(ThreadState *thr, u64 *shadow_mem,
2807ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany                              Shadow cur, Shadow old) {
2817ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  thr->racy_state[0] = cur.raw();
2827ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  thr->racy_state[1] = old.raw();
2837ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  thr->racy_shadow_addr = shadow_mem;
284b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#ifndef TSAN_GO
2857ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  HACKY_CALL(__tsan_report_race);
286b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#else
287b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov  ReportRace(thr);
288b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#endif
2897ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
2907ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
2917ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic inline bool BothReads(Shadow s, int kAccessIsWrite) {
2927ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return !kAccessIsWrite && !s.is_write();
2937ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
2947ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
2957ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic inline bool OldIsRWStronger(Shadow old, int kAccessIsWrite) {
2967ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return old.is_write() || !kAccessIsWrite;
2977ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
2987ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
2997ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic inline bool OldIsRWWeaker(Shadow old, int kAccessIsWrite) {
3007ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return !old.is_write() || kAccessIsWrite;
3017ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
3027ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
3037ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic inline bool OldIsInSameSynchEpoch(Shadow old, ThreadState *thr) {
3047ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return old.epoch() >= thr->fast_synch_epoch;
3057ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
3067ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
3077ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic inline bool HappensBefore(Shadow old, ThreadState *thr) {
3087ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return thr->clock.get(old.tid()) >= old.epoch();
3097ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
3107ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
3117ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyALWAYS_INLINE
3127ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid MemoryAccessImpl(ThreadState *thr, uptr addr,
3137ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    int kAccessSizeLog, bool kAccessIsWrite, FastState fast_state,
3147ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    u64 *shadow_mem, Shadow cur) {
3157ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  StatInc(thr, StatMop);
3167ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  StatInc(thr, kAccessIsWrite ? StatMopWrite : StatMopRead);
3177ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  StatInc(thr, (StatType)(StatMop1 + kAccessSizeLog));
3187ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
3197ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // This potentially can live in an MMX/SSE scratch register.
3207ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // The required intrinsics are:
3217ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // __m128i _mm_move_epi64(__m128i*);
3227ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // _mm_storel_epi64(u64*, __m128i);
3237ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  u64 store_word = cur.raw();
3247ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
3257ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // scan all the shadow values and dispatch to 4 categories:
3267ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // same, replace, candidate and race (see comments below).
3277ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // we consider only 3 cases regarding access sizes:
3287ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // equal, intersect and not intersect. initially I considered
3297ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // larger and smaller as well, it allowed to replace some
3307ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // 'candidates' with 'same' or 'replace', but I think
3317ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // it's just not worth it (performance- and complexity-wise).
3327ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
3337ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  Shadow old(0);
3347ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (kShadowCnt == 1) {
3357ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    int idx = 0;
3367ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h"
3377ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  } else if (kShadowCnt == 2) {
3387ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    int idx = 0;
3397ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h"
3407ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    idx = 1;
3417ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h"
3427ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  } else if (kShadowCnt == 4) {
3437ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    int idx = 0;
3447ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h"
3457ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    idx = 1;
3467ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h"
3477ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    idx = 2;
3487ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h"
3497ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    idx = 3;
3507ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h"
3517ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  } else if (kShadowCnt == 8) {
3527ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    int idx = 0;
3537ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h"
3547ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    idx = 1;
3557ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h"
3567ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    idx = 2;
3577ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h"
3587ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    idx = 3;
3597ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h"
3607ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    idx = 4;
3617ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h"
3627ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    idx = 5;
3637ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h"
3647ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    idx = 6;
3657ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h"
3667ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    idx = 7;
3677ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_update_shadow_word_inl.h"
3687ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  } else {
3697ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    CHECK(false);
3707ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
3717ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
3727ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // we did not find any races and had already stored
3737ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // the current access info, so we are done
3747ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (LIKELY(store_word == 0))
3757ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    return;
3767ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // choose a random candidate slot and replace it
3777ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  StoreShadow(shadow_mem + (cur.epoch() % kShadowCnt), store_word);
3787ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  StatInc(thr, StatShadowReplace);
3797ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return;
3807ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany RACE:
3817ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  HandleRace(thr, shadow_mem, cur, old);
3827ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  return;
3837ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
3847ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
3857ac41484ea322e0ea5774df681660269f5dc321eKostya SerebryanyALWAYS_INLINE
3867ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid MemoryAccess(ThreadState *thr, uptr pc, uptr addr,
3877ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    int kAccessSizeLog, bool kAccessIsWrite) {
3887ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  u64 *shadow_mem = (u64*)MemToShadow(addr);
3897ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  DPrintf2("#%d: tsan::OnMemoryAccess: @%p %p size=%d"
390e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov      " is_write=%d shadow_mem=%p {%zx, %zx, %zx, %zx}\n",
3917ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany      (int)thr->fast_state.tid(), (void*)pc, (void*)addr,
3927ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany      (int)(1 << kAccessSizeLog), kAccessIsWrite, shadow_mem,
393e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov      (uptr)shadow_mem[0], (uptr)shadow_mem[1],
394e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov      (uptr)shadow_mem[2], (uptr)shadow_mem[3]);
3957ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#if TSAN_DEBUG
3967ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (!IsAppMem(addr)) {
397e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov    TsanPrintf("Access to non app mem %zx\n", addr);
3987ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    DCHECK(IsAppMem(addr));
3997ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
4007ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (!IsShadowMem((uptr)shadow_mem)) {
401e954101f6602ac181a2c3accfbbad0ae51b0bf7cAlexey Samsonov    TsanPrintf("Bad shadow addr %p (%zx)\n", shadow_mem, addr);
4027ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    DCHECK(IsShadowMem((uptr)shadow_mem));
4037ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
4047ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#endif
4057ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
4067ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  FastState fast_state = thr->fast_state;
4077ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (fast_state.GetIgnoreBit())
4087ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    return;
4097ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  fast_state.IncrementEpoch();
4107ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  thr->fast_state = fast_state;
4117ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  Shadow cur(fast_state);
4127ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  cur.SetAddr0AndSizeLog(addr & 7, kAccessSizeLog);
4137ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  cur.SetWrite(kAccessIsWrite);
4147ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
4157ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // We must not store to the trace if we do not store to the shadow.
4167ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // That is, this call must be moved somewhere below.
4177ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TraceAddEvent(thr, fast_state.epoch(), EventTypeMop, pc);
4187ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
4197ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  MemoryAccessImpl(thr, addr, kAccessSizeLog, kAccessIsWrite, fast_state,
4207ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany      shadow_mem, cur);
4217ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
4227ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
4237ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanystatic void MemoryRangeSet(ThreadState *thr, uptr pc, uptr addr, uptr size,
4247ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany                           u64 val) {
4257ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (size == 0)
4267ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    return;
4277ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // FIXME: fix me.
4287ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  uptr offset = addr % kShadowCell;
4297ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (offset) {
4307ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    offset = kShadowCell - offset;
4317ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    if (size <= offset)
4327ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany      return;
4337ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    addr += offset;
4347ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    size -= offset;
4357ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  }
4367ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  CHECK_EQ(addr % 8, 0);
4377ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  CHECK(IsAppMem(addr));
4387ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  CHECK(IsAppMem(addr + size - 1));
4397ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  (void)thr;
4407ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  (void)pc;
4417ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // Some programs mmap like hundreds of GBs but actually used a small part.
4427ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // So, it's better to report a false positive on the memory
4437ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // then to hang here senselessly.
4447ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  const uptr kMaxResetSize = 1024*1024*1024;
4457ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (size > kMaxResetSize)
4467ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    size = kMaxResetSize;
44726af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov  size = (size + (kShadowCell - 1)) & ~(kShadowCell - 1);
4487ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  u64 *p = (u64*)MemToShadow(addr);
4497ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  CHECK(IsShadowMem((uptr)p));
4507ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  CHECK(IsShadowMem((uptr)(p + size * kShadowCnt / kShadowCell - 1)));
4517ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // FIXME: may overwrite a part outside the region
45226af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov  for (uptr i = 0; i < size * kShadowCnt / kShadowCell;) {
45326af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov    p[i++] = val;
45426af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov    for (uptr j = 1; j < kShadowCnt; j++)
45526af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov      p[i++] = 0;
45626af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov  }
4577ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
4587ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
4597ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid MemoryResetRange(ThreadState *thr, uptr pc, uptr addr, uptr size) {
4607ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  MemoryRangeSet(thr, pc, addr, size, 0);
4617ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
4627ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
4637ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid MemoryRangeFreed(ThreadState *thr, uptr pc, uptr addr, uptr size) {
4647ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  MemoryAccessRange(thr, pc, addr, size, true);
465069ce828e3057819ee34426496ea7080f7cc52f0Dmitry Vyukov  Shadow s(thr->fast_state);
466069ce828e3057819ee34426496ea7080f7cc52f0Dmitry Vyukov  s.MarkAsFreed();
467069ce828e3057819ee34426496ea7080f7cc52f0Dmitry Vyukov  s.SetWrite(true);
468069ce828e3057819ee34426496ea7080f7cc52f0Dmitry Vyukov  s.SetAddr0AndSizeLog(0, 3);
469069ce828e3057819ee34426496ea7080f7cc52f0Dmitry Vyukov  MemoryRangeSet(thr, pc, addr, size, s.raw());
4707ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
4717ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
47226af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukovvoid MemoryRangeImitateWrite(ThreadState *thr, uptr pc, uptr addr, uptr size) {
47326af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov  Shadow s(thr->fast_state);
47426af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov  s.SetWrite(true);
47526af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov  s.SetAddr0AndSizeLog(0, 3);
47626af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov  MemoryRangeSet(thr, pc, addr, size, s.raw());
47726af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov}
47826af89330051837bab68dcf25cf669c194b4e310Dmitry Vyukov
4797ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid FuncEntry(ThreadState *thr, uptr pc) {
4807ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  DCHECK_EQ(thr->in_rtl, 0);
4817ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  StatInc(thr, StatFuncEnter);
48225d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov  DPrintf2("#%d: FuncEntry %p\n", (int)thr->fast_state.tid(), (void*)pc);
4837ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  thr->fast_state.IncrementEpoch();
4847ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TraceAddEvent(thr, thr->fast_state.epoch(), EventTypeFuncEnter, pc);
4857ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
4867ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // Shadow stack maintenance can be replaced with
4877ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  // stack unwinding during trace switch (which presumably must be faster).
488769544eed418993abb8efcb4ea939ed5c93a5ba2Dmitry Vyukov  DCHECK_GE(thr->shadow_stack_pos, &thr->shadow_stack[0]);
48925d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov#ifndef TSAN_GO
490769544eed418993abb8efcb4ea939ed5c93a5ba2Dmitry Vyukov  DCHECK_LT(thr->shadow_stack_pos, &thr->shadow_stack[kShadowStackSize]);
49125d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov#else
49225d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov  if (thr->shadow_stack_pos == thr->shadow_stack_end) {
49325d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov    const int sz = thr->shadow_stack_end - thr->shadow_stack;
49425d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov    const int newsz = 2 * sz;
49525d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov    uptr *newstack = (uptr*)internal_alloc(MBlockShadowStack,
49625d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov        newsz * sizeof(uptr));
49725d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov    internal_memcpy(newstack, thr->shadow_stack, sz * sizeof(uptr));
49825d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov    internal_free(thr->shadow_stack);
49925d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov    thr->shadow_stack = newstack;
50025d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov    thr->shadow_stack_pos = newstack + sz;
50125d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov    thr->shadow_stack_end = newstack + newsz;
50225d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov  }
50325d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov#endif
5047ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  thr->shadow_stack_pos[0] = pc;
5057ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  thr->shadow_stack_pos++;
5067ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
5077ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
5087ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid FuncExit(ThreadState *thr) {
5097ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  DCHECK_EQ(thr->in_rtl, 0);
5107ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  StatInc(thr, StatFuncExit);
51125d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov  DPrintf2("#%d: FuncExit\n", (int)thr->fast_state.tid());
5127ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  thr->fast_state.IncrementEpoch();
5137ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  TraceAddEvent(thr, thr->fast_state.epoch(), EventTypeFuncExit, 0);
5147ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
515769544eed418993abb8efcb4ea939ed5c93a5ba2Dmitry Vyukov  DCHECK_GT(thr->shadow_stack_pos, &thr->shadow_stack[0]);
51625d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov#ifndef TSAN_GO
517769544eed418993abb8efcb4ea939ed5c93a5ba2Dmitry Vyukov  DCHECK_LT(thr->shadow_stack_pos, &thr->shadow_stack[kShadowStackSize]);
51825d1c799087af5757ab6efc4a77558565fb1744aDmitry Vyukov#endif
5197ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  thr->shadow_stack_pos--;
5207ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
5217ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
5227ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid IgnoreCtl(ThreadState *thr, bool write, bool begin) {
5237ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  DPrintf("#%d: IgnoreCtl(%d, %d)\n", thr->tid, write, begin);
5247ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  thr->ignore_reads_and_writes += begin ? 1 : -1;
5257ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  CHECK_GE(thr->ignore_reads_and_writes, 0);
5267ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  if (thr->ignore_reads_and_writes)
5277ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    thr->fast_state.SetIgnoreBit();
5287ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany  else
5297ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany    thr->fast_state.ClearIgnoreBit();
5307ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}
5317ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
532b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukovbool MD5Hash::operator==(const MD5Hash &other) const {
533b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov  return hash[0] == other.hash[0] && hash[1] == other.hash[1];
534b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov}
535b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov
5367ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#if TSAN_DEBUG
5377ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid build_consistency_debug() {}
5387ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#else
5397ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid build_consistency_release() {}
5407ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#endif
5417ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
5427ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#if TSAN_COLLECT_STATS
5437ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid build_consistency_stats() {}
5447ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#else
5457ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid build_consistency_nostats() {}
5467ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#endif
5477ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
5487ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#if TSAN_SHADOW_COUNT == 1
5497ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid build_consistency_shadow1() {}
5507ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#elif TSAN_SHADOW_COUNT == 2
5517ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid build_consistency_shadow2() {}
5527ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#elif TSAN_SHADOW_COUNT == 4
5537ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid build_consistency_shadow4() {}
5547ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#else
5557ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryanyvoid build_consistency_shadow8() {}
5567ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#endif
5577ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
5587ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany}  // namespace __tsan
5597ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany
560b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#ifndef TSAN_GO
5617ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany// Must be included in this file to make sure everything is inlined.
5627ac41484ea322e0ea5774df681660269f5dc321eKostya Serebryany#include "tsan_interface_inl.h"
563b78caa645f70eff2f037f1f8bb43ca9129dbd8d9Dmitry Vyukov#endif
564