From 78693730a41bce7254b366d37b618233571dbdb8 Mon Sep 17 00:00:00 2001 From: Dmitry Vyukov Date: Thu, 21 Mar 2013 06:24:31 +0000 Subject: [PATCH] tsan: use a single background thread for memory profiler and memory flush (and later for symbolizer flush) llvm-svn: 177627 --- .../lib/sanitizer_common/sanitizer_common.h | 1 + .../lib/sanitizer_common/sanitizer_linux.cc | 12 +++ compiler-rt/lib/tsan/rtl/tsan_rtl.cc | 84 +++++++++---------- 3 files changed, 53 insertions(+), 44 deletions(-) diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common.h b/compiler-rt/lib/sanitizer_common/sanitizer_common.h index 00a8c5ee1677..53a43b4050c5 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 3c9ae418af73..5f490145c0c0 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc @@ -44,6 +44,12 @@ #include #endif +// +struct kernel_timeval { + long tv_sec; + long tv_usec; +}; + // 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 36fe5787080f..b39b836234ce 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(); - for (int i = 0; ; i++) { - InternalScopedBuffer 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); - } + InternalScopedBuffer 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 InitializeMemoryProfile() { - if (flags()->profile_memory == 0 || flags()->profile_memory[0] == 0) - return; - InternalScopedBuffer 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(); +static void BackgroundThread(void *arg) { + ScopedInRtl in_rtl; + + fd_t mprof_fd = kInvalidFd; + if (flags()->profile_memory && flags()->profile_memory[0]) { + InternalScopedBuffer 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++) { + SleepForSeconds(1); + u64 now = NanoTime(); + + 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",