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