Remove/make private the default ***Holder constructor to allow compile time detection...
[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/FBString.h>
20 #include <folly/File.h>
21 #include <folly/Range.h>
22 #include <glog/logging.h>
23 #include <boost/noncopyable.hpp>
24
25 namespace folly {
26
27 /**
28  * Maps files in memory (read-only).
29  *
30  * @author Tudor Bosman (tudorb@fb.com)
31  */
32 class MemoryMapping : boost::noncopyable {
33  public:
34   /**
35    * Lock the pages in memory?
36    * TRY_LOCK  = try to lock, log warning if permission denied
37    * MUST_LOCK = lock, fail assertion if permission denied.
38    */
39   enum class LockMode {
40     TRY_LOCK,
41     MUST_LOCK
42   };
43   /**
44    * Map a portion of the file indicated by filename in memory, causing a CHECK
45    * failure on error.
46    *
47    * By default, map the whole file.  length=-1: map from offset to EOF.
48    * Unlike the mmap() system call, offset and length don't need to be
49    * page-aligned.  length is clipped to the end of the file if it's too large.
50    *
51    * The mapping will be destroyed (and the memory pointed-to by data() will
52    * likely become inaccessible) when the MemoryMapping object is destroyed.
53    */
54   struct Options {
55     Options() {}
56
57     // Convenience methods; return *this for chaining.
58     Options& setPageSize(off_t v) { pageSize = v; return *this; }
59     Options& setShared(bool v) { shared = v; return *this; }
60     Options& setPrefault(bool v) { prefault = v; return *this; }
61     Options& setReadable(bool v) { readable = v; return *this; }
62     Options& setWritable(bool v) { writable = v; return *this; }
63     Options& setGrow(bool v) { grow = v; return *this; }
64
65     // Page size. 0 = use appropriate page size.
66     // (On Linux, we use a huge page size if the file is on a hugetlbfs
67     // file system, and the default page size otherwise)
68     off_t pageSize = 0;
69
70     // If shared (default), the memory mapping is shared with other processes
71     // mapping the same file (or children); if not shared (private), each
72     // process has its own mapping. Changes in writable, private mappings are
73     // not reflected to the underlying file. See the discussion of
74     // MAP_PRIVATE vs MAP_SHARED in the mmap(2) manual page.
75     bool shared = true;
76
77     // Populate page tables; subsequent accesses should not be blocked
78     // by page faults. This is a hint, as it may not be supported.
79     bool prefault = false;
80
81     // Map the pages readable. Note that mapping pages without read permissions
82     // is not universally supported (not supported on hugetlbfs on Linux, for
83     // example)
84     bool readable = true;
85
86     // Map the pages writable.
87     bool writable = false;
88
89     // When mapping a file in writable mode, grow the file to the requested
90     // length (using ftruncate()) before mapping; if false, truncate the
91     // mapping to the actual file size instead.
92     bool grow = false;
93
94     // Fix map at this address, if not nullptr. Must be aligned to a multiple
95     // of the appropriate page size.
96     void* address = nullptr;
97   };
98
99   // Options to emulate the old WritableMemoryMapping: readable and writable,
100   // allow growing the file if mapping past EOF.
101   static Options writable() {
102     return Options().setWritable(true).setGrow(true);
103   }
104
105   enum AnonymousType {
106     kAnonymous
107   };
108
109   /**
110    * Create an anonymous mapping.
111    */
112   MemoryMapping(AnonymousType, off_t length, Options options=Options());
113
114   explicit MemoryMapping(File file,
115                          off_t offset=0,
116                          off_t length=-1,
117                          Options options=Options());
118
119   explicit MemoryMapping(const char* name,
120                          off_t offset=0,
121                          off_t length=-1,
122                          Options options=Options());
123
124   explicit MemoryMapping(int fd,
125                          off_t offset=0,
126                          off_t length=-1,
127                          Options options=Options());
128
129   MemoryMapping(MemoryMapping&&) noexcept;
130
131   ~MemoryMapping();
132
133   MemoryMapping& operator=(MemoryMapping);
134
135   void swap(MemoryMapping& other) noexcept;
136
137   /**
138    * Lock the pages in memory
139    */
140   bool mlock(LockMode lock);
141
142   /**
143    * Unlock the pages.
144    * If dontneed is true, the kernel is instructed to release these pages
145    * (per madvise(MADV_DONTNEED)).
146    */
147   void munlock(bool dontneed = false);
148
149   /**
150    * Hint that these pages will be scanned linearly.
151    * madvise(MADV_SEQUENTIAL)
152    */
153   void hintLinearScan();
154
155   /**
156    * Advise the kernel about memory access.
157    */
158   void advise(int advice) const;
159   void advise(int advice, size_t offset, size_t length) 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&) noexcept;
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