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

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

Issue 2000523003: Fully support read/write memory-mapped files for persistent memory. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rebased Created 4 years, 7 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 #include "base/metrics/persistent_memory_allocator.h" 5 #include "base/metrics/persistent_memory_allocator.h"
6 6
7 #include <assert.h> 7 #include <assert.h>
8 #include <algorithm> 8 #include <algorithm>
9 9
10 #include "base/files/memory_mapped_file.h" 10 #include "base/files/memory_mapped_file.h"
11 #include "base/logging.h" 11 #include "base/logging.h"
12 #include "base/memory/shared_memory.h" 12 #include "base/memory/shared_memory.h"
13 #include "base/metrics/histogram_macros.h" 13 #include "base/metrics/histogram_macros.h"
14 14
15 namespace { 15 namespace {
16 16
17 // Required range of memory segment sizes. It has to fit in an unsigned 32-bit 17 // Limit of memory segment size. It has to fit in an unsigned 32-bit number
18 // number and should be a power of 2 in order to accomodate almost any page 18 // and should be a power of 2 in order to accomodate almost any page size.
19 // size.
20 const uint32_t kSegmentMinSize = 1 << 10; // 1 KiB
21 const uint32_t kSegmentMaxSize = 1 << 30; // 1 GiB 19 const uint32_t kSegmentMaxSize = 1 << 30; // 1 GiB
22 20
23 // A constant (random) value placed in the shared metadata to identify 21 // A constant (random) value placed in the shared metadata to identify
24 // an already initialized memory segment. 22 // an already initialized memory segment.
25 const uint32_t kGlobalCookie = 0x408305DC; 23 const uint32_t kGlobalCookie = 0x408305DC;
26 24
27 // The current version of the metadata. If updates are made that change 25 // The current version of the metadata. If updates are made that change
28 // the metadata, the version number can be queried to operate in a backward- 26 // the metadata, the version number can be queried to operate in a backward-
29 // compatible manner until the memory segment is completely re-initalized. 27 // compatible manner until the memory segment is completely re-initalized.
30 const uint32_t kGlobalVersion = 1; 28 const uint32_t kGlobalVersion = 1;
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after
232 } 230 }
233 231
234 232
235 // static 233 // static
236 bool PersistentMemoryAllocator::IsMemoryAcceptable(const void* base, 234 bool PersistentMemoryAllocator::IsMemoryAcceptable(const void* base,
237 size_t size, 235 size_t size,
238 size_t page_size, 236 size_t page_size,
239 bool readonly) { 237 bool readonly) {
240 return ((base && reinterpret_cast<uintptr_t>(base) % kAllocAlignment == 0) && 238 return ((base && reinterpret_cast<uintptr_t>(base) % kAllocAlignment == 0) &&
241 (size >= sizeof(SharedMetadata) && size <= kSegmentMaxSize) && 239 (size >= sizeof(SharedMetadata) && size <= kSegmentMaxSize) &&
242 (size >= kSegmentMinSize || readonly) &&
243 (size % kAllocAlignment == 0 || readonly) && 240 (size % kAllocAlignment == 0 || readonly) &&
244 (page_size == 0 || size % page_size == 0 || readonly)); 241 (page_size == 0 || size % page_size == 0 || readonly));
245 } 242 }
246 243
247 PersistentMemoryAllocator::PersistentMemoryAllocator( 244 PersistentMemoryAllocator::PersistentMemoryAllocator(
248 void* base, 245 void* base,
249 size_t size, 246 size_t size,
250 size_t page_size, 247 size_t page_size,
251 uint64_t id, 248 uint64_t id,
252 base::StringPiece name, 249 base::StringPiece name,
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
294 shared_meta()->id != 0 || 291 shared_meta()->id != 0 ||
295 shared_meta()->name != 0 || 292 shared_meta()->name != 0 ||
296 shared_meta()->tailptr != 0 || 293 shared_meta()->tailptr != 0 ||
297 shared_meta()->queue.cookie != 0 || 294 shared_meta()->queue.cookie != 0 ||
298 shared_meta()->queue.next.load(std::memory_order_relaxed) != 0 || 295 shared_meta()->queue.next.load(std::memory_order_relaxed) != 0 ||
299 first_block->size != 0 || 296 first_block->size != 0 ||
300 first_block->cookie != 0 || 297 first_block->cookie != 0 ||
301 first_block->type_id != 0 || 298 first_block->type_id != 0 ||
302 first_block->next != 0) { 299 first_block->next != 0) {
303 // ...or something malicious has been playing with the metadata. 300 // ...or something malicious has been playing with the metadata.
304 NOTREACHED();
305 SetCorrupt(); 301 SetCorrupt();
306 } 302 }
307 303
308 // This is still safe to do even if corruption has been detected. 304 // This is still safe to do even if corruption has been detected.
309 shared_meta()->cookie = kGlobalCookie; 305 shared_meta()->cookie = kGlobalCookie;
310 shared_meta()->size = mem_size_; 306 shared_meta()->size = mem_size_;
311 shared_meta()->page_size = mem_page_; 307 shared_meta()->page_size = mem_page_;
312 shared_meta()->version = kGlobalVersion; 308 shared_meta()->version = kGlobalVersion;
313 shared_meta()->id = id; 309 shared_meta()->id = id;
314 shared_meta()->freeptr.store(sizeof(SharedMetadata), 310 shared_meta()->freeptr.store(sizeof(SharedMetadata),
(...skipping 17 matching lines...) Expand all
332 if (shared_meta()->size == 0 || 328 if (shared_meta()->size == 0 ||
333 shared_meta()->version == 0 || 329 shared_meta()->version == 0 ||
334 shared_meta()->freeptr.load(std::memory_order_relaxed) == 0 || 330 shared_meta()->freeptr.load(std::memory_order_relaxed) == 0 ||
335 shared_meta()->tailptr == 0 || 331 shared_meta()->tailptr == 0 ||
336 shared_meta()->queue.cookie == 0 || 332 shared_meta()->queue.cookie == 0 ||
337 shared_meta()->queue.next.load(std::memory_order_relaxed) == 0) { 333 shared_meta()->queue.next.load(std::memory_order_relaxed) == 0) {
338 SetCorrupt(); 334 SetCorrupt();
339 } 335 }
340 if (!readonly) { 336 if (!readonly) {
341 // The allocator is attaching to a previously initialized segment of 337 // The allocator is attaching to a previously initialized segment of
342 // memory. Make sure the embedded data matches what has been passed. 338 // memory. If the initialization parameters differ, make the best of it
343 if (shared_meta()->size != mem_size_ || 339 // by reducing the local construction parameters to match those of
344 shared_meta()->page_size != mem_page_) { 340 // the actual memory area. This ensures that the local object never
345 NOTREACHED(); 341 // tries to write outside of the original bounds.
342 // Because the fields are const to ensure that no code other than the
343 // constructor makes changes to them as well as to give optimization
344 // hints to the compiler, it's necessary to const-cast them for changes
345 // here.
346 if (shared_meta()->size < mem_size_)
347 *const_cast<uint32_t*>(&mem_size_) = shared_meta()->size;
348 if (shared_meta()->page_size < mem_page_)
349 *const_cast<uint32_t*>(&mem_page_) = shared_meta()->page_size;
350
351 // Ensure that settings are still valid after the above adjustments.
352 if (!IsMemoryAcceptable(base, mem_size_, mem_page_, readonly))
346 SetCorrupt(); 353 SetCorrupt();
347 }
348 } 354 }
349 } 355 }
350 } 356 }
351 357
352 PersistentMemoryAllocator::~PersistentMemoryAllocator() { 358 PersistentMemoryAllocator::~PersistentMemoryAllocator() {
353 // It's strictly forbidden to do any memory access here in case there is 359 // It's strictly forbidden to do any memory access here in case there is
354 // some issue with the underlying memory segment. The "Local" allocator 360 // some issue with the underlying memory segment. The "Local" allocator
355 // makes use of this to allow deletion of the segment on the heap from 361 // makes use of this to allow deletion of the segment on the heap from
356 // within its destructor. 362 // within its destructor.
357 } 363 }
(...skipping 379 matching lines...) Expand 10 before | Expand all | Expand 10 after
737 id, 743 id,
738 name, 744 name,
739 read_only), 745 read_only),
740 shared_memory_(std::move(memory)) {} 746 shared_memory_(std::move(memory)) {}
741 747
742 SharedPersistentMemoryAllocator::~SharedPersistentMemoryAllocator() {} 748 SharedPersistentMemoryAllocator::~SharedPersistentMemoryAllocator() {}
743 749
744 // static 750 // static
745 bool SharedPersistentMemoryAllocator::IsSharedMemoryAcceptable( 751 bool SharedPersistentMemoryAllocator::IsSharedMemoryAcceptable(
746 const SharedMemory& memory) { 752 const SharedMemory& memory) {
747 return IsMemoryAcceptable(memory.memory(), memory.mapped_size(), 0, true); 753 return IsMemoryAcceptable(memory.memory(), memory.mapped_size(), 0, false);
748 } 754 }
749 755
750 756
751 //----- FilePersistentMemoryAllocator ------------------------------------------ 757 //----- FilePersistentMemoryAllocator ------------------------------------------
752 758
753 FilePersistentMemoryAllocator::FilePersistentMemoryAllocator( 759 FilePersistentMemoryAllocator::FilePersistentMemoryAllocator(
754 std::unique_ptr<MemoryMappedFile> file, 760 std::unique_ptr<MemoryMappedFile> file,
761 size_t max_size,
755 uint64_t id, 762 uint64_t id,
756 base::StringPiece name) 763 base::StringPiece name,
764 bool read_only)
757 : PersistentMemoryAllocator(const_cast<uint8_t*>(file->data()), 765 : PersistentMemoryAllocator(const_cast<uint8_t*>(file->data()),
758 file->length(), 766 max_size != 0 ? max_size : file->length(),
759 0, 767 0,
760 id, 768 id,
761 name, 769 name,
762 true), 770 read_only),
763 mapped_file_(std::move(file)) {} 771 mapped_file_(std::move(file)) {}
764 772
765 FilePersistentMemoryAllocator::~FilePersistentMemoryAllocator() {} 773 FilePersistentMemoryAllocator::~FilePersistentMemoryAllocator() {}
766 774
767 // static 775 // static
768 bool FilePersistentMemoryAllocator::IsFileAcceptable( 776 bool FilePersistentMemoryAllocator::IsFileAcceptable(
769 const MemoryMappedFile& file) { 777 const MemoryMappedFile& file,
770 return IsMemoryAcceptable(file.data(), file.length(), 0, true); 778 bool read_only) {
779 return IsMemoryAcceptable(file.data(), file.length(), 0, read_only);
771 } 780 }
772 781
773 } // namespace base 782 } // namespace base
OLDNEW
« no previous file with comments | « base/metrics/persistent_memory_allocator.h ('k') | base/metrics/persistent_memory_allocator_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698