mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-18 18:56:43 +00:00
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:
parent
c962f9a624
commit
78693730a4
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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",
|
||||
|
Loading…
x
Reference in New Issue
Block a user