diff options
author | Dmitry Vyukov <dvyukov@google.com> | 2013-03-18 16:56:48 +0000 |
---|---|---|
committer | Dmitry Vyukov <dvyukov@google.com> | 2013-03-18 16:56:48 +0000 |
commit | 74172de3ce25bf52d9d3918c94216f2eef5956e2 (patch) | |
tree | 631319e7f45290bc44f6005705d4b3992fc6616d | |
parent | 7ac33ac529ff93a57419f5ddf71b1fde68428577 (diff) | |
download | compiler-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.cc | 4 | ||||
-rw-r--r-- | lib/tsan/rtl/tsan_rtl.cc | 58 | ||||
-rw-r--r-- | lib/tsan/rtl/tsan_rtl_thread.cc | 7 |
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); } } |