1 /* 2 * Copyright (C) 2017 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 SRC_TRACING_CORE_SERVICE_IMPL_H_ 18 #define SRC_TRACING_CORE_SERVICE_IMPL_H_ 19 20 #include <functional> 21 #include <map> 22 #include <memory> 23 #include <set> 24 25 #include "gtest/gtest_prod.h" 26 #include "perfetto/base/logging.h" 27 #include "perfetto/base/page_allocator.h" 28 #include "perfetto/base/time.h" 29 #include "perfetto/base/weak_ptr.h" 30 #include "perfetto/tracing/core/basic_types.h" 31 #include "perfetto/tracing/core/commit_data_request.h" 32 #include "perfetto/tracing/core/data_source_descriptor.h" 33 #include "perfetto/tracing/core/service.h" 34 #include "perfetto/tracing/core/shared_memory_abi.h" 35 #include "perfetto/tracing/core/trace_config.h" 36 #include "src/tracing/core/id_allocator.h" 37 38 namespace perfetto { 39 40 namespace base { 41 class TaskRunner; 42 } // namespace base 43 44 class Consumer; 45 class DataSourceConfig; 46 class Producer; 47 class SharedMemory; 48 class SharedMemoryArbiterImpl; 49 class TraceBuffer; 50 class TraceConfig; 51 class TracePacket; 52 53 // The tracing service business logic. 54 class ServiceImpl : public Service { 55 public: 56 static constexpr size_t kDefaultShmSize = 256 * 1024ul; 57 static constexpr size_t kMaxShmSize = 32 * 1024 * 1024ul; 58 59 // The implementation behind the service endpoint exposed to each producer. 60 class ProducerEndpointImpl : public Service::ProducerEndpoint { 61 public: 62 ProducerEndpointImpl(ProducerID, 63 uid_t uid, 64 ServiceImpl*, 65 base::TaskRunner*, 66 Producer*, 67 const std::string& producer_name); 68 ~ProducerEndpointImpl() override; 69 70 // Service::ProducerEndpoint implementation. 71 void RegisterDataSource(const DataSourceDescriptor&) override; 72 void UnregisterDataSource(const std::string& name) override; 73 void CommitData(const CommitDataRequest&, CommitDataCallback) override; 74 void SetSharedMemory(std::unique_ptr<SharedMemory>); 75 76 std::unique_ptr<TraceWriter> CreateTraceWriter(BufferID) override; 77 void OnTracingSetup(); 78 void Flush(FlushRequestID, const std::vector<DataSourceInstanceID>&); 79 void CreateDataSourceInstance(DataSourceInstanceID, 80 const DataSourceConfig&); 81 void NotifyFlushComplete(FlushRequestID) override; 82 void TearDownDataSource(DataSourceInstanceID); 83 SharedMemory* shared_memory() const override; 84 size_t shared_buffer_page_size_kb() const override; 85 86 private: 87 friend class ServiceImpl; 88 friend class ServiceImplTest; 89 ProducerEndpointImpl(const ProducerEndpointImpl&) = delete; 90 ProducerEndpointImpl& operator=(const ProducerEndpointImpl&) = delete; 91 SharedMemoryArbiterImpl* GetOrCreateShmemArbiter(); 92 93 ProducerID const id_; 94 const uid_t uid_; 95 ServiceImpl* const service_; 96 base::TaskRunner* const task_runner_; 97 Producer* producer_; 98 std::unique_ptr<SharedMemory> shared_memory_; 99 size_t shared_buffer_page_size_kb_ = 0; 100 SharedMemoryABI shmem_abi_; 101 size_t shmem_size_hint_bytes_ = 0; 102 const std::string name_; 103 104 // This is used only in in-process configurations (mostly tests). 105 std::unique_ptr<SharedMemoryArbiterImpl> inproc_shmem_arbiter_; 106 PERFETTO_THREAD_CHECKER(thread_checker_) 107 base::WeakPtrFactory<ProducerEndpointImpl> weak_ptr_factory_; // Keep last. 108 }; 109 110 // The implementation behind the service endpoint exposed to each consumer. 111 class ConsumerEndpointImpl : public Service::ConsumerEndpoint { 112 public: 113 ConsumerEndpointImpl(ServiceImpl*, base::TaskRunner*, Consumer*); 114 ~ConsumerEndpointImpl() override; 115 116 void NotifyOnTracingDisabled(); 117 base::WeakPtr<ConsumerEndpointImpl> GetWeakPtr(); 118 119 // Service::ConsumerEndpoint implementation. 120 void EnableTracing(const TraceConfig&, base::ScopedFile) override; 121 void DisableTracing() override; 122 void ReadBuffers() override; 123 void FreeBuffers() override; 124 void Flush(uint32_t timeout_ms, FlushCallback) override; 125 126 private: 127 friend class ServiceImpl; 128 ConsumerEndpointImpl(const ConsumerEndpointImpl&) = delete; 129 ConsumerEndpointImpl& operator=(const ConsumerEndpointImpl&) = delete; 130 131 base::TaskRunner* const task_runner_; 132 ServiceImpl* const service_; 133 Consumer* const consumer_; 134 TracingSessionID tracing_session_id_ = 0; 135 PERFETTO_THREAD_CHECKER(thread_checker_) 136 base::WeakPtrFactory<ConsumerEndpointImpl> weak_ptr_factory_; // Keep last. 137 }; 138 139 explicit ServiceImpl(std::unique_ptr<SharedMemory::Factory>, 140 base::TaskRunner*); 141 ~ServiceImpl() override; 142 143 // Called by ProducerEndpointImpl. 144 void DisconnectProducer(ProducerID); 145 void RegisterDataSource(ProducerID, const DataSourceDescriptor&); 146 void UnregisterDataSource(ProducerID, const std::string& name); 147 void CopyProducerPageIntoLogBuffer(ProducerID, 148 uid_t, 149 WriterID, 150 ChunkID, 151 BufferID, 152 uint16_t num_fragments, 153 uint8_t chunk_flags, 154 const uint8_t* src, 155 size_t size); 156 void ApplyChunkPatches(ProducerID, 157 const std::vector<CommitDataRequest::ChunkToPatch>&); 158 void NotifyFlushDoneForProducer(ProducerID, FlushRequestID); 159 160 // Called by ConsumerEndpointImpl. 161 void DisconnectConsumer(ConsumerEndpointImpl*); 162 bool EnableTracing(ConsumerEndpointImpl*, 163 const TraceConfig&, 164 base::ScopedFile); 165 void DisableTracing(TracingSessionID); 166 void Flush(TracingSessionID tsid, 167 uint32_t timeout_ms, 168 ConsumerEndpoint::FlushCallback); 169 void FlushAndDisableTracing(TracingSessionID); 170 void ReadBuffers(TracingSessionID, ConsumerEndpointImpl*); 171 void FreeBuffers(TracingSessionID); 172 173 // Service implementation. 174 std::unique_ptr<Service::ProducerEndpoint> ConnectProducer( 175 Producer*, 176 uid_t uid, 177 const std::string& producer_name, 178 size_t shared_memory_size_hint_bytes = 0) override; 179 180 std::unique_ptr<Service::ConsumerEndpoint> ConnectConsumer( 181 Consumer*) override; 182 183 // Exposed mainly for testing. 184 size_t num_producers() const { return producers_.size(); } 185 ProducerEndpointImpl* GetProducer(ProducerID) const; 186 187 private: 188 friend class ServiceImplTest; 189 190 struct RegisteredDataSource { 191 ProducerID producer_id; 192 DataSourceDescriptor descriptor; 193 }; 194 195 // Represents an active data source for a tracing session. 196 struct DataSourceInstance { 197 DataSourceInstanceID instance_id; 198 std::string data_source_name; 199 }; 200 201 struct PendingFlush { 202 std::set<ProducerID> producers; 203 ConsumerEndpoint::FlushCallback callback; 204 explicit PendingFlush(decltype(callback) cb) : callback(std::move(cb)) {} 205 }; 206 207 // Holds the state of a tracing session. A tracing session is uniquely bound 208 // a specific Consumer. Each Consumer can own one or more sessions. 209 struct TracingSession { 210 TracingSession(ConsumerEndpointImpl*, const TraceConfig&); 211 212 size_t num_buffers() const { return buffers_index.size(); } 213 214 uint32_t delay_to_next_write_period_ms() const { 215 PERFETTO_DCHECK(write_period_ms > 0); 216 return write_period_ms - 217 (base::GetWallTimeMs().count() % write_period_ms); 218 } 219 220 // The consumer that started the session. 221 ConsumerEndpointImpl* const consumer; 222 223 // The original trace config provided by the Consumer when calling 224 // EnableTracing(). 225 const TraceConfig config; 226 227 // List of data source instances that have been enabled on the various 228 // producers for this tracing session. 229 std::multimap<ProducerID, DataSourceInstance> data_source_instances; 230 231 // For each Flush(N) request, keeps track of the set of producers for which 232 // we are still awaiting a NotifyFlushComplete(N) ack. 233 std::map<FlushRequestID, PendingFlush> pending_flushes; 234 235 // Maps a per-trace-session buffer index into the corresponding global 236 // BufferID (shared namespace amongst all consumers). This vector has as 237 // many entries as |config.buffers_size()|. 238 std::vector<BufferID> buffers_index; 239 240 // When the last clock snapshot was emitted into the output stream. 241 base::TimeMillis last_clock_snapshot = {}; 242 243 // When the last TraceStats snapshot was emitted into the output stream. 244 base::TimeMillis last_stats_snapshot = {}; 245 246 // Whether we mirrored the trace config back to the trace output yet. 247 bool did_emit_config = false; 248 249 bool tracing_enabled = false; 250 251 // This is set when the Consumer calls sets |write_into_file| == true in the 252 // TraceConfig. In this case this represents the file we should stream the 253 // trace packets into, rather than returning it to the consumer via 254 // OnTraceData(). 255 base::ScopedFile write_into_file; 256 uint32_t write_period_ms = 0; 257 uint64_t max_file_size_bytes = 0; 258 uint64_t bytes_written_into_file = 0; 259 }; 260 261 ServiceImpl(const ServiceImpl&) = delete; 262 ServiceImpl& operator=(const ServiceImpl&) = delete; 263 264 void CreateDataSourceInstance(const TraceConfig::DataSource&, 265 const TraceConfig::ProducerConfig&, 266 const RegisteredDataSource&, 267 TracingSession*); 268 269 // Returns the next available ProducerID that is not in |producers_|. 270 ProducerID GetNextProducerID(); 271 272 // Returns a pointer to the |tracing_sessions_| entry or nullptr if the 273 // session doesn't exists. 274 TracingSession* GetTracingSession(TracingSessionID); 275 276 // Update the memory guard rail by using the latest information from the 277 // shared memory and trace buffers. 278 void UpdateMemoryGuardrail(); 279 280 void MaybeSnapshotClocks(TracingSession*, std::vector<TracePacket>*); 281 void MaybeEmitTraceConfig(TracingSession*, std::vector<TracePacket>*); 282 void MaybeSnapshotStats(TracingSession*, std::vector<TracePacket>*); 283 void OnFlushTimeout(TracingSessionID, FlushRequestID); 284 TraceBuffer* GetBufferByID(BufferID); 285 286 base::TaskRunner* const task_runner_; 287 std::unique_ptr<SharedMemory::Factory> shm_factory_; 288 ProducerID last_producer_id_ = 0; 289 DataSourceInstanceID last_data_source_instance_id_ = 0; 290 TracingSessionID last_tracing_session_id_ = 0; 291 FlushRequestID last_flush_request_id_ = 0; 292 uid_t uid_ = 0; 293 294 // Buffer IDs are global across all consumers (because a Producer can produce 295 // data for more than one trace session, hence more than one consumer). 296 IdAllocator<BufferID> buffer_ids_; 297 298 std::multimap<std::string /*name*/, RegisteredDataSource> data_sources_; 299 std::map<ProducerID, ProducerEndpointImpl*> producers_; 300 std::set<ConsumerEndpointImpl*> consumers_; 301 std::map<TracingSessionID, TracingSession> tracing_sessions_; 302 std::map<BufferID, std::unique_ptr<TraceBuffer>> buffers_; 303 304 bool lockdown_mode_ = false; 305 306 PERFETTO_THREAD_CHECKER(thread_checker_) 307 308 base::WeakPtrFactory<ServiceImpl> weak_ptr_factory_; // Keep at the end. 309 }; 310 311 } // namespace perfetto 312 313 #endif // SRC_TRACING_CORE_SERVICE_IMPL_H_ 314