OLD | NEW |
(Empty) | |
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 // Defines a shared memory heap. One of these is created by each process |
| 6 // using the blame service. This heap takes care of registering all of its slabs |
| 7 // with the central blamer service, allowing it to iterate over all blame |
| 8 // information across all processes. |
| 9 |
| 10 #ifndef SERVICES_BLAMER_SHARED_MEMORY_HEAP_H_ |
| 11 #define SERVICES_BLAMER_SHARED_MEMORY_HEAP_H_ |
| 12 |
| 13 #include "base/metrics/persistent_memory_allocator.h" |
| 14 #include "mojo/public/cpp/system/buffer.h" |
| 15 #include "services/blamer/heap_object_types.h" |
| 16 #include "services/blamer/public/interfaces/shared_memory_heap_registry.mojom.h" |
| 17 |
| 18 namespace blamer { |
| 19 |
| 20 // This class is thread safe. Most of the operations will actually be performed |
| 21 // without using any locks, however occasionally a lock will need to be |
| 22 // acquired in support of some operations. |
| 23 class SharedMemoryHeap { |
| 24 public: |
| 25 static constexpr size_t kSlabSizeBits = 22; |
| 26 static constexpr size_t kSlabSize = 1 << kSlabSizeBits; |
| 27 |
| 28 // Represents a pointer in a process-portable way. This is what would be sent |
| 29 // over IPC to communicate pointers between processes. Knowing the ID of the |
| 30 // process owning the memory and the |raw_value| of the PortablePointer is |
| 31 // sufficient to extract an actual pointer to the object in the process |
| 32 // hosting the service. |
| 33 struct PortablePointer { |
| 34 union { |
| 35 uint32_t raw_value; |
| 36 struct { |
| 37 unsigned int slab_id : 32 - kSlabSizeBits; |
| 38 unsigned int slab_offset : kSlabSizeBits; |
| 39 }; |
| 40 }; |
| 41 }; |
| 42 static_assert(sizeof(PortablePointer) == 4, |
| 43 "unexpected PortablePointer size"); |
| 44 |
| 45 // Encapsulates pointers as they are doled out by this shared memory |
| 46 // allocator. Dereferencing has a non-trivial cost so the result should |
| 47 // ideally be cached by clients that need to do this often. |
| 48 template<typename ObjectType> |
| 49 struct TypedLocalPointer { |
| 50 TypedLocalPointer(void* slab, PortablePointer pointer) |
| 51 : slab(slab), pointer(pointer) { |
| 52 } |
| 53 |
| 54 ObjectType* Get() const { |
| 55 auto* allocator = reinterpret_cast<base::PersistentMemoryAllocator*>( |
| 56 slab); |
| 57 base::PersistentMemoryAllocator::Reference ref = pointer.slab_offset; |
| 58 return allocator->GetAsObject<ObjectType>(ref); |
| 59 } |
| 60 ObjectType* operator->() const { return Get(); } |
| 61 ObjectType& operator*() const { return *Get(); } |
| 62 |
| 63 void* slab; |
| 64 PortablePointer pointer; |
| 65 }; |
| 66 |
| 67 SharedMemoryHeap(mojom::SharedMemoryHeapRegistryPtr heap_registry); |
| 68 ~SharedMemoryHeap(); |
| 69 |
| 70 // Allocates an object on the shared memory heap. Uses the actual object size. |
| 71 template<typename ObjectType> |
| 72 TypedLocalPointer<ObjectType> Allocate() { |
| 73 return MakePointer<ObjectType>(Allocate( |
| 74 ObjectType::kPersistentTypeId, sizeof(ObjectType))); |
| 75 } |
| 76 |
| 77 // Allocates an object on the shared memory heap. Uses the request object |
| 78 // size. |
| 79 template<typename ObjectType> |
| 80 TypedLocalPointer<ObjectType> Allocate(size_t object_size) { |
| 81 return MakePointer<ObjectType>(Allocate( |
| 82 ObjectType::kPersistentTypeId, object_size)); |
| 83 } |
| 84 |
| 85 // Frees an object. Once freed the object will no longer be visible to |
| 86 // remote processes. |
| 87 template<typename ObjectType> |
| 88 void Free(const TypedLocalPointer<ObjectType>& pointer) { |
| 89 Free(ObjectType::kPersistentTypeId, MakePointer(pointer)); |
| 90 } |
| 91 |
| 92 private: |
| 93 struct LocalPointer { |
| 94 void* slab; |
| 95 PortablePointer pointer; |
| 96 }; |
| 97 |
| 98 struct Slab { |
| 99 Slab(); |
| 100 Slab(Slab&& other); |
| 101 ~Slab(); |
| 102 |
| 103 mojo::ScopedSharedBufferHandle buffer; |
| 104 mojo::ScopedSharedBufferMapping mapping; |
| 105 std::unique_ptr<base::PersistentMemoryAllocator> allocator; |
| 106 |
| 107 private: |
| 108 DISALLOW_COPY_AND_ASSIGN(Slab); |
| 109 }; |
| 110 |
| 111 // Returns the current slab, creating one if none exists. |
| 112 base::PersistentMemoryAllocator* GetCurrentSlab(); |
| 113 |
| 114 // Creates a new slab, and updates |current_slab_|. Returns a pointer to the |
| 115 // newly created slab. |
| 116 base::PersistentMemoryAllocator* CreateNewSlab( |
| 117 base::PersistentMemoryAllocator* current_slab); |
| 118 |
| 119 // Creates a TypedLocalPointer from an untyped LocalPointer. |
| 120 template<typename ObjectType> |
| 121 TypedLocalPointer<ObjectType> MakePointer(const LocalPointer& pointer) { |
| 122 return TypedLocalPointer<ObjectType>(pointer.slab, pointer.pointer); |
| 123 } |
| 124 |
| 125 // Creates an untyped LocalPointer from a TypedLocalPointer. |
| 126 template<typename ObjectType> |
| 127 LocalPointer MakePointer(const TypedLocalPointer<ObjectType>& pointer) { |
| 128 LocalPointer lp = {}; |
| 129 lp.slab = pointer.slab; |
| 130 lp.slab = pointer.pointer = pointer.pointer; |
| 131 return lp; |
| 132 } |
| 133 |
| 134 // Allocates an object from the current slab. Creates a new slab if the |
| 135 // current slab fails to perform the allocation. |
| 136 LocalPointer Allocate(HeapObjectType object_type, size_t object_size); |
| 137 |
| 138 // Frees the provided object. |
| 139 void Free(HeapObjectType object_type, const LocalPointer& pointer); |
| 140 |
| 141 // Pointer to the heap registry to be notified of new slabs. |
| 142 mojom::SharedMemoryHeapRegistryPtr heap_registry_; |
| 143 |
| 144 // The current persistent memory allocator. This is updated in a lock-free |
| 145 // manner. The common use case is to grab the current allocator and make an |
| 146 // allocation, which is very fast. |
| 147 std::atomic<base::PersistentMemoryAllocator*> current_slab_; |
| 148 |
| 149 // |current_slab_| is used as a lock for modifying this safely. |
| 150 std::vector<Slab> slabs_; |
| 151 }; |
| 152 |
| 153 } // namespace blamer |
| 154 |
| 155 #endif // SERVICES_BLAMER_SHARED_MEMORY_HEAP_H_ |
OLD | NEW |