From 29865e63664d5b513d0f06e9414fbe0b7a43bd49 Mon Sep 17 00:00:00 2001 From: Maarten ter Huurne Date: Wed, 30 Nov 2011 00:37:57 +0100 Subject: [PATCH] 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. --- Source/Core/Common/Src/MemoryUtil.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/Source/Core/Common/Src/MemoryUtil.cpp b/Source/Core/Common/Src/MemoryUtil.cpp index 2d64a434f1..3e3cafa335 100644 --- a/Source/Core/Common/Src/MemoryUtil.cpp +++ b/Source/Core/Common/Src/MemoryUtil.cpp @@ -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) */