proxygen
SysMman.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2016-present Facebook, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
18 
19 #ifdef _WIN32
20 
21 #include <cassert>
22 
23 #include <folly/Portability.h>
25 
26 static bool mmap_to_page_protection(int prot, DWORD& ret, DWORD& acc) {
27  if (prot == PROT_NONE) {
28  ret = PAGE_NOACCESS;
29  acc = 0;
30  } else if (prot == PROT_READ) {
31  ret = PAGE_READONLY;
32  acc = FILE_MAP_READ;
33  } else if (prot == PROT_EXEC) {
34  ret = PAGE_EXECUTE;
35  acc = FILE_MAP_EXECUTE;
36  } else if (prot == (PROT_READ | PROT_EXEC)) {
37  ret = PAGE_EXECUTE_READ;
38  acc = FILE_MAP_READ | FILE_MAP_EXECUTE;
39  } else if (prot == (PROT_READ | PROT_WRITE)) {
40  ret = PAGE_READWRITE;
41  acc = FILE_MAP_READ | FILE_MAP_WRITE;
42  } else if (prot == (PROT_READ | PROT_WRITE | PROT_EXEC)) {
43  ret = PAGE_EXECUTE_READWRITE;
44  acc = FILE_MAP_READ | FILE_MAP_WRITE | FILE_MAP_EXECUTE;
45  } else {
46  return false;
47  }
48  return true;
49 }
50 
51 static size_t alignToAllocationGranularity(size_t s) {
52  static size_t granularity = [] {
53  static SYSTEM_INFO inf;
54  GetSystemInfo(&inf);
55  return inf.dwAllocationGranularity;
56  }();
57  return (s + granularity - 1) / granularity * granularity;
58 }
59 
60 extern "C" {
61 int madvise(const void* /* addr */, size_t /* len */, int /* advise */) {
62  // We do nothing at all.
63  // Could probably implement dontneed via VirtualAlloc
64  // with the MEM_RESET and MEM_RESET_UNDO flags.
65  return 0;
66 }
67 
68 int mlock(const void* addr, size_t len) {
69  // For some strange reason, it's allowed to
70  // lock a nullptr as long as length is zero.
71  // VirtualLock doesn't allow it, so handle
72  // it specially.
73  if (addr == nullptr && len == 0) {
74  return 0;
75  }
76  if (!VirtualLock((void*)addr, len)) {
77  return -1;
78  }
79  return 0;
80 }
81 
82 namespace {
83 constexpr uint32_t kMMapLengthMagic = 0xFACEB00C;
84 struct MemMapDebugTrailer {
85  size_t length;
86  uint32_t magic;
87 };
88 } // namespace
89 
90 void* mmap(void* addr, size_t length, int prot, int flags, int fd, off_t off) {
91  // Make sure it's something we support first.
92 
93  // No Anon shared.
94  if ((flags & (MAP_ANONYMOUS | MAP_SHARED)) == (MAP_ANONYMOUS | MAP_SHARED)) {
95  return MAP_FAILED;
96  }
97  // No private copy on write.
98  if ((flags & MAP_PRIVATE) == MAP_PRIVATE && fd != -1) {
99  return MAP_FAILED;
100  }
101  // Map isn't anon, must be file backed.
102  if (!(flags & MAP_ANONYMOUS) && fd == -1) {
103  return MAP_FAILED;
104  }
105 
106  DWORD newProt;
107  DWORD accessFlags;
108  if (!mmap_to_page_protection(prot, newProt, accessFlags)) {
109  return MAP_FAILED;
110  }
111 
112  void* ret;
113  if (!(flags & MAP_ANONYMOUS) || (flags & MAP_SHARED)) {
114  HANDLE h = INVALID_HANDLE_VALUE;
115  if (!(flags & MAP_ANONYMOUS)) {
116  h = (HANDLE)_get_osfhandle(fd);
117  }
118 
119  HANDLE fmh = CreateFileMapping(
120  h,
121  nullptr,
122  newProt,
123  (DWORD)((length >> 32) & 0xFFFFFFFF),
124  (DWORD)(length & 0xFFFFFFFF),
125  nullptr);
126  if (fmh == nullptr) {
127  return MAP_FAILED;
128  }
129  ret = MapViewOfFileEx(
130  fmh,
131  accessFlags,
132  (DWORD)(0), // off_t is only 32-bit :(
133  (DWORD)(off & 0xFFFFFFFF),
134  0,
135  addr);
136  if (ret == nullptr) {
137  ret = MAP_FAILED;
138  }
139  CloseHandle(fmh);
140  } else {
141  auto baseLength = length;
142  if (folly::kIsDebug) {
143  // In debug mode we keep track of the length to make
144  // sure you're only munmapping the entire thing if
145  // we're using VirtualAlloc.
146  length += sizeof(MemMapDebugTrailer);
147  }
148 
149  // VirtualAlloc rounds size down to a multiple
150  // of the system allocation granularity :(
151  length = alignToAllocationGranularity(length);
152  ret = VirtualAlloc(addr, length, MEM_COMMIT | MEM_RESERVE, newProt);
153  if (ret == nullptr) {
154  return MAP_FAILED;
155  }
156 
157  if (folly::kIsDebug) {
158  auto deb = (MemMapDebugTrailer*)((char*)ret + baseLength);
159  deb->length = baseLength;
160  deb->magic = kMMapLengthMagic;
161  }
162  }
163 
164  // TODO: Could technically implement MAP_POPULATE via PrefetchVirtualMemory
165  // Should also see about implementing MAP_NORESERVE
166  return ret;
167 }
168 
169 int mprotect(void* addr, size_t size, int prot) {
170  DWORD newProt;
171  DWORD access;
172  if (!mmap_to_page_protection(prot, newProt, access)) {
173  return -1;
174  }
175 
176  DWORD oldProt;
177  BOOL res = VirtualProtect(addr, size, newProt, &oldProt);
178  if (!res) {
179  return -1;
180  }
181  return 0;
182 }
183 
184 int munlock(const void* addr, size_t length) {
185  // See comment in mlock
186  if (addr == nullptr && length == 0) {
187  return 0;
188  }
189  if (!VirtualUnlock((void*)addr, length)) {
190  return -1;
191  }
192  return 0;
193 }
194 
195 int munmap(void* addr, size_t length) {
196  // Try to unmap it as a file, otherwise VirtualFree.
197  if (!UnmapViewOfFile(addr)) {
198  if (folly::kIsDebug) {
199  // We can't do partial unmapping with Windows, so
200  // assert that we aren't trying to do that if we're
201  // in debug mode.
202  MEMORY_BASIC_INFORMATION inf;
203  VirtualQuery(addr, &inf, sizeof(inf));
204  assert(inf.AllocationBase == addr);
205 
206  auto deb = (MemMapDebugTrailer*)((char*)addr + length);
207  assert(deb->length == length);
208  assert(deb->magic == kMMapLengthMagic);
209  }
210  if (!VirtualFree(addr, 0, MEM_RELEASE)) {
211  return -1;
212  }
213  return 0;
214  }
215  return 0;
216 }
217 }
218 
219 #endif
*than *hazptr_holder h
Definition: Hazptr.h:116
flags
Definition: http_parser.h:127
constexpr auto kIsDebug
Definition: Portability.h:264
constexpr auto size(C const &c) -> decltype(c.size())
Definition: Access.h:45
static set< string > s
ThreadPoolListHook * addr