Primiano Tucci | ce72002 | 2017-10-30 12:50:06 +0000 | [diff] [blame] | 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 | #include "tracing/src/core/service_impl.h" |
| 18 | |
| 19 | #include <inttypes.h> |
| 20 | |
Primiano Tucci | f54cae4 | 2017-11-21 19:37:13 +0000 | [diff] [blame] | 21 | #include <algorithm> |
| 22 | |
Oystein Eftevaag | dd727e4 | 2017-12-05 08:49:55 -0800 | [diff] [blame^] | 23 | #include "perfetto_base/logging.h" |
| 24 | #include "perfetto_base/task_runner.h" |
Primiano Tucci | ce72002 | 2017-10-30 12:50:06 +0000 | [diff] [blame] | 25 | #include "tracing/core/data_source_config.h" |
| 26 | #include "tracing/core/producer.h" |
| 27 | #include "tracing/core/shared_memory.h" |
Primiano Tucci | ce72002 | 2017-10-30 12:50:06 +0000 | [diff] [blame] | 28 | |
| 29 | namespace perfetto { |
| 30 | |
| 31 | // TODO add ThreadChecker everywhere. |
| 32 | |
| 33 | namespace { |
Primiano Tucci | f54cae4 | 2017-11-21 19:37:13 +0000 | [diff] [blame] | 34 | constexpr size_t kPageSize = 4096; |
| 35 | constexpr size_t kDefaultShmSize = kPageSize * 16; // 64 KB. |
| 36 | constexpr size_t kMaxShmSize = kPageSize * 1024; // 4 MB. |
Primiano Tucci | ce72002 | 2017-10-30 12:50:06 +0000 | [diff] [blame] | 37 | } // namespace |
| 38 | |
| 39 | // static |
| 40 | std::unique_ptr<Service> Service::CreateInstance( |
| 41 | std::unique_ptr<SharedMemory::Factory> shm_factory, |
Primiano Tucci | d7d1be0 | 2017-10-30 17:41:34 +0000 | [diff] [blame] | 42 | base::TaskRunner* task_runner) { |
Primiano Tucci | ce72002 | 2017-10-30 12:50:06 +0000 | [diff] [blame] | 43 | return std::unique_ptr<Service>( |
| 44 | new ServiceImpl(std::move(shm_factory), task_runner)); |
| 45 | } |
| 46 | |
| 47 | ServiceImpl::ServiceImpl(std::unique_ptr<SharedMemory::Factory> shm_factory, |
Primiano Tucci | d7d1be0 | 2017-10-30 17:41:34 +0000 | [diff] [blame] | 48 | base::TaskRunner* task_runner) |
Primiano Tucci | ce72002 | 2017-10-30 12:50:06 +0000 | [diff] [blame] | 49 | : shm_factory_(std::move(shm_factory)), task_runner_(task_runner) { |
Primiano Tucci | d7d1be0 | 2017-10-30 17:41:34 +0000 | [diff] [blame] | 50 | PERFETTO_DCHECK(task_runner_); |
Primiano Tucci | ce72002 | 2017-10-30 12:50:06 +0000 | [diff] [blame] | 51 | } |
| 52 | |
| 53 | ServiceImpl::~ServiceImpl() { |
| 54 | // TODO handle teardown of all Producer. |
| 55 | } |
| 56 | |
| 57 | std::unique_ptr<Service::ProducerEndpoint> ServiceImpl::ConnectProducer( |
Primiano Tucci | f54cae4 | 2017-11-21 19:37:13 +0000 | [diff] [blame] | 58 | Producer* producer, |
| 59 | size_t shared_buffer_size_hint_bytes) { |
Primiano Tucci | ce72002 | 2017-10-30 12:50:06 +0000 | [diff] [blame] | 60 | const ProducerID id = ++last_producer_id_; |
Primiano Tucci | f54cae4 | 2017-11-21 19:37:13 +0000 | [diff] [blame] | 61 | |
| 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 Tucci | ce72002 | 2017-10-30 12:50:06 +0000 | [diff] [blame] | 70 | 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 Tucci | d7d1be0 | 2017-10-30 17:41:34 +0000 | [diff] [blame] | 73 | PERFETTO_DCHECK(it_and_inserted.second); |
Primiano Tucci | a616648 | 2017-11-20 13:05:45 +0000 | [diff] [blame] | 74 | task_runner_->PostTask(std::bind(&Producer::OnConnect, endpoint->producer())); |
| 75 | if (observer_) |
| 76 | observer_->OnProducerConnected(id); |
Primiano Tucci | ce72002 | 2017-10-30 12:50:06 +0000 | [diff] [blame] | 77 | return std::move(endpoint); |
| 78 | } |
| 79 | |
| 80 | void ServiceImpl::DisconnectProducer(ProducerID id) { |
Primiano Tucci | d7d1be0 | 2017-10-30 17:41:34 +0000 | [diff] [blame] | 81 | PERFETTO_DCHECK(producers_.count(id)); |
Primiano Tucci | ce72002 | 2017-10-30 12:50:06 +0000 | [diff] [blame] | 82 | producers_.erase(id); |
Primiano Tucci | a616648 | 2017-11-20 13:05:45 +0000 | [diff] [blame] | 83 | if (observer_) |
| 84 | observer_->OnProducerDisconnected(id); |
Primiano Tucci | ce72002 | 2017-10-30 12:50:06 +0000 | [diff] [blame] | 85 | } |
| 86 | |
Primiano Tucci | a616648 | 2017-11-20 13:05:45 +0000 | [diff] [blame] | 87 | ServiceImpl::ProducerEndpointImpl* ServiceImpl::GetProducer( |
| 88 | ProducerID id) const { |
Primiano Tucci | ce72002 | 2017-10-30 12:50:06 +0000 | [diff] [blame] | 89 | 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 | |
| 99 | ServiceImpl::ProducerEndpointImpl::ProducerEndpointImpl( |
| 100 | ProducerID id, |
| 101 | ServiceImpl* service, |
Primiano Tucci | d7d1be0 | 2017-10-30 17:41:34 +0000 | [diff] [blame] | 102 | base::TaskRunner* task_runner, |
Primiano Tucci | ce72002 | 2017-10-30 12:50:06 +0000 | [diff] [blame] | 103 | 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 | |
| 111 | ServiceImpl::ProducerEndpointImpl::~ProducerEndpointImpl() { |
Primiano Tucci | a616648 | 2017-11-20 13:05:45 +0000 | [diff] [blame] | 112 | producer_->OnDisconnect(); |
Primiano Tucci | ce72002 | 2017-10-30 12:50:06 +0000 | [diff] [blame] | 113 | service_->DisconnectProducer(id_); |
| 114 | } |
| 115 | |
Primiano Tucci | ce72002 | 2017-10-30 12:50:06 +0000 | [diff] [blame] | 116 | void ServiceImpl::ProducerEndpointImpl::RegisterDataSource( |
| 117 | const DataSourceDescriptor&, |
| 118 | RegisterDataSourceCallback callback) { |
| 119 | const DataSourceID dsid = ++last_data_source_id_; |
Primiano Tucci | ce72002 | 2017-10-30 12:50:06 +0000 | [diff] [blame] | 120 | task_runner_->PostTask(std::bind(std::move(callback), dsid)); |
| 121 | // TODO implement the bookkeeping logic. |
Primiano Tucci | a616648 | 2017-11-20 13:05:45 +0000 | [diff] [blame] | 122 | if (service_->observer_) |
| 123 | service_->observer_->OnDataSourceRegistered(id_, dsid); |
Primiano Tucci | ce72002 | 2017-10-30 12:50:06 +0000 | [diff] [blame] | 124 | } |
| 125 | |
| 126 | void ServiceImpl::ProducerEndpointImpl::UnregisterDataSource( |
| 127 | DataSourceID dsid) { |
Primiano Tucci | d7d1be0 | 2017-10-30 17:41:34 +0000 | [diff] [blame] | 128 | PERFETTO_CHECK(dsid); |
Primiano Tucci | ce72002 | 2017-10-30 12:50:06 +0000 | [diff] [blame] | 129 | // TODO implement the bookkeeping logic. |
Primiano Tucci | a616648 | 2017-11-20 13:05:45 +0000 | [diff] [blame] | 130 | if (service_->observer_) |
| 131 | service_->observer_->OnDataSourceUnregistered(id_, dsid); |
Primiano Tucci | ce72002 | 2017-10-30 12:50:06 +0000 | [diff] [blame] | 132 | } |
| 133 | |
Primiano Tucci | a616648 | 2017-11-20 13:05:45 +0000 | [diff] [blame] | 134 | void ServiceImpl::ProducerEndpointImpl::NotifySharedMemoryUpdate( |
| 135 | const std::vector<uint32_t>& changed_pages) { |
Primiano Tucci | ce72002 | 2017-10-30 12:50:06 +0000 | [diff] [blame] | 136 | // TODO implement the bookkeeping logic. |
| 137 | return; |
| 138 | } |
| 139 | |
Primiano Tucci | a616648 | 2017-11-20 13:05:45 +0000 | [diff] [blame] | 140 | void ServiceImpl::set_observer_for_testing(ObserverForTesting* observer) { |
| 141 | observer_ = observer; |
Primiano Tucci | ce72002 | 2017-10-30 12:50:06 +0000 | [diff] [blame] | 142 | } |
| 143 | |
Primiano Tucci | f54cae4 | 2017-11-21 19:37:13 +0000 | [diff] [blame] | 144 | SharedMemory* ServiceImpl::ProducerEndpointImpl::shared_memory() const { |
| 145 | return shared_memory_.get(); |
| 146 | } |
| 147 | |
Primiano Tucci | ce72002 | 2017-10-30 12:50:06 +0000 | [diff] [blame] | 148 | } // namespace perfetto |