blob: 2717d2d0dabbf795691c2ad4d9de3ffbc2992e08 [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
Sami Kyostila32e0b542018-02-14 08:55:43 +000025#include "gtest/gtest_prod.h"
Primiano Tuccibbaa58c2017-12-20 13:48:20 +010026#include "perfetto/base/page_allocator.h"
Primiano Tucci42e2de12017-12-07 16:46:04 +000027#include "perfetto/base/weak_ptr.h"
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000028#include "perfetto/tracing/core/basic_types.h"
Primiano Tucci53589332017-12-19 11:31:13 +010029#include "perfetto/tracing/core/data_source_descriptor.h"
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000030#include "perfetto/tracing/core/service.h"
Primiano Tucci53589332017-12-19 11:31:13 +010031#include "perfetto/tracing/core/shared_memory_abi.h"
Oystein Eftevaag1269b4a2018-01-10 16:29:38 -080032#include "perfetto/tracing/core/trace_config.h"
Primiano Tucci53589332017-12-19 11:31:13 +010033#include "src/tracing/core/id_allocator.h"
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000034
35namespace perfetto {
36
37namespace base {
38class TaskRunner;
39} // namespace base
40
Primiano Tucci42e2de12017-12-07 16:46:04 +000041class Consumer;
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000042class DataSourceConfig;
43class Producer;
44class SharedMemory;
Primiano Tucci42e2de12017-12-07 16:46:04 +000045class TraceConfig;
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000046
47// The tracing service business logic.
48class ServiceImpl : public Service {
49 public:
Primiano Tucci20d441d2018-01-16 09:25:51 +000050 using TracingSessionID = uint64_t;
51
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000052 // The implementation behind the service endpoint exposed to each producer.
53 class ProducerEndpointImpl : public Service::ProducerEndpoint {
54 public:
55 ProducerEndpointImpl(ProducerID,
Sami Kyostila32e0b542018-02-14 08:55:43 +000056 uid_t uid,
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000057 ServiceImpl*,
58 base::TaskRunner*,
59 Producer*,
60 std::unique_ptr<SharedMemory>);
61 ~ProducerEndpointImpl() override;
62
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000063 // Service::ProducerEndpoint implementation.
64 void RegisterDataSource(const DataSourceDescriptor&,
65 RegisterDataSourceCallback) override;
66 void UnregisterDataSource(DataSourceID) override;
Primiano Tucci79f3f912018-03-02 12:00:31 +000067 void CommitData(const CommitDataRequest&) override;
Primiano Tucciaf429f92017-12-19 01:51:50 +010068 std::unique_ptr<TraceWriter> CreateTraceWriter(BufferID) override;
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000069 SharedMemory* shared_memory() const override;
70
71 private:
Primiano Tucci20d441d2018-01-16 09:25:51 +000072 friend class ServiceImpl;
Sami Kyostila32e0b542018-02-14 08:55:43 +000073 FRIEND_TEST(ServiceImplTest, RegisterAndUnregister);
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000074 ProducerEndpointImpl(const ProducerEndpointImpl&) = delete;
75 ProducerEndpointImpl& operator=(const ProducerEndpointImpl&) = delete;
76
77 ProducerID const id_;
Sami Kyostila32e0b542018-02-14 08:55:43 +000078 const uid_t uid_;
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000079 ServiceImpl* const service_;
80 base::TaskRunner* const task_runner_;
81 Producer* producer_;
82 std::unique_ptr<SharedMemory> shared_memory_;
Primiano Tucci53589332017-12-19 11:31:13 +010083 SharedMemoryABI shmem_abi_;
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000084 DataSourceID last_data_source_id_ = 0;
Florian Mayercd08ec62018-01-31 17:49:25 +000085 PERFETTO_THREAD_CHECKER(thread_checker_)
Primiano Tucci4f9b6d72017-12-05 20:59:16 +000086 };
87
Primiano Tucci42e2de12017-12-07 16:46:04 +000088 // The implementation behind the service endpoint exposed to each consumer.
89 class ConsumerEndpointImpl : public Service::ConsumerEndpoint {
90 public:
91 ConsumerEndpointImpl(ServiceImpl*, base::TaskRunner*, Consumer*);
92 ~ConsumerEndpointImpl() override;
93
Primiano Tucci42e2de12017-12-07 16:46:04 +000094 base::WeakPtr<ConsumerEndpointImpl> GetWeakPtr();
95
96 // Service::ConsumerEndpoint implementation.
97 void EnableTracing(const TraceConfig&) override;
98 void DisableTracing() override;
99 void ReadBuffers() override;
100 void FreeBuffers() override;
101
102 private:
Primiano Tucci20d441d2018-01-16 09:25:51 +0000103 friend class ServiceImpl;
Primiano Tucci42e2de12017-12-07 16:46:04 +0000104 ConsumerEndpointImpl(const ConsumerEndpointImpl&) = delete;
105 ConsumerEndpointImpl& operator=(const ConsumerEndpointImpl&) = delete;
106
107 ServiceImpl* const service_;
108 Consumer* const consumer_;
Primiano Tucci20d441d2018-01-16 09:25:51 +0000109 TracingSessionID tracing_session_id_ = 0;
Florian Mayercd08ec62018-01-31 17:49:25 +0000110
111 PERFETTO_THREAD_CHECKER(thread_checker_)
112
Primiano Tucci42e2de12017-12-07 16:46:04 +0000113 base::WeakPtrFactory<ConsumerEndpointImpl> weak_ptr_factory_;
114 };
115
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000116 explicit ServiceImpl(std::unique_ptr<SharedMemory::Factory>,
117 base::TaskRunner*);
118 ~ServiceImpl() override;
119
Primiano Tucci42e2de12017-12-07 16:46:04 +0000120 // Called by ProducerEndpointImpl.
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000121 void DisconnectProducer(ProducerID);
Primiano Tucci53589332017-12-19 11:31:13 +0100122 void RegisterDataSource(ProducerID,
123 DataSourceID,
124 const DataSourceDescriptor&);
Sami Kyostila06487a22018-02-27 13:48:38 +0000125 void UnregisterDataSource(ProducerID, DataSourceID);
Primiano Tucci53589332017-12-19 11:31:13 +0100126 void CopyProducerPageIntoLogBuffer(ProducerID,
127 BufferID,
128 const uint8_t*,
129 size_t);
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000130
Primiano Tucci42e2de12017-12-07 16:46:04 +0000131 // Called by ConsumerEndpointImpl.
132 void DisconnectConsumer(ConsumerEndpointImpl*);
133 void EnableTracing(ConsumerEndpointImpl*, const TraceConfig&);
Primiano Tucci20d441d2018-01-16 09:25:51 +0000134 void DisableTracing(TracingSessionID);
135 void ReadBuffers(TracingSessionID, ConsumerEndpointImpl*);
136 void FreeBuffers(TracingSessionID);
Primiano Tucci42e2de12017-12-07 16:46:04 +0000137
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000138 // Service implementation.
139 std::unique_ptr<Service::ProducerEndpoint> ConnectProducer(
140 Producer*,
Sami Kyostila32e0b542018-02-14 08:55:43 +0000141 uid_t uid,
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000142 size_t shared_buffer_size_hint_bytes = 0) override;
Primiano Tucci42e2de12017-12-07 16:46:04 +0000143
144 std::unique_ptr<Service::ConsumerEndpoint> ConnectConsumer(
145 Consumer*) override;
146
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000147 // Exposed mainly for testing.
148 size_t num_producers() const { return producers_.size(); }
149 ProducerEndpointImpl* GetProducer(ProducerID) const;
150
151 private:
Primiano Tucci081d46a2018-02-28 11:09:43 +0000152 FRIEND_TEST(ServiceImplTest, ProducerIDWrapping);
153
Primiano Tucci53589332017-12-19 11:31:13 +0100154 struct RegisteredDataSource {
155 ProducerID producer_id;
156 DataSourceID data_source_id;
157 DataSourceDescriptor descriptor;
158 };
159
Sami Kyostila06487a22018-02-27 13:48:38 +0000160 // Represents an active data source for a tracing session.
161 struct DataSourceInstance {
162 DataSourceInstanceID instance_id;
163 DataSourceID data_source_id;
164 };
165
Primiano Tucci53589332017-12-19 11:31:13 +0100166 struct TraceBuffer {
Primiano Tucci20d441d2018-01-16 09:25:51 +0000167 TraceBuffer();
Primiano Tucci53589332017-12-19 11:31:13 +0100168 ~TraceBuffer();
169 TraceBuffer(TraceBuffer&&) noexcept;
170 TraceBuffer& operator=(TraceBuffer&&);
171
Primiano Tucci081d46a2018-02-28 11:09:43 +0000172 bool Create(size_t size_in_bytes);
Primiano Tucci53589332017-12-19 11:31:13 +0100173 size_t num_pages() const { return size / kBufferPageSize; }
174
175 uint8_t* get_page(size_t page) {
176 PERFETTO_DCHECK(page < num_pages());
177 return reinterpret_cast<uint8_t*>(data.get()) + page * kBufferPageSize;
178 }
179
Sami Kyostila32e0b542018-02-14 08:55:43 +0000180 uid_t get_page_owner(size_t page) const {
181 PERFETTO_DCHECK(page < num_pages());
182 return page_owners[page];
183 }
184
185 uint8_t* acquire_next_page(uid_t uid) {
Primiano Tucci53589332017-12-19 11:31:13 +0100186 size_t cur = cur_page;
187 cur_page = cur_page == num_pages() - 1 ? 0 : cur_page + 1;
Sami Kyostila32e0b542018-02-14 08:55:43 +0000188 page_owners[cur] = uid;
Primiano Tucci53589332017-12-19 11:31:13 +0100189 return get_page(cur);
190 }
191
Primiano Tucci20d441d2018-01-16 09:25:51 +0000192 size_t size = 0;
Primiano Tucci53589332017-12-19 11:31:13 +0100193 size_t cur_page = 0; // Write pointer in the ring buffer.
Primiano Tuccibbaa58c2017-12-20 13:48:20 +0100194 base::PageAllocator::UniquePtr data;
Primiano Tucci53589332017-12-19 11:31:13 +0100195
196 // TODO(primiano): The TraceBuffer is not shared and there is no reason to
197 // use the SharedMemoryABI. This is just a a temporary workaround to reuse
198 // the convenience of SharedMemoryABI for bookkeeping of the buffer when
199 // implementing ReadBuffers().
200 std::unique_ptr<SharedMemoryABI> abi;
Sami Kyostila32e0b542018-02-14 08:55:43 +0000201
202 // Trusted uid for each acquired page.
203 std::vector<uid_t> page_owners;
Primiano Tucci53589332017-12-19 11:31:13 +0100204 };
205
206 // Holds the state of a tracing session. A tracing session is uniquely bound
207 // a specific Consumer. Each Consumer can own one or more sessions.
208 struct TracingSession {
Primiano Tucci20d441d2018-01-16 09:25:51 +0000209 explicit TracingSession(const TraceConfig&);
210
211 size_t num_buffers() const { return buffers_index.size(); }
212
213 // The original trace config provided by the Consumer when calling
214 // EnableTracing().
215 const TraceConfig config;
Oystein Eftevaag1269b4a2018-01-10 16:29:38 -0800216
Primiano Tucci53589332017-12-19 11:31:13 +0100217 // List of data source instances that have been enabled on the various
218 // producers for this tracing session.
Sami Kyostila06487a22018-02-27 13:48:38 +0000219 std::multimap<ProducerID, DataSourceInstance> data_source_instances;
Primiano Tucci53589332017-12-19 11:31:13 +0100220
Primiano Tucci20d441d2018-01-16 09:25:51 +0000221 // Maps a per-trace-session buffer index into the corresponding global
222 // BufferID (shared namespace amongst all consumers). This vector has as
223 // many entries as |config.buffers_size()|.
224 std::vector<BufferID> buffers_index;
Primiano Tucci53589332017-12-19 11:31:13 +0100225 };
226
Primiano Tucci20d441d2018-01-16 09:25:51 +0000227 ServiceImpl(const ServiceImpl&) = delete;
228 ServiceImpl& operator=(const ServiceImpl&) = delete;
229
Sami Kyostila06487a22018-02-27 13:48:38 +0000230 void CreateDataSourceInstance(const TraceConfig::DataSource&,
231 const RegisteredDataSource&,
232 TracingSession*);
Oystein Eftevaag1269b4a2018-01-10 16:29:38 -0800233
Primiano Tucci081d46a2018-02-28 11:09:43 +0000234 // Returns the next available ProducerID that is not in |producers_|.
235 ProducerID GetNextProducerID();
236
Primiano Tucci20d441d2018-01-16 09:25:51 +0000237 // Returns a pointer to the |tracing_sessions_| entry or nullptr if the
238 // session doesn't exists.
239 TracingSession* GetTracingSession(TracingSessionID);
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000240
Lalit Maganti485faff2018-03-06 11:51:35 +0000241 // Update the memory guard rail by using the latest information from the
242 // shared memory and trace buffers.
243 void UpdateMemoryGuardrail();
244
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000245 base::TaskRunner* const task_runner_;
Primiano Tucci53589332017-12-19 11:31:13 +0100246 std::unique_ptr<SharedMemory::Factory> shm_factory_;
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000247 ProducerID last_producer_id_ = 0;
Primiano Tucci53589332017-12-19 11:31:13 +0100248 DataSourceInstanceID last_data_source_instance_id_ = 0;
Primiano Tucci20d441d2018-01-16 09:25:51 +0000249 TracingSessionID last_tracing_session_id_ = 0;
Primiano Tucci53589332017-12-19 11:31:13 +0100250
251 // Buffer IDs are global across all consumers (because a Producer can produce
252 // data for more than one trace session, hence more than one consumer).
Primiano Tucci20d441d2018-01-16 09:25:51 +0000253 IdAllocator<BufferID> buffer_ids_;
Primiano Tucci53589332017-12-19 11:31:13 +0100254
255 std::multimap<std::string /*name*/, RegisteredDataSource> data_sources_;
256
257 // TODO(primiano): There doesn't seem to be any good reason why |producers_|
258 // is a map indexed by ID and not just a set<ProducerEndpointImpl*>.
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000259 std::map<ProducerID, ProducerEndpointImpl*> producers_;
Primiano Tucci53589332017-12-19 11:31:13 +0100260
Primiano Tucci42e2de12017-12-07 16:46:04 +0000261 std::set<ConsumerEndpointImpl*> consumers_;
Primiano Tucci20d441d2018-01-16 09:25:51 +0000262 std::map<TracingSessionID, TracingSession> tracing_sessions_;
263 std::map<BufferID, TraceBuffer> buffers_;
264
Florian Mayercd08ec62018-01-31 17:49:25 +0000265 PERFETTO_THREAD_CHECKER(thread_checker_)
266
Primiano Tucci20d441d2018-01-16 09:25:51 +0000267 base::WeakPtrFactory<ServiceImpl> weak_ptr_factory_; // Keep at the end.
Primiano Tucci4f9b6d72017-12-05 20:59:16 +0000268};
269
270} // namespace perfetto
271
272#endif // SRC_TRACING_CORE_SERVICE_IMPL_H_