[compiler-rt] [scudo] Add primary option to zero block on dealloc. (PR #142394)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Jun 2 06:52:53 PDT 2025
https://github.com/piwicode created https://github.com/llvm/llvm-project/pull/142394
When all the blocks of a page are unused, the page will be full of zero and decommitted on operating systems that scan the memory.
Change-Id: I278055d82057090b0a04d812b49cf93fdf467478
>From 7b140733b4f317db535bcbaac70a5ed7da00102f Mon Sep 17 00:00:00 2001
From: Pierre Labatut <plabatut at google.com>
Date: Mon, 2 Jun 2025 15:19:02 +0200
Subject: [PATCH] [scudo] Add primary option to zero block on dealloc.
When all the blocks of a page are unused, the page will be full of zero
and decommitted on operating systems that scan the memory.
Change-Id: I278055d82057090b0a04d812b49cf93fdf467478
---
.../lib/scudo/standalone/allocator_config.def | 5 ++++
compiler-rt/lib/scudo/standalone/primary64.h | 1 +
.../scudo/standalone/size_class_allocator.h | 9 +++++++
.../scudo/standalone/tests/primary_test.cpp | 24 ++++++++++++++++++-
4 files changed, 38 insertions(+), 1 deletion(-)
diff --git a/compiler-rt/lib/scudo/standalone/allocator_config.def b/compiler-rt/lib/scudo/standalone/allocator_config.def
index 84fcec0877d40..2d58cb0a4d392 100644
--- a/compiler-rt/lib/scudo/standalone/allocator_config.def
+++ b/compiler-rt/lib/scudo/standalone/allocator_config.def
@@ -111,6 +111,11 @@ PRIMARY_OPTIONAL_TYPE(ConditionVariableT, ConditionVariableDummy)
// to, in increments of a power-of-2 scale. See `CompactPtrScale` also.
PRIMARY_OPTIONAL_TYPE(CompactPtrT, uptr)
+// Clears the memory slot when a allocation is returned to the allocator.
+// Operating systems that detects pages filled with zeroes will decommit
+// memory.
+PRIMARY_OPTIONAL(const bool, ZeroOnDealloc, false)
+
// SECONDARY_REQUIRED_TEMPLATE_TYPE(NAME)
//
// Defines the type of Secondary Cache to use.
diff --git a/compiler-rt/lib/scudo/standalone/primary64.h b/compiler-rt/lib/scudo/standalone/primary64.h
index 25ee999199114..145ee26dd855f 100644
--- a/compiler-rt/lib/scudo/standalone/primary64.h
+++ b/compiler-rt/lib/scudo/standalone/primary64.h
@@ -53,6 +53,7 @@ template <typename Config> class SizeClassAllocator64 {
static const uptr CompactPtrScale = Config::getCompactPtrScale();
static const uptr RegionSizeLog = Config::getRegionSizeLog();
static const uptr GroupSizeLog = Config::getGroupSizeLog();
+ static const bool ZeroOnDealloc = Config::getZeroOnDealloc();
static_assert(RegionSizeLog >= GroupSizeLog,
"Group size shouldn't be greater than the region size");
static const uptr GroupScale = GroupSizeLog - CompactPtrScale;
diff --git a/compiler-rt/lib/scudo/standalone/size_class_allocator.h b/compiler-rt/lib/scudo/standalone/size_class_allocator.h
index 7c7d6307f8f0a..219b08774bcb6 100644
--- a/compiler-rt/lib/scudo/standalone/size_class_allocator.h
+++ b/compiler-rt/lib/scudo/standalone/size_class_allocator.h
@@ -59,6 +59,11 @@ template <class SizeClassAllocator> struct SizeClassAllocatorLocalCache {
bool deallocate(uptr ClassId, void *P) {
CHECK_LT(ClassId, NumClasses);
+
+ if(SizeClassAllocator::ZeroOnDealloc) {
+ memset(P, 0, SizeClassAllocator::getSizeByClassId(ClassId));
+ }
+
PerClass *C = &PerClassArray[ClassId];
// If the cache is full, drain half of blocks back to the main allocator.
@@ -211,6 +216,10 @@ template <class SizeClassAllocator> struct SizeClassAllocatorNoCache {
bool deallocate(uptr ClassId, void *P) {
CHECK_LT(ClassId, NumClasses);
+ if(SizeClassAllocator::ZeroOnDealloc) {
+ memset(P, 0, SizeClassAllocator::getSizeByClassId(ClassId));
+ }
+
if (ClassId == BatchClassId)
return deallocateBatchClassBlock(P);
diff --git a/compiler-rt/lib/scudo/standalone/tests/primary_test.cpp b/compiler-rt/lib/scudo/standalone/tests/primary_test.cpp
index 7dc38c2ede8ca..47bfc3a9fc242 100644
--- a/compiler-rt/lib/scudo/standalone/tests/primary_test.cpp
+++ b/compiler-rt/lib/scudo/standalone/tests/primary_test.cpp
@@ -150,6 +150,27 @@ template <typename SizeClassMapT> struct TestConfig5 {
};
};
+// Enable `ZeroOnDealloc`
+template <typename SizeClassMapT> struct TestConfig6 {
+ static const bool MaySupportMemoryTagging = false;
+ template <typename> using TSDRegistryT = void;
+ template <typename> using PrimaryT = void;
+ template <typename> using SecondaryT = void;
+
+ struct Primary {
+ using SizeClassMap = SizeClassMapT;
+ static const scudo::uptr RegionSizeLog = 18U;
+ static const scudo::uptr GroupSizeLog = 18U;
+ static const scudo::s32 MinReleaseToOsIntervalMs = INT32_MIN;
+ static const scudo::s32 MaxReleaseToOsIntervalMs = INT32_MAX;
+ typedef scudo::uptr CompactPtrT;
+ static const scudo::uptr CompactPtrScale = 0;
+ static const bool EnableRandomOffset = true;
+ static const scudo::uptr MapSizeIncrement = 1UL << 18;
+ static const bool ZeroOnDealloc = true;
+ };
+};
+
template <template <typename> class BaseConfig, typename SizeClassMapT>
struct Config : public BaseConfig<SizeClassMapT> {};
@@ -191,7 +212,8 @@ struct ScudoPrimaryTest : public Test {};
SCUDO_TYPED_TEST_TYPE(FIXTURE, NAME, TestConfig2) \
SCUDO_TYPED_TEST_TYPE(FIXTURE, NAME, TestConfig3) \
SCUDO_TYPED_TEST_TYPE(FIXTURE, NAME, TestConfig4) \
- SCUDO_TYPED_TEST_TYPE(FIXTURE, NAME, TestConfig5)
+ SCUDO_TYPED_TEST_TYPE(FIXTURE, NAME, TestConfig5) \
+ SCUDO_TYPED_TEST_TYPE(FIXTURE, NAME, TestConfig6)
#endif
#define SCUDO_TYPED_TEST_TYPE(FIXTURE, NAME, TYPE) \
More information about the llvm-commits
mailing list