Create the sys/mman.h portability header
authorChristopher Dykes <cdykes@fb.com>
Fri, 18 Mar 2016 21:57:46 +0000 (14:57 -0700)
committerFacebook Github Bot 5 <facebook-github-bot-5-bot@fb.com>
Fri, 18 Mar 2016 22:05:23 +0000 (15:05 -0700)
Summary: Something that Windows very definitely lacks. This is a fun one.

Reviewed By: yfeldblum

Differential Revision: D2979661

fb-gh-sync-id: e23c1db0cb8655b22308b874bd421a7cc1e4759e
shipit-source-id: e23c1db0cb8655b22308b874bd421a7cc1e4759e

folly/IndexedMemPool.h
folly/Makefile.am
folly/MemoryMapping.cpp
folly/Portability.h
folly/detail/AtomicUnorderedMapUtils.h
folly/experimental/fibers/GuardPageAllocator.cpp
folly/portability/SysMman.cpp [new file with mode: 0755]
folly/portability/SysMman.h [new file with mode: 0755]
folly/test/AtomicHashArrayTest.cpp

index 8cfe0e7fccf40e1fa6098b148d8846b2153822b5..f8771f33f01fd18c8619957ff8746e1e7ed08cf3 100644 (file)
 #include <stdint.h>
 #include <assert.h>
 #include <unistd.h>
 #include <stdint.h>
 #include <assert.h>
 #include <unistd.h>
-#include <sys/mman.h>
 #include <boost/noncopyable.hpp>
 #include <folly/AtomicStruct.h>
 #include <folly/detail/CacheLocality.h>
 #include <boost/noncopyable.hpp>
 #include <folly/AtomicStruct.h>
 #include <folly/detail/CacheLocality.h>
+#include <folly/portability/SysMman.h>
 
 // Ignore shadowing warnings within this file, so includers can use -Wshadow.
 #pragma GCC diagnostic push
 
 // Ignore shadowing warnings within this file, so includers can use -Wshadow.
 #pragma GCC diagnostic push
index 5428b5fa997a1b132fa9351ba18f427b9a51d2f4..fffd7edfd257afc717baa0c0905dc69ffa397bec 100644 (file)
@@ -276,6 +276,7 @@ nobase_follyinclude_HEADERS = \
        portability/Strings.h \
        portability/Syscall.h \
        portability/SysFile.h \
        portability/Strings.h \
        portability/Syscall.h \
        portability/SysFile.h \
+       portability/SysMman.h \
        portability/SysStat.h \
        portability/SysTime.h \
        portability/SysTypes.h \
        portability/SysStat.h \
        portability/SysTime.h \
        portability/SysTypes.h \
@@ -410,6 +411,7 @@ libfolly_la_SOURCES = \
        portability/Environment.cpp \
        portability/Strings.cpp \
        portability/SysFile.cpp \
        portability/Environment.cpp \
        portability/Strings.cpp \
        portability/SysFile.cpp \
+       portability/SysMman.cpp \
        portability/SysStat.cpp \
        portability/SysTime.cpp \
        portability/Time.cpp \
        portability/SysStat.cpp \
        portability/SysTime.cpp \
        portability/Time.cpp \
index 5fa25accfc3cdf37721c96d56281ba2c94898bc9..17f1e760a968f15f22af9c35ba2714f7d249755d 100644 (file)
 #include <utility>
 
 #include <folly/Format.h>
 #include <utility>
 
 #include <folly/Format.h>
+#include <folly/portability/SysMman.h>
 
 #ifdef __linux__
 #include <folly/experimental/io/HugePages.h>
 #endif
 
 #include <fcntl.h>
 
 #ifdef __linux__
 #include <folly/experimental/io/HugePages.h>
 #endif
 
 #include <fcntl.h>
-#include <sys/mman.h>
 #include <sys/types.h>
 #include <system_error>
 #include <gflags/gflags.h>
 #include <sys/types.h>
 #include <system_error>
 #include <gflags/gflags.h>
index b1aa36e5d9181cac3e72ec96b6e328edad16852e..fb01114eddc226e30161ccb23b0cff138ec0a6a8 100644 (file)
@@ -46,17 +46,6 @@ constexpr bool kHasUnalignedAccess = false;
 #endif
 }
 
 #endif
 }
 
-// A change in folly/MemoryMapping.cpp uses MAP_ANONYMOUS, which is named
-// MAP_ANON on OSX/BSD.
-#if defined(__APPLE__) || defined(__FreeBSD__)
-  #include <sys/mman.h>
-  #ifndef MAP_ANONYMOUS
-    #ifdef MAP_ANON
-      #define MAP_ANONYMOUS MAP_ANON
-    #endif
-  #endif
-#endif
-
 // compiler specific attribute translation
 // msvc should come first, so if clang is in msvc mode it gets the right defines
 
 // compiler specific attribute translation
 // msvc should come first, so if clang is in msvc mode it gets the right defines
 
index f5737972481395f85f5791ca7abcb5f9d30e4f8d..4142ade82ff7675983c7ea91a7bec8d7de4ef1b4 100644 (file)
@@ -2,9 +2,10 @@
 
 #include <atomic>
 #include <stdint.h>
 
 #include <atomic>
 #include <stdint.h>
-#include <sys/mman.h>
 #include <unistd.h>
 
 #include <unistd.h>
 
+#include <folly/portability/SysMman.h>
+
 namespace folly { namespace detail {
 
 class MMapAlloc {
 namespace folly { namespace detail {
 
 class MMapAlloc {
index f4e7b790f9fbdf6d27793859ab12e16fd5eb8c9d..0a732ae1febd972dc9dd31331e92aa7fecb0fc9e 100644 (file)
  */
 #include "GuardPageAllocator.h"
 
  */
 #include "GuardPageAllocator.h"
 
-#include <sys/mman.h>
 #include <unistd.h>
 
 #include <mutex>
 
 #include <folly/Singleton.h>
 #include <folly/SpinLock.h>
 #include <unistd.h>
 
 #include <mutex>
 
 #include <folly/Singleton.h>
 #include <folly/SpinLock.h>
+#include <folly/portability/SysMman.h>
 
 #include <glog/logging.h>
 
 
 #include <glog/logging.h>
 
diff --git a/folly/portability/SysMman.cpp b/folly/portability/SysMman.cpp
new file mode 100755 (executable)
index 0000000..8420c82
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+ * Copyright 2016 Facebook, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <folly/portability/SysMman.h>
+
+#ifdef _WIN32
+#include <folly/portability/Windows.h>
+
+static bool mmap_to_page_protection(int prot, DWORD& ret) {
+  if (prot == PROT_NONE) {
+    ret = PAGE_NOACCESS;
+  } else if (prot == PROT_READ) {
+    ret = PAGE_READONLY;
+  } else if (prot == PROT_EXEC) {
+    ret = PAGE_EXECUTE;
+  } else if (prot == (PROT_READ | PROT_EXEC)) {
+    ret = PAGE_EXECUTE_READ;
+  } else if (prot == (PROT_READ | PROT_WRITE)) {
+    ret = PAGE_READWRITE;
+  } else if (prot == (PROT_READ | PROT_WRITE | PROT_EXEC)) {
+    ret = PAGE_EXECUTE_READWRITE;
+  } else {
+    return false;
+  }
+  return true;
+}
+
+extern "C" {
+int madvise(const void* addr, size_t len, int advise) {
+  // We do nothing at all.
+  // Could probably implement dontneed via VirtualAlloc
+  // with the MEM_RESET and MEM_RESET_UNDO flags.
+  return 0;
+}
+
+int mlock(const void* addr, size_t len) {
+  if (!VirtualLock((void*)addr, len)) {
+    return -1;
+  }
+  return 0;
+}
+
+void* mmap(void* addr, size_t length, int prot, int flags, int fd, off_t off) {
+  // Make sure it's something we support first.
+
+  // No Anon shared.
+  if ((flags & (MAP_ANONYMOUS | MAP_SHARED)) == (MAP_ANONYMOUS | MAP_SHARED)) {
+    return MAP_FAILED;
+  }
+  // No private copy on write.
+  if ((flags & MAP_PRIVATE) == MAP_PRIVATE && fd != -1) {
+    return MAP_FAILED;
+  }
+  // Map isn't anon, must be file backed.
+  if (!(flags & MAP_ANONYMOUS) && fd == -1) {
+    return MAP_FAILED;
+  }
+
+  DWORD newProt;
+  if (!mmap_to_page_protection(prot, newProt)) {
+    return MAP_FAILED;
+  }
+
+  void* ret;
+  if (!(flags & MAP_ANONYMOUS) || (flags & MAP_SHARED)) {
+    HANDLE h = INVALID_HANDLE_VALUE;
+    if (!(flags & MAP_ANONYMOUS)) {
+      h = (HANDLE)_get_osfhandle(fd);
+    }
+
+    HANDLE fmh = CreateFileMapping(
+        h,
+        nullptr,
+        newProt | SEC_COMMIT | SEC_RESERVE,
+        (DWORD)((length >> 32) & 0xFFFFFFFF),
+        (DWORD)(length & 0xFFFFFFFF),
+        nullptr);
+    ret = MapViewOfFileEx(
+        fmh,
+        FILE_MAP_ALL_ACCESS,
+        (DWORD)((off >> 32) & 0xFFFFFFFF),
+        (DWORD)(off & 0xFFFFFFFF),
+        0,
+        addr);
+    if (ret == nullptr) {
+      ret = MAP_FAILED;
+    }
+    CloseHandle(fmh);
+  } else {
+    ret = VirtualAlloc(addr, length, MEM_COMMIT | MEM_RESERVE, newProt);
+    if (ret == nullptr) {
+      return MAP_FAILED;
+    }
+  }
+
+  // TODO: Could technically implement MAP_POPULATE via PrefetchVirtualMemory
+  //       Should also see about implementing MAP_NORESERVE
+  return ret;
+}
+
+int mprotect(void* addr, size_t size, int prot) {
+  DWORD newProt;
+  if (!mmap_to_page_protection(prot, newProt)) {
+    return -1;
+  }
+
+  DWORD oldProt;
+  BOOL res = VirtualProtect(addr, size, newProt, &oldProt);
+  if (!res) {
+    return -1;
+  }
+  return 0;
+}
+
+int munlock(const void* addr, size_t length) {
+  if (!VirtualUnlock((void*)addr, length)) {
+    return -1;
+  }
+  return 0;
+}
+
+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)) {
+      return -1;
+    }
+    return 0;
+  }
+  return 0;
+}
+}
+#endif
diff --git a/folly/portability/SysMman.h b/folly/portability/SysMman.h
new file mode 100755 (executable)
index 0000000..52dd33c
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2016 Facebook, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#ifndef _WIN32
+#include <sys/mman.h>
+
+// MAP_ANONYMOUS is named MAP_ANON on OSX/BSD.
+#if defined(__APPLE__) || defined(__FreeBSD__)
+# if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
+#  define MAP_ANONYMOUS MAP_ANON
+# endif
+#endif
+#else
+#include <cstdint>
+#include <sys/types.h>
+
+#define MAP_ANONYMOUS 1
+#define MAP_ANON MAP_ANONYMOUS
+#define MAP_SHARED 2
+#define MAP_PRIVATE 4
+#define MAP_POPULATE 8
+#define MAP_NORESERVE 16
+#define MAP_FIXED 32
+
+#define MAP_FAILED ((void*)-1)
+
+#define PROT_NONE 0
+#define PROT_READ 1
+#define PROT_WRITE 2
+#define PROT_EXEC 4
+
+#define MADV_DONTNEED 0
+#define MADV_SEQUENTIAL 0
+
+extern "C" {
+int madvise(const void* addr, size_t len, int advise);
+int mlock(const void* addr, size_t len);
+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);
+int munlock(const void* addr, size_t length);
+int munmap(void* addr, size_t length);
+}
+#endif
index 5c3eb70a1fcbd22deacad008048d5916f2b35bd6..4facc7d797069b87c74042df8714df4e38840f01 100644 (file)
  * limitations under the License.
  */
 
  * limitations under the License.
  */
 
-#include <sys/mman.h>
-
 #include <cstddef>
 #include <map>
 #include <stdexcept>
 
 #include <folly/AtomicHashArray.h>
 #include <cstddef>
 #include <map>
 #include <stdexcept>
 
 #include <folly/AtomicHashArray.h>
-#include <folly/Hash.h>
 #include <folly/Conv.h>
 #include <folly/Conv.h>
+#include <folly/Hash.h>
 #include <folly/Memory.h>
 #include <folly/Memory.h>
+#include <folly/portability/SysMman.h>
 #include <gtest/gtest.h>
 
 #include <gtest/gtest.h>
 
-#if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
-#define MAP_ANONYMOUS MAP_ANON
-#endif
-
 using namespace std;
 using namespace folly;
 
 using namespace std;
 using namespace folly;