From 06e640532aa093902e81f09aa18de1b084fcc5ce Mon Sep 17 00:00:00 2001 From: NeoBrainX Date: Sat, 27 Aug 2011 20:42:11 +0200 Subject: Various changes which improve FreeBSD support. Patches by martymac, all credits go to him ;) --- Source/Core/Common/Src/MemoryUtil.cpp | 48 ++++++++++++++++++++++++++++++----- 1 file changed, 42 insertions(+), 6 deletions(-) (limited to 'Source/Core/Common/Src/MemoryUtil.cpp') diff --git a/Source/Core/Common/Src/MemoryUtil.cpp b/Source/Core/Common/Src/MemoryUtil.cpp index bc65f856f4..65c70e0c5e 100644 --- a/Source/Core/Common/Src/MemoryUtil.cpp +++ b/Source/Core/Common/Src/MemoryUtil.cpp @@ -27,28 +27,64 @@ #include #endif +#if !defined(MAP_32BIT) +#include +#define PAGE_MASK (getpagesize() - 1) +#define round_page(x) ((((unsigned long)(x)) + PAGE_MASK) & ~(PAGE_MASK)) +#endif + // This is purposely not a full wrapper for virtualalloc/mmap, but it // provides exactly the primitive operations that Dolphin needs. void* AllocateExecutableMemory(size_t size, bool low) { -#ifdef _WIN32 + static char *map_hint = 0; +#if defined(__x86_64__) && !defined(MAP_32BIT) + if (low && (!map_hint)) + map_hint = (char*)round_page(512*1024*1024); /* 0.5 GB rounded up to the next page */ +#endif + +#if defined(_WIN32) void* ptr = VirtualAlloc(0, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE); #else - void* ptr = mmap(0, size, PROT_READ | PROT_WRITE | PROT_EXEC, + void* ptr = mmap(map_hint, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANON | MAP_PRIVATE -#if defined __linux__ && defined __x86_64__ +#if defined(__x86_64__) +#if defined(MAP_32BIT) | (low ? MAP_32BIT : 0) -#endif +#else + | (low ? MAP_FIXED : 0) +#endif /* defined(MAP_32BIT) */ +#endif /* defined(__x86_64__) */ , -1, 0); -#endif +#endif /* defined(_WIN32) */ // printf("Mapped executable memory at %p (size %ld)\n", ptr, // (unsigned long)size); +#if defined(__FreeBSD__) + if (ptr == MAP_FAILED) + { + ptr = NULL; +#else if (ptr == NULL) + { +#endif PanicAlert("Failed to allocate executable memory"); -#ifdef _M_X64 + } +#if defined(__x86_64__) && !defined(MAP_32BIT) + else + { + if (low) + { + map_hint += size; + map_hint = (char*)round_page(map_hint); /* round up to the next page */ + // printf("Next map will (hopefully) be at %p\n", map_hint); + } + } +#endif + +#if defined(_M_X64) if ((u64)ptr >= 0x80000000 && low == true) PanicAlert("Executable memory ended up above 2GB!"); #endif -- cgit v1.2.3 From ee1dc962bfd01a6ce7908496897cf46073155412 Mon Sep 17 00:00:00 2001 From: NeoBrainX Date: Tue, 6 Sep 2011 14:45:05 +0200 Subject: Fix Windows build. --- Source/Core/Common/Src/MemoryUtil.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'Source/Core/Common/Src/MemoryUtil.cpp') diff --git a/Source/Core/Common/Src/MemoryUtil.cpp b/Source/Core/Common/Src/MemoryUtil.cpp index 65c70e0c5e..2d64a434f1 100644 --- a/Source/Core/Common/Src/MemoryUtil.cpp +++ b/Source/Core/Common/Src/MemoryUtil.cpp @@ -27,7 +27,7 @@ #include #endif -#if !defined(MAP_32BIT) +#if !defined(_WIN32) && defined(__x86_64__) && !defined(MAP_32BIT) #include #define PAGE_MASK (getpagesize() - 1) #define round_page(x) ((((unsigned long)(x)) + PAGE_MASK) & ~(PAGE_MASK)) @@ -38,15 +38,14 @@ void* AllocateExecutableMemory(size_t size, bool low) { +#if defined(_WIN32) + void* ptr = VirtualAlloc(0, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE); +#else static char *map_hint = 0; #if defined(__x86_64__) && !defined(MAP_32BIT) if (low && (!map_hint)) map_hint = (char*)round_page(512*1024*1024); /* 0.5 GB rounded up to the next page */ #endif - -#if defined(_WIN32) - void* ptr = VirtualAlloc(0, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE); -#else void* ptr = mmap(map_hint, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANON | MAP_PRIVATE #if defined(__x86_64__) @@ -72,7 +71,7 @@ void* AllocateExecutableMemory(size_t size, bool low) #endif PanicAlert("Failed to allocate executable memory"); } -#if defined(__x86_64__) && !defined(MAP_32BIT) +#if !defined(_WIN32) && defined(__x86_64__) && !defined(MAP_32BIT) else { if (low) -- cgit v1.2.3 From 29865e63664d5b513d0f06e9414fbe0b7a43bd49 Mon Sep 17 00:00:00 2001 From: Maarten ter Huurne Date: Wed, 30 Nov 2011 00:37:57 +0100 Subject: 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(-) (limited to 'Source/Core/Common/Src/MemoryUtil.cpp') 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) */ -- cgit v1.2.3