diff options
| -rw-r--r-- | compiler-rt/lib/tsan/output_tests/suppress_sequence.cc | 26 | ||||
| -rw-r--r-- | compiler-rt/lib/tsan/rtl/tsan_clock.h | 8 | ||||
| -rw-r--r-- | compiler-rt/lib/tsan/rtl/tsan_defs.h | 2 | ||||
| -rw-r--r-- | compiler-rt/lib/tsan/rtl/tsan_flags.cc | 4 | ||||
| -rw-r--r-- | compiler-rt/lib/tsan/rtl/tsan_flags.h | 4 | ||||
| -rw-r--r-- | compiler-rt/lib/tsan/rtl/tsan_platform.h | 1 | ||||
| -rw-r--r-- | compiler-rt/lib/tsan/rtl/tsan_platform_linux.cc | 6 | ||||
| -rw-r--r-- | compiler-rt/lib/tsan/rtl/tsan_rtl.cc | 32 | ||||
| -rw-r--r-- | compiler-rt/lib/tsan/rtl/tsan_rtl.h | 26 | ||||
| -rw-r--r-- | compiler-rt/lib/tsan/rtl/tsan_rtl_report.cc | 7 | ||||
| -rw-r--r-- | compiler-rt/lib/tsan/rtl/tsan_rtl_thread.cc | 3 | 
11 files changed, 60 insertions, 59 deletions
diff --git a/compiler-rt/lib/tsan/output_tests/suppress_sequence.cc b/compiler-rt/lib/tsan/output_tests/suppress_sequence.cc deleted file mode 100644 index 1ce02071814..00000000000 --- a/compiler-rt/lib/tsan/output_tests/suppress_sequence.cc +++ /dev/null @@ -1,26 +0,0 @@ -#include <pthread.h> -#include <unistd.h> - -volatile int g_data1; -volatile int g_data2; -volatile int g_data3; -volatile int g_data4; - -void *Thread1(void *x) { -  if (x) -    usleep(1000000); -  g_data1 = 42; -  g_data2 = 43; -  g_data3 = 44; -  g_data4 = 45; -  return 0; -} - -int main() { -  pthread_t t; -  pthread_create(&t, 0, Thread1, (void*)1); -  Thread1(0); -  pthread_join(t, 0); -} - -// CHECK: ThreadSanitizer: reported 1 warnings diff --git a/compiler-rt/lib/tsan/rtl/tsan_clock.h b/compiler-rt/lib/tsan/rtl/tsan_clock.h index 2ad635ed69d..691185039b6 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_clock.h +++ b/compiler-rt/lib/tsan/rtl/tsan_clock.h @@ -42,20 +42,20 @@ struct ThreadClock {    ThreadClock();    u64 get(unsigned tid) const { -    DCHECK(tid < kMaxTidInClock); +    DCHECK_LT(tid, kMaxTidInClock);      return clk_[tid];    }    void set(unsigned tid, u64 v) { -    DCHECK(tid < kMaxTid); -    DCHECK(v >= clk_[tid]); +    DCHECK_LT(tid, kMaxTid); +    DCHECK_GE(v, clk_[tid]);      clk_[tid] = v;      if (nclk_ <= tid)        nclk_ = tid + 1;    }    void tick(unsigned tid) { -    DCHECK(tid < kMaxTid); +    DCHECK_LT(tid, kMaxTid);      clk_[tid]++;      if (nclk_ <= tid)        nclk_ = tid + 1; diff --git a/compiler-rt/lib/tsan/rtl/tsan_defs.h b/compiler-rt/lib/tsan/rtl/tsan_defs.h index 2cd205d4009..2002ad0ae9b 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_defs.h +++ b/compiler-rt/lib/tsan/rtl/tsan_defs.h @@ -32,7 +32,7 @@ const uptr kPageSize = 4096;  const int kTidBits = 13;  const unsigned kMaxTid = 1 << kTidBits;  const unsigned kMaxTidInClock = kMaxTid * 2;  // This includes msb 'freed' bit. -const int kClkBits = 40; +const int kClkBits = 43;  #ifdef TSAN_SHADOW_COUNT  # if TSAN_SHADOW_COUNT == 2 \ diff --git a/compiler-rt/lib/tsan/rtl/tsan_flags.cc b/compiler-rt/lib/tsan/rtl/tsan_flags.cc index 5a0b7cec6f2..b7f604ac06e 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_flags.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_flags.cc @@ -47,6 +47,8 @@ void InitializeFlags(Flags *f, const char *env) {    f->atexit_sleep_ms = 1000;    f->verbosity = 0;    f->profile_memory = ""; +  f->flush_memory_ms = 0; +  f->stop_on_start = false;    // Let a frontend override.    OverrideFlags(f); @@ -65,6 +67,8 @@ void InitializeFlags(Flags *f, const char *env) {    Flag(env, &f->atexit_sleep_ms, "atexit_sleep_ms");    Flag(env, &f->verbosity, "verbosity");    Flag(env, &f->profile_memory, "profile_memory"); +  Flag(env, &f->flush_memory_ms, "flush_memory_ms"); +  Flag(env, &f->stop_on_start, "stop_on_start");  }  static const char *GetFlagValue(const char *env, const char *name, diff --git a/compiler-rt/lib/tsan/rtl/tsan_flags.h b/compiler-rt/lib/tsan/rtl/tsan_flags.h index 8e0dc815a4c..dea01417ffe 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_flags.h +++ b/compiler-rt/lib/tsan/rtl/tsan_flags.h @@ -48,6 +48,10 @@ struct Flags {    int verbosity;    // If set, periodically write memory profile to that file.    const char *profile_memory; +  // Flush shadow memory every X ms. +  int flush_memory_ms; +  // Stops on start until __tsan_resume() is called (for debugging). +  bool stop_on_start;  };  Flags *flags(); diff --git a/compiler-rt/lib/tsan/rtl/tsan_platform.h b/compiler-rt/lib/tsan/rtl/tsan_platform.h index 61b8a697ec7..5b2e62c9405 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_platform.h +++ b/compiler-rt/lib/tsan/rtl/tsan_platform.h @@ -65,6 +65,7 @@ static inline uptr ShadowToMem(uptr shadow) {  }  uptr GetShadowMemoryConsumption(); +void FlushShadowMemory();  const char *InitializePlatform();  void FinalizePlatform(); diff --git a/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cc b/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cc index 7b8be3dbf23..64ba6a8e0b5 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cc @@ -63,6 +63,12 @@ uptr GetShadowMemoryConsumption() {    return 0;  } +void FlushShadowMemory() { +  madvise((void*)kLinuxShadowBeg, +          kLinuxShadowEnd - kLinuxShadowBeg, +          MADV_DONTNEED); +} +  static void *my_mmap(void *addr, size_t length, int prot, int flags,                      int fd, u64 offset) {    ScopedInRtl in_rtl; diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl.cc b/compiler-rt/lib/tsan/rtl/tsan_rtl.cc index 05be9581806..c93bdcf87e1 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_rtl.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_rtl.cc @@ -21,10 +21,10 @@  #include "tsan_placement_new.h"  #include "tsan_suppressions.h" -volatile int __tsan_stop = 0; +volatile int __tsan_resumed = 0;  extern "C" void __tsan_resume() { -  __tsan_stop = 0; +  __tsan_resumed = 1;  }  namespace __tsan { @@ -59,7 +59,6 @@ ThreadState::ThreadState(Context *ctx, int tid, u64 epoch,    // , in_rtl()    , shadow_stack_pos(&shadow_stack[0])    , tid(tid) -  , func_call_count()    , stk_addr(stk_addr)    , stk_size(stk_size)    , tls_addr(tls_addr) @@ -138,6 +137,22 @@ static void InitializeMemoryProfile() {    internal_start_thread(&MemoryProfileThread, (void*)(uptr)fd);  } +static void MemoryFlushThread(void *arg) { +  ScopedInRtl in_rtl; +  for (int i = 0; ; i++) { +    internal_sleep_ms(flags()->flush_memory_ms); +    FlushShadowMemory(); +  } +} + +static void InitializeMemoryFlush() { +  if (flags()->flush_memory_ms == 0) +    return; +  if (flags()->flush_memory_ms < 100) +    flags()->flush_memory_ms = 100; +  internal_start_thread(&MemoryFlushThread, 0); +} +  void Initialize(ThreadState *thr) {    // Thread safe because done before all threads exist.    static bool is_initialized = false; @@ -157,9 +172,10 @@ void Initialize(ThreadState *thr) {    InitializeFlags(&ctx->flags, env);    InitializeSuppressions();    InitializeMemoryProfile(); +  InitializeMemoryFlush();    if (ctx->flags.verbosity) -    Printf("***** Running under ThreadSanitizer v2 (pid=%d) *****\n", GetPid()); +    Printf("***** Running under ThreadSanitizer v2 (pid %d) *****\n", GetPid());    // Initialize thread 0.    ctx->thread_seq = 0; @@ -169,9 +185,11 @@ void Initialize(ThreadState *thr) {    CHECK_EQ(thr->in_rtl, 1);    ctx->initialized = true; -  if (__tsan_stop) { -    Printf("ThreadSanitizer is suspended at startup.\n"); -    while (__tsan_stop); +  if (flags()->stop_on_start) { +    Printf("ThreadSanitizer is suspended at startup (pid %d)." +           " Call __tsan_resume().\n", +           GetPid()); +    while (__tsan_resumed == 0);    }  } diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl.h b/compiler-rt/lib/tsan/rtl/tsan_rtl.h index 10f5890c6e1..5da0b14d272 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_rtl.h +++ b/compiler-rt/lib/tsan/rtl/tsan_rtl.h @@ -82,7 +82,7 @@ class FastState {    void SetIgnoreBit() { x_ |= kIgnoreBit; }    void ClearIgnoreBit() { x_ &= ~kIgnoreBit; } -  bool GetIgnoreBit() { return x_ & kIgnoreBit; } +  bool GetIgnoreBit() const { return x_ & kIgnoreBit; }   private:    friend class Shadow; @@ -125,25 +125,17 @@ class Shadow: public FastState {    bool IsZero() const { return x_ == 0; }    u64 raw() const { return x_; } -  static inline bool TidsAreEqual(Shadow s1, Shadow s2) { +  static inline bool TidsAreEqual(const Shadow s1, const Shadow s2) {      u64 shifted_xor = (s1.x_ ^ s2.x_) >> kTidShift;      DCHECK_EQ(shifted_xor == 0, s1.tid() == s2.tid());      return shifted_xor == 0;    } -  static inline bool Addr0AndSizeAreEqual(Shadow s1, Shadow s2) { + +  static inline bool Addr0AndSizeAreEqual(const Shadow s1, const Shadow s2) {      u64 masked_xor = (s1.x_ ^ s2.x_) & 31;      return masked_xor == 0;    } -  static bool TwoRangesIntersectSLOW(Shadow s1, Shadow s2) { -    if (s1.addr0() == s2.addr0()) return true; -    if (s1.addr0() < s2.addr0() && s1.addr0() + s1.size() > s2.addr0()) -      return true; -    if (s2.addr0() < s1.addr0() && s2.addr0() + s2.size() > s1.addr0()) -      return true; -    return false; -  } -    static inline bool TwoRangesIntersect(Shadow s1, Shadow s2,        unsigned kS2AccessSize) {      bool res = false; @@ -201,6 +193,15 @@ class Shadow: public FastState {   private:    u64 size_log() const { return (x_ >> 3) & 3; } + +  static bool TwoRangesIntersectSLOW(const Shadow s1, const Shadow s2) { +    if (s1.addr0() == s2.addr0()) return true; +    if (s1.addr0() < s2.addr0() && s1.addr0() + s1.size() > s2.addr0()) +      return true; +    if (s2.addr0() < s1.addr0() && s2.addr0() + s2.size() > s1.addr0()) +      return true; +    return false; +  }  };  // Freed memory. @@ -248,7 +249,6 @@ struct ThreadState {    u64 stat[StatCnt];    const int tid;    int in_rtl; -  int func_call_count;    const uptr stk_addr;    const uptr stk_size;    const uptr tls_addr; diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cc b/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cc index d7aad3c3451..bc3a016ff6b 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_rtl_report.cc @@ -344,13 +344,6 @@ void ReportRace(ThreadState *thr) {      return;    AddRacyStacks(thr, traces, addr_min, addr_max); - -  // Bump the thread's clock a bit. -  // This avoids series of similar reports between the same threads -  // that happen close to each other (e.g. accessing several fields -  // of the same object). -  FastState s(thr->racy_state[1]); -  thr->clock.set(s.tid(), s.epoch() + 100);  }  void CheckFailed(const char *file, int line, const char *cond, u64 v1, u64 v2) { diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl_thread.cc b/compiler-rt/lib/tsan/rtl/tsan_rtl_thread.cc index c13e6edf40d..a74c85a632c 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_rtl_thread.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_rtl_thread.cc @@ -92,6 +92,7 @@ int ThreadCreate(ThreadState *thr, uptr pc, uptr uid, bool detached) {      CHECK_EQ(tctx->status, ThreadStatusDead);      tctx->status = ThreadStatusInvalid;      tctx->reuse_count++; +    tctx->sync.Reset();      tid = tctx->tid;      DestroyAndFree(tctx->dead_info);    } else { @@ -214,7 +215,7 @@ void ThreadFinish(ThreadState *thr) {      tctx->dead_info->trace.headers[i].stack0.CopyFrom(          thr->trace.headers[i].stack0);    } -  tctx->epoch1 = thr->clock.get(tctx->tid); +  tctx->epoch1 = thr->fast_state.epoch();    thr->~ThreadState();    StatAggregate(ctx->stat, thr->stat);  | 

