tsan: use a single background thread for memory profiler and memory flush (and later for symbolizer flush)

llvm-svn: 177627
This commit is contained in:
Dmitry Vyukov 2013-03-21 06:24:31 +00:00
parent c962f9a624
commit 78693730a4
3 changed files with 53 additions and 44 deletions

View File

@ -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);

View File

@ -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

View File

@ -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<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);
}
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 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();
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++) {
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",