forked from OSchip/llvm-project
[NFC][scudo] Extract MapAllocatorTest for TEST_F
This commit is contained in:
parent
f03d29601e
commit
39a15b5ae0
|
@ -11,11 +11,11 @@
|
|||
#include "allocator_config.h"
|
||||
#include "secondary.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <condition_variable>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <random>
|
||||
#include <stdio.h>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
|
@ -94,14 +94,22 @@ TEST(ScudoSecondaryTest, SecondaryBasic) {
|
|||
|
||||
using LargeAllocator = scudo::MapAllocator<scudo::DefaultConfig>;
|
||||
|
||||
struct MapAllocatorTest : public Test {
|
||||
void SetUp() override { Allocator->init(nullptr); }
|
||||
|
||||
void TearDown() override { Allocator->unmapTestOnly(); }
|
||||
|
||||
std::unique_ptr<LargeAllocator> Allocator =
|
||||
std::make_unique<LargeAllocator>();
|
||||
scudo::Options Options = {};
|
||||
};
|
||||
|
||||
// This exercises a variety of combinations of size and alignment for the
|
||||
// MapAllocator. The size computation done here mimic the ones done by the
|
||||
// combined allocator.
|
||||
TEST(ScudoSecondaryTest, SecondaryCombinations) {
|
||||
TEST_F(MapAllocatorTest, SecondaryCombinations) {
|
||||
constexpr scudo::uptr MinAlign = FIRST_32_SECOND_64(8, 16);
|
||||
constexpr scudo::uptr HeaderSize = scudo::roundUpTo(8, MinAlign);
|
||||
std::unique_ptr<LargeAllocator> L(new LargeAllocator);
|
||||
L->init(nullptr);
|
||||
for (scudo::uptr SizeLog = 0; SizeLog <= 20; SizeLog++) {
|
||||
for (scudo::uptr AlignLog = FIRST_32_SECOND_64(3, 4); AlignLog <= 16;
|
||||
AlignLog++) {
|
||||
|
@ -113,103 +121,102 @@ TEST(ScudoSecondaryTest, SecondaryCombinations) {
|
|||
scudo::roundUpTo((1U << SizeLog) + Delta, MinAlign);
|
||||
const scudo::uptr Size =
|
||||
HeaderSize + UserSize + (Align > MinAlign ? Align - HeaderSize : 0);
|
||||
void *P = L->allocate(scudo::Options{}, Size, Align);
|
||||
void *P = Allocator->allocate(Options, Size, Align);
|
||||
EXPECT_NE(P, nullptr);
|
||||
void *AlignedP = reinterpret_cast<void *>(
|
||||
scudo::roundUpTo(reinterpret_cast<scudo::uptr>(P), Align));
|
||||
memset(AlignedP, 0xff, UserSize);
|
||||
L->deallocate(scudo::Options{}, P);
|
||||
Allocator->deallocate(Options, P);
|
||||
}
|
||||
}
|
||||
}
|
||||
scudo::ScopedString Str;
|
||||
L->getStats(&Str);
|
||||
Allocator->getStats(&Str);
|
||||
Str.output();
|
||||
L->unmapTestOnly();
|
||||
}
|
||||
|
||||
TEST(ScudoSecondaryTest, SecondaryIterate) {
|
||||
std::unique_ptr<LargeAllocator> L(new LargeAllocator);
|
||||
L->init(nullptr);
|
||||
TEST_F(MapAllocatorTest, SecondaryIterate) {
|
||||
std::vector<void *> V;
|
||||
const scudo::uptr PageSize = scudo::getPageSizeCached();
|
||||
for (scudo::uptr I = 0; I < 32U; I++)
|
||||
V.push_back(L->allocate(scudo::Options{}, (std::rand() % 16) * PageSize));
|
||||
V.push_back(Allocator->allocate(Options, (std::rand() % 16) * PageSize));
|
||||
auto Lambda = [V](scudo::uptr Block) {
|
||||
EXPECT_NE(std::find(V.begin(), V.end(), reinterpret_cast<void *>(Block)),
|
||||
V.end());
|
||||
};
|
||||
L->disable();
|
||||
L->iterateOverBlocks(Lambda);
|
||||
L->enable();
|
||||
Allocator->disable();
|
||||
Allocator->iterateOverBlocks(Lambda);
|
||||
Allocator->enable();
|
||||
while (!V.empty()) {
|
||||
L->deallocate(scudo::Options{}, V.back());
|
||||
Allocator->deallocate(Options, V.back());
|
||||
V.pop_back();
|
||||
}
|
||||
scudo::ScopedString Str;
|
||||
L->getStats(&Str);
|
||||
Allocator->getStats(&Str);
|
||||
Str.output();
|
||||
L->unmapTestOnly();
|
||||
}
|
||||
|
||||
TEST(ScudoSecondaryTest, SecondaryOptions) {
|
||||
std::unique_ptr<LargeAllocator> L(new LargeAllocator);
|
||||
L->init(nullptr);
|
||||
TEST_F(MapAllocatorTest, SecondaryOptions) {
|
||||
// Attempt to set a maximum number of entries higher than the array size.
|
||||
EXPECT_FALSE(L->setOption(scudo::Option::MaxCacheEntriesCount, 4096U));
|
||||
EXPECT_FALSE(
|
||||
Allocator->setOption(scudo::Option::MaxCacheEntriesCount, 4096U));
|
||||
// A negative number will be cast to a scudo::u32, and fail.
|
||||
EXPECT_FALSE(L->setOption(scudo::Option::MaxCacheEntriesCount, -1));
|
||||
if (L->canCache(0U)) {
|
||||
EXPECT_FALSE(Allocator->setOption(scudo::Option::MaxCacheEntriesCount, -1));
|
||||
if (Allocator->canCache(0U)) {
|
||||
// Various valid combinations.
|
||||
EXPECT_TRUE(L->setOption(scudo::Option::MaxCacheEntriesCount, 4U));
|
||||
EXPECT_TRUE(L->setOption(scudo::Option::MaxCacheEntrySize, 1UL << 20));
|
||||
EXPECT_TRUE(L->canCache(1UL << 18));
|
||||
EXPECT_TRUE(L->setOption(scudo::Option::MaxCacheEntrySize, 1UL << 17));
|
||||
EXPECT_FALSE(L->canCache(1UL << 18));
|
||||
EXPECT_TRUE(L->canCache(1UL << 16));
|
||||
EXPECT_TRUE(L->setOption(scudo::Option::MaxCacheEntriesCount, 0U));
|
||||
EXPECT_FALSE(L->canCache(1UL << 16));
|
||||
EXPECT_TRUE(L->setOption(scudo::Option::MaxCacheEntriesCount, 4U));
|
||||
EXPECT_TRUE(L->setOption(scudo::Option::MaxCacheEntrySize, 1UL << 20));
|
||||
EXPECT_TRUE(L->canCache(1UL << 16));
|
||||
}
|
||||
L->unmapTestOnly();
|
||||
}
|
||||
|
||||
static std::mutex Mutex;
|
||||
static std::condition_variable Cv;
|
||||
static bool Ready;
|
||||
|
||||
static void performAllocations(LargeAllocator *L) {
|
||||
std::vector<void *> V;
|
||||
const scudo::uptr PageSize = scudo::getPageSizeCached();
|
||||
{
|
||||
std::unique_lock<std::mutex> Lock(Mutex);
|
||||
while (!Ready)
|
||||
Cv.wait(Lock);
|
||||
}
|
||||
for (scudo::uptr I = 0; I < 128U; I++) {
|
||||
// Deallocate 75% of the blocks.
|
||||
const bool Deallocate = (rand() & 3) != 0;
|
||||
void *P = L->allocate(scudo::Options{}, (std::rand() % 16) * PageSize);
|
||||
if (Deallocate)
|
||||
L->deallocate(scudo::Options{}, P);
|
||||
else
|
||||
V.push_back(P);
|
||||
}
|
||||
while (!V.empty()) {
|
||||
L->deallocate(scudo::Options{}, V.back());
|
||||
V.pop_back();
|
||||
EXPECT_TRUE(Allocator->setOption(scudo::Option::MaxCacheEntriesCount, 4U));
|
||||
EXPECT_TRUE(
|
||||
Allocator->setOption(scudo::Option::MaxCacheEntrySize, 1UL << 20));
|
||||
EXPECT_TRUE(Allocator->canCache(1UL << 18));
|
||||
EXPECT_TRUE(
|
||||
Allocator->setOption(scudo::Option::MaxCacheEntrySize, 1UL << 17));
|
||||
EXPECT_FALSE(Allocator->canCache(1UL << 18));
|
||||
EXPECT_TRUE(Allocator->canCache(1UL << 16));
|
||||
EXPECT_TRUE(Allocator->setOption(scudo::Option::MaxCacheEntriesCount, 0U));
|
||||
EXPECT_FALSE(Allocator->canCache(1UL << 16));
|
||||
EXPECT_TRUE(Allocator->setOption(scudo::Option::MaxCacheEntriesCount, 4U));
|
||||
EXPECT_TRUE(
|
||||
Allocator->setOption(scudo::Option::MaxCacheEntrySize, 1UL << 20));
|
||||
EXPECT_TRUE(Allocator->canCache(1UL << 16));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(ScudoSecondaryTest, SecondaryThreadsRace) {
|
||||
Ready = false;
|
||||
std::unique_ptr<LargeAllocator> L(new LargeAllocator);
|
||||
L->init(nullptr, /*ReleaseToOsInterval=*/0);
|
||||
struct MapAllocatorWithReleaseTest : public MapAllocatorTest {
|
||||
void SetUp() override { Allocator->init(nullptr, /*ReleaseToOsInterval=*/0); }
|
||||
|
||||
void performAllocations() {
|
||||
std::vector<void *> V;
|
||||
const scudo::uptr PageSize = scudo::getPageSizeCached();
|
||||
{
|
||||
std::unique_lock<std::mutex> Lock(Mutex);
|
||||
while (!Ready)
|
||||
Cv.wait(Lock);
|
||||
}
|
||||
for (scudo::uptr I = 0; I < 128U; I++) {
|
||||
// Deallocate 75% of the blocks.
|
||||
const bool Deallocate = (rand() & 3) != 0;
|
||||
void *P = Allocator->allocate(Options, (std::rand() % 16) * PageSize);
|
||||
if (Deallocate)
|
||||
Allocator->deallocate(Options, P);
|
||||
else
|
||||
V.push_back(P);
|
||||
}
|
||||
while (!V.empty()) {
|
||||
Allocator->deallocate(Options, V.back());
|
||||
V.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
std::mutex Mutex;
|
||||
std::condition_variable Cv;
|
||||
bool Ready = false;
|
||||
};
|
||||
|
||||
TEST_F(MapAllocatorWithReleaseTest, SecondaryThreadsRace) {
|
||||
std::thread Threads[16];
|
||||
for (scudo::uptr I = 0; I < ARRAY_SIZE(Threads); I++)
|
||||
Threads[I] = std::thread(performAllocations, L.get());
|
||||
Threads[I] =
|
||||
std::thread(&MapAllocatorWithReleaseTest::performAllocations, this);
|
||||
{
|
||||
std::unique_lock<std::mutex> Lock(Mutex);
|
||||
Ready = true;
|
||||
|
@ -218,7 +225,6 @@ TEST(ScudoSecondaryTest, SecondaryThreadsRace) {
|
|||
for (auto &T : Threads)
|
||||
T.join();
|
||||
scudo::ScopedString Str;
|
||||
L->getStats(&Str);
|
||||
Allocator->getStats(&Str);
|
||||
Str.output();
|
||||
L->unmapTestOnly();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue