diff options
author | Christopher Ferris <cferris@google.com> | 2020-06-19 00:55:04 +0000 |
---|---|---|
committer | Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> | 2020-06-19 00:55:04 +0000 |
commit | 1d271ba67bc88223db592cb721f2d0cc578ac978 (patch) | |
tree | e70da4e823d0f3ad195b7a2dbc480cb1e81b31ba | |
parent | 8441e8499d4963930036d8a1ca4d9e61d87d5f92 (diff) | |
parent | 520badfbe371eabc17415b0e79c03f1f7bf957fd (diff) | |
download | scudo-1d271ba67bc88223db592cb721f2d0cc578ac978.tar.gz |
[scudo][standalone] Allow Primary allocations to fail up multiple times. am: b7a688e544 am: 520badfbe3
Original change: https://googleplex-android-review.googlesource.com/c/platform/external/scudo/+/11914615
Change-Id: I4198484b6aa9916feaf442c6bcbb0efe9c3b3925
-rw-r--r-- | standalone/combined.h | 18 | ||||
-rw-r--r-- | standalone/tests/combined_test.cpp | 17 |
2 files changed, 21 insertions, 14 deletions
diff --git a/standalone/combined.h b/standalone/combined.h index 1aa93510d22..3ed34c21aa5 100644 --- a/standalone/combined.h +++ b/standalone/combined.h @@ -269,16 +269,20 @@ public: bool UnlockRequired; auto *TSD = TSDRegistry.getTSDAndLock(&UnlockRequired); Block = TSD->Cache.allocate(ClassId); - // If the allocation failed, the most likely reason with a 64-bit primary - // is the region being full. In that event, retry once using the - // immediately larger class (except if the failing class was already the - // largest). This will waste some memory but will allow the application to - // not fail. If dealing with the largest class, fallback to the Secondary. + // If the allocation failed, the most likely reason with a 32-bit primary + // is the region being full. In that event, retry in each successively + // larger class until it fits. If it fails to fit in the largest class, + // fallback to the Secondary. if (UNLIKELY(!Block)) { - if (ClassId < SizeClassMap::LargestClassId) + while (ClassId < SizeClassMap::LargestClassId) { Block = TSD->Cache.allocate(++ClassId); - else + if (LIKELY(Block)) { + break; + } + } + if (UNLIKELY(!Block)) { ClassId = 0; + } } if (UnlockRequired) TSD->unlock(); diff --git a/standalone/tests/combined_test.cpp b/standalone/tests/combined_test.cpp index a6f29a2610e..a2c06182a68 100644 --- a/standalone/tests/combined_test.cpp +++ b/standalone/tests/combined_test.cpp @@ -348,14 +348,14 @@ struct DeathSizeClassConfig { static const scudo::uptr NumBits = 1; static const scudo::uptr MinSizeLog = 10; static const scudo::uptr MidSizeLog = 10; - static const scudo::uptr MaxSizeLog = 11; + static const scudo::uptr MaxSizeLog = 13; static const scudo::u32 MaxNumCachedHint = 4; static const scudo::uptr MaxBytesCachedLog = 12; }; static const scudo::uptr DeathRegionSizeLog = 20U; struct DeathConfig { - // Tiny allocator, its Primary only serves chunks of two sizes. + // Tiny allocator, its Primary only serves chunks of four sizes. using DeathSizeClassMap = scudo::FixedSizeClassMap<DeathSizeClassConfig>; typedef scudo::SizeClassAllocator64<DeathSizeClassMap, DeathRegionSizeLog> Primary; @@ -435,7 +435,10 @@ TEST(ScudoCombinedTest, FullRegion) { ClassId <= DeathConfig::DeathSizeClassMap::LargestClassId; ClassId++) { const scudo::uptr Size = DeathConfig::DeathSizeClassMap::getSizeByClassId(ClassId); - const scudo::uptr MaxNumberOfChunks = (1U << DeathRegionSizeLog) / Size; + // Allocate enough to fill all of the regions above this one. + const scudo::uptr MaxNumberOfChunks = + ((1U << DeathRegionSizeLog) / Size) * + (DeathConfig::DeathSizeClassMap::LargestClassId - ClassId + 1); void *P; for (scudo::uptr I = 0; I <= MaxNumberOfChunks; I++) { P = Allocator->allocate(Size - 64U, Origin); @@ -444,10 +447,10 @@ TEST(ScudoCombinedTest, FullRegion) { else V.push_back(P); } - } - while (!V.empty()) { - Allocator->deallocate(V.back(), Origin); - V.pop_back(); + while (!V.empty()) { + Allocator->deallocate(V.back(), Origin); + V.pop_back(); + } } EXPECT_EQ(FailedAllocationsCount, 0U); } |