| 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 |