Harden failure signal handler in the face of memory corruptions
[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   explicit MemoryMapping(File file,
56                          off_t offset=0,
57                          off_t length=-1);
58
59   explicit MemoryMapping(const char* name,
60                          off_t offset=0,
61                          off_t length=-1);
62
63   explicit MemoryMapping(int fd,
64                          off_t offset=0,
65                          off_t length=-1);
66
67   virtual ~MemoryMapping();
68
69   /**
70    * Lock the pages in memory
71    */
72   bool mlock(LockMode lock);
73
74   /**
75    * Unlock the pages.
76    * If dontneed is true, the kernel is instructed to release these pages
77    * (per madvise(MADV_DONTNEED)).
78    */
79   void munlock(bool dontneed=false);
80
81   /**
82    * Hint that these pages will be scanned linearly.
83    * madvise(MADV_SEQUENTIAL)
84    */
85   void hintLinearScan();
86
87   /**
88    * Advise the kernel about memory access.
89    */
90   void advise(int advice) const;
91
92   /**
93    * A bitwise cast of the mapped bytes as range of values. Only intended for
94    * use with POD or in-place usable types.
95    */
96   template<class T>
97   Range<const T*> asRange() const {
98     size_t count = data_.size() / sizeof(T);
99     return Range<const T*>(static_cast<const T*>(
100                              static_cast<const void*>(data_.data())),
101                            count);
102   }
103
104   /**
105    * A range of bytes mapped by this mapping.
106    */
107   Range<const uint8_t*> range() const {
108     return {data_.begin(), data_.end()};
109   }
110
111   /**
112    * Return the memory area where the file was mapped.
113    */
114   StringPiece data() const {
115     return asRange<const char>();
116   }
117
118   bool mlocked() const {
119     return locked_;
120   }
121
122   int fd() const { return file_.fd(); }
123
124  protected:
125   MemoryMapping();
126
127   void init(File file,
128             off_t offset, off_t length,
129             int prot,
130             bool grow);
131
132   File file_;
133   void* mapStart_;
134   off_t mapLength_;
135   bool locked_;
136   Range<uint8_t*> data_;
137 };
138
139 /**
140  * Maps files in memory for writing.
141  *
142  * @author Tom Jackson (tjackson@fb.com)
143  */
144 class WritableMemoryMapping : public MemoryMapping {
145  public:
146   explicit WritableMemoryMapping(File file,
147                                  off_t offset = 0,
148                                  off_t length = -1);
149   /**
150    * A bitwise cast of the mapped bytes as range of mutable values. Only
151    * intended for use with POD or in-place usable types.
152    */
153   template<class T>
154   Range<T*> asWritableRange() const {
155     size_t count = data_.size() / sizeof(T);
156     return Range<T*>(static_cast<T*>(
157                        static_cast<void*>(data_.data())),
158                      count);
159   }
160
161   /**
162    * A range of mutable bytes mapped by this mapping.
163    */
164   Range<uint8_t*> writableRange() const {
165     return data_;
166   }
167 };
168
169 }  // namespace folly
170
171 #endif /* FOLLY_MEMORYMAPPING_H_ */