Index: services/blamer/shared_memory_heap_registry.cc |
diff --git a/services/blamer/shared_memory_heap_registry.cc b/services/blamer/shared_memory_heap_registry.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..db03c2d63b782fd099db965e478b719c26e1386b |
--- /dev/null |
+++ b/services/blamer/shared_memory_heap_registry.cc |
@@ -0,0 +1,93 @@ |
+// Copyright 2017 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "services/blamer/shared_memory_heap_registry.h" |
+ |
+#include <map> |
+ |
+#include "base/process/process_handle.h" |
+#include "base/lazy_instance.h" |
+#include "base/metrics/persistent_memory_allocator.h" |
+#include "services/blamer/public/interfaces/service_constants.mojom.h" |
+#include "services/service_manager/public/cpp/connection.h" |
+ |
+namespace blamer { |
+ |
+namespace { |
+ |
+// The identity of a heap slab, from the point of view of the blamer service. |
+// This is the tuple of (process_id, slab_id). |
+using HeapSlabId = std::pair<base::ProcessId, uint32_t>; |
+ |
+// A heap slab. This holds the mojom shared memory handle, a mapping to the |
+// underlying data, and a PersistentMemoryAllocator on top of that for safe |
+// iteration of the underlying data. |
+class HeapSlab { |
+ public: |
+ HeapSlab(mojom::SharedMemoryHeapSlabPtr slab) |
+ : buffer_(std::move(slab->buffer)), |
+ mapping_(buffer_->Map(slab->size)), |
+ size_(slab->size), |
+ allocator_(new base::PersistentMemoryAllocator( |
+ mapping_.get(), size_, mojom::kPageSize, slab->id, nullptr, true)) { |
+ } |
+ |
+ ~HeapSlab() {} |
+ |
+ private: |
+ // A handle to the shared memory buffer. This is owned by the remote |
+ // process. |
+ mojo::ScopedSharedBufferHandle buffer_; |
+ |
+ // A handle to the shared buffer mapping. This is permanently mapped. |
+ // TODO(chrisha): Revisit this! They could be mapped in on demand! |
+ mojo::ScopedSharedBufferMapping mapping_; |
+ |
+ // The size of the slab. |
+ uint32_t size_; |
+ |
+ // A persistent memory allocator over this slab, allowing iteration and |
+ // inspection. |
+ std::unique_ptr<base::PersistentMemoryAllocator> allocator_; |
+}; |
+ |
+// A map of heap slabs across all processes, indexed by their unique IDs. |
+using HeapSlabMap = std::map<HeapSlabId, std::unique_ptr<HeapSlab>>; |
+ |
+base::LazyInstance<HeapSlabMap>::Leaky g_heap_slab_map_ = |
+ LAZY_INSTANCE_INITIALIZER; |
+ |
+} // namespace |
+ |
+SharedMemoryHeapRegistry::SharedMemoryHeapRegistry( |
+ service_manager::ServiceContextRefFactory* service_ref_factory) |
+ : service_ref_factory_(service_ref_factory) { |
+ service_ref_ = service_ref_factory_->CreateRef(); |
+} |
+ |
+SharedMemoryHeapRegistry::~SharedMemoryHeapRegistry() = default; |
+ |
+// static |
+void SharedMemoryHeapRegistry::Create( |
+ service_manager::ServiceContextRefFactory* service_ref_factory, |
+ blamer::mojom::SharedMemoryHeapRegistryRequest request) { |
+ mojo::MakeStrongBinding( |
+ base::MakeUnique<SharedMemoryHeapRegistry>(service_ref_factory), |
+ std::move(request)); |
+} |
+ |
+void SharedMemoryHeapRegistry::RegisterSlab( |
+ mojom::SharedMemoryHeapSlabPtr slab) { |
+ // TODO(chrisha): Get the remote process ID from the channel? |
+ base::ProcessId process_id = 0; |
+ |
+ // Add the slab to the map. |
+ // TODO(chrisha): A way to remove mappings for processes that die! |
+ g_heap_slab_map_.Get().insert(std::make_pair( |
+ HeapSlabId(process_id, slab->id), |
+ base::MakeUnique<HeapSlab>(std::move(slab)))); |
+} |
+ |
+} // namespace blamer |
+ |