2 * Copyright 2015 Facebook, Inc.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #ifndef FOLLY_MEMORYMAPPING_H_
18 #define FOLLY_MEMORYMAPPING_H_
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>
29 * Maps files in memory (read-only).
31 * @author Tudor Bosman (tudorb@fb.com)
33 class MemoryMapping : boost::noncopyable {
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.
45 * Map a portion of the file indicated by filename in memory, causing a CHECK
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.
52 * The mapping will be destroyed (and the memory pointed-to by data() will
53 * likely become inaccessible) when the MemoryMapping object is destroyed.
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; }
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)
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.
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;
82 // Map the pages readable. Note that mapping pages without read permissions
83 // is not universally supported (not supported on hugetlbfs on Linux, for
87 // Map the pages writable.
88 bool writable = false;
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.
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;
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);
111 * Create an anonymous mapping.
113 MemoryMapping(AnonymousType, off_t length, Options options=Options());
115 explicit MemoryMapping(File file,
118 Options options=Options());
120 explicit MemoryMapping(const char* name,
123 Options options=Options());
125 explicit MemoryMapping(int fd,
128 Options options=Options());
130 MemoryMapping(MemoryMapping&&) noexcept;
134 MemoryMapping& operator=(MemoryMapping);
136 void swap(MemoryMapping& other) noexcept;
139 * Lock the pages in memory
141 bool mlock(LockMode lock);
145 * If dontneed is true, the kernel is instructed to release these pages
146 * (per madvise(MADV_DONTNEED)).
148 void munlock(bool dontneed = false);
151 * Hint that these pages will be scanned linearly.
152 * madvise(MADV_SEQUENTIAL)
154 void hintLinearScan();
157 * Advise the kernel about memory access.
159 void advise(int advice) const;
160 void advise(int advice, size_t offset, size_t length) const;
163 * A bitwise cast of the mapped bytes as range of values. Only intended for
164 * use with POD or in-place usable types.
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())),
175 * A range of bytes mapped by this mapping.
177 ByteRange range() const {
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.
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())),
195 * A range of mutable bytes mapped by this mapping.
197 MutableByteRange writableRange() const {
198 DCHECK(options_.writable); // you'll segfault anyway...
203 * Return the memory area where the file was mapped.
204 * Deprecated; use range() instead.
206 StringPiece data() const {
207 return asRange<const char>();
210 bool mlocked() const {
214 int fd() const { return file_.fd(); }
223 void init(off_t offset, off_t length);
226 void* mapStart_ = nullptr;
227 off_t mapLength_ = 0;
229 bool locked_ = false;
230 MutableByteRange data_;
233 void swap(MemoryMapping&, MemoryMapping&) noexcept;
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).
240 * Assumes src and dest are aligned to alignof(unsigned long).
242 * Useful when copying from/to memory mappings after hintLinearScan();
243 * copying backwards renders any prefetching useless (even harmful).
245 void alignedForwardMemcpy(void* dest, const void* src, size_t size);
248 * Copy a file using mmap(). Overwrites dest.
250 void mmapFileCopy(const char* src, const char* dest, mode_t mode = 0666);
254 #endif /* FOLLY_MEMORYMAPPING_H_ */