summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2012-05-22 18:07:45 +0000
committerDmitry Vyukov <dvyukov@google.com>2012-05-22 18:07:45 +0000
commit302cebb8f1a193052f0739b4da90b013f3638e94 (patch)
tree7cf26d110f098c9c66d6a8e1c6fc589be3886c6e
parent8b3304da56822ae35fd223eafd2d0c558aafabc4 (diff)
downloadbcm5719-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.cc26
-rw-r--r--compiler-rt/lib/tsan/rtl/tsan_clock.h8
-rw-r--r--compiler-rt/lib/tsan/rtl/tsan_defs.h2
-rw-r--r--compiler-rt/lib/tsan/rtl/tsan_flags.cc4
-rw-r--r--compiler-rt/lib/tsan/rtl/tsan_flags.h4
-rw-r--r--compiler-rt/lib/tsan/rtl/tsan_platform.h1
-rw-r--r--compiler-rt/lib/tsan/rtl/tsan_platform_linux.cc6
-rw-r--r--compiler-rt/lib/tsan/rtl/tsan_rtl.cc32
-rw-r--r--compiler-rt/lib/tsan/rtl/tsan_rtl.h26
-rw-r--r--compiler-rt/lib/tsan/rtl/tsan_rtl_report.cc7
-rw-r--r--compiler-rt/lib/tsan/rtl/tsan_rtl_thread.cc3
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);
OpenPOWER on IntegriCloud