From: Christopher Dykes Date: Thu, 4 Aug 2016 17:48:08 +0000 (-0700) Subject: Fix the Windows portability implementations of mmap and munmap X-Git-Tag: v2016.08.08.00~22 X-Git-Url: http://plrg.eecs.uci.edu/git/?a=commitdiff_plain;h=59bcc4529e8d3490612ce6f41e6ba36226dcb93b;p=folly.git Fix the Windows portability implementations of mmap and munmap Summary: Because they simply didn't work before. Reviewed By: yfeldblum Differential Revision: D3666894 fbshipit-source-id: 7a34073b2bbc43c489ad963c28fac24dcbb187f2 --- diff --git a/folly/portability/SysMman.cpp b/folly/portability/SysMman.cpp index 8420c82b..9827f045 100755 --- a/folly/portability/SysMman.cpp +++ b/folly/portability/SysMman.cpp @@ -17,27 +17,44 @@ #include #ifdef _WIN32 +#include +#include #include -static bool mmap_to_page_protection(int prot, DWORD& ret) { +static bool mmap_to_page_protection(int prot, DWORD& ret, DWORD& acc) { if (prot == PROT_NONE) { ret = PAGE_NOACCESS; + acc = 0; } else if (prot == PROT_READ) { ret = PAGE_READONLY; + acc = FILE_MAP_READ; } else if (prot == PROT_EXEC) { ret = PAGE_EXECUTE; + acc = FILE_MAP_EXECUTE; } else if (prot == (PROT_READ | PROT_EXEC)) { ret = PAGE_EXECUTE_READ; + acc = FILE_MAP_READ | FILE_MAP_EXECUTE; } else if (prot == (PROT_READ | PROT_WRITE)) { ret = PAGE_READWRITE; + acc = FILE_MAP_READ | FILE_MAP_WRITE; } else if (prot == (PROT_READ | PROT_WRITE | PROT_EXEC)) { ret = PAGE_EXECUTE_READWRITE; + acc = FILE_MAP_READ | FILE_MAP_WRITE | FILE_MAP_EXECUTE; } else { return false; } return true; } +static size_t alignToAllocationGranularity(size_t s) { + static size_t granularity = [] { + static SYSTEM_INFO inf; + GetSystemInfo(&inf); + return inf.dwAllocationGranularity; + }(); + return (s + granularity - 1) / granularity * granularity; +} + extern "C" { int madvise(const void* addr, size_t len, int advise) { // We do nothing at all. @@ -70,7 +87,8 @@ void* mmap(void* addr, size_t length, int prot, int flags, int fd, off_t off) { } DWORD newProt; - if (!mmap_to_page_protection(prot, newProt)) { + DWORD accessFlags; + if (!mmap_to_page_protection(prot, newProt, accessFlags)) { return MAP_FAILED; } @@ -84,13 +102,13 @@ void* mmap(void* addr, size_t length, int prot, int flags, int fd, off_t off) { HANDLE fmh = CreateFileMapping( h, nullptr, - newProt | SEC_COMMIT | SEC_RESERVE, + newProt, (DWORD)((length >> 32) & 0xFFFFFFFF), (DWORD)(length & 0xFFFFFFFF), nullptr); ret = MapViewOfFileEx( fmh, - FILE_MAP_ALL_ACCESS, + accessFlags, (DWORD)((off >> 32) & 0xFFFFFFFF), (DWORD)(off & 0xFFFFFFFF), 0, @@ -100,6 +118,9 @@ void* mmap(void* addr, size_t length, int prot, int flags, int fd, off_t off) { } CloseHandle(fmh); } else { + // VirtualAlloc rounds size down to a multiple + // of the system allocation granularity :( + length = alignToAllocationGranularity(length); ret = VirtualAlloc(addr, length, MEM_COMMIT | MEM_RESERVE, newProt); if (ret == nullptr) { return MAP_FAILED; @@ -113,7 +134,8 @@ void* mmap(void* addr, size_t length, int prot, int flags, int fd, off_t off) { int mprotect(void* addr, size_t size, int prot) { DWORD newProt; - if (!mmap_to_page_protection(prot, newProt)) { + DWORD access; + if (!mmap_to_page_protection(prot, newProt, access)) { return -1; } @@ -135,7 +157,16 @@ int munlock(const void* addr, size_t length) { int munmap(void* addr, size_t length) { // Try to unmap it as a file, otherwise VirtualFree. if (!UnmapViewOfFile(addr)) { - if (!VirtualFree(addr, length, MEM_RELEASE)) { + if (folly::kIsDebug) { + // We can't do partial unmapping with Windows, so + // assert that we aren't trying to do that if we're + // in debug mode. + MEMORY_BASIC_INFORMATION inf; + VirtualQuery(addr, &inf, sizeof(inf)); + assert(inf.BaseAddress == addr); + assert(inf.RegionSize == alignToAllocationGranularity(length)); + } + if (!VirtualFree(addr, 0, MEM_RELEASE)) { return -1; } return 0;