// 512KB regions
typedef SizeClassAllocator32<SizeClassMap, 19U> Primary;
#endif
- typedef MapAllocator<MapAllocatorCache<>> Secondary;
+ typedef MapAllocatorCache<DefaultConfig> 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 <class A> using TSDRegistryT = TSDRegistryExT<A>; // Exclusive
};
// 256KB regions
typedef SizeClassAllocator32<SizeClassMap, 18U, 1000, 1000> Primary;
#endif
- // Cache blocks up to 2MB
- typedef MapAllocator<MapAllocatorCache<256U, 32U, 2UL << 20, 0, 1000>>
- Secondary;
+ typedef MapAllocatorCache<AndroidConfig> 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 <class A>
using TSDRegistryT = TSDRegistrySharedT<A, 8U, 2U>; // Shared, max 8 TSDs.
};
// 64KB regions
typedef SizeClassAllocator32<SizeClassMap, 16U, 1000, 1000> Primary;
#endif
- typedef MapAllocator<MapAllocatorCache<16U, 4U, 1UL << 18, 0, 0>> Secondary;
+ typedef MapAllocatorCache<AndroidSvelteConfig> 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 <class A>
using TSDRegistryT = TSDRegistrySharedT<A, 2U, 1U>; // Shared, max 2 TSDs.
};
struct FuchsiaConfig {
// 1GB Regions
typedef SizeClassAllocator64<DefaultSizeClassMap, 30U> Primary;
- typedef MapAllocator<MapAllocatorNoCache> Secondary;
+ typedef MapAllocatorNoCache SecondaryCache;
template <class A>
using TSDRegistryT = TSDRegistrySharedT<A, 8U, 4U>; // Shared, max 8 TSDs.
};
}
private:
- using SecondaryT = typename Params::Secondary;
+ using SecondaryT = MapAllocator<typename Params::SecondaryCache>;
typedef typename PrimaryT::SizeClassMap SizeClassMap;
static const uptr MinAlignmentLog = SCUDO_MIN_ALIGNMENT_LOG;
}
};
-template <u32 EntriesArraySize = 32U, u32 DefaultMaxEntriesCount = 32U,
- uptr DefaultMaxEntrySize = 1UL << 19,
- s32 MinReleaseToOsIntervalMs = INT32_MIN,
- s32 MaxReleaseToOsIntervalMs = INT32_MAX>
-class MapAllocatorCache {
+template <typename Config> 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<sptr>(DefaultMaxEntriesCount));
+ static_cast<sptr>(Config::SecondaryCacheDefaultMaxEntriesCount));
setOption(Option::MaxCacheEntrySize,
- static_cast<sptr>(DefaultMaxEntrySize));
+ static_cast<sptr>(Config::SecondaryCacheDefaultMaxEntrySize));
setOption(Option::ReleaseInterval, static_cast<sptr>(ReleaseToOsInterval));
}
void init(s32 ReleaseToOsInterval) {
bool setOption(Option O, sptr Value) {
if (O == Option::ReleaseInterval) {
const s32 Interval =
- Max(Min(static_cast<s32>(Value), MaxReleaseToOsIntervalMs),
- MinReleaseToOsIntervalMs);
+ Max(Min(static_cast<s32>(Value),
+ Config::SecondaryCacheMaxReleaseToOsIntervalMs),
+ Config::SecondaryCacheMinReleaseToOsIntervalMs);
atomic_store_relaxed(&ReleaseToOsIntervalMs, Interval);
return true;
} else if (O == Option::MaxCacheEntriesCount) {
const u32 MaxCount = static_cast<u32>(Value);
- if (MaxCount > EntriesArraySize)
+ if (MaxCount > Config::SecondaryCacheEntriesArraySize)
return false;
atomic_store_relaxed(&MaxEntriesCount, MaxCount);
return true;
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<void *>(Entries[I].MapBase);
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,
};
HybridMutex Mutex;
- CachedBlock Entries[EntriesArraySize];
+ CachedBlock Entries[Config::SecondaryCacheEntriesArraySize];
u32 EntriesCount;
atomic_u32 MaxEntriesCount;
atomic_uptr MaxEntrySize;
using DeathSizeClassMap = scudo::FixedSizeClassMap<DeathSizeClassConfig>;
typedef scudo::SizeClassAllocator64<DeathSizeClassMap, DeathRegionSizeLog>
Primary;
- typedef scudo::MapAllocator<scudo::MapAllocatorNoCache> Secondary;
+ typedef scudo::MapAllocatorNoCache SecondaryCache;
template <class A> using TSDRegistryT = scudo::TSDRegistrySharedT<A, 1U, 1U>;
};
#include "tests/scudo_unit_test.h"
+#include "allocator_config.h"
#include "secondary.h"
#include <stdio.h>
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<scudo::MapAllocator<scudo::MapAllocatorNoCache>>();
- testSecondaryBasic<scudo::MapAllocator<scudo::MapAllocatorCache<>>>();
testSecondaryBasic<
- scudo::MapAllocator<scudo::MapAllocatorCache<128U, 64U, 1UL << 20>>>();
+ scudo::MapAllocator<scudo::MapAllocatorCache<scudo::DefaultConfig>>>();
+ testSecondaryBasic<
+ scudo::MapAllocator<scudo::MapAllocatorCache<TestConfig>>>();
}
-using LargeAllocator = scudo::MapAllocator<scudo::MapAllocatorCache<>>;
+using LargeAllocator =
+ scudo::MapAllocator<scudo::MapAllocatorCache<scudo::DefaultConfig>>;
// This exercises a variety of combinations of size and alignment for the
// MapAllocator. The size computation done here mimic the ones done by the