diff options
author | Dmitry Vyukov <dvyukov@google.com> | 2012-05-22 18:07:45 +0000 |
---|---|---|
committer | Dmitry Vyukov <dvyukov@google.com> | 2012-05-22 18:07:45 +0000 |
commit | 302cebb8f1a193052f0739b4da90b013f3638e94 (patch) | |
tree | 7cf26d110f098c9c66d6a8e1c6fc589be3886c6e | |
parent | 8b3304da56822ae35fd223eafd2d0c558aafabc4 (diff) | |
download | bcm5719-llvm-302cebb8f1a193052f0739b4da90b013f3638e94.tar.gz bcm5719-llvm-302cebb8f1a193052f0739b4da90b013f3638e94.zip |
tsan: add shadow memory flush + fix few bugs
llvm-svn: 157270
-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); |