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