diff --git a/src/coreclr/minipal/Unix/doublemapping.cpp b/src/coreclr/minipal/Unix/doublemapping.cpp index 47a91c6243d9c0..205a2cac789fae 100644 --- a/src/coreclr/minipal/Unix/doublemapping.cpp +++ b/src/coreclr/minipal/Unix/doublemapping.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #if defined(TARGET_LINUX) && !defined(MFD_CLOEXEC) #include #include // __NR_memfd_create @@ -81,14 +82,53 @@ bool VMToOSInterface::CreateDoubleMemoryMapper(void** pHandle, size_t *pMaxExecu return false; } #endif + uint64_t maxDoubleMappedMemorySize = MaxDoubleMappedSize; + + // Set the maximum double mapped memory size to the size of the physical memory + long pages = sysconf(_SC_PHYS_PAGES); + if (pages != -1) + { + long pageSize = sysconf(_SC_PAGE_SIZE); + if (pageSize != -1) + { + uint64_t physicalMemorySize = (uint64_t)pages * pageSize; + if (maxDoubleMappedMemorySize > physicalMemorySize) + { + maxDoubleMappedMemorySize = physicalMemorySize; + } + } + } + + // Clip the maximum double mapped memory size to 1/4 of the virtual address space limit. + // When such a limit is set, GC reserves 1/2 of it, so we need to leave something + // for the rest of the process. + struct rlimit virtualAddressSpaceLimit; + if ((getrlimit(RLIMIT_AS, &virtualAddressSpaceLimit) == 0) && (virtualAddressSpaceLimit.rlim_cur != RLIM_INFINITY)) + { + virtualAddressSpaceLimit.rlim_cur /= 4; + if (maxDoubleMappedMemorySize > virtualAddressSpaceLimit.rlim_cur) + { + maxDoubleMappedMemorySize = virtualAddressSpaceLimit.rlim_cur; + } + } + + // Clip the maximum double mapped memory size to the file size limit + struct rlimit fileSizeLimit; + if ((getrlimit(RLIMIT_FSIZE, &fileSizeLimit) == 0) && (fileSizeLimit.rlim_cur != RLIM_INFINITY)) + { + if (maxDoubleMappedMemorySize > fileSizeLimit.rlim_cur) + { + maxDoubleMappedMemorySize = fileSizeLimit.rlim_cur; + } + } - if (ftruncate(fd, MaxDoubleMappedSize) == -1) + if (ftruncate(fd, maxDoubleMappedMemorySize) == -1) { close(fd); return false; } - *pMaxExecutableCodeSize = MaxDoubleMappedSize; + *pMaxExecutableCodeSize = maxDoubleMappedMemorySize; *pHandle = (void*)(size_t)fd; #else // !TARGET_APPLE