Skip to content

Commit 11d45d8

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 11d45d8

File tree

5 files changed

+47
-1
lines changed

5 files changed

+47
-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/flags.inc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ SCUDO_FLAG(bool, delete_size_mismatch, true,
3434

3535
SCUDO_FLAG(bool, zero_contents, false, "Zero chunk contents on allocation.")
3636

37+
SCUDO_FLAG(bool, zero_on_dealloc, false,
38+
"Clears the memory slot when a allocation is returned to the "
39+
"allocator.")
40+
3741
SCUDO_FLAG(bool, pattern_fill_contents, false,
3842
"Pattern fill chunk contents on allocation.")
3943

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: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "report.h"
1616
#include "stats.h"
1717
#include "string_utils.h"
18+
#include "flags.h"
1819

1920
namespace scudo {
2021

@@ -28,6 +29,7 @@ template <class SizeClassAllocator> struct SizeClassAllocatorLocalCache {
2829
if (LIKELY(S))
2930
S->link(&Stats);
3031
Allocator = A;
32+
ZeroOnDealloc = getFlags()->zero_on_dealloc;
3133
initAllocator();
3234
}
3335

@@ -59,6 +61,11 @@ template <class SizeClassAllocator> struct SizeClassAllocatorLocalCache {
5961

6062
bool deallocate(uptr ClassId, void *P) {
6163
CHECK_LT(ClassId, NumClasses);
64+
65+
if (SizeClassAllocator::ZeroOnDealloc || ZeroOnDealloc) {
66+
memset(P, 0, SizeClassAllocator::getSizeByClassId(ClassId));
67+
}
68+
6269
PerClass *C = &PerClassArray[ClassId];
6370

6471
// If the cache is full, drain half of blocks back to the main allocator.
@@ -145,6 +152,7 @@ template <class SizeClassAllocator> struct SizeClassAllocatorLocalCache {
145152
PerClass PerClassArray[NumClasses] = {};
146153
LocalStats Stats;
147154
SizeClassAllocator *Allocator = nullptr;
155+
bool ZeroOnDealloc = false;
148156

149157
NOINLINE void initAllocator() {
150158
for (uptr I = 0; I < NumClasses; I++) {
@@ -188,6 +196,7 @@ template <class SizeClassAllocator> struct SizeClassAllocatorNoCache {
188196
if (LIKELY(S))
189197
S->link(&Stats);
190198
Allocator = A;
199+
ZeroOnDealloc = getFlags()->zero_on_dealloc;
191200
initAllocator();
192201
}
193202

@@ -211,6 +220,10 @@ template <class SizeClassAllocator> struct SizeClassAllocatorNoCache {
211220
bool deallocate(uptr ClassId, void *P) {
212221
CHECK_LT(ClassId, NumClasses);
213222

223+
if (SizeClassAllocator::ZeroOnDealloc || ZeroOnDealloc) {
224+
memset(P, 0, SizeClassAllocator::getSizeByClassId(ClassId));
225+
}
226+
214227
if (ClassId == BatchClassId)
215228
return deallocateBatchClassBlock(P);
216229

@@ -288,6 +301,7 @@ template <class SizeClassAllocator> struct SizeClassAllocatorNoCache {
288301
CompactPtrT BatchClassStorage[SizeClassMap::MaxNumCachedHint] = {};
289302
LocalStats Stats;
290303
SizeClassAllocator *Allocator = nullptr;
304+
bool ZeroOnDealloc = false;
291305

292306
bool deallocateBatchClassBlock(void *P) {
293307
PerClass *C = &PerClassArray[BatchClassId];

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)