blob: 9a56e62e230b77ece00002713b185da3d1391ed1 [file] [log] [blame]
Primiano Tuccice720022017-10-30 12:50:06 +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#include "tracing/src/core/service_impl.h"
18
19#include <inttypes.h>
20
Primiano Tuccif54cae42017-11-21 19:37:13 +000021#include <algorithm>
22
Oystein Eftevaagdd727e42017-12-05 08:49:55 -080023#include "perfetto_base/logging.h"
24#include "perfetto_base/task_runner.h"
Primiano Tuccice720022017-10-30 12:50:06 +000025#include "tracing/core/data_source_config.h"
26#include "tracing/core/producer.h"
27#include "tracing/core/shared_memory.h"
Primiano Tuccice720022017-10-30 12:50:06 +000028
29namespace perfetto {
30
31// TODO add ThreadChecker everywhere.
32
33namespace {
Primiano Tuccif54cae42017-11-21 19:37:13 +000034constexpr size_t kPageSize = 4096;
35constexpr size_t kDefaultShmSize = kPageSize * 16; // 64 KB.
36constexpr size_t kMaxShmSize = kPageSize * 1024; // 4 MB.
Primiano Tuccice720022017-10-30 12:50:06 +000037} // namespace
38
39// static
40std::unique_ptr<Service> Service::CreateInstance(
41 std::unique_ptr<SharedMemory::Factory> shm_factory,
Primiano Tuccid7d1be02017-10-30 17:41:34 +000042 base::TaskRunner* task_runner) {
Primiano Tuccice720022017-10-30 12:50:06 +000043 return std::unique_ptr<Service>(
44 new ServiceImpl(std::move(shm_factory), task_runner));
45}
46
47ServiceImpl::ServiceImpl(std::unique_ptr<SharedMemory::Factory> shm_factory,
Primiano Tuccid7d1be02017-10-30 17:41:34 +000048 base::TaskRunner* task_runner)
Primiano Tuccice720022017-10-30 12:50:06 +000049 : shm_factory_(std::move(shm_factory)), task_runner_(task_runner) {
Primiano Tuccid7d1be02017-10-30 17:41:34 +000050 PERFETTO_DCHECK(task_runner_);
Primiano Tuccice720022017-10-30 12:50:06 +000051}
52
53ServiceImpl::~ServiceImpl() {
54 // TODO handle teardown of all Producer.
55}
56
57std::unique_ptr<Service::ProducerEndpoint> ServiceImpl::ConnectProducer(
Primiano Tuccif54cae42017-11-21 19:37:13 +000058 Producer* producer,
59 size_t shared_buffer_size_hint_bytes) {
Primiano Tuccice720022017-10-30 12:50:06 +000060 const ProducerID id = ++last_producer_id_;
Primiano Tuccif54cae42017-11-21 19:37:13 +000061
62 size_t shm_size = std::min(shared_buffer_size_hint_bytes, kMaxShmSize);
63 if (shm_size % kPageSize || shm_size < kPageSize)
64 shm_size = kDefaultShmSize;
65
66 // TODO(primiano): right now Create() will suicide in case of OOM if the mmap
67 // fails. We should instead gracefully fail the request and tell the client
68 // to go away.
69 auto shared_memory = shm_factory_->CreateSharedMemory(shm_size);
Primiano Tuccice720022017-10-30 12:50:06 +000070 std::unique_ptr<ProducerEndpointImpl> endpoint(new ProducerEndpointImpl(
71 id, this, task_runner_, producer, std::move(shared_memory)));
72 auto it_and_inserted = producers_.emplace(id, endpoint.get());
Primiano Tuccid7d1be02017-10-30 17:41:34 +000073 PERFETTO_DCHECK(it_and_inserted.second);
Primiano Tuccia6166482017-11-20 13:05:45 +000074 task_runner_->PostTask(std::bind(&Producer::OnConnect, endpoint->producer()));
75 if (observer_)
76 observer_->OnProducerConnected(id);
Primiano Tuccice720022017-10-30 12:50:06 +000077 return std::move(endpoint);
78}
79
80void ServiceImpl::DisconnectProducer(ProducerID id) {
Primiano Tuccid7d1be02017-10-30 17:41:34 +000081 PERFETTO_DCHECK(producers_.count(id));
Primiano Tuccice720022017-10-30 12:50:06 +000082 producers_.erase(id);
Primiano Tuccia6166482017-11-20 13:05:45 +000083 if (observer_)
84 observer_->OnProducerDisconnected(id);
Primiano Tuccice720022017-10-30 12:50:06 +000085}
86
Primiano Tuccia6166482017-11-20 13:05:45 +000087ServiceImpl::ProducerEndpointImpl* ServiceImpl::GetProducer(
88 ProducerID id) const {
Primiano Tuccice720022017-10-30 12:50:06 +000089 auto it = producers_.find(id);
90 if (it == producers_.end())
91 return nullptr;
92 return it->second;
93}
94
95////////////////////////////////////////////////////////////////////////////////
96// ServiceImpl::ProducerEndpointImpl implementation
97////////////////////////////////////////////////////////////////////////////////
98
99ServiceImpl::ProducerEndpointImpl::ProducerEndpointImpl(
100 ProducerID id,
101 ServiceImpl* service,
Primiano Tuccid7d1be02017-10-30 17:41:34 +0000102 base::TaskRunner* task_runner,
Primiano Tuccice720022017-10-30 12:50:06 +0000103 Producer* producer,
104 std::unique_ptr<SharedMemory> shared_memory)
105 : id_(id),
106 service_(service),
107 task_runner_(task_runner),
108 producer_(std::move(producer)),
109 shared_memory_(std::move(shared_memory)) {}
110
111ServiceImpl::ProducerEndpointImpl::~ProducerEndpointImpl() {
Primiano Tuccia6166482017-11-20 13:05:45 +0000112 producer_->OnDisconnect();
Primiano Tuccice720022017-10-30 12:50:06 +0000113 service_->DisconnectProducer(id_);
114}
115
Primiano Tuccice720022017-10-30 12:50:06 +0000116void ServiceImpl::ProducerEndpointImpl::RegisterDataSource(
117 const DataSourceDescriptor&,
118 RegisterDataSourceCallback callback) {
119 const DataSourceID dsid = ++last_data_source_id_;
Primiano Tuccice720022017-10-30 12:50:06 +0000120 task_runner_->PostTask(std::bind(std::move(callback), dsid));
121 // TODO implement the bookkeeping logic.
Primiano Tuccia6166482017-11-20 13:05:45 +0000122 if (service_->observer_)
123 service_->observer_->OnDataSourceRegistered(id_, dsid);
Primiano Tuccice720022017-10-30 12:50:06 +0000124}
125
126void ServiceImpl::ProducerEndpointImpl::UnregisterDataSource(
127 DataSourceID dsid) {
Primiano Tuccid7d1be02017-10-30 17:41:34 +0000128 PERFETTO_CHECK(dsid);
Primiano Tuccice720022017-10-30 12:50:06 +0000129 // TODO implement the bookkeeping logic.
Primiano Tuccia6166482017-11-20 13:05:45 +0000130 if (service_->observer_)
131 service_->observer_->OnDataSourceUnregistered(id_, dsid);
Primiano Tuccice720022017-10-30 12:50:06 +0000132}
133
Primiano Tuccia6166482017-11-20 13:05:45 +0000134void ServiceImpl::ProducerEndpointImpl::NotifySharedMemoryUpdate(
135 const std::vector<uint32_t>& changed_pages) {
Primiano Tuccice720022017-10-30 12:50:06 +0000136 // TODO implement the bookkeeping logic.
137 return;
138}
139
Primiano Tuccia6166482017-11-20 13:05:45 +0000140void ServiceImpl::set_observer_for_testing(ObserverForTesting* observer) {
141 observer_ = observer;
Primiano Tuccice720022017-10-30 12:50:06 +0000142}
143
Primiano Tuccif54cae42017-11-21 19:37:13 +0000144SharedMemory* ServiceImpl::ProducerEndpointImpl::shared_memory() const {
145 return shared_memory_.get();
146}
147
Primiano Tuccice720022017-10-30 12:50:06 +0000148} // namespace perfetto