• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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