summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2013-03-18 16:56:48 +0000
committerDmitry Vyukov <dvyukov@google.com>2013-03-18 16:56:48 +0000
commit74172de3ce25bf52d9d3918c94216f2eef5956e2 (patch)
tree631319e7f45290bc44f6005705d4b3992fc6616d
parent7ac33ac529ff93a57419f5ddf71b1fde68428577 (diff)
downloadcompiler-rt-74172de3ce25bf52d9d3918c94216f2eef5956e2.tar.gz
compiler-rt-74172de3ce25bf52d9d3918c94216f2eef5956e2.tar.bz2
compiler-rt-74172de3ce25bf52d9d3918c94216f2eef5956e2.tar.xz
tsan: touch less shadow memory during operations on big memory ranges
greatly reduces memory consumption git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@177289 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/tsan/rtl/tsan_interceptors.cc4
-rw-r--r--lib/tsan/rtl/tsan_rtl.cc58
-rw-r--r--lib/tsan/rtl/tsan_rtl_thread.cc7
3 files changed, 48 insertions, 21 deletions
diff --git a/lib/tsan/rtl/tsan_interceptors.cc b/lib/tsan/rtl/tsan_interceptors.cc
index 5c849899..8bc2762d 100644
--- a/lib/tsan/rtl/tsan_interceptors.cc
+++ b/lib/tsan/rtl/tsan_interceptors.cc
@@ -598,7 +598,7 @@ TSAN_INTERCEPTOR(void*, mmap, void *addr, long_t sz, int prot,
if (res != MAP_FAILED) {
if (fd > 0)
FdAccess(thr, pc, fd);
- MemoryResetRange(thr, pc, (uptr)res, sz);
+ MemoryRangeImitateWrite(thr, pc, (uptr)res, sz);
}
return res;
}
@@ -612,7 +612,7 @@ TSAN_INTERCEPTOR(void*, mmap64, void *addr, long_t sz, int prot,
if (res != MAP_FAILED) {
if (fd > 0)
FdAccess(thr, pc, fd);
- MemoryResetRange(thr, pc, (uptr)res, sz);
+ MemoryRangeImitateWrite(thr, pc, (uptr)res, sz);
}
return res;
}
diff --git a/lib/tsan/rtl/tsan_rtl.cc b/lib/tsan/rtl/tsan_rtl.cc
index 9ed3a4c8..37f65eb6 100644
--- a/lib/tsan/rtl/tsan_rtl.cc
+++ b/lib/tsan/rtl/tsan_rtl.cc
@@ -470,6 +470,8 @@ void MemoryAccess(ThreadState *thr, uptr pc, uptr addr,
static void MemoryRangeSet(ThreadState *thr, uptr pc, uptr addr, uptr size,
u64 val) {
+ (void)thr;
+ (void)pc;
if (size == 0)
return;
// FIXME: fix me.
@@ -486,23 +488,42 @@ static void MemoryRangeSet(ThreadState *thr, uptr pc, uptr addr, uptr size,
// let it just crash as usual.
if (!IsAppMem(addr) || !IsAppMem(addr + size - 1))
return;
- (void)thr;
- (void)pc;
- // Some programs mmap like hundreds of GBs but actually used a small part.
- // So, it's better to report a false positive on the memory
- // then to hang here senselessly.
- const uptr kMaxResetSize = 4ull*1024*1024*1024;
- if (size > kMaxResetSize)
- size = kMaxResetSize;
+ // Don't want to touch lots of shadow memory.
+ // If a program maps 10MB stack, there is no need reset the whole range.
size = (size + (kShadowCell - 1)) & ~(kShadowCell - 1);
- u64 *p = (u64*)MemToShadow(addr);
- CHECK(IsShadowMem((uptr)p));
- CHECK(IsShadowMem((uptr)(p + size * kShadowCnt / kShadowCell - 1)));
- // FIXME: may overwrite a part outside the region
- for (uptr i = 0; i < size * kShadowCnt / kShadowCell;) {
- p[i++] = val;
- for (uptr j = 1; j < kShadowCnt; j++)
- p[i++] = 0;
+ if (size < 64*1024) {
+ u64 *p = (u64*)MemToShadow(addr);
+ CHECK(IsShadowMem((uptr)p));
+ CHECK(IsShadowMem((uptr)(p + size * kShadowCnt / kShadowCell - 1)));
+ // FIXME: may overwrite a part outside the region
+ for (uptr i = 0; i < size / kShadowCell * kShadowCnt;) {
+ p[i++] = val;
+ for (uptr j = 1; j < kShadowCnt; j++)
+ p[i++] = 0;
+ }
+ } else {
+ // The region is big, reset only beginning and end.
+ const uptr kPageSize = 4096;
+ u64 *begin = (u64*)MemToShadow(addr);
+ u64 *end = begin + size / kShadowCell * kShadowCnt;
+ u64 *p = begin;
+ // Set at least first kPageSize/2 to page boundary.
+ while ((p < begin + kPageSize / kShadowSize / 2) || ((uptr)p % kPageSize)) {
+ *p++ = val;
+ for (uptr j = 1; j < kShadowCnt; j++)
+ *p++ = 0;
+ }
+ // Reset middle part.
+ u64 *p1 = p;
+ p = RoundDown(end, kPageSize);
+ UnmapOrDie((void*)p1, (uptr)p - (uptr)p1);
+ MmapFixedNoReserve((uptr)p1, (uptr)p - (uptr)p1);
+ // Set the ending.
+ while (p < end) {
+ *p++ = val;
+ for (uptr j = 1; j < kShadowCnt; j++)
+ *p++ = 0;
+ }
}
}
@@ -511,6 +532,11 @@ void MemoryResetRange(ThreadState *thr, uptr pc, uptr addr, uptr size) {
}
void MemoryRangeFreed(ThreadState *thr, uptr pc, uptr addr, uptr size) {
+ // Processing more than 1k (4k of shadow) is expensive,
+ // can cause excessive memory consumption (user does not necessary touch
+ // the whole range) and most likely unnecessary.
+ if (size > 1024)
+ size = 1024;
CHECK_EQ(thr->is_freeing, false);
thr->is_freeing = true;
MemoryAccessRange(thr, pc, addr, size, true);
diff --git a/lib/tsan/rtl/tsan_rtl_thread.cc b/lib/tsan/rtl/tsan_rtl_thread.cc
index 0372bb53..72b9f1a7 100644
--- a/lib/tsan/rtl/tsan_rtl_thread.cc
+++ b/lib/tsan/rtl/tsan_rtl_thread.cc
@@ -201,7 +201,7 @@ void ThreadStart(ThreadState *thr, int tid, uptr os_id) {
if (tid) {
if (stk_addr && stk_size)
- MemoryResetRange(thr, /*pc=*/ 1, stk_addr, stk_size);
+ MemoryRangeImitateWrite(thr, /*pc=*/ 1, stk_addr, stk_size);
if (tls_addr && tls_size) {
// Check that the thr object is in tls;
@@ -212,8 +212,9 @@ void ThreadStart(ThreadState *thr, int tid, uptr os_id) {
CHECK_GE(thr_end, tls_addr);
CHECK_LE(thr_end, tls_addr + tls_size);
// Since the thr object is huge, skip it.
- MemoryResetRange(thr, /*pc=*/ 2, tls_addr, thr_beg - tls_addr);
- MemoryResetRange(thr, /*pc=*/ 2, thr_end, tls_addr + tls_size - thr_end);
+ MemoryRangeImitateWrite(thr, /*pc=*/ 2, tls_addr, thr_beg - tls_addr);
+ MemoryRangeImitateWrite(thr, /*pc=*/ 2,
+ thr_end, tls_addr + tls_size - thr_end);
}
}