diff --git a/compiler-rt/lib/scudo/standalone/allocator_config.h b/compiler-rt/lib/scudo/standalone/allocator_config.h --- a/compiler-rt/lib/scudo/standalone/allocator_config.h +++ b/compiler-rt/lib/scudo/standalone/allocator_config.h @@ -32,7 +32,13 @@ // 512KB regions typedef SizeClassAllocator32 Primary; #endif - typedef MapAllocator> Secondary; + typedef MapAllocatorCache SecondaryCache; + static const u32 SecondaryCacheEntriesArraySize = 32U; + static const u32 SecondaryCacheDefaultMaxEntriesCount = 32U; + static const uptr SecondaryCacheDefaultMaxEntrySize = 1UL << 19; + static const s32 SecondaryCacheMinReleaseToOsIntervalMs = INT32_MIN; + static const s32 SecondaryCacheMaxReleaseToOsIntervalMs = INT32_MAX; + template using TSDRegistryT = TSDRegistryExT; // Exclusive }; @@ -47,9 +53,13 @@ // 256KB regions typedef SizeClassAllocator32 Primary; #endif - // Cache blocks up to 2MB - typedef MapAllocator> - Secondary; + typedef MapAllocatorCache SecondaryCache; + static const u32 SecondaryCacheEntriesArraySize = 256U; + static const u32 SecondaryCacheDefaultMaxEntriesCount = 32U; + static const uptr SecondaryCacheDefaultMaxEntrySize = 2UL << 20; + static const s32 SecondaryCacheMinReleaseToOsIntervalMs = 0; + static const s32 SecondaryCacheMaxReleaseToOsIntervalMs = 1000; + template using TSDRegistryT = TSDRegistrySharedT; // Shared, max 8 TSDs. }; @@ -63,7 +73,13 @@ // 64KB regions typedef SizeClassAllocator32 Primary; #endif - typedef MapAllocator> Secondary; + typedef MapAllocatorCache SecondaryCache; + static const u32 SecondaryCacheEntriesArraySize = 16U; + static const u32 SecondaryCacheDefaultMaxEntriesCount = 4U; + static const uptr SecondaryCacheDefaultMaxEntrySize = 1UL << 18; + static const s32 SecondaryCacheMinReleaseToOsIntervalMs = 0; + static const s32 SecondaryCacheMaxReleaseToOsIntervalMs = 0; + template using TSDRegistryT = TSDRegistrySharedT; // Shared, max 2 TSDs. }; @@ -72,7 +88,7 @@ struct FuchsiaConfig { // 1GB Regions typedef SizeClassAllocator64 Primary; - typedef MapAllocator Secondary; + typedef MapAllocatorNoCache SecondaryCache; template using TSDRegistryT = TSDRegistrySharedT; // Shared, max 8 TSDs. }; diff --git a/compiler-rt/lib/scudo/standalone/combined.h b/compiler-rt/lib/scudo/standalone/combined.h --- a/compiler-rt/lib/scudo/standalone/combined.h +++ b/compiler-rt/lib/scudo/standalone/combined.h @@ -930,7 +930,7 @@ } private: - using SecondaryT = typename Params::Secondary; + using SecondaryT = MapAllocator; typedef typename PrimaryT::SizeClassMap SizeClassMap; static const uptr MinAlignmentLog = SCUDO_MIN_ALIGNMENT_LOG; diff --git a/compiler-rt/lib/scudo/standalone/secondary.h b/compiler-rt/lib/scudo/standalone/secondary.h --- a/compiler-rt/lib/scudo/standalone/secondary.h +++ b/compiler-rt/lib/scudo/standalone/secondary.h @@ -70,20 +70,18 @@ } }; -template -class MapAllocatorCache { +template class MapAllocatorCache { public: // Ensure the default maximum specified fits the array. - static_assert(DefaultMaxEntriesCount <= EntriesArraySize, ""); + static_assert(Config::SecondaryCacheDefaultMaxEntriesCount <= + Config::SecondaryCacheEntriesArraySize, + ""); void initLinkerInitialized(s32 ReleaseToOsInterval) { setOption(Option::MaxCacheEntriesCount, - static_cast(DefaultMaxEntriesCount)); + static_cast(Config::SecondaryCacheDefaultMaxEntriesCount)); setOption(Option::MaxCacheEntrySize, - static_cast(DefaultMaxEntrySize)); + static_cast(Config::SecondaryCacheDefaultMaxEntrySize)); setOption(Option::ReleaseInterval, static_cast(ReleaseToOsInterval)); } void init(s32 ReleaseToOsInterval) { @@ -162,13 +160,14 @@ bool setOption(Option O, sptr Value) { if (O == Option::ReleaseInterval) { const s32 Interval = - Max(Min(static_cast(Value), MaxReleaseToOsIntervalMs), - MinReleaseToOsIntervalMs); + Max(Min(static_cast(Value), + Config::SecondaryCacheMaxReleaseToOsIntervalMs), + Config::SecondaryCacheMinReleaseToOsIntervalMs); atomic_store_relaxed(&ReleaseToOsIntervalMs, Interval); return true; } else if (O == Option::MaxCacheEntriesCount) { const u32 MaxCount = static_cast(Value); - if (MaxCount > EntriesArraySize) + if (MaxCount > Config::SecondaryCacheEntriesArraySize) return false; atomic_store_relaxed(&MaxEntriesCount, MaxCount); return true; @@ -192,11 +191,11 @@ void *MapBase; uptr MapSize; MapPlatformData Data; - } MapInfo[EntriesArraySize]; + } MapInfo[Config::SecondaryCacheEntriesArraySize]; uptr N = 0; { ScopedLock L(Mutex); - for (uptr I = 0; I < EntriesArraySize; I++) { + for (uptr I = 0; I < Config::SecondaryCacheEntriesArraySize; I++) { if (!Entries[I].Block) continue; MapInfo[N].MapBase = reinterpret_cast(Entries[I].MapBase); @@ -217,7 +216,7 @@ ScopedLock L(Mutex); if (!EntriesCount) return; - for (uptr I = 0; I < EntriesArraySize; I++) { + for (uptr I = 0; I < Config::SecondaryCacheEntriesArraySize; I++) { if (!Entries[I].Block || !Entries[I].Time || Entries[I].Time > Time) continue; releasePagesToOS(Entries[I].Block, 0, @@ -237,7 +236,7 @@ }; HybridMutex Mutex; - CachedBlock Entries[EntriesArraySize]; + CachedBlock Entries[Config::SecondaryCacheEntriesArraySize]; u32 EntriesCount; atomic_u32 MaxEntriesCount; atomic_uptr MaxEntrySize; diff --git a/compiler-rt/lib/scudo/standalone/tests/combined_test.cpp b/compiler-rt/lib/scudo/standalone/tests/combined_test.cpp --- a/compiler-rt/lib/scudo/standalone/tests/combined_test.cpp +++ b/compiler-rt/lib/scudo/standalone/tests/combined_test.cpp @@ -401,7 +401,7 @@ using DeathSizeClassMap = scudo::FixedSizeClassMap; typedef scudo::SizeClassAllocator64 Primary; - typedef scudo::MapAllocator Secondary; + typedef scudo::MapAllocatorNoCache SecondaryCache; template using TSDRegistryT = scudo::TSDRegistrySharedT; }; diff --git a/compiler-rt/lib/scudo/standalone/tests/secondary_test.cpp b/compiler-rt/lib/scudo/standalone/tests/secondary_test.cpp --- a/compiler-rt/lib/scudo/standalone/tests/secondary_test.cpp +++ b/compiler-rt/lib/scudo/standalone/tests/secondary_test.cpp @@ -8,6 +8,7 @@ #include "tests/scudo_unit_test.h" +#include "allocator_config.h" #include "secondary.h" #include @@ -54,14 +55,24 @@ Str.output(); } +struct TestConfig { + static const scudo::u32 SecondaryCacheEntriesArraySize = 128U; + static const scudo::u32 SecondaryCacheDefaultMaxEntriesCount = 64U; + static const scudo::uptr SecondaryCacheDefaultMaxEntrySize = 1UL << 20; + static const scudo::s32 SecondaryCacheMinReleaseToOsIntervalMs = INT32_MIN; + static const scudo::s32 SecondaryCacheMaxReleaseToOsIntervalMs = INT32_MAX; +}; + TEST(ScudoSecondaryTest, SecondaryBasic) { testSecondaryBasic>(); - testSecondaryBasic>>(); testSecondaryBasic< - scudo::MapAllocator>>(); + scudo::MapAllocator>>(); + testSecondaryBasic< + scudo::MapAllocator>>(); } -using LargeAllocator = scudo::MapAllocator>; +using LargeAllocator = + scudo::MapAllocator>; // This exercises a variety of combinations of size and alignment for the // MapAllocator. The size computation done here mimic the ones done by the