tsan: fix a bug in MetaMap::ResetRange
The bug was uncovered by NegativeTests.MmapTest from
data-race-test suite, so port it as well.
llvm-svn: 232032
diff --git a/compiler-rt/lib/tsan/rtl/tsan_sync.cc b/compiler-rt/lib/tsan/rtl/tsan_sync.cc
index 3d24633..49c4d15 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_sync.cc
+++ b/compiler-rt/lib/tsan/rtl/tsan_sync.cc
@@ -162,8 +162,10 @@
// freed). Note: we can't simply madvise, because we need to leave a zeroed
// range (otherwise __tsan_java_move can crash if it encounters a left-over
// meta objects in java heap).
- UnmapOrDie((void*)p0, sz0);
- MmapFixedNoReserve(p0, sz0);
+ uptr metap = (uptr)MemToMeta(p0);
+ uptr metasz = sz0 / kMetaRatio;
+ UnmapOrDie((void*)metap, metasz);
+ MmapFixedNoReserve(metap, metasz);
}
MBlock* MetaMap::GetBlock(uptr p) {
diff --git a/compiler-rt/test/tsan/mmap_stress.cc b/compiler-rt/test/tsan/mmap_stress.cc
new file mode 100644
index 0000000..5e3904a
--- /dev/null
+++ b/compiler-rt/test/tsan/mmap_stress.cc
@@ -0,0 +1,47 @@
+// RUN: %clang_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s
+#include "test.h"
+#include <errno.h>
+#include <sys/mman.h>
+
+void *SubWorker(void *arg) {
+ (void)arg;
+ const int kMmapSize = 65536;
+ for (int i = 0; i < 500; i++) {
+ int *ptr = (int*)mmap(0, kMmapSize, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANON, -1, 0);
+ *ptr = 42;
+ munmap(ptr, kMmapSize);
+ }
+ return 0;
+}
+
+void *Worker1(void *arg) {
+ (void)arg;
+ pthread_t th[4];
+ for (int i = 0; i < 4; i++)
+ pthread_create(&th[i], 0, SubWorker, 0);
+ for (int i = 0; i < 4; i++)
+ pthread_join(th[i], 0);
+ return 0;
+}
+
+void *Worker(void *arg) {
+ (void)arg;
+ pthread_t th[4];
+ for (int i = 0; i < 4; i++)
+ pthread_create(&th[i], 0, Worker1, 0);
+ for (int i = 0; i < 4; i++)
+ pthread_join(th[i], 0);
+ return 0;
+}
+
+int main() {
+ pthread_t th[4];
+ for (int i = 0; i < 4; i++)
+ pthread_create(&th[i], 0, Worker, 0);
+ for (int i = 0; i < 4; i++)
+ pthread_join(th[i], 0);
+ fprintf(stderr, "DONE\n");
+}
+
+// CHECK: DONE