Avoid virtual memory range collision between JIT and emulated RAM.

Passing MAP_FIXED to mmap causes already mapped pages in the requested
region to be replaced. On Mac OS X this caused pages for JIT-generatd
code to appear in the memory range previously auto-allocated for the RAM
of the emulated machine. This led to a hang at boot time. The same problem
can probably occur on FreeBSD, but not on Linux since MAP_32BIT is used
there instead of MAP_FIXED.

The solution is to not use MAP_FIXED, but instead rely on the OS honoring
the hinted address which is below 4 GB: we don't need an exact match,
just a low address.
This commit is contained in:
Maarten ter Huurne 2011-11-30 00:37:57 +01:00
parent 933d2dde42
commit 29865e6366

View File

@ -43,18 +43,20 @@ void* AllocateExecutableMemory(size_t size, bool low)
#else
static char *map_hint = 0;
#if defined(__x86_64__) && !defined(MAP_32BIT)
// This OS has no flag to enforce allocation below the 4 GB boundary,
// but if we hint that we want a low address it is very likely we will
// get one.
// An older version of this code used MAP_FIXED, but that has the side
// effect of discarding already mapped pages that happen to be in the
// requested virtual memory range (such as the emulated RAM, sometimes).
if (low && (!map_hint))
map_hint = (char*)round_page(512*1024*1024); /* 0.5 GB rounded up to the next page */
#endif
void* ptr = mmap(map_hint, size, PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_ANON | MAP_PRIVATE
#if defined(__x86_64__)
#if defined(MAP_32BIT)
#if defined(__x86_64__) && defined(MAP_32BIT)
| (low ? MAP_32BIT : 0)
#else
| (low ? MAP_FIXED : 0)
#endif /* defined(MAP_32BIT) */
#endif /* defined(__x86_64__) */
#endif
, -1, 0);
#endif /* defined(_WIN32) */