Update SSLContext to use folly::Random and discrete_distribution
[folly.git] / folly / MemoryMapping.h
1 /*
2  * Copyright 2015 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&&) noexcept;
131
132   ~MemoryMapping();
133
134   MemoryMapping& operator=(MemoryMapping);
135
136   void swap(MemoryMapping& other) noexcept;
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   void advise(int advice, size_t offset, size_t length) const;
161
162   /**
163    * A bitwise cast of the mapped bytes as range of values. Only intended for
164    * use with POD or in-place usable types.
165    */
166   template<class T>
167   Range<const T*> asRange() const {
168     size_t count = data_.size() / sizeof(T);
169     return Range<const T*>(static_cast<const T*>(
170                              static_cast<const void*>(data_.data())),
171                            count);
172   }
173
174   /**
175    * A range of bytes mapped by this mapping.
176    */
177   ByteRange range() const {
178     return data_;
179   }
180
181   /**
182    * A bitwise cast of the mapped bytes as range of mutable values. Only
183    * intended for use with POD or in-place usable types.
184    */
185   template<class T>
186   Range<T*> asWritableRange() const {
187     DCHECK(options_.writable);  // you'll segfault anyway...
188     size_t count = data_.size() / sizeof(T);
189     return Range<T*>(static_cast<T*>(
190                        static_cast<void*>(data_.data())),
191                      count);
192   }
193
194   /**
195    * A range of mutable bytes mapped by this mapping.
196    */
197   MutableByteRange writableRange() const {
198     DCHECK(options_.writable);  // you'll segfault anyway...
199     return data_;
200   }
201
202   /**
203    * Return the memory area where the file was mapped.
204    * Deprecated; use range() instead.
205    */
206   StringPiece data() const {
207     return asRange<const char>();
208   }
209
210   bool mlocked() const {
211     return locked_;
212   }
213
214   int fd() const { return file_.fd(); }
215
216  private:
217   MemoryMapping();
218
219   enum InitFlags {
220     kGrow = 1 << 0,
221     kAnon = 1 << 1,
222   };
223   void init(off_t offset, off_t length);
224
225   File file_;
226   void* mapStart_ = nullptr;
227   off_t mapLength_ = 0;
228   Options options_;
229   bool locked_ = false;
230   MutableByteRange data_;
231 };
232
233 void swap(MemoryMapping&, MemoryMapping&) noexcept;
234
235 /**
236  * A special case of memcpy() that always copies memory forwards.
237  * (libc's memcpy() is allowed to copy memory backwards, and will do so
238  * when using SSSE3 instructions).
239  *
240  * Assumes src and dest are aligned to alignof(unsigned long).
241  *
242  * Useful when copying from/to memory mappings after hintLinearScan();
243  * copying backwards renders any prefetching useless (even harmful).
244  */
245 void alignedForwardMemcpy(void* dest, const void* src, size_t size);
246
247 /**
248  * Copy a file using mmap(). Overwrites dest.
249  */
250 void mmapFileCopy(const char* src, const char* dest, mode_t mode = 0666);
251
252 }  // namespace folly
253
254 #endif /* FOLLY_MEMORYMAPPING_H_ */