Skip to content

Commit 6ca806a

Browse files
committed
[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
1 parent 399865c commit 6ca806a

File tree

5 files changed

+39
-1
lines changed

5 files changed

+39
-1
lines changed

compiler-rt/lib/scudo/standalone/allocator_config.def

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,11 @@ PRIMARY_OPTIONAL_TYPE(ConditionVariableT, ConditionVariableDummy)
111111
// to, in increments of a power-of-2 scale. See `CompactPtrScale` also.
112112
PRIMARY_OPTIONAL_TYPE(CompactPtrT, uptr)
113113

114+
// Clears the memory slot when a allocation is returned to the allocator.
115+
// Operating systems that detects pages filled with zeroes will decommit
116+
// memory.
117+
PRIMARY_OPTIONAL(const bool, ZeroOnDealloc, false)
118+
114119
// SECONDARY_REQUIRED_TEMPLATE_TYPE(NAME)
115120
//
116121
// Defines the type of Secondary Cache to use.

compiler-rt/lib/scudo/standalone/primary32.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ template <typename Config> class SizeClassAllocator32 {
4646
typedef typename Config::CompactPtrT CompactPtrT;
4747
typedef typename Config::SizeClassMap SizeClassMap;
4848
static const uptr GroupSizeLog = Config::getGroupSizeLog();
49+
static const bool ZeroOnDealloc = Config::getZeroOnDealloc();
4950
// The bytemap can only track UINT8_MAX - 1 classes.
5051
static_assert(SizeClassMap::LargestClassId <= (UINT8_MAX - 1), "");
5152
// Regions should be large enough to hold the largest Block.

compiler-rt/lib/scudo/standalone/primary64.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ template <typename Config> class SizeClassAllocator64 {
5353
static const uptr CompactPtrScale = Config::getCompactPtrScale();
5454
static const uptr RegionSizeLog = Config::getRegionSizeLog();
5555
static const uptr GroupSizeLog = Config::getGroupSizeLog();
56+
static const bool ZeroOnDealloc = Config::getZeroOnDealloc();
5657
static_assert(RegionSizeLog >= GroupSizeLog,
5758
"Group size shouldn't be greater than the region size");
5859
static const uptr GroupScale = GroupSizeLog - CompactPtrScale;

compiler-rt/lib/scudo/standalone/size_class_allocator.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,11 @@ template <class SizeClassAllocator> struct SizeClassAllocatorLocalCache {
5959

6060
bool deallocate(uptr ClassId, void *P) {
6161
CHECK_LT(ClassId, NumClasses);
62+
63+
if(SizeClassAllocator::ZeroOnDealloc) {
64+
memset(P, 0, SizeClassAllocator::getSizeByClassId(ClassId));
65+
}
66+
6267
PerClass *C = &PerClassArray[ClassId];
6368

6469
// If the cache is full, drain half of blocks back to the main allocator.
@@ -211,6 +216,10 @@ template <class SizeClassAllocator> struct SizeClassAllocatorNoCache {
211216
bool deallocate(uptr ClassId, void *P) {
212217
CHECK_LT(ClassId, NumClasses);
213218

219+
if(SizeClassAllocator::ZeroOnDealloc) {
220+
memset(P, 0, SizeClassAllocator::getSizeByClassId(ClassId));
221+
}
222+
214223
if (ClassId == BatchClassId)
215224
return deallocateBatchClassBlock(P);
216225

compiler-rt/lib/scudo/standalone/tests/primary_test.cpp

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,27 @@ template <typename SizeClassMapT> struct TestConfig5 {
150150
};
151151
};
152152

153+
// Enable `ZeroOnDealloc`
154+
template <typename SizeClassMapT> struct TestConfig6 {
155+
static const bool MaySupportMemoryTagging = false;
156+
template <typename> using TSDRegistryT = void;
157+
template <typename> using PrimaryT = void;
158+
template <typename> using SecondaryT = void;
159+
160+
struct Primary {
161+
using SizeClassMap = SizeClassMapT;
162+
static const scudo::uptr RegionSizeLog = 18U;
163+
static const scudo::uptr GroupSizeLog = 18U;
164+
static const scudo::s32 MinReleaseToOsIntervalMs = INT32_MIN;
165+
static const scudo::s32 MaxReleaseToOsIntervalMs = INT32_MAX;
166+
typedef scudo::uptr CompactPtrT;
167+
static const scudo::uptr CompactPtrScale = 0;
168+
static const bool EnableRandomOffset = true;
169+
static const scudo::uptr MapSizeIncrement = 1UL << 18;
170+
static const bool ZeroOnDealloc = true;
171+
};
172+
};
173+
153174
template <template <typename> class BaseConfig, typename SizeClassMapT>
154175
struct Config : public BaseConfig<SizeClassMapT> {};
155176

@@ -191,7 +212,8 @@ struct ScudoPrimaryTest : public Test {};
191212
SCUDO_TYPED_TEST_TYPE(FIXTURE, NAME, TestConfig2) \
192213
SCUDO_TYPED_TEST_TYPE(FIXTURE, NAME, TestConfig3) \
193214
SCUDO_TYPED_TEST_TYPE(FIXTURE, NAME, TestConfig4) \
194-
SCUDO_TYPED_TEST_TYPE(FIXTURE, NAME, TestConfig5)
215+
SCUDO_TYPED_TEST_TYPE(FIXTURE, NAME, TestConfig5) \
216+
SCUDO_TYPED_TEST_TYPE(FIXTURE, NAME, TestConfig6)
195217
#endif
196218

197219
#define SCUDO_TYPED_TEST_TYPE(FIXTURE, NAME, TYPE) \

0 commit comments

Comments
 (0)