OLD | NEW |
1 // Copyright (c) 2015 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef BASE_METRICS_PERSISTENT_MEMORY_ALLOCATOR_H_ | 5 #ifndef BASE_METRICS_PERSISTENT_MEMORY_ALLOCATOR_H_ |
6 #define BASE_METRICS_PERSISTENT_MEMORY_ALLOCATOR_H_ | 6 #define BASE_METRICS_PERSISTENT_MEMORY_ALLOCATOR_H_ |
7 | 7 |
8 #include <stdint.h> | 8 #include <stdint.h> |
9 | 9 |
10 #include <atomic> | 10 #include <atomic> |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
43 // segment. In other words, don't share the segment until at least one | 43 // segment. In other words, don't share the segment until at least one |
44 // allocator has been attached to it. | 44 // allocator has been attached to it. |
45 // | 45 // |
46 // Note that memory not in active use is not accessed so it is possible to | 46 // Note that memory not in active use is not accessed so it is possible to |
47 // use virtual memory, including memory-mapped files, as backing storage with | 47 // use virtual memory, including memory-mapped files, as backing storage with |
48 // the OS "pinning" new (zeroed) physical RAM pages only as they are needed. | 48 // the OS "pinning" new (zeroed) physical RAM pages only as they are needed. |
49 class BASE_EXPORT PersistentMemoryAllocator { | 49 class BASE_EXPORT PersistentMemoryAllocator { |
50 public: | 50 public: |
51 typedef uint32_t Reference; | 51 typedef uint32_t Reference; |
52 | 52 |
53 // Internal state information when iterating over memory allocations. | 53 // Iterator for going through all iterable memory records in an allocator. |
54 class Iterator { | 54 // Like the allocator itself, iterators are lock-free and thread-secure. |
| 55 // That means that multiple threads can share an iterator and the same |
| 56 // reference will not be returned twice. |
| 57 // |
| 58 // Iteration, in general, is tolerant of corrupted memory. It will return |
| 59 // what it can and stop only when corruption forces it to. Bad corruption |
| 60 // could cause the same object to be returned many times but it will |
| 61 // eventually quit. |
| 62 class BASE_EXPORT Iterator { |
55 public: | 63 public: |
56 Iterator() : last(0) {} | 64 // Constructs an iterator on a given |allocator|, starting at the beginning. |
| 65 // The allocator must live beyond the lifetime of the iterator. This class |
| 66 // has read-only access to the allocator (hence "const") but the returned |
| 67 // references can be used on a read/write version, too. |
| 68 explicit Iterator(const PersistentMemoryAllocator* allocator); |
57 | 69 |
58 bool operator==(const Iterator& rhs) const { return last == rhs.last; } | 70 // As above but resuming from the |starting_after| reference. The first call |
59 bool operator!=(const Iterator& rhs) const { return last != rhs.last; } | 71 // to GetNext() will return the next object found after that reference. The |
| 72 // reference must be to an "iterable" object; references to non-iterable |
| 73 // objects (those that never had MakeIterable() called for them) will cause |
| 74 // a run-time error. |
| 75 Iterator(const PersistentMemoryAllocator* allocator, |
| 76 Reference starting_after); |
60 | 77 |
61 void clear() { last = 0; } | 78 // Gets the next iterable, storing that type in |type_return|. The actual |
62 bool is_clear() const { return last == 0; } | 79 // return value is a reference to the allocation inside the allocator or |
| 80 // zero if there are no more. GetNext() may still be called again at a |
| 81 // later time to retrieve any new allocations that have been added. |
| 82 Reference GetNext(uint32_t* type_return); |
| 83 |
| 84 // Similar to above but gets the next iterable of a specific |type_match|. |
| 85 // This should not be mixed with calls to GetNext() because any allocations |
| 86 // skipped here due to a type mis-match will never be returned by later |
| 87 // calls to GetNext() meaning it's possible to completely miss entries. |
| 88 Reference GetNextOfType(uint32_t type_match); |
| 89 |
| 90 // Converts references to objects. This is a convenience method so that |
| 91 // users of the iterator don't need to also have their own pointer to the |
| 92 // allocator over which the iterator runs in order to retrieve objects. |
| 93 // Because the iterator is not read/write, only "const" objects can be |
| 94 // fetched. Non-const objects can be fetched using the reference on a |
| 95 // non-const (external) pointer to the same allocator (or use const_cast |
| 96 // to remove the qualifier). |
| 97 template <typename T> |
| 98 const T* GetAsObject(Reference ref, uint32_t type_id) const { |
| 99 return allocator_->GetAsObject<T>(ref, type_id); |
| 100 } |
63 | 101 |
64 private: | 102 private: |
65 friend class PersistentMemoryAllocator; | 103 // Weak-pointer to memory allocator being iterated over. |
| 104 const PersistentMemoryAllocator* allocator_; |
66 | 105 |
67 Reference last; | 106 // The last record that was returned. |
68 uint32_t niter; | 107 std::atomic<Reference> last_record_; |
| 108 |
| 109 // The number of records found; used for detecting loops. |
| 110 std::atomic<uint32_t> record_count_; |
| 111 |
| 112 DISALLOW_COPY_AND_ASSIGN(Iterator); |
69 }; | 113 }; |
70 | 114 |
71 // Returned information about the internal state of the heap. | 115 // Returned information about the internal state of the heap. |
72 struct MemoryInfo { | 116 struct MemoryInfo { |
73 size_t total; | 117 size_t total; |
74 size_t free; | 118 size_t free; |
75 }; | 119 }; |
76 | 120 |
77 enum : uint32_t { | 121 enum : uint32_t { |
78 kTypeIdAny = 0 // Match any type-id inside GetAsObject(). | 122 kTypeIdAny = 0 // Match any type-id inside GetAsObject(). |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
205 // Once an object is made iterable, its position in iteration can never | 249 // Once an object is made iterable, its position in iteration can never |
206 // change; new iterable objects will always be added after it in the series. | 250 // change; new iterable objects will always be added after it in the series. |
207 void MakeIterable(Reference ref); | 251 void MakeIterable(Reference ref); |
208 | 252 |
209 // Get the information about the amount of free space in the allocator. The | 253 // Get the information about the amount of free space in the allocator. The |
210 // amount of free space should be treated as approximate due to extras from | 254 // amount of free space should be treated as approximate due to extras from |
211 // alignment and metadata. Concurrent allocations from other threads will | 255 // alignment and metadata. Concurrent allocations from other threads will |
212 // also make the true amount less than what is reported. | 256 // also make the true amount less than what is reported. |
213 void GetMemoryInfo(MemoryInfo* meminfo) const; | 257 void GetMemoryInfo(MemoryInfo* meminfo) const; |
214 | 258 |
215 // Iterating uses a |state| structure (initialized by CreateIterator) and | |
216 // returns both the reference to the object as well as the |type_id| of | |
217 // that object. A zero return value indicates there are currently no more | |
218 // objects to be found but future attempts can be made without having to | |
219 // reset the iterator to "first". Creating an iterator |starting_after| | |
220 // a known iterable object allows "resume" from that point with the next | |
221 // call to GetNextIterable returning the object after it. | |
222 void CreateIterator(Iterator* state) const { CreateIterator(state, 0); }; | |
223 void CreateIterator(Iterator* state, Reference starting_after) const; | |
224 Reference GetNextIterable(Iterator* state, uint32_t* type_id) const; | |
225 | |
226 // If there is some indication that the memory has become corrupted, | 259 // If there is some indication that the memory has become corrupted, |
227 // calling this will attempt to prevent further damage by indicating to | 260 // calling this will attempt to prevent further damage by indicating to |
228 // all processes that something is not as expected. | 261 // all processes that something is not as expected. |
229 void SetCorrupt() const; | 262 void SetCorrupt() const; |
230 | 263 |
231 // This can be called to determine if corruption has been detected in the | 264 // This can be called to determine if corruption has been detected in the |
232 // segment, possibly my a malicious actor. Once detected, future allocations | 265 // segment, possibly my a malicious actor. Once detected, future allocations |
233 // will fail and iteration may not locate all objects. | 266 // will fail and iteration may not locate all objects. |
234 bool IsCorrupt() const; | 267 bool IsCorrupt() const; |
235 | 268 |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
362 | 395 |
363 private: | 396 private: |
364 std::unique_ptr<MemoryMappedFile> mapped_file_; | 397 std::unique_ptr<MemoryMappedFile> mapped_file_; |
365 | 398 |
366 DISALLOW_COPY_AND_ASSIGN(FilePersistentMemoryAllocator); | 399 DISALLOW_COPY_AND_ASSIGN(FilePersistentMemoryAllocator); |
367 }; | 400 }; |
368 | 401 |
369 } // namespace base | 402 } // namespace base |
370 | 403 |
371 #endif // BASE_METRICS_PERSISTENT_MEMORY_ALLOCATOR_H_ | 404 #endif // BASE_METRICS_PERSISTENT_MEMORY_ALLOCATOR_H_ |
OLD | NEW |