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

Unified Diff: services/blamer/shared_memory_heap.h

Issue 2885363004: [Hacky prototype] Create a shared-memory high-performance reporting service.
Patch Set: Created 3 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 side-by-side diff with in-line comments
Download patch
Index: services/blamer/shared_memory_heap.h
diff --git a/services/blamer/shared_memory_heap.h b/services/blamer/shared_memory_heap.h
new file mode 100644
index 0000000000000000000000000000000000000000..e38142cf104c0b8fd29eaf301fea8146c02a340b
--- /dev/null
+++ b/services/blamer/shared_memory_heap.h
@@ -0,0 +1,155 @@
+// 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.
+
+// Defines a shared memory heap. One of these is created by each process
+// using the blame service. This heap takes care of registering all of its slabs
+// with the central blamer service, allowing it to iterate over all blame
+// information across all processes.
+
+#ifndef SERVICES_BLAMER_SHARED_MEMORY_HEAP_H_
+#define SERVICES_BLAMER_SHARED_MEMORY_HEAP_H_
+
+#include "base/metrics/persistent_memory_allocator.h"
+#include "mojo/public/cpp/system/buffer.h"
+#include "services/blamer/heap_object_types.h"
+#include "services/blamer/public/interfaces/shared_memory_heap_registry.mojom.h"
+
+namespace blamer {
+
+// This class is thread safe. Most of the operations will actually be performed
+// without using any locks, however occasionally a lock will need to be
+// acquired in support of some operations.
+class SharedMemoryHeap {
+ public:
+ static constexpr size_t kSlabSizeBits = 22;
+ static constexpr size_t kSlabSize = 1 << kSlabSizeBits;
+
+ // Represents a pointer in a process-portable way. This is what would be sent
+ // over IPC to communicate pointers between processes. Knowing the ID of the
+ // process owning the memory and the |raw_value| of the PortablePointer is
+ // sufficient to extract an actual pointer to the object in the process
+ // hosting the service.
+ struct PortablePointer {
+ union {
+ uint32_t raw_value;
+ struct {
+ unsigned int slab_id : 32 - kSlabSizeBits;
+ unsigned int slab_offset : kSlabSizeBits;
+ };
+ };
+ };
+ static_assert(sizeof(PortablePointer) == 4,
+ "unexpected PortablePointer size");
+
+ // Encapsulates pointers as they are doled out by this shared memory
+ // allocator. Dereferencing has a non-trivial cost so the result should
+ // ideally be cached by clients that need to do this often.
+ template<typename ObjectType>
+ struct TypedLocalPointer {
+ TypedLocalPointer(void* slab, PortablePointer pointer)
+ : slab(slab), pointer(pointer) {
+ }
+
+ ObjectType* Get() const {
+ auto* allocator = reinterpret_cast<base::PersistentMemoryAllocator*>(
+ slab);
+ base::PersistentMemoryAllocator::Reference ref = pointer.slab_offset;
+ return allocator->GetAsObject<ObjectType>(ref);
+ }
+ ObjectType* operator->() const { return Get(); }
+ ObjectType& operator*() const { return *Get(); }
+
+ void* slab;
+ PortablePointer pointer;
+ };
+
+ SharedMemoryHeap(mojom::SharedMemoryHeapRegistryPtr heap_registry);
+ ~SharedMemoryHeap();
+
+ // Allocates an object on the shared memory heap. Uses the actual object size.
+ template<typename ObjectType>
+ TypedLocalPointer<ObjectType> Allocate() {
+ return MakePointer<ObjectType>(Allocate(
+ ObjectType::kPersistentTypeId, sizeof(ObjectType)));
+ }
+
+ // Allocates an object on the shared memory heap. Uses the request object
+ // size.
+ template<typename ObjectType>
+ TypedLocalPointer<ObjectType> Allocate(size_t object_size) {
+ return MakePointer<ObjectType>(Allocate(
+ ObjectType::kPersistentTypeId, object_size));
+ }
+
+ // Frees an object. Once freed the object will no longer be visible to
+ // remote processes.
+ template<typename ObjectType>
+ void Free(const TypedLocalPointer<ObjectType>& pointer) {
+ Free(ObjectType::kPersistentTypeId, MakePointer(pointer));
+ }
+
+ private:
+ struct LocalPointer {
+ void* slab;
+ PortablePointer pointer;
+ };
+
+ struct Slab {
+ Slab();
+ Slab(Slab&& other);
+ ~Slab();
+
+ mojo::ScopedSharedBufferHandle buffer;
+ mojo::ScopedSharedBufferMapping mapping;
+ std::unique_ptr<base::PersistentMemoryAllocator> allocator;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(Slab);
+ };
+
+ // Returns the current slab, creating one if none exists.
+ base::PersistentMemoryAllocator* GetCurrentSlab();
+
+ // Creates a new slab, and updates |current_slab_|. Returns a pointer to the
+ // newly created slab.
+ base::PersistentMemoryAllocator* CreateNewSlab(
+ base::PersistentMemoryAllocator* current_slab);
+
+ // Creates a TypedLocalPointer from an untyped LocalPointer.
+ template<typename ObjectType>
+ TypedLocalPointer<ObjectType> MakePointer(const LocalPointer& pointer) {
+ return TypedLocalPointer<ObjectType>(pointer.slab, pointer.pointer);
+ }
+
+ // Creates an untyped LocalPointer from a TypedLocalPointer.
+ template<typename ObjectType>
+ LocalPointer MakePointer(const TypedLocalPointer<ObjectType>& pointer) {
+ LocalPointer lp = {};
+ lp.slab = pointer.slab;
+ lp.slab = pointer.pointer = pointer.pointer;
+ return lp;
+ }
+
+ // Allocates an object from the current slab. Creates a new slab if the
+ // current slab fails to perform the allocation.
+ LocalPointer Allocate(HeapObjectType object_type, size_t object_size);
+
+ // Frees the provided object.
+ void Free(HeapObjectType object_type, const LocalPointer& pointer);
+
+ // Pointer to the heap registry to be notified of new slabs.
+ mojom::SharedMemoryHeapRegistryPtr heap_registry_;
+
+ // The current persistent memory allocator. This is updated in a lock-free
+ // manner. The common use case is to grab the current allocator and make an
+ // allocation, which is very fast.
+ std::atomic<base::PersistentMemoryAllocator*> current_slab_;
+
+ // |current_slab_| is used as a lock for modifying this safely.
+ std::vector<Slab> slabs_;
+};
+
+} // namespace blamer
+
+#endif // SERVICES_BLAMER_SHARED_MEMORY_HEAP_H_

Powered by Google App Engine
This is Rietveld 408576698