diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl.cpp b/compiler-rt/lib/tsan/rtl/tsan_rtl.cpp --- a/compiler-rt/lib/tsan/rtl/tsan_rtl.cpp +++ b/compiler-rt/lib/tsan/rtl/tsan_rtl.cpp @@ -132,6 +132,10 @@ ctx->trace_part_finished_excess = 0; } +uptr mapped_shadow_begin; +uptr mapped_shadow_end; +bool mapped_shadow_captured; + static void DoResetImpl(uptr epoch) { ThreadRegistryLock lock0(&ctx->thread_registry); Lock lock1(&ctx->slot_mtx); @@ -197,8 +201,13 @@ } DPrintf("Resetting shadow...\n"); - if (!MmapFixedSuperNoReserve(ShadowBeg(), ShadowEnd() - ShadowBeg(), - "shadow")) { + auto shadow_begin = ShadowBeg(); + auto shadow_end = ShadowEnd(); + if (mapped_shadow_captured) { + shadow_begin = mapped_shadow_begin; + shadow_end = mapped_shadow_end; + } + if (!MmapFixedSuperNoReserve(shadow_begin, shadow_end - shadow_begin, "shadow")) { Printf("failed to reset shadow memory\n"); Die(); } @@ -559,15 +568,42 @@ #endif void MapShadow(uptr addr, uptr size) { - // Global data is not 64K aligned, but there are no adjacent mappings, - // so we can get away with unaligned mapping. - // CHECK_EQ(addr, addr & ~((64 << 10) - 1)); // windows wants 64K alignment - const uptr kPageSize = GetPageSizeCached(); - uptr shadow_begin = RoundDownTo((uptr)MemToShadow(addr), kPageSize); - uptr shadow_end = RoundUpTo((uptr)MemToShadow(addr + size), kPageSize); - if (!MmapFixedSuperNoReserve(shadow_begin, shadow_end - shadow_begin, - "shadow")) - Die(); + // Ensure thead registry lock held, so as to synchronize + // with DoReset, which also access the mapped_shadow_* vars. + ThreadRegistryLock lock0(&ctx->thread_registry); + + /* no longer relevant + | + v + // Global data is not 64K aligned, but there are no adjacent mappings, + // so we can get away with unaligned mapping. + // CHECK_EQ(addr, addr & ~((64 << 10) - 1)); // windows wants 64K alignment + ^ + | + no longer relevant */ + + static bool first_complete = false; + uptr shadow_begin = RoundDownTo((uptr)MemToShadow(addr), (64 << 10)); + uptr shadow_end = RoundUpTo((uptr)MemToShadow(addr + size), (64 << 10)); + VPrintf(2, "=-= mapping shadow for (0x%zx-0x%zx) at (0x%zx-0x%zx)\n", + addr, addr + size, shadow_begin, shadow_end); + if (!first_complete) { + first_complete = true; + // First call maps data+bss. + if (!MmapFixedSuperNoReserve(shadow_begin, shadow_end - shadow_begin, "shadow")) + Die(); + } else { + if (shadow_end <= mapped_shadow_end) + return; + if (mapped_shadow_begin < shadow_begin) + mapped_shadow_begin = shadow_begin; + if (shadow_begin < mapped_shadow_end) + shadow_begin = mapped_shadow_end; + if (!MmapFixedSuperNoReserve(shadow_begin, shadow_end - shadow_begin, + "shadow")) + Die(); + mapped_shadow_end = shadow_end; + } // Meta shadow is 2:1, so tread carefully. static bool data_mapped = false; @@ -587,8 +623,10 @@ // Windows wants 64K alignment. meta_begin = RoundDownTo(meta_begin, 64 << 10); meta_end = RoundUpTo(meta_end, 64 << 10); - if (meta_end <= mapped_meta_end) - return; + if (meta_end <= mapped_meta_end) { + Printf("should never happen"); + Die(); + } if (meta_begin < mapped_meta_end) meta_begin = mapped_meta_end; if (!MmapFixedSuperNoReserve(meta_begin, meta_end - meta_begin,