From f8f116109a664d6cb523228641748c43897ec20a Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Fri, 2 Aug 2024 15:45:16 +0200 Subject: [PATCH] Use back-off strategy when allocating virtual memory. --- src/utils/vmem.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/src/utils/vmem.c b/src/utils/vmem.c index a7d41d16e..88a905ea6 100644 --- a/src/utils/vmem.c +++ b/src/utils/vmem.c @@ -7,6 +7,8 @@ #if PLATFORM_POSIX #include +#include + #endif #if PLATFORM_WINDOWS @@ -17,7 +19,6 @@ static inline void mmap_init(Vmem *vmem, size_t size) { - vmem->size = size; #if PLATFORM_WINDOWS void* ptr = VirtualAlloc(0, size, MEM_RESERVE, PAGE_NOACCESS); vmem->committed = 0; @@ -26,14 +27,29 @@ static inline void mmap_init(Vmem *vmem, size_t size) FATAL_ERROR("Failed to map virtual memory block"); } #elif PLATFORM_POSIX - void* ptr = mmap(0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); + void* ptr = NULL; + size_t min_size = size / 16; + if (min_size < 1) min_size = size; + while (size >= min_size) + { + ptr = mmap(0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); + // It worked? + if (ptr != MAP_FAILED && ptr) break; + // Did it fail in a non-retriable way? + if (errno != ENOMEM && errno != EOVERFLOW && errno != EAGAIN) break; + // Try a smaller size + size /= 2; + } + // Check if we ended on a failure. if ((ptr == MAP_FAILED) || !ptr) { - FATAL_ERROR("Failed to map virtual memory block"); + FATAL_ERROR("Failed to map a virtual memory block."); } + // Otherwise, record the size and we're fine! #else FATAL_ERROR("Unsupported platform."); #endif + vmem->size = size; vmem->ptr = ptr; vmem->allocated = 0; }