From 297d831192b797157851125a71af4deec9a4773c Mon Sep 17 00:00:00 2001 From: Andrew Noyes <andrew.noyes@snowflake.com> Date: Tue, 19 Apr 2022 11:22:35 -0700 Subject: [PATCH] Put guard pages next to fast alloc memory (#6885) * Put guard pages next to fast alloc memory I verified that we can now detect #6753 without creating tons of threads. * Use pageSize instead of 4096 * Don't include mmapInternal for windows --- flow/FastAlloc.cpp | 2 +- flow/Platform.actor.cpp | 27 +++++++++++++++++++++------ flow/Platform.h | 2 +- 3 files changed, 23 insertions(+), 8 deletions(-) diff --git a/flow/FastAlloc.cpp b/flow/FastAlloc.cpp index 262d1b017c..dd6f68c542 100644 --- a/flow/FastAlloc.cpp +++ b/flow/FastAlloc.cpp @@ -519,7 +519,7 @@ void FastAllocator<Size>::getMagazine() { --g_allocation_tracing_disabled; } #endif - block = (void**)::allocate(magazine_size * Size, false); + block = (void**)::allocate(magazine_size * Size, /*allowLargePages*/ false, /*includeGuardPages*/ true); #endif // void** block = new void*[ magazine_size * PSize ]; diff --git a/flow/Platform.actor.cpp b/flow/Platform.actor.cpp index c07ff01bca..4661c0c6ea 100644 --- a/flow/Platform.actor.cpp +++ b/flow/Platform.actor.cpp @@ -2037,7 +2037,22 @@ static void enableLargePages() { #endif } -static void* allocateInternal(size_t length, bool largePages) { +#ifndef _WIN32 +static void* mmapInternal(size_t length, int flags, bool guardPages) { + if (guardPages) { + constexpr size_t pageSize = 4096; + length += 2 * pageSize; // Map enough for the guard pages + void* resultWithGuardPages = mmap(nullptr, length, PROT_READ | PROT_WRITE, flags, -1, 0); + mprotect(resultWithGuardPages, pageSize, PROT_NONE); // left guard page + mprotect((void*)(uintptr_t(resultWithGuardPages) + length - pageSize), pageSize, PROT_NONE); // right guard page + return (void*)(uintptr_t(resultWithGuardPages) + pageSize); + } else { + return mmap(nullptr, length, PROT_READ | PROT_WRITE, flags, -1, 0); + } +} +#endif + +static void* allocateInternal(size_t length, bool largePages, bool guardPages) { #ifdef _WIN32 DWORD allocType = MEM_COMMIT | MEM_RESERVE; @@ -2052,31 +2067,31 @@ static void* allocateInternal(size_t length, bool largePages) { if (largePages) flags |= MAP_HUGETLB; - return mmap(nullptr, length, PROT_READ | PROT_WRITE, flags, -1, 0); + return mmapInternal(length, flags, guardPages); #elif defined(__APPLE__) || defined(__FreeBSD__) int flags = MAP_PRIVATE | MAP_ANON; - return mmap(nullptr, length, PROT_READ | PROT_WRITE, flags, -1, 0); + return mmapInternal(length, flags, guardPages); #else #error Port me! #endif } static bool largeBlockFail = false; -void* allocate(size_t length, bool allowLargePages) { +void* allocate(size_t length, bool allowLargePages, bool includeGuardPages) { if (allowLargePages) enableLargePages(); void* block = ALLOC_FAIL; if (allowLargePages && !largeBlockFail) { - block = allocateInternal(length, true); + block = allocateInternal(length, true, includeGuardPages); if (block == ALLOC_FAIL) largeBlockFail = true; } if (block == ALLOC_FAIL) - block = allocateInternal(length, false); + block = allocateInternal(length, false, includeGuardPages); // FIXME: SevWarnAlways trace if "close" to out of memory diff --git a/flow/Platform.h b/flow/Platform.h index 020544178f..272c8e3588 100644 --- a/flow/Platform.h +++ b/flow/Platform.h @@ -284,7 +284,7 @@ std::string epochsToGMTString(double epochs); void setMemoryQuota(size_t limit); -void* allocate(size_t length, bool allowLargePages); +void* allocate(size_t length, bool allowLargePages, bool includeGuardPages); void setAffinity(int proc);