From 08b0ede194ae790775661a6b36a17d3f6cca873f Mon Sep 17 00:00:00 2001 From: Mike Pall Date: Sat, 23 Oct 2010 16:31:27 +0200 Subject: [PATCH] Reduce 32GB RLIMIT_DATA on FreeBSD/x64 to allocate low-2GB memory. Thanks to Tony Finch. --- src/lj_alloc.c | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/src/lj_alloc.c b/src/lj_alloc.c index b027899a..2c686597 100644 --- a/src/lj_alloc.c +++ b/src/lj_alloc.c @@ -171,12 +171,20 @@ static LJ_AINLINE int CALL_MUNMAP(void *ptr, size_t size) /* Actually this only gives us max. 1GB in current Linux kernels. */ #define CALL_MMAP(s) mmap(NULL, (s), MMAP_PROT, MAP_32BIT|MMAP_FLAGS, -1, 0) -#elif defined(__MACH__) && defined(__APPLE__) +#elif (defined(__MACH__) && defined(__APPLE__)) || \ + defined(__FreeBSD__) || defined(__FreeBSD_kernel__) -/* OSX mmap() uses a naive first-fit linear search. That's perfect for us. -** But -pagezero_size must be set, otherwise the lower 4GB are blocked. +/* OSX and FreeBSD mmap() use a naive first-fit linear search. +** That's perfect for us. Except that -pagezero_size must be set for OSX, +** otherwise the lower 4GB are blocked. And the 32GB RLIMIT_DATA needs +** to be reduced to 250MB on FreeBSD. */ +#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) +#include +#define MMAP_REGION_START ((uintptr_t)0x10000000) +#else #define MMAP_REGION_START ((uintptr_t)0x10000) +#endif #define MMAP_REGION_END ((uintptr_t)0x80000000) static LJ_AINLINE void *CALL_MMAP(size_t size) @@ -184,6 +192,15 @@ static LJ_AINLINE void *CALL_MMAP(size_t size) /* Hint for next allocation. Doesn't need to be thread-safe. */ static uintptr_t alloc_hint = MMAP_REGION_START; int retry = 0; +#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) + static int rlimit_modified = 0; + if (LJ_UNLIKELY(rlimit_modified == 0)) { + struct rlimit rlim; + rlim.rlim_cur = rlim.rlim_max = MMAP_REGION_START; + setrlimit(RLIMIT_DATA, &rlim); /* Ignore result. May fail below. */ + rlimit_modified = 1; + } +#endif for (;;) { void *p = mmap((void *)alloc_hint, size, MMAP_PROT, MMAP_FLAGS, -1, 0); if ((uintptr_t)p >= MMAP_REGION_START && @@ -199,12 +216,6 @@ static LJ_AINLINE void *CALL_MMAP(size_t size) return CMFAIL; } -#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) - -/* FreeBSD 64 bit kernel ignores mmap() hints for lower 32GB of memory. */ -/* See: grep -C15 RLIMIT_DATA /usr/src/sys/vm/vm_mmap.c */ -#error "No support for 64 bit FreeBSD" - #else #error "NYI: need an equivalent of MAP_32BIT for this 64 bit OS"