1 /* 2 * Copyright (C) 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef INCLUDE_PERFETTO_TRACING_CORE_STARTUP_TRACE_WRITER_REGISTRY_H_ 18 #define INCLUDE_PERFETTO_TRACING_CORE_STARTUP_TRACE_WRITER_REGISTRY_H_ 19 20 #include <functional> 21 #include <memory> 22 #include <mutex> 23 #include <set> 24 #include <vector> 25 26 #include "perfetto/base/export.h" 27 #include "perfetto/base/weak_ptr.h" 28 #include "perfetto/tracing/core/basic_types.h" 29 30 namespace perfetto { 31 32 class SharedMemoryArbiterImpl; 33 class StartupTraceWriter; 34 class StartupTraceWriterRegistry; 35 36 namespace base { 37 class TaskRunner; 38 } // namespace base 39 40 // Notifies the registry about the destruction of a StartupTraceWriter, provided 41 // the registry itself wasn't deleted yet. The indirection via the handle is 42 // necessary to avoid potential deadlocks caused by lock order inversion. These 43 // issues are avoided by locking on the handle's common lock in the destructors 44 // of the registry and writer. 45 class StartupTraceWriterRegistryHandle { 46 public: 47 explicit StartupTraceWriterRegistryHandle(StartupTraceWriterRegistry*); 48 49 // Called by StartupTraceWriter destructor. 50 void OnWriterDestroyed(StartupTraceWriter*); 51 52 // Called by StartupTraceWriterRegistry destructor. 53 void OnRegistryDestroyed(); 54 55 private: 56 StartupTraceWriterRegistryHandle(const StartupTraceWriterRegistryHandle&) = 57 delete; 58 StartupTraceWriterRegistryHandle& operator=( 59 const StartupTraceWriterRegistryHandle&) = delete; 60 61 std::mutex lock_; 62 StartupTraceWriterRegistry* registry_; 63 }; 64 65 // Embedders can use this registry to create unbound StartupTraceWriters during 66 // startup, and later bind them all safely to an arbiter and target buffer. 67 class PERFETTO_EXPORT StartupTraceWriterRegistry { 68 public: 69 StartupTraceWriterRegistry(); 70 ~StartupTraceWriterRegistry(); 71 72 // Returns a new unbound StartupTraceWriter. Should only be called while 73 // unbound. Usually called on a writer thread. 74 std::unique_ptr<StartupTraceWriter> CreateUnboundTraceWriter(); 75 76 // Return an unbound StartupTraceWriter back to the registry before it could 77 // be bound (usually called when the writer's thread is destroyed). The 78 // registry will keep this writer alive until the registry is bound to an 79 // arbiter (or destroyed itself). This way, its buffered data is retained. 80 // Should only be called while unbound. All packets written to the passed 81 // writer should have been completed and it should no longer be used to write 82 // data after calling this method. 83 void ReturnUnboundTraceWriter(std::unique_ptr<StartupTraceWriter>); 84 85 // Binds all StartupTraceWriters created by this registry to the given arbiter 86 // and target buffer. Should only be called once and on the passed 87 // TaskRunner's sequence. See 88 // SharedMemoryArbiter::BindStartupTraceWriterRegistry() for details. 89 // 90 // Note that the writers may not be bound synchronously if they are 91 // concurrently being written to. The registry will retry on the passed 92 // TaskRunner until all writers were bound successfully. 93 // 94 // Calls |on_bound_callback| asynchronously on the passed TaskRunner once all 95 // writers were bound. 96 void BindToArbiter( 97 SharedMemoryArbiterImpl*, 98 BufferID target_buffer, 99 base::TaskRunner*, 100 std::function<void(StartupTraceWriterRegistry*)> on_bound_callback); 101 102 private: 103 friend class StartupTraceWriterRegistryHandle; 104 friend class StartupTraceWriterTest; 105 106 StartupTraceWriterRegistry(const StartupTraceWriterRegistry&) = delete; 107 StartupTraceWriterRegistry& operator=(const StartupTraceWriterRegistry&) = 108 delete; 109 110 // Called by StartupTraceWriterRegistryHandle. 111 void OnStartupTraceWriterDestroyed(StartupTraceWriter*); 112 113 // Try to bind the remaining unbound writers and post a continuation to 114 // |task_runner_| if any writers could not be bound. 115 void TryBindWriters(); 116 117 // Notifies the arbiter when we have bound all writers. May delete |this|. 118 void OnUnboundWritersRemovedLocked(); 119 120 std::shared_ptr<StartupTraceWriterRegistryHandle> handle_; 121 122 // Begin lock-protected members. 123 std::mutex lock_; 124 125 // Unbound writers that we handed out to writer threads. These writers may be 126 // concurrently written to by the writer threads. 127 std::set<StartupTraceWriter*> unbound_writers_; 128 129 // Unbound writers that writer threads returned to the registry by calling 130 // ReturnUnboundTraceWriter(). Writers are removed from |unbound_writers_| 131 // when they are added to |unbound_owned_writers_|. No new data can be written 132 // to these writers. 133 std::vector<std::unique_ptr<StartupTraceWriter>> unbound_owned_writers_; 134 135 SharedMemoryArbiterImpl* arbiter_ = nullptr; // |nullptr| while unbound. 136 BufferID target_buffer_ = 0; 137 base::TaskRunner* task_runner_; 138 std::function<void(StartupTraceWriterRegistry*)> on_bound_callback_ = nullptr; 139 140 // Keep at the end. Initialized during |BindToArbiter()|, like |task_runner_|. 141 // Weak pointers are only valid on |task_runner_|'s thread/sequence. 142 std::unique_ptr<base::WeakPtrFactory<StartupTraceWriterRegistry>> 143 weak_ptr_factory_; 144 // End lock-protected members. 145 }; 146 147 } // namespace perfetto 148 149 #endif // INCLUDE_PERFETTO_TRACING_CORE_STARTUP_TRACE_WRITER_REGISTRY_H_ 150