From: Vitaly Buka Date: Sat, 16 Oct 2021 20:31:59 +0000 (-0700) Subject: [NFC][sanitizer] Add StackDepotTestOnlyUnmap X-Git-Tag: upstream/15.0.7~28431 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=746dd6a700931988dd9021d3d04718f1929885a5;p=platform%2Fupstream%2Fllvm.git [NFC][sanitizer] Add StackDepotTestOnlyUnmap --- diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_flat_map.h b/compiler-rt/lib/sanitizer_common/sanitizer_flat_map.h index dcd1bfd..a9055e1 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_flat_map.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_flat_map.h @@ -82,6 +82,7 @@ class TwoLevelMap { MapUnmapCallback().OnUnmap(reinterpret_cast(p), MmapSize()); UnmapOrDie(p, kSize2); } + Init(); } uptr MemoryUsage() const { diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_persistent_allocator.h b/compiler-rt/lib/sanitizer_common/sanitizer_persistent_allocator.h index be7c345..e18b003 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_persistent_allocator.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_persistent_allocator.h @@ -26,6 +26,8 @@ class PersistentAllocator { T *alloc(uptr count = 1); uptr allocated() const { return atomic_load_relaxed(&mapped_size); } + void TestOnlyUnmap(); + private: T *tryAlloc(uptr count); T *refillAndAlloc(uptr count); @@ -33,6 +35,13 @@ class PersistentAllocator { atomic_uintptr_t region_pos; // Region allocator for Node's. atomic_uintptr_t region_end; atomic_uintptr_t mapped_size; + + struct BlockInfo { + const BlockInfo *next; + uptr ptr; + uptr size; + }; + const BlockInfo *curr; }; template @@ -68,17 +77,34 @@ inline T *PersistentAllocator::refillAndAlloc(uptr count) { if (s) return s; atomic_store(®ion_pos, 0, memory_order_relaxed); - uptr size = count * sizeof(T); - uptr allocsz = 64 * 1024; - if (allocsz < size) - allocsz = size; + uptr size = count * sizeof(T) + sizeof(BlockInfo); + uptr allocsz = RoundUpTo(Max(size, 64u * 1024u), GetPageSizeCached()); uptr mem = (uptr)MmapOrDie(allocsz, "stack depot"); + BlockInfo *new_block = (BlockInfo *)(mem + allocsz) - 1; + new_block->next = curr; + new_block->ptr = mem; + new_block->size = allocsz; + curr = new_block; + atomic_fetch_add(&mapped_size, allocsz, memory_order_relaxed); + + allocsz -= sizeof(BlockInfo); atomic_store(®ion_end, mem + allocsz, memory_order_release); atomic_store(®ion_pos, mem, memory_order_release); } } +template +void PersistentAllocator::TestOnlyUnmap() { + while (curr) { + uptr mem = curr->ptr; + uptr allocsz = curr->size; + curr = curr->next; + UnmapOrDie((void *)mem, allocsz); + } + internal_memset(this, 0, sizeof(*this)); +} + } // namespace __sanitizer #endif // SANITIZER_PERSISTENT_ALLOCATOR_H diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_stackdepot.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_stackdepot.cpp index 7b9bb37..f6a2437 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_stackdepot.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_stackdepot.cpp @@ -36,7 +36,7 @@ struct StackDepotNode { bool eq(hash_type hash, const args_type &args) const { return hash == stack_hash; } - static uptr allocated() { return traceAllocator.allocated(); } + static uptr allocated(); static hash_type hash(const args_type &args) { MurMur2Hash64Builder H(args.size * sizeof(uptr)); for (uptr i = 0; i < args.size; i++) H.add(args.trace[i]); @@ -75,6 +75,10 @@ static StackDepot theDepot; static TwoLevelMap tracePtrs; +uptr StackDepotNode::allocated() { + return traceAllocator.allocated() + tracePtrs.MemoryUsage(); +} + void StackDepotNode::store(u32 id, const args_type &args, hash_type hash) { CHECK_EQ(args.tag & (~kUseCountMask >> kUseCountBits), args.tag); atomic_store(&tag_and_use_count, args.tag << kUseCountBits, @@ -125,4 +129,10 @@ StackDepotHandle StackDepotNode::get_handle(u32 id) { return StackDepotHandle(&theDepot.nodes[id], id); } +void StackDepotTestOnlyUnmap() { + theDepot.TestOnlyUnmap(); + tracePtrs.TestOnlyUnmap(); + traceAllocator.TestOnlyUnmap(); +} + } // namespace __sanitizer diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_stackdepot.h b/compiler-rt/lib/sanitizer_common/sanitizer_stackdepot.h index bbfb7f8..56d655d 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_stackdepot.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_stackdepot.h @@ -43,6 +43,8 @@ void StackDepotLockAll(); void StackDepotUnlockAll(); void StackDepotPrintAll(); +void StackDepotTestOnlyUnmap(); + } // namespace __sanitizer #endif // SANITIZER_STACKDEPOT_H diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_stackdepotbase.h b/compiler-rt/lib/sanitizer_common/sanitizer_stackdepotbase.h index d19e542..96d1ddc 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_stackdepotbase.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_stackdepotbase.h @@ -56,6 +56,11 @@ class StackDepotBase { void UnlockAll(); void PrintAll(); + void TestOnlyUnmap() { + nodes.TestOnlyUnmap(); + internal_memset(this, 0, sizeof(*this)); + } + private: friend Node; u32 find(u32 s, args_type args, hash_type hash) const; diff --git a/compiler-rt/lib/sanitizer_common/tests/sanitizer_stackdepot_test.cpp b/compiler-rt/lib/sanitizer_common/tests/sanitizer_stackdepot_test.cpp index 113c41e..df9cada 100644 --- a/compiler-rt/lib/sanitizer_common/tests/sanitizer_stackdepot_test.cpp +++ b/compiler-rt/lib/sanitizer_common/tests/sanitizer_stackdepot_test.cpp @@ -26,10 +26,12 @@ namespace __sanitizer { class StackDepotTest : public testing::Test { protected: + void SetUp() override { StackDepotTestOnlyUnmap(); } void TearDown() override { StackDepotStats stack_depot_stats = StackDepotGetStats(); Printf("StackDepot: %zd ids; %zdM allocated\n", stack_depot_stats.n_uniq_ids, stack_depot_stats.allocated >> 20); + StackDepotTestOnlyUnmap(); } }; @@ -159,43 +161,37 @@ static std::string PrintStackDepotBenchmarkParams( class StackDepotBenchmark : public StackDepotTest, - public testing::WithParamInterface { - protected: - void Run() { - auto Param = GetParam(); - std::atomic here = {}; - - auto thread = [&](int idx) { - here++; - while (here < Param.UniqueThreads) std::this_thread::yield(); - - std::vector frames(64); - for (int r = 0; r < Param.RepeatPerThread; ++r) { - std::iota(frames.begin(), frames.end(), idx + 1); - for (int i = 0; i < Param.UniqueStacksPerThread; ++i) { - StackTrace s(frames.data(), frames.size()); - auto h = StackDepotPut_WithHandle(s); - if (Param.UseCount) - h.inc_use_count_unsafe(); - std::next_permutation(frames.begin(), frames.end()); - }; - } - }; - - std::vector threads; - for (int i = 0; i < Param.Threads; ++i) - threads.emplace_back(thread, Param.UniqueThreads * i); - for (auto& t : threads) t.join(); - } -}; + public testing::WithParamInterface {}; // Test which can be used as a simple benchmark. It's disabled to avoid slowing // down check-sanitizer. // Usage: Sanitizer--Test --gtest_also_run_disabled_tests \ // '--gtest_filter=*Benchmark*' TEST_P(StackDepotBenchmark, DISABLED_Benchmark) { - // Call in subprocess to avoid reuse of the depot. - EXPECT_EXIT((Run(), exit(0)), ::testing::ExitedWithCode(0), ""); + auto Param = GetParam(); + std::atomic here = {}; + + auto thread = [&](int idx) { + here++; + while (here < Param.UniqueThreads) std::this_thread::yield(); + + std::vector frames(64); + for (int r = 0; r < Param.RepeatPerThread; ++r) { + std::iota(frames.begin(), frames.end(), idx + 1); + for (int i = 0; i < Param.UniqueStacksPerThread; ++i) { + StackTrace s(frames.data(), frames.size()); + auto h = StackDepotPut_WithHandle(s); + if (Param.UseCount) + h.inc_use_count_unsafe(); + std::next_permutation(frames.begin(), frames.end()); + }; + } + }; + + std::vector threads; + for (int i = 0; i < Param.Threads; ++i) + threads.emplace_back(thread, Param.UniqueThreads * i); + for (auto& t : threads) t.join(); } INSTANTIATE_TEST_SUITE_P(StackDepotBenchmarkSuite, StackDepotBenchmark,