diff --git a/compiler-rt/lib/scudo/standalone/tests/combined_test.cpp b/compiler-rt/lib/scudo/standalone/tests/combined_test.cpp --- a/compiler-rt/lib/scudo/standalone/tests/combined_test.cpp +++ b/compiler-rt/lib/scudo/standalone/tests/combined_test.cpp @@ -69,6 +69,52 @@ } } +constexpr size_t kMaxSize = + std::max({sizeof(scudo::Allocator), + sizeof(scudo::Allocator), + sizeof(scudo::Allocator), + sizeof(scudo::Allocator)}); +constexpr size_t kMaxAlign = + std::max({alignof(scudo::Allocator), + alignof(scudo::Allocator), + alignof(scudo::Allocator), + alignof(scudo::Allocator)}); + +#if SCUDO_RISCV64 +// The allocator is over 4MB large. Rather than creating an instance of this on +// the heap, keep it in a global storage to reduce fragmentation from having to +// mmap this at the start of every test. +struct TestAllocatorStorage { + // To alleviate some problem, let's skip the thread safety analysis here. + static void *get(size_t size) NO_THREAD_SAFETY_ANALYSIS { + assert(size <= kMaxSize && + "Allocation size doesn't fit in the allocator storage"); + M.lock(); + return AllocatorStorage; + } + + static void release(void *ptr) NO_THREAD_SAFETY_ANALYSIS { + M.assertHeld(); + M.unlock(); + ASSERT_EQ(ptr, AllocatorStorage); + } + + static scudo::HybridMutex M; + static uint8_t AllocatorStorage[kMaxSize]; +}; +scudo::HybridMutex TestAllocatorStorage::M; +alignas(kMaxAlign) uint8_t TestAllocatorStorage::AllocatorStorage[kMaxSize]; +#else +struct TestAllocatorStorage { + static void *get(size_t size) NO_THREAD_SAFETY_ANALYSIS { + void *p = nullptr; + EXPECT_EQ(0, posix_memalign(&p, kMaxAlign, size)); + return p; + } + static void release(void *ptr) NO_THREAD_SAFETY_ANALYSIS { free(ptr); } +}; +#endif + template struct TestAllocator : scudo::Allocator { TestAllocator() { this->initThreadMaybe(); @@ -78,13 +124,9 @@ } ~TestAllocator() { this->unmapTestOnly(); } - void *operator new(size_t size) { - void *p = nullptr; - EXPECT_EQ(0, posix_memalign(&p, alignof(TestAllocator), size)); - return p; - } + void *operator new(size_t size) { return TestAllocatorStorage::get(size); } - void operator delete(void *ptr) { free(ptr); } + void operator delete(void *ptr) { TestAllocatorStorage::release(ptr); } }; template struct ScudoCombinedTest : public Test {