1 // Copyright 2015 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef BASE_METRICS_PERSISTENT_MEMORY_ALLOCATOR_H_ 6 #define BASE_METRICS_PERSISTENT_MEMORY_ALLOCATOR_H_ 7 8 #include <stdint.h> 9 10 #include <atomic> 11 #include <memory> 12 #include <string_view> 13 #include <type_traits> 14 15 #include "base/atomicops.h" 16 #include "base/base_export.h" 17 #include "base/check.h" 18 #include "base/check_op.h" 19 #include "base/containers/span.h" 20 #include "base/files/file_path.h" 21 #include "base/gtest_prod_util.h" 22 #include "base/memory/raw_ptr.h" 23 #include "base/memory/raw_ptr_exclusion.h" 24 #include "base/memory/shared_memory_mapping.h" 25 #include "build/build_config.h" 26 27 namespace metrics { 28 class FileMetricsProvider; 29 } 30 31 namespace base { 32 33 class HistogramBase; 34 class MemoryMappedFile; 35 36 // Simple allocator for pieces of a memory block that may be persistent 37 // to some storage or shared across multiple processes. This class resides 38 // under base/metrics because it was written for that purpose. It is, 39 // however, fully general-purpose and can be freely moved to base/memory 40 // if other uses are found. 41 // 42 // This class provides for thread-secure (i.e. safe against other threads 43 // or processes that may be compromised and thus have malicious intent) 44 // allocation of memory within a designated block and also a mechanism by 45 // which other threads can learn of these allocations. 46 // 47 // There is (currently) no way to release an allocated block of data because 48 // doing so would risk invalidating pointers held by other processes and 49 // greatly complicate the allocation algorithm. 50 // 51 // Construction of this object can accept new, clean (i.e. zeroed) memory 52 // or previously initialized memory. In the first case, construction must 53 // be allowed to complete before letting other allocators attach to the same 54 // segment. In other words, don't share the segment until at least one 55 // allocator has been attached to it. 56 // 57 // Note that memory not in active use is not accessed so it is possible to 58 // use virtual memory, including memory-mapped files, as backing storage with 59 // the OS "pinning" new (zeroed) physical RAM pages only as they are needed. 60 // 61 // OBJECTS: Although the allocator can be used in a "malloc" sense, fetching 62 // character arrays and manipulating that memory manually, the better way is 63 // generally to use the "object" methods to create and manage allocations. In 64 // this way the sizing, type-checking, and construction are all automatic. For 65 // this to work, however, every type of stored object must define two public 66 // "constexpr" values, kPersistentTypeId and kExpectedInstanceSize, as such: 67 // 68 // struct MyPersistentObjectType { 69 // // SHA1(MyPersistentObjectType): Increment this if structure changes! 70 // static constexpr uint32_t kPersistentTypeId = 0x3E15F6DE + 1; 71 // 72 // // Expected size for 32/64-bit check. Update this if structure changes! 73 // static constexpr size_t kExpectedInstanceSize = 20; 74 // 75 // ... 76 // }; 77 // 78 // kPersistentTypeId: This value is an arbitrary identifier that allows the 79 // identification of these objects in the allocator, including the ability 80 // to find them via iteration. The number is arbitrary but using the first 81 // four bytes of the SHA1 hash of the type name means that there shouldn't 82 // be any conflicts with other types that may also be stored in the memory. 83 // The fully qualified name (e.g. base::debug::MyPersistentObjectType) could 84 // be used to generate the hash if the type name seems common. Use a command 85 // like this to get the hash: echo -n "MyPersistentObjectType" | sha1sum 86 // If the structure layout changes, ALWAYS increment this number so that 87 // newer versions of the code don't try to interpret persistent data written 88 // by older versions with a different layout. 89 // 90 // kExpectedInstanceSize: This value is the hard-coded number that matches 91 // what sizeof(T) would return. By providing it explicitly, the allocator can 92 // verify that the structure is compatible between both 32-bit and 64-bit 93 // versions of the code. 94 // 95 // Using New manages the memory and then calls the default constructor for the 96 // object. Given that objects are persistent, no destructor is ever called 97 // automatically though a caller can explicitly call Delete to destruct it and 98 // change the type to something indicating it is no longer in use. 99 // 100 // Though persistent memory segments are transferrable between programs built 101 // for different natural word widths, they CANNOT be exchanged between CPUs 102 // of different endianess. Attempts to do so will simply see the existing data 103 // as corrupt and refuse to access any of it. 104 class BASE_EXPORT PersistentMemoryAllocator { 105 public: 106 typedef uint32_t Reference; 107 108 // All allocations and data-structures must be aligned to this byte boundary. 109 // Alignment as large as the physical bus between CPU and RAM is _required_ 110 // for some architectures, is simply more efficient on other CPUs, and 111 // generally a Good Idea(tm) for all platforms as it reduces/eliminates the 112 // chance that a type will span cache lines. Alignment mustn't be less 113 // than 8 to ensure proper alignment for all types. The rest is a balance 114 // between reducing spans across multiple cache lines and wasted space spent 115 // padding out allocations. An alignment of 16 would ensure that the block 116 // header structure always sits in a single cache line. An average of about 117 // 1/2 this value will be wasted with every allocation. 118 static constexpr size_t kAllocAlignment = 8; 119 120 // These states are used to indicate the overall condition of the memory 121 // segment irrespective of what is stored within it. Because the data is 122 // often persistent and thus needs to be readable by different versions of 123 // a program, these values are fixed and can never change. 124 enum MemoryState : uint8_t { 125 // Persistent memory starts all zeros and so shows "uninitialized". 126 MEMORY_UNINITIALIZED = 0, 127 128 // The header has been written and the memory is ready for use. 129 MEMORY_INITIALIZED = 1, 130 131 // The data should be considered deleted. This would be set when the 132 // allocator is being cleaned up. If file-backed, the file is likely 133 // to be deleted but since deletion can fail for a variety of reasons, 134 // having this extra status means a future reader can realize what 135 // should have happened. 136 MEMORY_DELETED = 2, 137 138 // The data should be considered complete. This is usually set when the 139 // browser is going to exit to indicate that it terminated cleanly and that 140 // the memory should be well-formed. In theory, this is not perfect as it is 141 // possible for the browser/device to crash after this has been set, but in 142 // practice this should be a reasonable indication as to whether the data 143 // comes from a completed or crashed session (if file-backed). Note that 144 // this might not be set on certain platforms (e.g. Android, iOS) due to not 145 // having a guaranteed clean shutdown path. 146 MEMORY_COMPLETED = 3, 147 148 // Outside code can create states starting with this number; these too 149 // must also never change between code versions. 150 MEMORY_USER_DEFINED = 100, 151 }; 152 153 // Iterator for going through all iterable memory records in an allocator. 154 // Like the allocator itself, iterators are lock-free and thread-secure. 155 // That means that multiple threads can share an iterator and the same 156 // reference will not be returned twice. 157 // 158 // The order of the items returned by an iterator matches the order in which 159 // MakeIterable() was called on them. Once an allocation is made iterable, 160 // it is always such so the only possible difference between successive 161 // iterations is for more to be added to the end. 162 // 163 // Iteration, in general, is tolerant of corrupted memory. It will return 164 // what it can and stop only when corruption forces it to. Bad corruption 165 // could cause the same object to be returned many times but it will 166 // eventually quit. 167 class BASE_EXPORT Iterator { 168 public: 169 // Constructs an iterator on a given |allocator|, starting at the beginning. 170 // The allocator must live beyond the lifetime of the iterator. This class 171 // has read-only access to the allocator (hence "const") but the returned 172 // references can be used on a read/write version, too. 173 explicit Iterator(const PersistentMemoryAllocator* allocator); 174 175 // As above but resuming from the |starting_after| reference. The first call 176 // to GetNext() will return the next object found after that reference. The 177 // reference must be to an "iterable" object; references to non-iterable 178 // objects (those that never had MakeIterable() called for them) will cause 179 // a run-time error. 180 Iterator(const PersistentMemoryAllocator* allocator, 181 Reference starting_after); 182 183 Iterator(const Iterator&) = delete; 184 Iterator& operator=(const Iterator&) = delete; 185 186 ~Iterator(); 187 188 // Resets the iterator back to the beginning. 189 void Reset(); 190 191 // Resets the iterator, resuming from the |starting_after| reference. 192 void Reset(Reference starting_after); 193 194 // Returns the previously retrieved reference, or kReferenceNull if none. 195 // If constructor or reset with a starting_after location, this will return 196 // that value. 197 Reference GetLast(); 198 199 // Gets the next iterable, storing that type in |type_return|. The actual 200 // return value is a reference to the allocation inside the allocator or 201 // zero if there are no more. GetNext() may still be called again at a 202 // later time to retrieve any new allocations that have been added. 203 Reference GetNext(uint32_t* type_return); 204 205 // Similar to above but gets the next iterable of a specific |type_match|. 206 // This should not be mixed with calls to GetNext() because any allocations 207 // skipped here due to a type mis-match will never be returned by later 208 // calls to GetNext() meaning it's possible to completely miss entries. 209 Reference GetNextOfType(uint32_t type_match); 210 211 // As above but works using object type. 212 template <typename T> GetNextOfType()213 Reference GetNextOfType() { 214 return GetNextOfType(T::kPersistentTypeId); 215 } 216 217 // As above but works using objects and returns null if not found. 218 template <typename T> GetNextOfObject()219 const T* GetNextOfObject() { 220 return GetAsObject<T>(GetNextOfType<T>()); 221 } 222 223 // Converts references to objects. This is a convenience method so that 224 // users of the iterator don't need to also have their own pointer to the 225 // allocator over which the iterator runs in order to retrieve objects. 226 // Because the iterator is not read/write, only "const" objects can be 227 // fetched. Non-const objects can be fetched using the reference on a 228 // non-const (external) pointer to the same allocator (or use const_cast 229 // to remove the qualifier). 230 template <typename T> GetAsObject(Reference ref)231 const T* GetAsObject(Reference ref) const { 232 return allocator_->GetAsObject<T>(ref); 233 } 234 235 // Similar to GetAsObject() but converts references to arrays of things. 236 template <typename T> GetAsArray(Reference ref,uint32_t type_id,size_t count)237 const T* GetAsArray(Reference ref, uint32_t type_id, size_t count) const { 238 return allocator_->GetAsArray<T>(ref, type_id, count); 239 } 240 241 // Convert a generic pointer back into a reference. A null reference will 242 // be returned if |memory| is not inside the persistent segment or does not 243 // point to an object of the specified |type_id|. GetAsReference(const void * memory,uint32_t type_id)244 Reference GetAsReference(const void* memory, uint32_t type_id) const { 245 return allocator_->GetAsReference(memory, type_id); 246 } 247 248 // As above but convert an object back into a reference. 249 template <typename T> GetAsReference(const T * obj)250 Reference GetAsReference(const T* obj) const { 251 return allocator_->GetAsReference(obj); 252 } 253 254 private: 255 // Weak-pointer to memory allocator being iterated over. 256 raw_ptr<const PersistentMemoryAllocator> allocator_; 257 258 // The last record that was returned. 259 std::atomic<Reference> last_record_; 260 261 // The number of records found; used for detecting loops. 262 std::atomic<uint32_t> record_count_; 263 }; 264 265 // Returned information about the internal state of the heap. 266 struct MemoryInfo { 267 size_t total; 268 size_t free; 269 }; 270 271 enum : Reference { 272 // A common "null" reference value. 273 kReferenceNull = 0, 274 }; 275 276 enum : uint32_t { 277 // A value that will match any type when doing lookups. 278 kTypeIdAny = 0x00000000, 279 280 // A value indicating that the type is in transition. Work is being done 281 // on the contents to prepare it for a new type to come. 282 kTypeIdTransitioning = 0xFFFFFFFF, 283 }; 284 285 enum : size_t { 286 kSizeAny = 1 // Constant indicating that any array size is acceptable. 287 }; 288 289 // Indicates the mode for accessing the underlying data. 290 enum AccessMode { 291 kReadOnly, 292 kReadWrite, 293 // Open existing initialized data in R/W mode. If the passed data appears to 294 // not have been initialized, does not write to it and instead marks the 295 // allocator as corrupt (without writing anything to the underlying data.) 296 kReadWriteExisting, 297 }; 298 299 // This is the standard file extension (suitable for being passed to the 300 // AddExtension() method of base::FilePath) for dumps of persistent memory. 301 static const base::FilePath::CharType kFileExtension[]; 302 303 // The allocator operates on any arbitrary block of memory. Creation and 304 // persisting or sharing of that block with another process is the 305 // responsibility of the caller. The allocator needs to know only the 306 // block's |base| address, the total |size| of the block, and any internal 307 // |page| size (zero if not paged) across which allocations should not span. 308 // The |id| is an arbitrary value the caller can use to identify a 309 // particular memory segment. It will only be loaded during the initial 310 // creation of the segment and can be checked by the caller for consistency. 311 // The |name|, if provided, is used to distinguish histograms for this 312 // allocator. Only the primary owner of the segment should define this value; 313 // other processes can learn it from the shared state. If the access mode 314 // is kReadOnly then no changes will be made to it. The resulting object 315 // should be stored as a "const" pointer. 316 // 317 // PersistentMemoryAllocator does NOT take ownership of the memory block. 318 // The caller must manage it and ensure it stays available throughout the 319 // lifetime of this object. 320 // 321 // Memory segments for sharing must have had an allocator attached to them 322 // before actually being shared. If the memory segment was just created, it 323 // should be zeroed before being passed here. If it was an existing segment, 324 // the values here will be compared to copies stored in the shared segment 325 // as a guard against corruption. 326 // 327 // Make sure that the memory segment is acceptable (see IsMemoryAcceptable() 328 // method below) before construction if the definition of the segment can 329 // vary in any way at run-time. Invalid memory segments will cause a crash. 330 PersistentMemoryAllocator(void* base, 331 size_t size, 332 size_t page_size, 333 uint64_t id, 334 std::string_view name, 335 AccessMode access_mode); 336 337 PersistentMemoryAllocator(const PersistentMemoryAllocator&) = delete; 338 PersistentMemoryAllocator& operator=(const PersistentMemoryAllocator&) = 339 delete; 340 341 virtual ~PersistentMemoryAllocator(); 342 343 // Check if memory segment is acceptable for creation of an Allocator. This 344 // doesn't do any analysis of the data and so doesn't guarantee that the 345 // contents are valid, just that the paramaters won't cause the program to 346 // abort. The IsCorrupt() method will report detection of data problems 347 // found during construction and general operation. 348 static bool IsMemoryAcceptable(const void* data, size_t size, 349 size_t page_size, bool readonly); 350 351 // Get the internal identifier for this persistent memory segment. 352 uint64_t Id() const; 353 354 // Get the internal name of this allocator (possibly an empty string). 355 const char* Name() const; 356 357 // Is this segment open only for read? IsReadonly()358 bool IsReadonly() const { return access_mode_ == kReadOnly; } 359 360 // Manage the saved state of the memory. 361 void SetMemoryState(uint8_t memory_state); 362 uint8_t GetMemoryState() const; 363 364 // Create internal histograms for tracking memory use and allocation sizes 365 // for allocator of |name| (which can simply be the result of Name()). This 366 // is done seperately from construction for situations such as when the 367 // histograms will be backed by memory provided by this very allocator. 368 // 369 // IMPORTANT: tools/metrics/histograms/metadata/uma/histograms.xml must 370 // be updated with the following histograms for each |name| param: 371 // UMA.PersistentAllocator.name.Errors 372 // UMA.PersistentAllocator.name.UsedPct 373 void CreateTrackingHistograms(std::string_view name); 374 375 // Flushes the persistent memory to any backing store. This typically does 376 // nothing but is used by the FilePersistentMemoryAllocator to inform the 377 // OS that all the data should be sent to the disk immediately. This is 378 // useful in the rare case where something has just been stored that needs 379 // to survive a hard shutdown of the machine like from a power failure. 380 // The |sync| parameter indicates if this call should block until the flush 381 // is complete but is only advisory and may or may not have an effect 382 // depending on the capabilities of the OS. Synchronous flushes are allowed 383 // only from threads that are allowed to do I/O but since |sync| is only 384 // advisory, all flushes should be done on IO-capable threads. 385 // TODO: Since |sync| is ignored on Windows, consider making it re-post on a 386 // background thread with |sync| set to true so that |sync| is not just 387 // advisory. 388 void Flush(bool sync); 389 390 // Direct access to underlying memory segment. If the segment is shared 391 // across threads or processes, reading data through these values does 392 // not guarantee consistency. Use with care. Do not write. data()393 const void* data() const { return const_cast<const char*>(mem_base_); } length()394 size_t length() const { return mem_size_; } size()395 size_t size() const { return mem_size_; } 396 size_t used() const; 397 398 // Get an object referenced by a |ref|. For safety reasons, the |type_id| 399 // code and size-of(|T|) are compared to ensure the reference is valid 400 // and cannot return an object outside of the memory segment. A |type_id| of 401 // kTypeIdAny (zero) will match any though the size is still checked. NULL is 402 // returned if any problem is detected, such as corrupted storage or incorrect 403 // parameters. Callers MUST check that the returned value is not-null EVERY 404 // TIME before accessing it or risk crashing! Once dereferenced, the pointer 405 // is safe to reuse forever. 406 // 407 // It is essential that the object be of a fixed size. All fields must be of 408 // a defined type that does not change based on the compiler or the CPU 409 // natural word size. Acceptable are char, float, double, and (u)intXX_t. 410 // Unacceptable are int, bool, and wchar_t which are implementation defined 411 // with regards to their size. 412 // 413 // Alignment must also be consistent. A uint64_t after a uint32_t will pad 414 // differently between 32 and 64 bit architectures. Either put the bigger 415 // elements first, group smaller elements into blocks the size of larger 416 // elements, or manually insert padding fields as appropriate for the 417 // largest architecture, including at the end. 418 // 419 // To protected against mistakes, all objects must have the attribute 420 // |kExpectedInstanceSize| (static constexpr size_t) that is a hard-coded 421 // numerical value -- NNN, not sizeof(T) -- that can be tested. If the 422 // instance size is not fixed, at least one build will fail. 423 // 424 // If the size of a structure changes, the type-ID used to recognize it 425 // should also change so later versions of the code don't try to read 426 // incompatible structures from earlier versions. 427 // 428 // NOTE: Though this method will guarantee that an object of the specified 429 // type can be accessed without going outside the bounds of the memory 430 // segment, it makes no guarantees of the validity of the data within the 431 // object itself. If it is expected that the contents of the segment could 432 // be compromised with malicious intent, the object must be hardened as well. 433 // 434 // Though the persistent data may be "volatile" if it is shared with 435 // other processes, such is not necessarily the case. The internal 436 // "volatile" designation is discarded so as to not propagate the viral 437 // nature of that keyword to the caller. It can add it back, if necessary, 438 // based on knowledge of how the allocator is being used. 439 template <typename T> GetAsObject(Reference ref)440 T* GetAsObject(Reference ref) { 441 static_assert(std::is_standard_layout_v<T>, "only standard objects"); 442 static_assert(!std::is_array_v<T>, "use GetAsArray<>()"); 443 static_assert(T::kExpectedInstanceSize == sizeof(T), "inconsistent size"); 444 return const_cast<T*>(reinterpret_cast<volatile T*>( 445 GetBlockData(ref, T::kPersistentTypeId, sizeof(T)))); 446 } 447 template <typename T> GetAsObject(Reference ref)448 const T* GetAsObject(Reference ref) const { 449 static_assert(std::is_standard_layout_v<T>, "only standard objects"); 450 static_assert(!std::is_array_v<T>, "use GetAsArray<>()"); 451 static_assert(T::kExpectedInstanceSize == sizeof(T), "inconsistent size"); 452 return const_cast<const T*>(reinterpret_cast<const volatile T*>( 453 GetBlockData(ref, T::kPersistentTypeId, sizeof(T)))); 454 } 455 456 // Like GetAsObject but get an array of simple, fixed-size types. 457 // 458 // Use a |count| of the required number of array elements, or kSizeAny. 459 // GetAllocSize() can be used to calculate the upper bound but isn't reliable 460 // because padding can make space for extra elements that were not written. 461 // 462 // Remember that an array of char is a string but may not be NUL terminated. 463 // 464 // There are no compile-time or run-time checks to ensure 32/64-bit size 465 // compatibilty when using these accessors. Only use fixed-size types such 466 // as char, float, double, or (u)intXX_t. 467 template <typename T> GetAsArray(Reference ref,uint32_t type_id,size_t count)468 T* GetAsArray(Reference ref, uint32_t type_id, size_t count) { 469 static_assert(std::is_fundamental_v<T>, "use GetAsObject<>()"); 470 return const_cast<T*>(reinterpret_cast<volatile T*>( 471 GetBlockData(ref, type_id, count * sizeof(T)))); 472 } 473 template <typename T> GetAsArray(Reference ref,uint32_t type_id,size_t count)474 const T* GetAsArray(Reference ref, uint32_t type_id, size_t count) const { 475 static_assert(std::is_fundamental_v<T>, "use GetAsObject<>()"); 476 return const_cast<const char*>(reinterpret_cast<const volatile T*>( 477 GetBlockData(ref, type_id, count * sizeof(T)))); 478 } 479 480 // Get the corresponding reference for an object held in persistent memory. 481 // If the |memory| is not valid or the type does not match, a kReferenceNull 482 // result will be returned. 483 Reference GetAsReference(const void* memory, uint32_t type_id) const; 484 485 // Get the number of bytes allocated to a block. This is useful when storing 486 // arrays in order to validate the ending boundary. The returned value will 487 // include any padding added to achieve the required alignment and so could 488 // be larger than given in the original Allocate() request. 489 size_t GetAllocSize(Reference ref) const; 490 491 // Access the internal "type" of an object. This generally isn't necessary 492 // but can be used to "clear" the type and so effectively mark it as deleted 493 // even though the memory stays valid and allocated. Changing the type is 494 // an atomic compare/exchange and so requires knowing the existing value. 495 // It will return false if the existing type is not what is expected. 496 // 497 // Changing the type doesn't mean the data is compatible with the new type. 498 // Passing true for |clear| will zero the memory after the type has been 499 // changed away from |from_type_id| but before it becomes |to_type_id| meaning 500 // that it is done in a manner that is thread-safe. Memory is guaranteed to 501 // be zeroed atomically by machine-word in a monotonically increasing order. 502 // 503 // It will likely be necessary to reconstruct the type before it can be used. 504 // Changing the type WILL NOT invalidate existing pointers to the data, either 505 // in this process or others, so changing the data structure could have 506 // unpredicatable results. USE WITH CARE! 507 uint32_t GetType(Reference ref) const; 508 bool ChangeType(Reference ref, 509 uint32_t to_type_id, 510 uint32_t from_type_id, 511 bool clear); 512 513 // Allocated objects can be added to an internal list that can then be 514 // iterated over by other processes. If an allocated object can be found 515 // another way, such as by having its reference within a different object 516 // that will be made iterable, then this call is not necessary. This always 517 // succeeds unless corruption is detected; check IsCorrupted() to find out. 518 // Once an object is made iterable, its position in iteration can never 519 // change; new iterable objects will always be added after it in the series. 520 // Changing the type does not alter its "iterable" status. 521 void MakeIterable(Reference ref); 522 523 // Get the information about the amount of free space in the allocator. The 524 // amount of free space should be treated as approximate due to extras from 525 // alignment and metadata. Concurrent allocations from other threads will 526 // also make the true amount less than what is reported. 527 void GetMemoryInfo(MemoryInfo* meminfo) const; 528 529 // If there is some indication that the memory has become corrupted, 530 // calling this will attempt to prevent further damage by indicating to 531 // all processes that something is not as expected. 532 // If `allow_write` is false, the corrupt bit will not be written to the data. 533 void SetCorrupt(bool allow_write = true) const; 534 535 // This can be called to determine if corruption has been detected in the 536 // segment, possibly my a malicious actor. Once detected, future allocations 537 // will fail and iteration may not locate all objects. 538 bool IsCorrupt() const; 539 540 // Flag set if an allocation has failed because the memory segment was full. 541 bool IsFull() const; 542 543 // Update those "tracking" histograms which do not get updates during regular 544 // operation, such as how much memory is currently used. This should be 545 // called before such information is to be displayed or uploaded. 546 void UpdateTrackingHistograms(); 547 548 // While the above works much like malloc & free, these next methods provide 549 // an "object" interface similar to new and delete. 550 551 // Reserve space in the memory segment of the desired |size| and |type_id|. 552 // 553 // A return value of zero indicates the allocation failed, otherwise the 554 // returned reference can be used by any process to get a real pointer via 555 // the GetAsObject() or GetAsArray calls. The actual allocated size may be 556 // larger and will always be a multiple of 8 bytes (64 bits). 557 Reference Allocate(size_t size, uint32_t type_id); 558 559 // Allocate and construct an object in persistent memory. The type must have 560 // both (size_t) kExpectedInstanceSize and (uint32_t) kPersistentTypeId 561 // static constexpr fields that are used to ensure compatibility between 562 // software versions. An optional size parameter can be specified to force 563 // the allocation to be bigger than the size of the object; this is useful 564 // when the last field is actually variable length. 565 template <typename T> New(size_t size)566 T* New(size_t size) { 567 static_assert(alignof(T) <= kAllocAlignment); 568 if (size < sizeof(T)) 569 size = sizeof(T); 570 Reference ref = Allocate(size, T::kPersistentTypeId); 571 void* mem = 572 const_cast<void*>(GetBlockData(ref, T::kPersistentTypeId, size)); 573 if (!mem) 574 return nullptr; 575 DCHECK_EQ(0U, reinterpret_cast<uintptr_t>(mem) & (alignof(T) - 1)); 576 return new (mem) T(); 577 } 578 template <typename T> New()579 T* New() { 580 return New<T>(sizeof(T)); 581 } 582 583 // Similar to New, above, but construct the object out of an existing memory 584 // block and of an expected type. If |clear| is true, memory will be zeroed 585 // before construction. Though this is not standard object behavior, it 586 // is present to match with new allocations that always come from zeroed 587 // memory. Anything previously present simply ceases to exist; no destructor 588 // is called for it so explicitly Delete() the old object first if need be. 589 // Calling this will not invalidate existing pointers to the object, either 590 // in this process or others, so changing the object could have unpredictable 591 // results. USE WITH CARE! 592 template <typename T> New(Reference ref,uint32_t from_type_id,bool clear)593 T* New(Reference ref, uint32_t from_type_id, bool clear) { 594 DCHECK_LE(sizeof(T), GetAllocSize(ref)) << "alloc not big enough for obj"; 595 // Make sure the memory is appropriate. This won't be used until after 596 // the type is changed but checking first avoids the possibility of having 597 // to change the type back. 598 void* mem = const_cast<void*>(GetBlockData(ref, 0, sizeof(T))); 599 if (!mem) 600 return nullptr; 601 // Ensure the allocator's internal alignment is sufficient for this object. 602 // This protects against coding errors in the allocator. 603 DCHECK_EQ(0U, reinterpret_cast<uintptr_t>(mem) & (alignof(T) - 1)); 604 // Change the type, clearing the memory if so desired. The new type is 605 // "transitioning" so that there is no race condition with the construction 606 // of the object should another thread be simultaneously iterating over 607 // data. This will "acquire" the memory so no changes get reordered before 608 // it. 609 if (!ChangeType(ref, kTypeIdTransitioning, from_type_id, clear)) 610 return nullptr; 611 // Construct an object of the desired type on this memory, just as if 612 // New() had been called to create it. 613 T* obj = new (mem) T(); 614 // Finally change the type to the desired one. This will "release" all of 615 // the changes above and so provide a consistent view to other threads. 616 bool success = 617 ChangeType(ref, T::kPersistentTypeId, kTypeIdTransitioning, false); 618 DCHECK(success); 619 return obj; 620 } 621 622 // Deletes an object by destructing it and then changing the type to a 623 // different value (default 0). 624 template <typename T> Delete(T * obj,uint32_t new_type)625 void Delete(T* obj, uint32_t new_type) { 626 // Get the reference for the object. 627 Reference ref = GetAsReference<T>(obj); 628 // First change the type to "transitioning" so there is no race condition 629 // where another thread could find the object through iteration while it 630 // is been destructed. This will "acquire" the memory so no changes get 631 // reordered before it. It will fail if |ref| is invalid. 632 if (!ChangeType(ref, kTypeIdTransitioning, T::kPersistentTypeId, false)) 633 return; 634 // Destruct the object. 635 obj->~T(); 636 // Finally change the type to the desired value. This will "release" all 637 // the changes above. 638 bool success = ChangeType(ref, new_type, kTypeIdTransitioning, false); 639 DCHECK(success); 640 } 641 template <typename T> Delete(T * obj)642 void Delete(T* obj) { 643 Delete<T>(obj, 0); 644 } 645 646 // As above but works with objects allocated from persistent memory. 647 template <typename T> GetAsReference(const T * obj)648 Reference GetAsReference(const T* obj) const { 649 return GetAsReference(obj, T::kPersistentTypeId); 650 } 651 652 // As above but works with an object allocated from persistent memory. 653 template <typename T> MakeIterable(const T * obj)654 void MakeIterable(const T* obj) { 655 MakeIterable(GetAsReference<T>(obj)); 656 } 657 658 protected: 659 enum MemoryType { 660 MEM_EXTERNAL, 661 MEM_MALLOC, 662 MEM_VIRTUAL, 663 MEM_SHARED, 664 MEM_FILE, 665 }; 666 667 struct Memory { MemoryMemory668 Memory(void* b, MemoryType t) : base(b), type(t) {} 669 670 raw_ptr<void> base; 671 MemoryType type; 672 }; 673 674 // Constructs the allocator. Everything is the same as the public allocator 675 // except |memory| which is a structure with additional information besides 676 // the base address. 677 PersistentMemoryAllocator(Memory memory, 678 size_t size, 679 size_t page_size, 680 uint64_t id, 681 std::string_view name, 682 AccessMode access_mode); 683 684 // Implementation of Flush that accepts how much to flush. 685 virtual void FlushPartial(size_t length, bool sync); 686 687 // This field is not a raw_ptr<> because it always points to a mmap'd region 688 // of memory outside of the PA heap. Thus, there would be overhead involved 689 // with using a raw_ptr<> but no safety gains. 690 RAW_PTR_EXCLUSION volatile char* const 691 mem_base_; // Memory base. (char so sizeof guaranteed 1) 692 const MemoryType mem_type_; // Type of memory allocation. 693 const uint32_t mem_size_; // Size of entire memory segment. 694 const uint32_t mem_page_; // Page size allocations shouldn't cross. 695 const size_t vm_page_size_; // The page size used by the OS. 696 697 private: 698 struct SharedMetadata; 699 struct BlockHeader; 700 static const Reference kReferenceQueue; 701 702 // The shared metadata is always located at the top of the memory segment. 703 // These convenience functions eliminate constant casting of the base 704 // pointer within the code. shared_meta()705 const SharedMetadata* shared_meta() const { 706 return reinterpret_cast<const SharedMetadata*>( 707 const_cast<const char*>(mem_base_)); 708 } shared_meta()709 SharedMetadata* shared_meta() { 710 return reinterpret_cast<SharedMetadata*>(const_cast<char*>(mem_base_)); 711 } 712 713 // Actual method for doing the allocation. 714 Reference AllocateImpl(size_t size, uint32_t type_id); 715 716 // Gets the block header associated with a specific reference. 717 const volatile BlockHeader* GetBlock(Reference ref, 718 uint32_t type_id, 719 size_t size, 720 bool queue_ok, 721 bool free_ok) const; GetBlock(Reference ref,uint32_t type_id,size_t size,bool queue_ok,bool free_ok)722 volatile BlockHeader* GetBlock(Reference ref, 723 uint32_t type_id, 724 size_t size, 725 bool queue_ok, 726 bool free_ok) { 727 return const_cast<volatile BlockHeader*>( 728 const_cast<const PersistentMemoryAllocator*>(this)->GetBlock( 729 ref, type_id, size, queue_ok, free_ok)); 730 } 731 732 // Gets the actual data within a block associated with a specific reference. 733 const volatile void* GetBlockData(Reference ref, 734 uint32_t type_id, 735 size_t size) const; GetBlockData(Reference ref,uint32_t type_id,size_t size)736 volatile void* GetBlockData(Reference ref, uint32_t type_id, size_t size) { 737 return const_cast<volatile void*>( 738 const_cast<const PersistentMemoryAllocator*>(this)->GetBlockData( 739 ref, type_id, size)); 740 } 741 742 // Records an error in the internal histogram. 743 void RecordError(int error) const; 744 745 // Returns the offset to the first free space segment. 746 uint32_t freeptr() const; 747 748 // Returns the metadata version used in this allocator. 749 uint32_t version() const; 750 751 const AccessMode access_mode_; 752 753 // Local version of "corrupted" flag. 754 mutable std::atomic<bool> corrupt_ = false; 755 756 // Histogram recording allocs. 757 raw_ptr<HistogramBase> allocs_histogram_ = nullptr; 758 // Histogram recording used space. 759 raw_ptr<HistogramBase> used_histogram_ = nullptr; 760 // Histogram recording errors. 761 raw_ptr<HistogramBase> errors_histogram_ = nullptr; 762 763 // TODO(crbug.com/1432981) For debugging purposes. Remove these once done. 764 friend class DelayedPersistentAllocation; 765 friend class metrics::FileMetricsProvider; 766 767 friend class PersistentMemoryAllocatorTest; 768 FRIEND_TEST_ALL_PREFIXES(PersistentMemoryAllocatorTest, AllocateAndIterate); 769 }; 770 771 772 // This allocator uses a local memory block it allocates from the general 773 // heap. It is generally used when some kind of "death rattle" handler will 774 // save the contents to persistent storage during process shutdown. It is 775 // also useful for testing. 776 class BASE_EXPORT LocalPersistentMemoryAllocator 777 : public PersistentMemoryAllocator { 778 public: 779 LocalPersistentMemoryAllocator(size_t size, 780 uint64_t id, 781 std::string_view name); 782 783 LocalPersistentMemoryAllocator(const LocalPersistentMemoryAllocator&) = 784 delete; 785 LocalPersistentMemoryAllocator& operator=( 786 const LocalPersistentMemoryAllocator&) = delete; 787 788 ~LocalPersistentMemoryAllocator() override; 789 790 private: 791 // Allocates a block of local memory of the specified |size|, ensuring that 792 // the memory will not be physically allocated until accessed and will read 793 // as zero when that happens. 794 static Memory AllocateLocalMemory(size_t size, std::string_view name); 795 796 // Deallocates a block of local |memory| of the specified |size|. 797 static void DeallocateLocalMemory(void* memory, size_t size, MemoryType type); 798 }; 799 800 801 // This allocator takes a writable shared memory mapping object and performs 802 // allocation from it. The allocator takes ownership of the mapping object. 803 class BASE_EXPORT WritableSharedPersistentMemoryAllocator 804 : public PersistentMemoryAllocator { 805 public: 806 WritableSharedPersistentMemoryAllocator( 807 base::WritableSharedMemoryMapping memory, 808 uint64_t id, 809 std::string_view name); 810 811 WritableSharedPersistentMemoryAllocator( 812 const WritableSharedPersistentMemoryAllocator&) = delete; 813 WritableSharedPersistentMemoryAllocator& operator=( 814 const WritableSharedPersistentMemoryAllocator&) = delete; 815 816 ~WritableSharedPersistentMemoryAllocator() override; 817 818 // Ensure that the memory isn't so invalid that it would crash when passing it 819 // to the allocator. This doesn't guarantee the data is valid, just that it 820 // won't cause the program to abort. The existing IsCorrupt() call will handle 821 // the rest. 822 static bool IsSharedMemoryAcceptable( 823 const base::WritableSharedMemoryMapping& memory); 824 825 private: 826 base::WritableSharedMemoryMapping shared_memory_; 827 }; 828 829 // This allocator takes a read-only shared memory mapping object and performs 830 // allocation from it. The allocator takes ownership of the mapping object. 831 class BASE_EXPORT ReadOnlySharedPersistentMemoryAllocator 832 : public PersistentMemoryAllocator { 833 public: 834 ReadOnlySharedPersistentMemoryAllocator( 835 base::ReadOnlySharedMemoryMapping memory, 836 uint64_t id, 837 std::string_view name); 838 839 ReadOnlySharedPersistentMemoryAllocator( 840 const ReadOnlySharedPersistentMemoryAllocator&) = delete; 841 ReadOnlySharedPersistentMemoryAllocator& operator=( 842 const ReadOnlySharedPersistentMemoryAllocator&) = delete; 843 844 ~ReadOnlySharedPersistentMemoryAllocator() override; 845 846 // Ensure that the memory isn't so invalid that it would crash when passing it 847 // to the allocator. This doesn't guarantee the data is valid, just that it 848 // won't cause the program to abort. The existing IsCorrupt() call will handle 849 // the rest. 850 static bool IsSharedMemoryAcceptable( 851 const base::ReadOnlySharedMemoryMapping& memory); 852 853 private: 854 base::ReadOnlySharedMemoryMapping shared_memory_; 855 }; 856 857 // NACL doesn't support any kind of file access in build. 858 #if !BUILDFLAG(IS_NACL) 859 // This allocator takes a memory-mapped file object and performs allocation 860 // from it. The allocator takes ownership of the file object. 861 class BASE_EXPORT FilePersistentMemoryAllocator 862 : public PersistentMemoryAllocator { 863 public: 864 // A |max_size| of zero will use the length of the file as the maximum 865 // size. The |file| object must have been already created with sufficient 866 // permissions (read, read/write, or read/write/extend). 867 FilePersistentMemoryAllocator(std::unique_ptr<MemoryMappedFile> file, 868 size_t max_size, 869 uint64_t id, 870 std::string_view name, 871 AccessMode access_mode); 872 873 FilePersistentMemoryAllocator(const FilePersistentMemoryAllocator&) = delete; 874 FilePersistentMemoryAllocator& operator=( 875 const FilePersistentMemoryAllocator&) = delete; 876 877 ~FilePersistentMemoryAllocator() override; 878 879 // Ensure that the file isn't so invalid that it would crash when passing it 880 // to the allocator. This doesn't guarantee the file is valid, just that it 881 // won't cause the program to abort. The existing IsCorrupt() call will handle 882 // the rest. 883 static bool IsFileAcceptable(const MemoryMappedFile& file, bool read_only); 884 885 // Load all or a portion of the file into memory for fast access. This can 886 // be used to force the disk access to be done on a background thread and 887 // then have the data available to be read on the main thread with a greatly 888 // reduced risk of blocking due to I/O. The risk isn't eliminated completely 889 // because the system could always release the memory when under pressure 890 // but this can happen to any block of memory (i.e. swapped out). 891 void Cache(); 892 893 protected: 894 // PersistentMemoryAllocator: 895 void FlushPartial(size_t length, bool sync) override; 896 897 private: 898 std::unique_ptr<MemoryMappedFile> mapped_file_; 899 }; 900 #endif // !BUILDFLAG(IS_NACL) 901 902 // An allocation that is defined but not executed until required at a later 903 // time. This allows for potential users of an allocation to be decoupled 904 // from the logic that defines it. In addition, there can be multiple users 905 // of the same allocation or any region thereof that are guaranteed to always 906 // use the same space. It's okay to copy/move these objects. 907 // 908 // This is a top-level class instead of an inner class of the PMA so that it 909 // can be forward-declared in other header files without the need to include 910 // the full contents of this file. 911 class BASE_EXPORT DelayedPersistentAllocation { 912 public: 913 using Reference = PersistentMemoryAllocator::Reference; 914 915 // Creates a delayed allocation using the specified |allocator|. When 916 // needed, the memory will be allocated using the specified |type| and 917 // |size|. If |offset| is given, the returned pointer will be at that 918 // offset into the segment; this allows combining allocations into a 919 // single persistent segment to reduce overhead and means an "all or 920 // nothing" request. Note that |size| is always the total memory size 921 // and |offset| is just indicating the start of a block within it. 922 // 923 // Once allocated, a reference to the segment will be stored at |ref|. 924 // This shared location must be initialized to zero (0); it is checked 925 // with every Get() request to see if the allocation has already been 926 // done. If reading |ref| outside of this object, be sure to do an 927 // "acquire" load. Don't write to it -- leave that to this object. 928 DelayedPersistentAllocation(PersistentMemoryAllocator* allocator, 929 std::atomic<Reference>* ref, 930 uint32_t type, 931 size_t size, 932 size_t offset = 0); 933 ~DelayedPersistentAllocation(); 934 935 // Gets a span to the defined allocation. This will realize the request 936 // and update the reference provided during construction. The memory will 937 // be zeroed the first time it is returned, after that it is shared with 938 // all other Get() requests and so shows any changes made to it elsewhere. 939 // 940 // If the allocation fails for any reason, an empty span will be returned. 941 // This works even on "const" objects because the allocation is already 942 // defined, just delayed. 943 template <typename T> Get()944 span<T> Get() const { 945 // PersistentMemoryAllocator only supports types with alignment at most 946 // kAllocAlignment. 947 static_assert(alignof(T) <= PersistentMemoryAllocator::kAllocAlignment); 948 // The offset must be a multiple of the alignment or misaligned pointers 949 // will result. 950 CHECK_EQ(offset_ % alignof(T), 0u); 951 span<uint8_t> untyped = GetUntyped(); 952 return make_span(reinterpret_cast<T*>(untyped.data()), 953 untyped.size() / sizeof(T)); 954 } 955 956 // Gets the internal reference value. If this returns a non-zero value then 957 // a subsequent call to Get() will do nothing but convert that reference into 958 // a memory location -- useful for accessing an existing allocation without 959 // creating one unnecessarily. reference()960 Reference reference() const { 961 return reference_->load(std::memory_order_relaxed); 962 } 963 964 private: 965 span<uint8_t> GetUntyped() const; 966 967 // The underlying object that does the actual allocation of memory. Its 968 // lifetime must exceed that of all DelayedPersistentAllocation objects 969 // that use it. 970 const raw_ptr<PersistentMemoryAllocator> allocator_; 971 972 // The desired type and size of the allocated segment plus the offset 973 // within it for the defined request. 974 const uint32_t type_; 975 const uint32_t size_; 976 const uint32_t offset_; 977 978 // The location at which a reference to the allocated segment is to be 979 // stored once the allocation is complete. If multiple delayed allocations 980 // share the same pointer then an allocation on one will amount to an 981 // allocation for all. 982 const raw_ptr<volatile std::atomic<Reference>, AllowPtrArithmetic> reference_; 983 984 // No DISALLOW_COPY_AND_ASSIGN as it's okay to copy/move these objects. 985 }; 986 987 } // namespace base 988 989 #endif // BASE_METRICS_PERSISTENT_MEMORY_ALLOCATOR_H_ 990