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