summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2013-03-21 06:24:31 +0000
committerDmitry Vyukov <dvyukov@google.com>2013-03-21 06:24:31 +0000
commit78693730a41bce7254b366d37b618233571dbdb8 (patch)
treec82353fd095558d02be788eda286be2d8ab7ea31
parentc962f9a624dc748a1c5b5a1c623db65312fed865 (diff)
downloadbcm5719-llvm-78693730a41bce7254b366d37b618233571dbdb8.tar.gz
bcm5719-llvm-78693730a41bce7254b366d37b618233571dbdb8.zip
tsan: use a single background thread for memory profiler and memory flush (and later for symbolizer flush)
llvm-svn: 177627
-rw-r--r--compiler-rt/lib/sanitizer_common/sanitizer_common.h1
-rw-r--r--compiler-rt/lib/sanitizer_common/sanitizer_linux.cc12
-rw-r--r--compiler-rt/lib/tsan/rtl/tsan_rtl.cc82
3 files changed, 52 insertions, 43 deletions
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common.h b/compiler-rt/lib/sanitizer_common/sanitizer_common.h
index 00a8c5ee167..53a43b4050c 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_common.h
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_common.h
@@ -140,6 +140,7 @@ uptr GetTlsSize();
// Other
void SleepForSeconds(int seconds);
void SleepForMillis(int millis);
+u64 NanoTime();
int Atexit(void (*function)(void));
void SortArray(uptr *array, uptr size);
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc
index 3c9ae418af7..5f490145c0c 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc
@@ -44,6 +44,12 @@
#include <sys/signal.h>
#endif
+// <linux/time.h>
+struct kernel_timeval {
+ long tv_sec;
+ long tv_usec;
+};
+
// <linux/futex.h> is broken on some linux distributions.
const int FUTEX_WAIT = 0;
const int FUTEX_WAKE = 1;
@@ -177,6 +183,12 @@ uptr GetTid() {
return syscall(__NR_gettid);
}
+u64 NanoTime() {
+ kernel_timeval tv;
+ syscall(__NR_gettimeofday, &tv, 0);
+ return (u64)tv.tv_sec * 1000*1000*1000 + tv.tv_usec * 1000;
+}
+
void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top,
uptr *stack_bottom) {
static const uptr kMaxThreadStackSize = 256 * (1 << 20); // 256M
diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl.cc b/compiler-rt/lib/tsan/rtl/tsan_rtl.cc
index 36fe5787080..b39b836234c 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_rtl.cc
+++ b/compiler-rt/lib/tsan/rtl/tsan_rtl.cc
@@ -95,36 +95,49 @@ ThreadState::ThreadState(Context *ctx, int tid, int unique_id, u64 epoch,
, tls_size(tls_size) {
}
-static void MemoryProfileThread(void *arg) {
- ScopedInRtl in_rtl;
- fd_t fd = (fd_t)(uptr)arg;
+static void MemoryProfiler(int i, fd_t fd) {
Context *ctx = CTX();
+ InternalScopedBuffer<char> buf(4096);
+ uptr n_threads;
+ uptr n_running_threads;
+ ctx->thread_registry->GetNumberOfThreads(&n_threads, &n_running_threads);
+ internal_snprintf(buf.data(), buf.size(), "%d: nthr=%d nlive=%d\n",
+ i, n_threads, n_running_threads);
+ internal_write(fd, buf.data(), internal_strlen(buf.data()));
+ WriteMemoryProfile(buf.data(), buf.size());
+ internal_write(fd, buf.data(), internal_strlen(buf.data()));
+}
+
+static void BackgroundThread(void *arg) {
+ ScopedInRtl in_rtl;
+
+ fd_t mprof_fd = kInvalidFd;
+ if (flags()->profile_memory && flags()->profile_memory[0]) {
+ InternalScopedBuffer<char> filename(4096);
+ internal_snprintf(filename.data(), filename.size(), "%s.%d",
+ flags()->profile_memory, GetPid());
+ mprof_fd = OpenFile(filename.data(), true);
+ if (mprof_fd == kInvalidFd) {
+ Printf("ThreadSanitizer: failed to open memory profile file '%s'\n",
+ &filename[0]);
+ }
+ }
+
+ u64 last_flush = NanoTime();
for (int i = 0; ; i++) {
- InternalScopedBuffer<char> buf(4096);
- uptr n_threads;
- uptr n_running_threads;
- ctx->thread_registry->GetNumberOfThreads(&n_threads, &n_running_threads);
- internal_snprintf(buf.data(), buf.size(), "%d: nthr=%d nlive=%d\n",
- i, n_threads, n_running_threads);
- internal_write(fd, buf.data(), internal_strlen(buf.data()));
- WriteMemoryProfile(buf.data(), buf.size());
- internal_write(fd, buf.data(), internal_strlen(buf.data()));
SleepForSeconds(1);
- }
-}
+ u64 now = NanoTime();
-static void InitializeMemoryProfile() {
- if (flags()->profile_memory == 0 || flags()->profile_memory[0] == 0)
- return;
- InternalScopedBuffer<char> filename(4096);
- internal_snprintf(filename.data(), filename.size(), "%s.%d",
- flags()->profile_memory, GetPid());
- fd_t fd = OpenFile(filename.data(), true);
- if (fd == kInvalidFd) {
- Printf("Failed to open memory profile file '%s'\n", &filename[0]);
- Die();
+ if (flags()->flush_memory_ms) {
+ if (last_flush + flags()->flush_memory_ms * 1000*1000 > now) {
+ FlushShadowMemory();
+ last_flush = NanoTime();
+ }
+ }
+
+ if (mprof_fd != kInvalidFd)
+ MemoryProfiler(i, mprof_fd);
}
- internal_start_thread(&MemoryProfileThread, (void*)(uptr)fd);
}
void DontNeedShadowFor(uptr addr, uptr size) {
@@ -133,22 +146,6 @@ void DontNeedShadowFor(uptr addr, uptr size) {
FlushUnneededShadowMemory(shadow_beg, shadow_end - shadow_beg);
}
-static void MemoryFlushThread(void *arg) {
- ScopedInRtl in_rtl;
- for (int i = 0; ; i++) {
- SleepForMillis(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 MapShadow(uptr addr, uptr size) {
MmapFixedNoReserve(MemToShadow(addr), size * kShadowMultiplier);
}
@@ -205,8 +202,7 @@ void Initialize(ThreadState *thr) {
}
}
#endif
- InitializeMemoryProfile();
- InitializeMemoryFlush();
+ internal_start_thread(&BackgroundThread, 0);
if (ctx->flags.verbosity)
Printf("***** Running under ThreadSanitizer v2 (pid %d) *****\n",
OpenPOWER on IntegriCloud