Skip to content

Commit 624a24e

Browse files
author
Kostya Kortchinsky
committed
[scudo][standalone] Unmap memory in tests
Summary: The more tests are added, the more we are limited by the size of the address space on 32-bit. Implement `unmapTestOnly` all around (like it is in sanitzer_common) to be able to free up some memory. This is not intended to be a proper "destructor" for an allocator, but allows us to not fail due to having no memory left. Reviewers: morehouse, vitalybuka, eugenis, hctim Reviewed By: morehouse Subscribers: delcypher, jfb, #sanitizers, llvm-commits Tags: #llvm, #sanitizers Differential Revision: https://reviews.llvm.org/D63146 llvm-svn: 363095
1 parent cb4ed8a commit 624a24e

File tree

8 files changed

+74
-16
lines changed

8 files changed

+74
-16
lines changed

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ template <uptr Size> class FlatByteMap {
2222
}
2323
void init() { initLinkerInitialized(); }
2424

25+
void unmapTestOnly() { unmap(reinterpret_cast<void *>(Map), Size); }
26+
2527
void set(uptr Index, u8 Value) {
2628
DCHECK_LT(Index, Size);
2729
DCHECK_EQ(0U, Map[Index]);
@@ -57,6 +59,12 @@ template <uptr Level1Size, uptr Level2Size> class TwoLevelByteMap {
5759
memset(Level1Map, 0, sizeof(atomic_uptr) * Level1Size);
5860
}
5961

62+
void unmapTestOnly() {
63+
reset();
64+
unmap(reinterpret_cast<void *>(Level1Map),
65+
sizeof(atomic_uptr) * Level1Size);
66+
}
67+
6068
uptr size() const { return Level1Size * Level2Size; }
6169

6270
void set(uptr Index, u8 Value) {

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,17 @@ template <class SizeClassMapT, uptr RegionSizeLog> class SizeClassAllocator32 {
8383
initLinkerInitialized(ReleaseToOsInterval);
8484
}
8585

86+
void unmapTestOnly() {
87+
while (NumberOfStashedRegions > 0)
88+
unmap(reinterpret_cast<void *>(RegionsStash[--NumberOfStashedRegions]),
89+
RegionSize);
90+
// TODO(kostyak): unmap the TransferBatch regions as well.
91+
for (uptr I = 0; I < NumRegions; I++)
92+
if (PossibleRegions[I])
93+
unmap(reinterpret_cast<void *>(I * RegionSize), RegionSize);
94+
PossibleRegions.unmapTestOnly();
95+
}
96+
8697
TransferBatch *popBatch(CacheT *C, uptr ClassId) {
8798
DCHECK_LT(ClassId, NumClasses);
8899
SizeClassInfo *Sci = getSizeClassInfo(ClassId);

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,12 @@ template <class SizeClassMapT, uptr RegionSizeLog> class SizeClassAllocator64 {
9191
initLinkerInitialized(ReleaseToOsInterval);
9292
}
9393

94+
void unmapTestOnly() {
95+
unmap(reinterpret_cast<void *>(PrimaryBase), PrimarySize, UNMAP_ALL, &Data);
96+
unmap(reinterpret_cast<void *>(RegionInfoArray),
97+
sizeof(RegionInfo) * NumClasses);
98+
}
99+
94100
TransferBatch *popBatch(CacheT *C, uptr ClassId) {
95101
DCHECK_LT(ClassId, NumClasses);
96102
RegionInfo *Region = getRegionInfo(ClassId);

compiler-rt/lib/scudo/standalone/tests/bytemap_test.cc

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,14 @@ TEST(ScudoByteMapTest, FlatByteMap) {
2828
const scudo::uptr Size = 1U << 10;
2929
scudo::FlatByteMap<Size> Map;
3030
testMap(Map, Size);
31+
Map.unmapTestOnly();
3132
}
3233

3334
TEST(ScudoByteMapTest, TwoLevelByteMap) {
3435
const scudo::uptr Size1 = 1U << 6, Size2 = 1U << 12;
3536
scudo::TwoLevelByteMap<Size1, Size2> Map;
3637
testMap(Map, Size1 * Size2);
37-
Map.reset();
38+
Map.unmapTestOnly();
3839
}
3940

4041
using TestByteMap = scudo::TwoLevelByteMap<1U << 12, 1U << 13>;
@@ -69,5 +70,5 @@ TEST(ScudoByteMapTest, ThreadedTwoLevelByteMap) {
6970
}
7071
for (scudo::uptr I = 0; I < NumberOfThreads; I++)
7172
pthread_join(T[I], 0);
72-
Map.reset();
73+
Map.unmapTestOnly();
7374
}

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

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,11 @@
2222

2323
template <typename Primary> static void testPrimary() {
2424
const scudo::uptr NumberOfAllocations = 32U;
25-
std::unique_ptr<Primary> Allocator(new Primary);
25+
auto Deleter = [](Primary *P) {
26+
P->unmapTestOnly();
27+
delete P;
28+
};
29+
std::unique_ptr<Primary, decltype(Deleter)> Allocator(new Primary, Deleter);
2630
Allocator->init(/*ReleaseToOsInterval=*/-1);
2731
typename Primary::CacheT Cache;
2832
Cache.init(nullptr, Allocator.get());
@@ -84,10 +88,15 @@ TEST(ScudoPrimaryTest, Primary64OOM) {
8488
Allocator.releaseToOS();
8589
Allocator.printStats();
8690
EXPECT_EQ(AllocationFailed, true);
91+
Allocator.unmapTestOnly();
8792
}
8893

8994
template <typename Primary> static void testIteratePrimary() {
90-
std::unique_ptr<Primary> Allocator(new Primary);
95+
auto Deleter = [](Primary *P) {
96+
P->unmapTestOnly();
97+
delete P;
98+
};
99+
std::unique_ptr<Primary, decltype(Deleter)> Allocator(new Primary, Deleter);
91100
Allocator->init(/*ReleaseToOsInterval=*/-1);
92101
typename Primary::CacheT Cache;
93102
Cache.init(nullptr, Allocator.get());
@@ -125,10 +134,6 @@ TEST(ScudoPrimaryTest, PrimaryIterate) {
125134
testIteratePrimary<scudo::SizeClassAllocator64<SizeClassMap, 24U>>();
126135
}
127136

128-
// TODO(kostyak): reenable on 32-bit after implementing unmapTestOnly for the
129-
// primary: we are running out of addressable space without.
130-
#if SCUDO_WORDSIZE == 64U
131-
132137
static std::mutex Mutex;
133138
static std::condition_variable Cv;
134139
static bool Ready = false;
@@ -143,7 +148,7 @@ template <typename Primary> static void performAllocations(Primary *Allocator) {
143148
Cv.wait(Lock);
144149
}
145150
for (scudo::uptr I = 0; I < 256U; I++) {
146-
const scudo::uptr Size = std::rand() % Primary::SizeClassMap::MaxSize;
151+
const scudo::uptr Size = std::rand() % Primary::SizeClassMap::MaxSize / 4;
147152
const scudo::uptr ClassId = Primary::SizeClassMap::getClassIdBySize(Size);
148153
void *P = Cache.allocate(ClassId);
149154
if (P)
@@ -158,7 +163,11 @@ template <typename Primary> static void performAllocations(Primary *Allocator) {
158163
}
159164

160165
template <typename Primary> static void testPrimaryThreaded() {
161-
std::unique_ptr<Primary> Allocator(new Primary);
166+
auto Deleter = [](Primary *P) {
167+
P->unmapTestOnly();
168+
delete P;
169+
};
170+
std::unique_ptr<Primary, decltype(Deleter)> Allocator(new Primary, Deleter);
162171
Allocator->init(/*ReleaseToOsInterval=*/-1);
163172
std::thread Threads[32];
164173
for (scudo::uptr I = 0; I < ARRAY_SIZE(Threads); I++)
@@ -177,7 +186,5 @@ template <typename Primary> static void testPrimaryThreaded() {
177186
TEST(ScudoPrimaryTest, PrimaryThreaded) {
178187
using SizeClassMap = scudo::SvelteSizeClassMap;
179188
testPrimaryThreaded<scudo::SizeClassAllocator32<SizeClassMap, 18U>>();
180-
testPrimaryThreaded<scudo::SizeClassAllocator64<SizeClassMap, 28U>>();
189+
testPrimaryThreaded<scudo::SizeClassAllocator64<SizeClassMap, 24U>>();
181190
}
182-
183-
#endif // SCUDO_WORDSIZE == 64U

compiler-rt/lib/scudo/standalone/tests/tsd_test.cc

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ template <class Config> class MockAllocator {
3232
}
3333
void reset() { memset(this, 0, sizeof(*this)); }
3434

35+
void unmapTestOnly() { TSDRegistry.unmapTestOnly(); }
3536
void initCache(CacheT *Cache) { memset(Cache, 0, sizeof(*Cache)); }
3637
void commitBack(scudo::TSD<MockAllocator> *TSD) {}
3738
TSDRegistryT *getTSDRegistry() { return &TSDRegistry; }
@@ -60,7 +61,12 @@ struct ExclusiveCaches {
6061

6162
TEST(ScudoTSDTest, TSDRegistryInit) {
6263
using AllocatorT = MockAllocator<OneCache>;
63-
std::unique_ptr<AllocatorT> Allocator(new AllocatorT);
64+
auto Deleter = [](AllocatorT *A) {
65+
A->unmapTestOnly();
66+
delete A;
67+
};
68+
std::unique_ptr<AllocatorT, decltype(Deleter)> Allocator(new AllocatorT,
69+
Deleter);
6470
Allocator->reset();
6571
EXPECT_FALSE(Allocator->isInitialized());
6672

@@ -70,7 +76,12 @@ TEST(ScudoTSDTest, TSDRegistryInit) {
7076
}
7177

7278
template <class AllocatorT> static void testRegistry() {
73-
std::unique_ptr<AllocatorT> Allocator(new AllocatorT);
79+
auto Deleter = [](AllocatorT *A) {
80+
A->unmapTestOnly();
81+
delete A;
82+
};
83+
std::unique_ptr<AllocatorT, decltype(Deleter)> Allocator(new AllocatorT,
84+
Deleter);
7485
Allocator->reset();
7586
EXPECT_FALSE(Allocator->isInitialized());
7687

@@ -131,7 +142,12 @@ template <typename AllocatorT> static void stressCache(AllocatorT *Allocator) {
131142
}
132143

133144
template <class AllocatorT> static void testRegistryThreaded() {
134-
std::unique_ptr<AllocatorT> Allocator(new AllocatorT);
145+
auto Deleter = [](AllocatorT *A) {
146+
A->unmapTestOnly();
147+
delete A;
148+
};
149+
std::unique_ptr<AllocatorT, decltype(Deleter)> Allocator(new AllocatorT,
150+
Deleter);
135151
Allocator->reset();
136152
std::thread Threads[32];
137153
for (scudo::uptr I = 0; I < ARRAY_SIZE(Threads); I++)

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@ template <class Allocator> struct TSDRegistryExT {
3737
initLinkerInitialized(Instance);
3838
}
3939

40+
void unmapTestOnly() {
41+
unmap(reinterpret_cast<void *>(FallbackTSD), sizeof(TSD<Allocator>));
42+
}
43+
4044
ALWAYS_INLINE void initThreadMaybe(Allocator *Instance, bool MinimalInit) {
4145
if (LIKELY(State != ThreadState::NotInitialized))
4246
return;

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,11 @@ template <class Allocator, u32 MaxTSDCount> struct TSDRegistrySharedT {
4747
initLinkerInitialized(Instance);
4848
}
4949

50+
void unmapTestOnly() {
51+
unmap(reinterpret_cast<void *>(TSDs),
52+
sizeof(TSD<Allocator>) * NumberOfTSDs);
53+
}
54+
5055
ALWAYS_INLINE void initThreadMaybe(Allocator *Instance,
5156
UNUSED bool MinimalInit) {
5257
if (LIKELY(getCurrentTSD()))

0 commit comments

Comments
 (0)