blob: 0883264ab66e6f3e8f663ceefa627272e1116620 [file] [log] [blame]
Primiano Tucci4f9b6d72017-12-05 20:59:16 +00001/*
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>
Primiano Tucci42e2de12017-12-07 16:46:04 +000023#include <set>
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000024
Primiano Tuccibbaa58c2017-12-20 13:48:20 +010025#include "perfetto/base/page_allocator.h"
Primiano Tucci42e2de12017-12-07 16:46:04 +000026#include "perfetto/base/weak_ptr.h"
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000027#include "perfetto/tracing/core/basic_types.h"
Primiano Tucci53589332017-12-19 11:31:13 +010028#include "perfetto/tracing/core/data_source_descriptor.h"
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000029#include "perfetto/tracing/core/service.h"
Primiano Tucci53589332017-12-19 11:31:13 +010030#include "perfetto/tracing/core/shared_memory_abi.h"
Oystein Eftevaag1269b4a2018-01-10 16:29:38 -080031#include "perfetto/tracing/core/trace_config.h"
Primiano Tucci53589332017-12-19 11:31:13 +010032#include "src/tracing/core/id_allocator.h"
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000033
34namespace perfetto {
35
36namespace base {
37class TaskRunner;
38} // namespace base
39
Primiano Tucci42e2de12017-12-07 16:46:04 +000040class Consumer;
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000041class DataSourceConfig;
42class Producer;
43class SharedMemory;
Primiano Tucci42e2de12017-12-07 16:46:04 +000044class TraceConfig;
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000045
46// The tracing service business logic.
47class ServiceImpl : public Service {
48 public:
Primiano Tucci20d441d2018-01-16 09:25:51 +000049 using TracingSessionID = uint64_t;
50
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000051 // The implementation behind the service endpoint exposed to each producer.
52 class ProducerEndpointImpl : public Service::ProducerEndpoint {
53 public:
54 ProducerEndpointImpl(ProducerID,
55 ServiceImpl*,
56 base::TaskRunner*,
57 Producer*,
58 std::unique_ptr<SharedMemory>);
59 ~ProducerEndpointImpl() override;
60
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000061 // Service::ProducerEndpoint implementation.
62 void RegisterDataSource(const DataSourceDescriptor&,
63 RegisterDataSourceCallback) override;
64 void UnregisterDataSource(DataSourceID) override;
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000065 void NotifySharedMemoryUpdate(
66 const std::vector<uint32_t>& changed_pages) override;
Primiano Tucciaf429f92017-12-19 01:51:50 +010067 std::unique_ptr<TraceWriter> CreateTraceWriter(BufferID) override;
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000068 SharedMemory* shared_memory() const override;
69
70 private:
Primiano Tucci20d441d2018-01-16 09:25:51 +000071 friend class ServiceImpl;
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000072 ProducerEndpointImpl(const ProducerEndpointImpl&) = delete;
73 ProducerEndpointImpl& operator=(const ProducerEndpointImpl&) = delete;
74
75 ProducerID const id_;
76 ServiceImpl* const service_;
77 base::TaskRunner* const task_runner_;
78 Producer* producer_;
79 std::unique_ptr<SharedMemory> shared_memory_;
Primiano Tucci53589332017-12-19 11:31:13 +010080 SharedMemoryABI shmem_abi_;
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000081 DataSourceID last_data_source_id_ = 0;
Florian Mayercd08ec62018-01-31 17:49:25 +000082 PERFETTO_THREAD_CHECKER(thread_checker_)
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000083 };
84
Primiano Tucci42e2de12017-12-07 16:46:04 +000085 // The implementation behind the service endpoint exposed to each consumer.
86 class ConsumerEndpointImpl : public Service::ConsumerEndpoint {
87 public:
88 ConsumerEndpointImpl(ServiceImpl*, base::TaskRunner*, Consumer*);
89 ~ConsumerEndpointImpl() override;
90
Primiano Tucci42e2de12017-12-07 16:46:04 +000091 base::WeakPtr<ConsumerEndpointImpl> GetWeakPtr();
92
93 // Service::ConsumerEndpoint implementation.
94 void EnableTracing(const TraceConfig&) override;
95 void DisableTracing() override;
96 void ReadBuffers() override;
97 void FreeBuffers() override;
98
99 private:
Primiano Tucci20d441d2018-01-16 09:25:51 +0000100 friend class ServiceImpl;
Primiano Tucci42e2de12017-12-07 16:46:04 +0000101 ConsumerEndpointImpl(const ConsumerEndpointImpl&) = delete;
102 ConsumerEndpointImpl& operator=(const ConsumerEndpointImpl&) = delete;
103
104 ServiceImpl* const service_;
105 Consumer* const consumer_;
Primiano Tucci20d441d2018-01-16 09:25:51 +0000106 TracingSessionID tracing_session_id_ = 0;
Florian Mayercd08ec62018-01-31 17:49:25 +0000107
108 PERFETTO_THREAD_CHECKER(thread_checker_)
109
Primiano Tucci42e2de12017-12-07 16:46:04 +0000110 base::WeakPtrFactory<ConsumerEndpointImpl> weak_ptr_factory_;
111 };
112
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000113 explicit ServiceImpl(std::unique_ptr<SharedMemory::Factory>,
114 base::TaskRunner*);
115 ~ServiceImpl() override;
116
Primiano Tucci42e2de12017-12-07 16:46:04 +0000117 // Called by ProducerEndpointImpl.
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000118 void DisconnectProducer(ProducerID);
Primiano Tucci53589332017-12-19 11:31:13 +0100119 void RegisterDataSource(ProducerID,
120 DataSourceID,
121 const DataSourceDescriptor&);
122 void CopyProducerPageIntoLogBuffer(ProducerID,
123 BufferID,
124 const uint8_t*,
125 size_t);
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000126
Primiano Tucci42e2de12017-12-07 16:46:04 +0000127 // Called by ConsumerEndpointImpl.
128 void DisconnectConsumer(ConsumerEndpointImpl*);
129 void EnableTracing(ConsumerEndpointImpl*, const TraceConfig&);
Primiano Tucci20d441d2018-01-16 09:25:51 +0000130 void DisableTracing(TracingSessionID);
131 void ReadBuffers(TracingSessionID, ConsumerEndpointImpl*);
132 void FreeBuffers(TracingSessionID);
Primiano Tucci42e2de12017-12-07 16:46:04 +0000133
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000134 // Service implementation.
135 std::unique_ptr<Service::ProducerEndpoint> ConnectProducer(
136 Producer*,
137 size_t shared_buffer_size_hint_bytes = 0) override;
Primiano Tucci42e2de12017-12-07 16:46:04 +0000138
139 std::unique_ptr<Service::ConsumerEndpoint> ConnectConsumer(
140 Consumer*) override;
141
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000142 // Exposed mainly for testing.
143 size_t num_producers() const { return producers_.size(); }
144 ProducerEndpointImpl* GetProducer(ProducerID) const;
145
146 private:
Primiano Tucci53589332017-12-19 11:31:13 +0100147 struct RegisteredDataSource {
148 ProducerID producer_id;
149 DataSourceID data_source_id;
150 DataSourceDescriptor descriptor;
151 };
152
153 struct TraceBuffer {
Primiano Tucci20d441d2018-01-16 09:25:51 +0000154 TraceBuffer();
Primiano Tucci53589332017-12-19 11:31:13 +0100155 ~TraceBuffer();
156 TraceBuffer(TraceBuffer&&) noexcept;
157 TraceBuffer& operator=(TraceBuffer&&);
158
Primiano Tucci20d441d2018-01-16 09:25:51 +0000159 bool Create(size_t size);
Primiano Tucci53589332017-12-19 11:31:13 +0100160 size_t num_pages() const { return size / kBufferPageSize; }
161
162 uint8_t* get_page(size_t page) {
163 PERFETTO_DCHECK(page < num_pages());
164 return reinterpret_cast<uint8_t*>(data.get()) + page * kBufferPageSize;
165 }
166
167 uint8_t* get_next_page() {
168 size_t cur = cur_page;
169 cur_page = cur_page == num_pages() - 1 ? 0 : cur_page + 1;
170 return get_page(cur);
171 }
172
Primiano Tucci20d441d2018-01-16 09:25:51 +0000173 size_t size = 0;
Primiano Tucci53589332017-12-19 11:31:13 +0100174 size_t cur_page = 0; // Write pointer in the ring buffer.
Primiano Tuccibbaa58c2017-12-20 13:48:20 +0100175 base::PageAllocator::UniquePtr data;
Primiano Tucci53589332017-12-19 11:31:13 +0100176
177 // TODO(primiano): The TraceBuffer is not shared and there is no reason to
178 // use the SharedMemoryABI. This is just a a temporary workaround to reuse
179 // the convenience of SharedMemoryABI for bookkeeping of the buffer when
180 // implementing ReadBuffers().
181 std::unique_ptr<SharedMemoryABI> abi;
182 };
183
184 // Holds the state of a tracing session. A tracing session is uniquely bound
185 // a specific Consumer. Each Consumer can own one or more sessions.
186 struct TracingSession {
Primiano Tucci20d441d2018-01-16 09:25:51 +0000187 explicit TracingSession(const TraceConfig&);
188
189 size_t num_buffers() const { return buffers_index.size(); }
190
191 // The original trace config provided by the Consumer when calling
192 // EnableTracing().
193 const TraceConfig config;
Oystein Eftevaag1269b4a2018-01-10 16:29:38 -0800194
Primiano Tucci53589332017-12-19 11:31:13 +0100195 // List of data source instances that have been enabled on the various
196 // producers for this tracing session.
197 std::multimap<ProducerID, DataSourceInstanceID> data_source_instances;
198
Primiano Tucci20d441d2018-01-16 09:25:51 +0000199 // Maps a per-trace-session buffer index into the corresponding global
200 // BufferID (shared namespace amongst all consumers). This vector has as
201 // many entries as |config.buffers_size()|.
202 std::vector<BufferID> buffers_index;
Primiano Tucci53589332017-12-19 11:31:13 +0100203 };
204
Primiano Tucci20d441d2018-01-16 09:25:51 +0000205 ServiceImpl(const ServiceImpl&) = delete;
206 ServiceImpl& operator=(const ServiceImpl&) = delete;
207
Oystein Eftevaag1269b4a2018-01-10 16:29:38 -0800208 void CreateDataSourceInstanceForProducer(
209 const TraceConfig::DataSource& cfg_data_source,
210 ProducerEndpointImpl* producer,
211 TracingSession* tracing_session);
212
Primiano Tucci20d441d2018-01-16 09:25:51 +0000213 // Returns a pointer to the |tracing_sessions_| entry or nullptr if the
214 // session doesn't exists.
215 TracingSession* GetTracingSession(TracingSessionID);
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000216
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000217 base::TaskRunner* const task_runner_;
Primiano Tucci53589332017-12-19 11:31:13 +0100218 std::unique_ptr<SharedMemory::Factory> shm_factory_;
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000219 ProducerID last_producer_id_ = 0;
Primiano Tucci53589332017-12-19 11:31:13 +0100220 DataSourceInstanceID last_data_source_instance_id_ = 0;
Primiano Tucci20d441d2018-01-16 09:25:51 +0000221 TracingSessionID last_tracing_session_id_ = 0;
Primiano Tucci53589332017-12-19 11:31:13 +0100222
223 // Buffer IDs are global across all consumers (because a Producer can produce
224 // data for more than one trace session, hence more than one consumer).
Primiano Tucci20d441d2018-01-16 09:25:51 +0000225 IdAllocator<BufferID> buffer_ids_;
Primiano Tucci53589332017-12-19 11:31:13 +0100226
227 std::multimap<std::string /*name*/, RegisteredDataSource> data_sources_;
228
229 // TODO(primiano): There doesn't seem to be any good reason why |producers_|
230 // is a map indexed by ID and not just a set<ProducerEndpointImpl*>.
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000231 std::map<ProducerID, ProducerEndpointImpl*> producers_;
Primiano Tucci53589332017-12-19 11:31:13 +0100232
Primiano Tucci42e2de12017-12-07 16:46:04 +0000233 std::set<ConsumerEndpointImpl*> consumers_;
Primiano Tucci20d441d2018-01-16 09:25:51 +0000234 std::map<TracingSessionID, TracingSession> tracing_sessions_;
235 std::map<BufferID, TraceBuffer> buffers_;
236
Florian Mayercd08ec62018-01-31 17:49:25 +0000237 PERFETTO_THREAD_CHECKER(thread_checker_)
238
Primiano Tucci20d441d2018-01-16 09:25:51 +0000239 base::WeakPtrFactory<ServiceImpl> weak_ptr_factory_; // Keep at the end.
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000240};
241
242} // namespace perfetto
243
244#endif // SRC_TRACING_CORE_SERVICE_IMPL_H_