summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2013-03-20 13:21:50 +0000
committerDmitry Vyukov <dvyukov@google.com>2013-03-20 13:21:50 +0000
commit82dbc5195ceedba0e1a9aab92d436614cc4b7ff9 (patch)
tree4519b7082705c98114ad19f67932620b161f9d22
parent286c914d37d28df611ae083cac40148cf2622ee7 (diff)
downloadcompiler-rt-82dbc5195ceedba0e1a9aab92d436614cc4b7ff9.tar.gz
compiler-rt-82dbc5195ceedba0e1a9aab92d436614cc4b7ff9.tar.bz2
compiler-rt-82dbc5195ceedba0e1a9aab92d436614cc4b7ff9.tar.xz
tsan: special handling of .rodata (don't try to find races, don't keep shadow, dont' put into traces)
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@177517 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/tsan/rtl/tsan_platform_linux.cc60
-rw-r--r--lib/tsan/rtl/tsan_rtl.cc10
-rw-r--r--lib/tsan/rtl/tsan_rtl_thread.cc7
-rw-r--r--lib/tsan/rtl/tsan_stat.cc2
-rw-r--r--lib/tsan/rtl/tsan_stat.h2
5 files changed, 81 insertions, 0 deletions
diff --git a/lib/tsan/rtl/tsan_platform_linux.cc b/lib/tsan/rtl/tsan_platform_linux.cc
index 54c7f8cc..7cfff146 100644
--- a/lib/tsan/rtl/tsan_platform_linux.cc
+++ b/lib/tsan/rtl/tsan_platform_linux.cc
@@ -51,6 +51,8 @@ extern "C" struct mallinfo __libc_mallinfo();
namespace __tsan {
+const uptr kPageSize = 4096;
+
#ifndef TSAN_GO
ScopedInRtl::ScopedInRtl()
: thr_(cur_thread()) {
@@ -162,6 +164,62 @@ static void ProtectRange(uptr beg, uptr end) {
#endif
#ifndef TSAN_GO
+// Mark shadow for .rodata sections with the special kShadowRodata marker.
+// Accesses to .rodata can't race, so this saves time, memory and trace space.
+static void MapRodata() {
+ // First create temp file.
+ const char *tmpdir = GetEnv("TMPDIR");
+ if (tmpdir == 0)
+ tmpdir = GetEnv("TEST_TMPDIR");
+#ifdef P_tmpdir
+ if (tmpdir == 0)
+ tmpdir = P_tmpdir;
+#endif
+ if (tmpdir == 0)
+ return;
+ char filename[256];
+ internal_snprintf(filename, sizeof(filename), "%s/tsan.rodata.%u",
+ tmpdir, GetPid());
+ fd_t fd = internal_open(filename, O_RDWR | O_CREAT | O_EXCL, 0600);
+ if (fd == kInvalidFd)
+ return;
+ // Fill the file with kShadowRodata.
+ const uptr kMarkerSize = 512 * 1024 / sizeof(u64);
+ InternalScopedBuffer<u64> marker(kMarkerSize);
+ for (u64 *p = marker.data(); p < marker.data() + kMarkerSize; p++)
+ *p = kShadowRodata;
+ internal_write(fd, marker.data(), marker.size());
+ // Map the file into memory.
+ void *page = internal_mmap(0, kPageSize, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS, fd, 0);
+ if (page == MAP_FAILED) {
+ internal_close(fd);
+ internal_unlink(filename);
+ return;
+ }
+ // Map the file into shadow of .rodata sections.
+ MemoryMappingLayout proc_maps;
+ uptr start, end, offset, prot;
+ char name[128];
+ while (proc_maps.Next(&start, &end, &offset, name, ARRAY_SIZE(name), &prot)) {
+ if (name[0] != 0 && name[0] != '['
+ && (prot & MemoryMappingLayout::kProtectionRead)
+ && (prot & MemoryMappingLayout::kProtectionExecute)
+ && !(prot & MemoryMappingLayout::kProtectionWrite)
+ && IsAppMem(start)) {
+ // Assume it's .rodata
+ char *shadow_start = (char*)MemToShadow(start);
+ char *shadow_end = (char*)MemToShadow(end);
+ for (char *p = shadow_start; p < shadow_end; p += marker.size()) {
+ internal_mmap(p, Min<uptr>(marker.size(), shadow_end - p),
+ PROT_READ, MAP_PRIVATE | MAP_FIXED, fd, 0);
+ }
+ }
+ }
+ internal_close(fd);
+ internal_unlink(filename);
+}
+
void InitializeShadowMemory() {
uptr shadow = (uptr)MmapFixedNoReserve(kLinuxShadowBeg,
kLinuxShadowEnd - kLinuxShadowBeg);
@@ -188,6 +246,8 @@ void InitializeShadowMemory() {
kLinuxAppMemBeg, kLinuxAppMemEnd,
(kLinuxAppMemEnd - kLinuxAppMemBeg) >> 30);
DPrintf("stack %zx\n", (uptr)&shadow);
+
+ MapRodata();
}
#endif
diff --git a/lib/tsan/rtl/tsan_rtl.cc b/lib/tsan/rtl/tsan_rtl.cc
index df41f188..36fe5787 100644
--- a/lib/tsan/rtl/tsan_rtl.cc
+++ b/lib/tsan/rtl/tsan_rtl.cc
@@ -457,6 +457,16 @@ void MemoryAccess(ThreadState *thr, uptr pc, uptr addr,
}
#endif
+ if (*shadow_mem == kShadowRodata) {
+ // Access to .rodata section, no races here.
+ // Measurements show that it can be 10-20% of all memory accesses.
+ StatInc(thr, StatMop);
+ StatInc(thr, kAccessIsWrite ? StatMopWrite : StatMopRead);
+ StatInc(thr, (StatType)(StatMop1 + kAccessSizeLog));
+ StatInc(thr, StatMopRodata);
+ return;
+ }
+
FastState fast_state = thr->fast_state;
if (fast_state.GetIgnoreBit())
return;
diff --git a/lib/tsan/rtl/tsan_rtl_thread.cc b/lib/tsan/rtl/tsan_rtl_thread.cc
index 3be9b83c..e93a7a34 100644
--- a/lib/tsan/rtl/tsan_rtl_thread.cc
+++ b/lib/tsan/rtl/tsan_rtl_thread.cc
@@ -298,6 +298,13 @@ void MemoryAccessRange(ThreadState *thr, uptr pc, uptr addr,
StatInc(thr, StatMopRange);
+ if (*shadow_mem == kShadowRodata) {
+ // Access to .rodata section, no races here.
+ // Measurements show that it can be 10-20% of all memory accesses.
+ StatInc(thr, StatMopRangeRodata);
+ return;
+ }
+
FastState fast_state = thr->fast_state;
if (fast_state.GetIgnoreBit())
return;
diff --git a/lib/tsan/rtl/tsan_stat.cc b/lib/tsan/rtl/tsan_stat.cc
index 4a0d0f4a..06476032 100644
--- a/lib/tsan/rtl/tsan_stat.cc
+++ b/lib/tsan/rtl/tsan_stat.cc
@@ -38,6 +38,8 @@ void StatOutput(u64 *stat) {
name[StatMop8] = " size 8 ";
name[StatMopSame] = " Including same ";
name[StatMopRange] = " Including range ";
+ name[StatMopRodata] = " Including .rodata ";
+ name[StatMopRangeRodata] = " Including .rodata range ";
name[StatShadowProcessed] = "Shadow processed ";
name[StatShadowZero] = " Including empty ";
name[StatShadowNonZero] = " Including non empty ";
diff --git a/lib/tsan/rtl/tsan_stat.h b/lib/tsan/rtl/tsan_stat.h
index 131dd662..4d8c61c7 100644
--- a/lib/tsan/rtl/tsan_stat.h
+++ b/lib/tsan/rtl/tsan_stat.h
@@ -27,6 +27,8 @@ enum StatType {
StatMop8,
StatMopSame,
StatMopRange,
+ StatMopRodata,
+ StatMopRangeRodata,
StatShadowProcessed,
StatShadowZero,
StatShadowNonZero, // Derived.