summaryrefslogtreecommitdiffstats
path: root/compiler-rt/lib
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2013-10-03 17:14:35 +0000
committerDmitry Vyukov <dvyukov@google.com>2013-10-03 17:14:35 +0000
commit302ec7b9bc49c4c88fd7c9e579de897005bff45e (patch)
tree10b6c3ee296fe16a96e51b19c989040c4afac91b /compiler-rt/lib
parent72f55d46c8873a76d9070ca200eeede6aca64d7c (diff)
downloadbcm5719-llvm-302ec7b9bc49c4c88fd7c9e579de897005bff45e.tar.gz
bcm5719-llvm-302ec7b9bc49c4c88fd7c9e579de897005bff45e.zip
tsan: add memory_limit_mb flag
The flag allows to bound maximum process memory consumption (best effort). If RSS reaches memory_limit_mb, tsan flushes all shadow memory. llvm-svn: 191913
Diffstat (limited to 'compiler-rt/lib')
-rwxr-xr-xcompiler-rt/lib/tsan/go/buildgo.sh1
-rw-r--r--compiler-rt/lib/tsan/rtl/tsan_flags.cc2
-rw-r--r--compiler-rt/lib/tsan/rtl/tsan_platform.h1
-rw-r--r--compiler-rt/lib/tsan/rtl/tsan_platform_linux.cc16
-rw-r--r--compiler-rt/lib/tsan/rtl/tsan_rtl.cc23
5 files changed, 41 insertions, 2 deletions
diff --git a/compiler-rt/lib/tsan/go/buildgo.sh b/compiler-rt/lib/tsan/go/buildgo.sh
index 70e00cc7213..bd03fc0b65e 100755
--- a/compiler-rt/lib/tsan/go/buildgo.sh
+++ b/compiler-rt/lib/tsan/go/buildgo.sh
@@ -34,6 +34,7 @@ if [ "`uname -a | grep Linux`" != "" ]; then
../../sanitizer_common/sanitizer_posix_libcdep.cc
../../sanitizer_common/sanitizer_linux.cc
../../sanitizer_common/sanitizer_linux_libcdep.cc
+ ../../sanitizer_common/sanitizer_stoptheworld_linux_libcdep.cc
"
elif [ "`uname -a | grep Darwin`" != "" ]; then
SUFFIX="darwin_amd64"
diff --git a/compiler-rt/lib/tsan/rtl/tsan_flags.cc b/compiler-rt/lib/tsan/rtl/tsan_flags.cc
index a1f82004074..acf787d56ce 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_flags.cc
+++ b/compiler-rt/lib/tsan/rtl/tsan_flags.cc
@@ -59,6 +59,7 @@ void InitializeFlags(Flags *f, const char *env) {
f->profile_memory = "";
f->flush_memory_ms = 0;
f->flush_symbolizer_ms = 5000;
+ f->memory_limit_mb = 0;
f->stop_on_start = false;
f->running_on_valgrind = false;
f->external_symbolizer_path = "";
@@ -92,6 +93,7 @@ void InitializeFlags(Flags *f, const char *env) {
ParseFlag(env, &f->profile_memory, "profile_memory");
ParseFlag(env, &f->flush_memory_ms, "flush_memory_ms");
ParseFlag(env, &f->flush_symbolizer_ms, "flush_symbolizer_ms");
+ ParseFlag(env, &f->memory_limit_mb, "memory_limit_mb");
ParseFlag(env, &f->stop_on_start, "stop_on_start");
ParseFlag(env, &f->external_symbolizer_path, "external_symbolizer_path");
ParseFlag(env, &f->history_size, "history_size");
diff --git a/compiler-rt/lib/tsan/rtl/tsan_platform.h b/compiler-rt/lib/tsan/rtl/tsan_platform.h
index 666b4d0c482..70e1183afa2 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_platform.h
+++ b/compiler-rt/lib/tsan/rtl/tsan_platform.h
@@ -134,6 +134,7 @@ static inline uptr AlternativeAddress(uptr addr) {
void FlushShadowMemory();
void WriteMemoryProfile(char *buf, uptr buf_size);
+uptr GetRSS();
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 8e2a081228b..cfac755f443 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cc
+++ b/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cc
@@ -19,6 +19,7 @@
#include "sanitizer_common/sanitizer_common.h"
#include "sanitizer_common/sanitizer_libc.h"
#include "sanitizer_common/sanitizer_procmaps.h"
+#include "sanitizer_common/sanitizer_stoptheworld.h"
#include "tsan_platform.h"
#include "tsan_rtl.h"
#include "tsan_flags.h"
@@ -106,10 +107,23 @@ void WriteMemoryProfile(char *buf, uptr buf_size) {
mi.arena >> 20, mi.hblkhd >> 20, mi.fordblks >> 20, mi.keepcost >> 20);
}
-void FlushShadowMemory() {
+uptr GetRSS() {
+ uptr mem[7] = {};
+ __sanitizer::GetMemoryProfile(FillProfileCallback, mem, 7);
+ return mem[6];
+}
+
+
+void FlushShadowMemoryCallback(
+ const SuspendedThreadsList &suspended_threads_list,
+ void *argument) {
FlushUnneededShadowMemory(kLinuxShadowBeg, kLinuxShadowEnd - kLinuxShadowBeg);
}
+void FlushShadowMemory() {
+ StopTheWorld(FlushShadowMemoryCallback, 0);
+}
+
#ifndef TSAN_GO
static void ProtectRange(uptr beg, uptr end) {
ScopedInRtl in_rtl;
diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl.cc b/compiler-rt/lib/tsan/rtl/tsan_rtl.cc
index aa8934adab4..9703bb46a89 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_rtl.cc
+++ b/compiler-rt/lib/tsan/rtl/tsan_rtl.cc
@@ -130,17 +130,38 @@ static void BackgroundThread(void *arg) {
}
u64 last_flush = NanoTime();
+ uptr last_rss = 0;
for (int i = 0; ; i++) {
SleepForSeconds(1);
u64 now = NanoTime();
// Flush memory if requested.
- if (flags()->flush_memory_ms) {
+ if (flags()->flush_memory_ms > 0) {
if (last_flush + flags()->flush_memory_ms * kMs2Ns < now) {
+ if (flags()->verbosity > 0)
+ Printf("ThreadSanitizer: periodic memory flush\n");
FlushShadowMemory();
last_flush = NanoTime();
}
}
+ if (flags()->memory_limit_mb > 0) {
+ uptr rss = GetRSS();
+ uptr limit = uptr(flags()->memory_limit_mb) << 20;
+ if (flags()->verbosity > 0) {
+ Printf("ThreadSanitizer: memory flush check"
+ " RSS=%llu LAST=%llu LIMIT=%llu\n",
+ (u64)rss>>20, (u64)last_rss>>20, (u64)limit>>20);
+ }
+ if (2 * rss > limit + last_rss) {
+ if (flags()->verbosity > 0)
+ Printf("ThreadSanitizer: flushing memory due to RSS\n");
+ FlushShadowMemory();
+ rss = GetRSS();
+ if (flags()->verbosity > 0)
+ Printf("ThreadSanitizer: memory flushed RSS=%llu\n", (u64)rss>>20);
+ }
+ last_rss = rss;
+ }
// Write memory profile if requested.
if (mprof_fd != kInvalidFd)
OpenPOWER on IntegriCloud