Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(88)

Side by Side Diff: base/metrics/persistent_memory_allocator.h

Issue 2742193002: Harden allocator for file-backed memory. (Closed)
Patch Set: addressed final review comments Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
89 // change the type to something indicating it is no longer in use. 89 // change the type to something indicating it is no longer in use.
90 // 90 //
91 // Though persistent memory segments are transferrable between programs built 91 // Though persistent memory segments are transferrable between programs built
92 // for different natural word widths, they CANNOT be exchanged between CPUs 92 // for different natural word widths, they CANNOT be exchanged between CPUs
93 // of different endianess. Attempts to do so will simply see the existing data 93 // of different endianess. Attempts to do so will simply see the existing data
94 // as corrupt and refuse to access any of it. 94 // as corrupt and refuse to access any of it.
95 class BASE_EXPORT PersistentMemoryAllocator { 95 class BASE_EXPORT PersistentMemoryAllocator {
96 public: 96 public:
97 typedef uint32_t Reference; 97 typedef uint32_t Reference;
98 98
99 // These states are used to indicate the overall condition of the memory
100 // segment irrespective of what is stored within it. Because the data is
101 // often persistent and thus needs to be readable by different versions of
102 // a program, these values are fixed and can never change.
103 enum MemoryState : uint8_t {
104 // Persistent memory starts all zeros and so shows "uninitialized".
105 MEMORY_UNINITIALIZED = 0,
106
107 // The header has been written and the memory is ready for use.
108 MEMORY_INITIALIZED = 1,
109
110 // The data should be considered deleted. This would be set when the
111 // allocator is being cleaned up. If file-backed, the file is likely
112 // to be deleted but since deletion can fail for a variety of reasons,
113 // having this extra status means a future reader can realize what
114 // should have happened.
115 MEMORY_DELETED = 2,
116
117 // Outside code can create states starting with this number; these too
118 // must also never change between code versions.
119 MEMORY_USER_DEFINED = 100,
120 };
121
99 // Iterator for going through all iterable memory records in an allocator. 122 // Iterator for going through all iterable memory records in an allocator.
100 // Like the allocator itself, iterators are lock-free and thread-secure. 123 // Like the allocator itself, iterators are lock-free and thread-secure.
101 // That means that multiple threads can share an iterator and the same 124 // That means that multiple threads can share an iterator and the same
102 // reference will not be returned twice. 125 // reference will not be returned twice.
103 // 126 //
104 // The order of the items returned by an iterator matches the order in which 127 // The order of the items returned by an iterator matches the order in which
105 // MakeIterable() was called on them. Once an allocation is made iterable, 128 // MakeIterable() was called on them. Once an allocation is made iterable,
106 // it is always such so the only possible difference between successive 129 // it is always such so the only possible difference between successive
107 // iterations is for more to be added to the end. 130 // iterations is for more to be added to the end.
108 // 131 //
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after
270 static bool IsMemoryAcceptable(const void* data, size_t size, 293 static bool IsMemoryAcceptable(const void* data, size_t size,
271 size_t page_size, bool readonly); 294 size_t page_size, bool readonly);
272 295
273 // Get the internal identifier for this persistent memory segment. 296 // Get the internal identifier for this persistent memory segment.
274 uint64_t Id() const; 297 uint64_t Id() const;
275 298
276 // Get the internal name of this allocator (possibly an empty string). 299 // Get the internal name of this allocator (possibly an empty string).
277 const char* Name() const; 300 const char* Name() const;
278 301
279 // Is this segment open only for read? 302 // Is this segment open only for read?
280 bool IsReadonly() { return readonly_; } 303 bool IsReadonly() const { return readonly_; }
304
305 // Manage the saved state of the memory.
306 void SetMemoryState(uint8_t memory_state);
307 uint8_t GetMemoryState() const;
281 308
282 // Create internal histograms for tracking memory use and allocation sizes 309 // Create internal histograms for tracking memory use and allocation sizes
283 // for allocator of |name| (which can simply be the result of Name()). This 310 // for allocator of |name| (which can simply be the result of Name()). This
284 // is done seperately from construction for situations such as when the 311 // is done seperately from construction for situations such as when the
285 // histograms will be backed by memory provided by this very allocator. 312 // histograms will be backed by memory provided by this very allocator.
286 // 313 //
287 // IMPORTANT: Callers must update tools/metrics/histograms/histograms.xml 314 // IMPORTANT: Callers must update tools/metrics/histograms/histograms.xml
288 // with the following histograms: 315 // with the following histograms:
289 // UMA.PersistentAllocator.name.Errors 316 // UMA.PersistentAllocator.name.Errors
290 // UMA.PersistentAllocator.name.UsedPct 317 // UMA.PersistentAllocator.name.UsedPct
291 void CreateTrackingHistograms(base::StringPiece name); 318 void CreateTrackingHistograms(base::StringPiece name);
292 319
320 // Flushes the persistent memory to any backing store. This typically does
321 // nothing but is used by the FilePersistentMemoryAllocator to inform the
322 // OS that all the data should be sent to the disk immediately. This is
323 // useful in the rare case where something has just been stored that needs
324 // to survive a hard shutdown of the machine like from a power failure.
325 // The |sync| parameter indicates if this call should block until the flush
326 // is complete but is only advisory and may or may not have an effect
327 // depending on the capabilities of the OS. Synchronous flushes are allowed
328 // only from theads that are allowed to do I/O.
329 void Flush(bool sync);
330
293 // Direct access to underlying memory segment. If the segment is shared 331 // Direct access to underlying memory segment. If the segment is shared
294 // across threads or processes, reading data through these values does 332 // across threads or processes, reading data through these values does
295 // not guarantee consistency. Use with care. Do not write. 333 // not guarantee consistency. Use with care. Do not write.
296 const void* data() const { return const_cast<const char*>(mem_base_); } 334 const void* data() const { return const_cast<const char*>(mem_base_); }
297 size_t length() const { return mem_size_; } 335 size_t length() const { return mem_size_; }
298 size_t size() const { return mem_size_; } 336 size_t size() const { return mem_size_; }
299 size_t used() const; 337 size_t used() const;
300 338
301 // Get an object referenced by a |ref|. For safety reasons, the |type_id| 339 // Get an object referenced by a |ref|. For safety reasons, the |type_id|
302 // code and size-of(|T|) are compared to ensure the reference is valid 340 // code and size-of(|T|) are compared to ensure the reference is valid
(...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after
569 MemoryType type; 607 MemoryType type;
570 }; 608 };
571 609
572 // Constructs the allocator. Everything is the same as the public allocator 610 // Constructs the allocator. Everything is the same as the public allocator
573 // except |memory| which is a structure with additional information besides 611 // except |memory| which is a structure with additional information besides
574 // the base address. 612 // the base address.
575 PersistentMemoryAllocator(Memory memory, size_t size, size_t page_size, 613 PersistentMemoryAllocator(Memory memory, size_t size, size_t page_size,
576 uint64_t id, base::StringPiece name, 614 uint64_t id, base::StringPiece name,
577 bool readonly); 615 bool readonly);
578 616
617 // Implementation of Flush that accepts how much to flush.
618 virtual void FlushPartial(size_t length, bool sync);
619
579 volatile char* const mem_base_; // Memory base. (char so sizeof guaranteed 1) 620 volatile char* const mem_base_; // Memory base. (char so sizeof guaranteed 1)
580 const MemoryType mem_type_; // Type of memory allocation. 621 const MemoryType mem_type_; // Type of memory allocation.
581 const uint32_t mem_size_; // Size of entire memory segment. 622 const uint32_t mem_size_; // Size of entire memory segment.
582 const uint32_t mem_page_; // Page size allocations shouldn't cross. 623 const uint32_t mem_page_; // Page size allocations shouldn't cross.
583 624
584 private: 625 private:
585 struct SharedMetadata; 626 struct SharedMetadata;
586 struct BlockHeader; 627 struct BlockHeader;
587 static const uint32_t kAllocAlignment; 628 static const uint32_t kAllocAlignment;
588 static const Reference kReferenceQueue; 629 static const Reference kReferenceQueue;
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
704 base::StringPiece name, 745 base::StringPiece name,
705 bool read_only); 746 bool read_only);
706 ~FilePersistentMemoryAllocator() override; 747 ~FilePersistentMemoryAllocator() override;
707 748
708 // Ensure that the file isn't so invalid that it would crash when passing it 749 // Ensure that the file isn't so invalid that it would crash when passing it
709 // to the allocator. This doesn't guarantee the file is valid, just that it 750 // to the allocator. This doesn't guarantee the file is valid, just that it
710 // won't cause the program to abort. The existing IsCorrupt() call will handle 751 // won't cause the program to abort. The existing IsCorrupt() call will handle
711 // the rest. 752 // the rest.
712 static bool IsFileAcceptable(const MemoryMappedFile& file, bool read_only); 753 static bool IsFileAcceptable(const MemoryMappedFile& file, bool read_only);
713 754
755 protected:
756 // PersistentMemoryAllocator:
757 void FlushPartial(size_t length, bool sync) override;
758
714 private: 759 private:
715 std::unique_ptr<MemoryMappedFile> mapped_file_; 760 std::unique_ptr<MemoryMappedFile> mapped_file_;
716 761
717 DISALLOW_COPY_AND_ASSIGN(FilePersistentMemoryAllocator); 762 DISALLOW_COPY_AND_ASSIGN(FilePersistentMemoryAllocator);
718 }; 763 };
719 #endif // !defined(OS_NACL) 764 #endif // !defined(OS_NACL)
720 765
721 } // namespace base 766 } // namespace base
722 767
723 #endif // BASE_METRICS_PERSISTENT_MEMORY_ALLOCATOR_H_ 768 #endif // BASE_METRICS_PERSISTENT_MEMORY_ALLOCATOR_H_
OLDNEW
« no previous file with comments | « base/metrics/persistent_histogram_allocator.cc ('k') | base/metrics/persistent_memory_allocator.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698