MemoryMapping.h 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. /*
  2. * Copyright 2013-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. #pragma once
  17. #include <boost/noncopyable.hpp>
  18. #include <glog/logging.h>
  19. #include <folly/File.h>
  20. #include <folly/Range.h>
  21. namespace folly {
  22. /**
  23. * Maps files in memory (read-only).
  24. *
  25. * @author Tudor Bosman (tudorb@fb.com)
  26. */
  27. class MemoryMapping : boost::noncopyable {
  28. public:
  29. /**
  30. * Lock the pages in memory?
  31. * TRY_LOCK = try to lock, log warning if permission denied
  32. * MUST_LOCK = lock, fail assertion if permission denied.
  33. */
  34. enum class LockMode {
  35. TRY_LOCK,
  36. MUST_LOCK,
  37. };
  38. /**
  39. * Map a portion of the file indicated by filename in memory, causing a CHECK
  40. * failure on error.
  41. *
  42. * By default, map the whole file. length=-1: map from offset to EOF.
  43. * Unlike the mmap() system call, offset and length don't need to be
  44. * page-aligned. length is clipped to the end of the file if it's too large.
  45. *
  46. * The mapping will be destroyed (and the memory pointed-to by data() will
  47. * likely become inaccessible) when the MemoryMapping object is destroyed.
  48. */
  49. struct Options {
  50. Options() {}
  51. // Convenience methods; return *this for chaining.
  52. Options& setPageSize(off_t v) {
  53. pageSize = v;
  54. return *this;
  55. }
  56. Options& setShared(bool v) {
  57. shared = v;
  58. return *this;
  59. }
  60. Options& setPrefault(bool v) {
  61. prefault = v;
  62. return *this;
  63. }
  64. Options& setReadable(bool v) {
  65. readable = v;
  66. return *this;
  67. }
  68. Options& setWritable(bool v) {
  69. writable = v;
  70. return *this;
  71. }
  72. Options& setGrow(bool v) {
  73. grow = v;
  74. return *this;
  75. }
  76. // Page size. 0 = use appropriate page size.
  77. // (On Linux, we use a huge page size if the file is on a hugetlbfs
  78. // file system, and the default page size otherwise)
  79. off_t pageSize = 0;
  80. // If shared (default), the memory mapping is shared with other processes
  81. // mapping the same file (or children); if not shared (private), each
  82. // process has its own mapping. Changes in writable, private mappings are
  83. // not reflected to the underlying file. See the discussion of
  84. // MAP_PRIVATE vs MAP_SHARED in the mmap(2) manual page.
  85. bool shared = true;
  86. // Populate page tables; subsequent accesses should not be blocked
  87. // by page faults. This is a hint, as it may not be supported.
  88. bool prefault = false;
  89. // Map the pages readable. Note that mapping pages without read permissions
  90. // is not universally supported (not supported on hugetlbfs on Linux, for
  91. // example)
  92. bool readable = true;
  93. // Map the pages writable.
  94. bool writable = false;
  95. // When mapping a file in writable mode, grow the file to the requested
  96. // length (using ftruncate()) before mapping; if false, truncate the
  97. // mapping to the actual file size instead.
  98. bool grow = false;
  99. // Fix map at this address, if not nullptr. Must be aligned to a multiple
  100. // of the appropriate page size.
  101. void* address = nullptr;
  102. };
  103. // Options to emulate the old WritableMemoryMapping: readable and writable,
  104. // allow growing the file if mapping past EOF.
  105. static Options writable() {
  106. return Options().setWritable(true).setGrow(true);
  107. }
  108. enum AnonymousType {
  109. kAnonymous,
  110. };
  111. /**
  112. * Create an anonymous mapping.
  113. */
  114. MemoryMapping(AnonymousType, off_t length, Options options = Options());
  115. explicit MemoryMapping(
  116. File file,
  117. off_t offset = 0,
  118. off_t length = -1,
  119. Options options = Options());
  120. explicit MemoryMapping(
  121. const char* name,
  122. off_t offset = 0,
  123. off_t length = -1,
  124. Options options = Options());
  125. explicit MemoryMapping(
  126. int fd,
  127. off_t offset = 0,
  128. off_t length = -1,
  129. Options options = Options());
  130. MemoryMapping(MemoryMapping&&) noexcept;
  131. ~MemoryMapping();
  132. MemoryMapping& operator=(MemoryMapping);
  133. void swap(MemoryMapping& other) noexcept;
  134. /**
  135. * Lock the pages in memory
  136. */
  137. bool mlock(LockMode lock);
  138. /**
  139. * Unlock the pages.
  140. * If dontneed is true, the kernel is instructed to release these pages
  141. * (per madvise(MADV_DONTNEED)).
  142. */
  143. void munlock(bool dontneed = false);
  144. /**
  145. * Hint that these pages will be scanned linearly.
  146. * madvise(MADV_SEQUENTIAL)
  147. */
  148. void hintLinearScan();
  149. /**
  150. * Advise the kernel about memory access.
  151. */
  152. void advise(int advice) const;
  153. void advise(int advice, size_t offset, size_t length) const;
  154. /**
  155. * A bitwise cast of the mapped bytes as range of values. Only intended for
  156. * use with POD or in-place usable types.
  157. */
  158. template <class T>
  159. Range<const T*> asRange() const {
  160. size_t count = data_.size() / sizeof(T);
  161. return Range<const T*>(
  162. static_cast<const T*>(static_cast<const void*>(data_.data())), count);
  163. }
  164. /**
  165. * A range of bytes mapped by this mapping.
  166. */
  167. ByteRange range() const {
  168. return data_;
  169. }
  170. /**
  171. * A bitwise cast of the mapped bytes as range of mutable values. Only
  172. * intended for use with POD or in-place usable types.
  173. */
  174. template <class T>
  175. Range<T*> asWritableRange() const {
  176. DCHECK(options_.writable); // you'll segfault anyway...
  177. size_t count = data_.size() / sizeof(T);
  178. return Range<T*>(static_cast<T*>(static_cast<void*>(data_.data())), count);
  179. }
  180. /**
  181. * A range of mutable bytes mapped by this mapping.
  182. */
  183. MutableByteRange writableRange() const {
  184. DCHECK(options_.writable); // you'll segfault anyway...
  185. return data_;
  186. }
  187. /**
  188. * Return the memory area where the file was mapped.
  189. * Deprecated; use range() instead.
  190. */
  191. StringPiece data() const {
  192. return asRange<const char>();
  193. }
  194. bool mlocked() const {
  195. return locked_;
  196. }
  197. int fd() const {
  198. return file_.fd();
  199. }
  200. private:
  201. MemoryMapping();
  202. enum InitFlags {
  203. kGrow = 1 << 0,
  204. kAnon = 1 << 1,
  205. };
  206. void init(off_t offset, off_t length);
  207. File file_;
  208. void* mapStart_ = nullptr;
  209. off_t mapLength_ = 0;
  210. Options options_;
  211. bool locked_ = false;
  212. MutableByteRange data_;
  213. };
  214. void swap(MemoryMapping&, MemoryMapping&) noexcept;
  215. /**
  216. * A special case of memcpy() that always copies memory forwards.
  217. * (libc's memcpy() is allowed to copy memory backwards, and will do so
  218. * when using SSSE3 instructions).
  219. *
  220. * Assumes src and dest are aligned to alignof(unsigned long).
  221. *
  222. * Useful when copying from/to memory mappings after hintLinearScan();
  223. * copying backwards renders any prefetching useless (even harmful).
  224. */
  225. void alignedForwardMemcpy(void* dest, const void* src, size_t size);
  226. /**
  227. * Copy a file using mmap(). Overwrites dest.
  228. */
  229. void mmapFileCopy(const char* src, const char* dest, mode_t mode = 0666);
  230. } // namespace folly