Primiano Tucci | 4f9b6d7 | 2017-12-05 20:59:16 +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 "perfetto/ftrace_reader/ftrace_controller.h" |
| 18 | |
| 19 | #include <fcntl.h> |
| 20 | #include <stdint.h> |
| 21 | #include <string.h> |
| 22 | #include <sys/stat.h> |
| 23 | #include <sys/types.h> |
Hector Dearman | c61e883 | 2018-01-25 12:10:12 +0000 | [diff] [blame] | 24 | #include <sys/wait.h> |
Primiano Tucci | 4f9b6d7 | 2017-12-05 20:59:16 +0000 | [diff] [blame] | 25 | |
| 26 | #include <array> |
| 27 | #include <string> |
| 28 | |
| 29 | #include "cpu_reader.h" |
Hector Dearman | 83d9803 | 2017-12-11 16:37:43 +0000 | [diff] [blame] | 30 | #include "event_info.h" |
Primiano Tucci | 4f9b6d7 | 2017-12-05 20:59:16 +0000 | [diff] [blame] | 31 | #include "ftrace_procfs.h" |
Hector Dearman | c61e883 | 2018-01-25 12:10:12 +0000 | [diff] [blame] | 32 | #include "perfetto/base/build_config.h" |
Primiano Tucci | 4f9b6d7 | 2017-12-05 20:59:16 +0000 | [diff] [blame] | 33 | #include "perfetto/base/logging.h" |
| 34 | #include "perfetto/base/utils.h" |
| 35 | #include "proto_translation_table.h" |
| 36 | |
Primiano Tucci | 20b760c | 2018-01-19 12:36:12 +0000 | [diff] [blame] | 37 | #include "perfetto/trace/ftrace/ftrace_event_bundle.pbzero.h" |
Primiano Tucci | 4f9b6d7 | 2017-12-05 20:59:16 +0000 | [diff] [blame] | 38 | |
| 39 | namespace perfetto { |
| 40 | namespace { |
| 41 | |
Isabelle Taylor | c31a431 | 2018-01-22 16:44:28 +0000 | [diff] [blame] | 42 | #if BUILDFLAG(OS_ANDROID) |
| 43 | const char* kTracingPaths[] = { |
| 44 | "/sys/kernel/tracing/", "/sys/kernel/debug/tracing/", nullptr, |
| 45 | }; |
| 46 | #else |
| 47 | const char* kTracingPaths[] = { |
| 48 | "/sys/kernel/debug/tracing/", nullptr, |
| 49 | }; |
| 50 | #endif |
Primiano Tucci | 4f9b6d7 | 2017-12-05 20:59:16 +0000 | [diff] [blame] | 51 | |
Hector Dearman | 6ea67b3 | 2018-02-01 15:45:15 +0000 | [diff] [blame] | 52 | const int kDefaultDrainPeriodMs = 100; |
| 53 | const int kMinDrainPeriodMs = 1; |
| 54 | const int kMaxDrainPeriodMs = 1000 * 60; |
| 55 | |
Hector Dearman | aa9ecf6 | 2018-02-07 10:48:42 +0000 | [diff] [blame] | 56 | const int kDefaultTotalBufferSizeKb = 1024 * 4; // 4mb |
| 57 | const int kMaxTotalBufferSizeKb = 1024 * 8; // 8mb |
Hector Dearman | 6ea67b3 | 2018-02-01 15:45:15 +0000 | [diff] [blame] | 58 | |
| 59 | uint32_t ClampDrainPeriodMs(uint32_t drain_period_ms) { |
| 60 | if (drain_period_ms == 0) { |
| 61 | return kDefaultDrainPeriodMs; |
| 62 | } |
| 63 | if (drain_period_ms < kMinDrainPeriodMs || |
| 64 | kMaxDrainPeriodMs < drain_period_ms) { |
| 65 | PERFETTO_LOG("drain_period_ms was %u should be between %u and %u", |
| 66 | drain_period_ms, kMinDrainPeriodMs, kMaxDrainPeriodMs); |
| 67 | return kDefaultDrainPeriodMs; |
| 68 | } |
| 69 | return drain_period_ms; |
| 70 | } |
| 71 | |
| 72 | // Post-conditions: |
| 73 | // 1. result >= 1 (should have at least one page per CPU) |
Hector Dearman | dbdec97 | 2018-02-02 16:31:42 +0000 | [diff] [blame] | 74 | // 2. result * 4 < kMaxTotalBufferSizeKb |
Hector Dearman | 6ea67b3 | 2018-02-01 15:45:15 +0000 | [diff] [blame] | 75 | // 3. If input is 0 output is a good default number. |
Hector Dearman | dbdec97 | 2018-02-02 16:31:42 +0000 | [diff] [blame] | 76 | size_t ComputeCpuBufferSizeInPages(uint32_t requested_buffer_size_kb) { |
Hector Dearman | 6ea67b3 | 2018-02-01 15:45:15 +0000 | [diff] [blame] | 77 | if (requested_buffer_size_kb == 0) |
| 78 | requested_buffer_size_kb = kDefaultTotalBufferSizeKb; |
| 79 | if (requested_buffer_size_kb > kMaxTotalBufferSizeKb) |
| 80 | requested_buffer_size_kb = kDefaultTotalBufferSizeKb; |
| 81 | |
Hector Dearman | dbdec97 | 2018-02-02 16:31:42 +0000 | [diff] [blame] | 82 | size_t pages = requested_buffer_size_kb / (base::kPageSize / 1024); |
Hector Dearman | 6ea67b3 | 2018-02-01 15:45:15 +0000 | [diff] [blame] | 83 | if (pages == 0) |
| 84 | return 1; |
| 85 | |
| 86 | return pages; |
| 87 | } |
Hector Dearman | 680a28b | 2018-01-11 18:34:24 +0000 | [diff] [blame] | 88 | |
Hector Dearman | c61e883 | 2018-01-25 12:10:12 +0000 | [diff] [blame] | 89 | bool RunAtrace(std::vector<std::string> args) { |
| 90 | int status = 1; |
| 91 | |
| 92 | std::vector<char*> argv; |
| 93 | // args, and then a null. |
| 94 | argv.reserve(1 + args.size()); |
| 95 | for (const auto& arg : args) |
| 96 | argv.push_back(const_cast<char*>(arg.c_str())); |
| 97 | argv.push_back(nullptr); |
| 98 | |
| 99 | pid_t pid = fork(); |
| 100 | PERFETTO_CHECK(pid >= 0); |
| 101 | if (pid == 0) { |
| 102 | execv("/system/bin/atrace", &argv[0]); |
| 103 | // Reached only if execv fails. |
| 104 | _exit(1); |
| 105 | } |
| 106 | waitpid(pid, &status, 0); |
| 107 | return status == 0; |
| 108 | } |
| 109 | |
Primiano Tucci | 4f9b6d7 | 2017-12-05 20:59:16 +0000 | [diff] [blame] | 110 | } // namespace |
| 111 | |
| 112 | // static |
Isabelle Taylor | c31a431 | 2018-01-22 16:44:28 +0000 | [diff] [blame] | 113 | // TODO(taylori): Add a test for tracing paths in integration tests. |
Primiano Tucci | 4f9b6d7 | 2017-12-05 20:59:16 +0000 | [diff] [blame] | 114 | std::unique_ptr<FtraceController> FtraceController::Create( |
| 115 | base::TaskRunner* runner) { |
Isabelle Taylor | c31a431 | 2018-01-22 16:44:28 +0000 | [diff] [blame] | 116 | size_t index = 0; |
| 117 | std::unique_ptr<FtraceProcfs> ftrace_procfs = nullptr; |
| 118 | while (!ftrace_procfs && kTracingPaths[index]) { |
| 119 | ftrace_procfs = FtraceProcfs::Create(kTracingPaths[index++]); |
| 120 | } |
| 121 | |
| 122 | if (!ftrace_procfs) { |
| 123 | return nullptr; |
| 124 | } |
| 125 | |
Hector Dearman | 77af133 | 2017-12-15 11:55:33 +0000 | [diff] [blame] | 126 | auto table = ProtoTranslationTable::Create( |
| 127 | ftrace_procfs.get(), GetStaticEventInfo(), GetStaticCommonFieldsInfo()); |
Primiano Tucci | 4f9b6d7 | 2017-12-05 20:59:16 +0000 | [diff] [blame] | 128 | return std::unique_ptr<FtraceController>( |
| 129 | new FtraceController(std::move(ftrace_procfs), runner, std::move(table))); |
| 130 | } |
| 131 | |
| 132 | FtraceController::FtraceController(std::unique_ptr<FtraceProcfs> ftrace_procfs, |
| 133 | base::TaskRunner* task_runner, |
| 134 | std::unique_ptr<ProtoTranslationTable> table) |
| 135 | : ftrace_procfs_(std::move(ftrace_procfs)), |
| 136 | task_runner_(task_runner), |
Primiano Tucci | 4f9b6d7 | 2017-12-05 20:59:16 +0000 | [diff] [blame] | 137 | enabled_count_(table->largest_id() + 1), |
Primiano Tucci | 68323b0 | 2017-12-18 10:54:13 +0100 | [diff] [blame] | 138 | table_(std::move(table)), |
| 139 | weak_factory_(this) {} |
Primiano Tucci | 4f9b6d7 | 2017-12-05 20:59:16 +0000 | [diff] [blame] | 140 | |
| 141 | FtraceController::~FtraceController() { |
| 142 | for (size_t id = 1; id <= table_->largest_id(); id++) { |
| 143 | if (enabled_count_[id]) { |
Hector Dearman | 83d9803 | 2017-12-11 16:37:43 +0000 | [diff] [blame] | 144 | const Event* event = table_->GetEventById(id); |
Primiano Tucci | 4f9b6d7 | 2017-12-05 20:59:16 +0000 | [diff] [blame] | 145 | ftrace_procfs_->DisableEvent(event->group, event->name); |
| 146 | } |
| 147 | } |
Hector Dearman | 5c87a75 | 2017-12-07 12:40:04 +0000 | [diff] [blame] | 148 | if (listening_for_raw_trace_data_) { |
| 149 | sinks_.clear(); |
| 150 | StopIfNeeded(); |
| 151 | } |
Primiano Tucci | 4f9b6d7 | 2017-12-05 20:59:16 +0000 | [diff] [blame] | 152 | } |
| 153 | |
Hector Dearman | 680a28b | 2018-01-11 18:34:24 +0000 | [diff] [blame] | 154 | // static |
| 155 | void FtraceController::PeriodicDrainCPU( |
| 156 | base::WeakPtr<FtraceController> weak_this, |
| 157 | size_t generation, |
| 158 | int cpu) { |
| 159 | // The controller might be gone. |
| 160 | if (!weak_this) |
| 161 | return; |
| 162 | // We might have stopped caring about events. |
| 163 | if (!weak_this->listening_for_raw_trace_data_) |
| 164 | return; |
| 165 | // We might have stopped tracing then quickly re-enabled it, in this case |
| 166 | // we don't want to end up with two periodic tasks for each CPU: |
| 167 | if (weak_this->generation_ != generation) |
| 168 | return; |
| 169 | |
| 170 | bool has_more = weak_this->OnRawFtraceDataAvailable(cpu); |
| 171 | weak_this->task_runner_->PostDelayedTask( |
| 172 | std::bind(&FtraceController::PeriodicDrainCPU, weak_this, generation, |
| 173 | cpu), |
Hector Dearman | 6ea67b3 | 2018-02-01 15:45:15 +0000 | [diff] [blame] | 174 | has_more ? 0 : weak_this->GetDrainPeriodMs()); |
Hector Dearman | 680a28b | 2018-01-11 18:34:24 +0000 | [diff] [blame] | 175 | } |
| 176 | |
Hector Dearman | 5c87a75 | 2017-12-07 12:40:04 +0000 | [diff] [blame] | 177 | void FtraceController::StartIfNeeded() { |
| 178 | if (sinks_.size() > 1) |
Primiano Tucci | 4f9b6d7 | 2017-12-05 20:59:16 +0000 | [diff] [blame] | 179 | return; |
Hector Dearman | 5c87a75 | 2017-12-07 12:40:04 +0000 | [diff] [blame] | 180 | PERFETTO_CHECK(sinks_.size() != 0); |
| 181 | PERFETTO_CHECK(!listening_for_raw_trace_data_); |
Primiano Tucci | 4f9b6d7 | 2017-12-05 20:59:16 +0000 | [diff] [blame] | 182 | listening_for_raw_trace_data_ = true; |
Hector Dearman | 6ea67b3 | 2018-02-01 15:45:15 +0000 | [diff] [blame] | 183 | ftrace_procfs_->SetCpuBufferSizeInPages(GetCpuBufferSizeInPages()); |
Primiano Tucci | 4f9b6d7 | 2017-12-05 20:59:16 +0000 | [diff] [blame] | 184 | ftrace_procfs_->EnableTracing(); |
Hector Dearman | 20b3c1c | 2018-01-15 15:34:03 +0000 | [diff] [blame] | 185 | generation_++; |
Primiano Tucci | 4f9b6d7 | 2017-12-05 20:59:16 +0000 | [diff] [blame] | 186 | for (size_t cpu = 0; cpu < ftrace_procfs_->NumberOfCpus(); cpu++) { |
Primiano Tucci | 4f9b6d7 | 2017-12-05 20:59:16 +0000 | [diff] [blame] | 187 | base::WeakPtr<FtraceController> weak_this = weak_factory_.GetWeakPtr(); |
Hector Dearman | 680a28b | 2018-01-11 18:34:24 +0000 | [diff] [blame] | 188 | task_runner_->PostDelayedTask(std::bind(&FtraceController::PeriodicDrainCPU, |
Hector Dearman | 20b3c1c | 2018-01-15 15:34:03 +0000 | [diff] [blame] | 189 | weak_this, generation_, cpu), |
Hector Dearman | 6ea67b3 | 2018-02-01 15:45:15 +0000 | [diff] [blame] | 190 | GetDrainPeriodMs()); |
Primiano Tucci | 4f9b6d7 | 2017-12-05 20:59:16 +0000 | [diff] [blame] | 191 | } |
| 192 | } |
| 193 | |
Hector Dearman | 6ea67b3 | 2018-02-01 15:45:15 +0000 | [diff] [blame] | 194 | uint32_t FtraceController::GetDrainPeriodMs() { |
| 195 | if (sinks_.size() == 0) |
| 196 | return kDefaultDrainPeriodMs; |
| 197 | uint32_t min_drain_period_ms = kMaxDrainPeriodMs + 1; |
| 198 | for (const FtraceSink* sink : sinks_) { |
| 199 | if (sink->config().drain_period_ms() < min_drain_period_ms) |
| 200 | min_drain_period_ms = sink->config().drain_period_ms(); |
| 201 | } |
| 202 | return ClampDrainPeriodMs(min_drain_period_ms); |
| 203 | } |
| 204 | |
| 205 | uint32_t FtraceController::GetCpuBufferSizeInPages() { |
Hector Dearman | dbdec97 | 2018-02-02 16:31:42 +0000 | [diff] [blame] | 206 | uint32_t max_buffer_size_kb = 0; |
Hector Dearman | 6ea67b3 | 2018-02-01 15:45:15 +0000 | [diff] [blame] | 207 | for (const FtraceSink* sink : sinks_) { |
Hector Dearman | dbdec97 | 2018-02-02 16:31:42 +0000 | [diff] [blame] | 208 | if (sink->config().buffer_size_kb() > max_buffer_size_kb) |
| 209 | max_buffer_size_kb = sink->config().buffer_size_kb(); |
Hector Dearman | 6ea67b3 | 2018-02-01 15:45:15 +0000 | [diff] [blame] | 210 | } |
Hector Dearman | dbdec97 | 2018-02-02 16:31:42 +0000 | [diff] [blame] | 211 | return ComputeCpuBufferSizeInPages(max_buffer_size_kb); |
Hector Dearman | 6ea67b3 | 2018-02-01 15:45:15 +0000 | [diff] [blame] | 212 | } |
| 213 | |
Hector Dearman | e4cc95d | 2018-01-09 14:32:24 +0000 | [diff] [blame] | 214 | void FtraceController::ClearTrace() { |
| 215 | ftrace_procfs_->ClearTrace(); |
| 216 | } |
| 217 | |
| 218 | void FtraceController::DisableAllEvents() { |
| 219 | ftrace_procfs_->DisableAllEvents(); |
| 220 | } |
| 221 | |
| 222 | void FtraceController::WriteTraceMarker(const std::string& s) { |
| 223 | ftrace_procfs_->WriteTraceMarker(s); |
| 224 | } |
| 225 | |
Hector Dearman | 5c87a75 | 2017-12-07 12:40:04 +0000 | [diff] [blame] | 226 | void FtraceController::StopIfNeeded() { |
| 227 | if (sinks_.size() != 0) |
Primiano Tucci | 4f9b6d7 | 2017-12-05 20:59:16 +0000 | [diff] [blame] | 228 | return; |
Hector Dearman | 5c87a75 | 2017-12-07 12:40:04 +0000 | [diff] [blame] | 229 | PERFETTO_CHECK(listening_for_raw_trace_data_); |
Primiano Tucci | 4f9b6d7 | 2017-12-05 20:59:16 +0000 | [diff] [blame] | 230 | listening_for_raw_trace_data_ = false; |
Hector Dearman | 5c87a75 | 2017-12-07 12:40:04 +0000 | [diff] [blame] | 231 | readers_.clear(); |
| 232 | ftrace_procfs_->DisableTracing(); |
Primiano Tucci | 4f9b6d7 | 2017-12-05 20:59:16 +0000 | [diff] [blame] | 233 | } |
| 234 | |
Hector Dearman | 680a28b | 2018-01-11 18:34:24 +0000 | [diff] [blame] | 235 | bool FtraceController::OnRawFtraceDataAvailable(size_t cpu) { |
Primiano Tucci | 4f9b6d7 | 2017-12-05 20:59:16 +0000 | [diff] [blame] | 236 | CpuReader* reader = GetCpuReader(cpu); |
| 237 | using BundleHandle = |
| 238 | protozero::ProtoZeroMessageHandle<protos::pbzero::FtraceEventBundle>; |
| 239 | std::array<const EventFilter*, kMaxSinks> filters{}; |
| 240 | std::array<BundleHandle, kMaxSinks> bundles{}; |
| 241 | size_t sink_count = sinks_.size(); |
| 242 | size_t i = 0; |
| 243 | for (FtraceSink* sink : sinks_) { |
| 244 | filters[i] = sink->get_event_filter(); |
| 245 | bundles[i++] = sink->GetBundleForCpu(cpu); |
| 246 | } |
Hector Dearman | 680a28b | 2018-01-11 18:34:24 +0000 | [diff] [blame] | 247 | bool res = reader->Drain(filters, bundles); |
Primiano Tucci | 4f9b6d7 | 2017-12-05 20:59:16 +0000 | [diff] [blame] | 248 | i = 0; |
| 249 | for (FtraceSink* sink : sinks_) |
| 250 | sink->OnBundleComplete(cpu, std::move(bundles[i++])); |
| 251 | PERFETTO_DCHECK(sinks_.size() == sink_count); |
Hector Dearman | 680a28b | 2018-01-11 18:34:24 +0000 | [diff] [blame] | 252 | return res; |
Primiano Tucci | 4f9b6d7 | 2017-12-05 20:59:16 +0000 | [diff] [blame] | 253 | } |
| 254 | |
| 255 | CpuReader* FtraceController::GetCpuReader(size_t cpu) { |
| 256 | PERFETTO_CHECK(cpu < ftrace_procfs_->NumberOfCpus()); |
| 257 | if (!readers_.count(cpu)) { |
| 258 | readers_.emplace( |
| 259 | cpu, std::unique_ptr<CpuReader>(new CpuReader( |
| 260 | table_.get(), cpu, ftrace_procfs_->OpenPipeForCpu(cpu)))); |
| 261 | } |
| 262 | return readers_.at(cpu).get(); |
| 263 | } |
| 264 | |
| 265 | std::unique_ptr<FtraceSink> FtraceController::CreateSink( |
Hector Dearman | cb4ba32 | 2018-02-09 14:12:27 +0000 | [diff] [blame^] | 266 | FtraceConfig config, |
Primiano Tucci | 4f9b6d7 | 2017-12-05 20:59:16 +0000 | [diff] [blame] | 267 | FtraceSink::Delegate* delegate) { |
| 268 | PERFETTO_DCHECK_THREAD(thread_checker_); |
| 269 | if (sinks_.size() >= kMaxSinks) |
| 270 | return nullptr; |
Hector Dearman | cb4ba32 | 2018-02-09 14:12:27 +0000 | [diff] [blame^] | 271 | if (!ValidConfig(config)) |
| 272 | return nullptr; |
Primiano Tucci | 4f9b6d7 | 2017-12-05 20:59:16 +0000 | [diff] [blame] | 273 | auto controller_weak = weak_factory_.GetWeakPtr(); |
Hector Dearman | 6ea67b3 | 2018-02-01 15:45:15 +0000 | [diff] [blame] | 274 | auto filter = std::unique_ptr<EventFilter>( |
Hector Dearman | cb4ba32 | 2018-02-09 14:12:27 +0000 | [diff] [blame^] | 275 | new EventFilter(*table_.get(), FtraceEventsAsSet(config))); |
| 276 | for (const std::string& event : config.event_names()) |
| 277 | PERFETTO_LOG("%s", event.c_str()); |
Hector Dearman | 6ea67b3 | 2018-02-01 15:45:15 +0000 | [diff] [blame] | 278 | auto sink = std::unique_ptr<FtraceSink>(new FtraceSink( |
| 279 | std::move(controller_weak), config, std::move(filter), delegate)); |
Primiano Tucci | 4f9b6d7 | 2017-12-05 20:59:16 +0000 | [diff] [blame] | 280 | Register(sink.get()); |
| 281 | return sink; |
| 282 | } |
| 283 | |
| 284 | void FtraceController::Register(FtraceSink* sink) { |
| 285 | PERFETTO_DCHECK_THREAD(thread_checker_); |
| 286 | auto it_and_inserted = sinks_.insert(sink); |
| 287 | PERFETTO_DCHECK(it_and_inserted.second); |
Hector Dearman | cb4ba32 | 2018-02-09 14:12:27 +0000 | [diff] [blame^] | 288 | if (RequiresAtrace(sink->config())) |
Hector Dearman | c61e883 | 2018-01-25 12:10:12 +0000 | [diff] [blame] | 289 | StartAtrace(sink->config()); |
Hector Dearman | 5c87a75 | 2017-12-07 12:40:04 +0000 | [diff] [blame] | 290 | |
| 291 | StartIfNeeded(); |
Primiano Tucci | 4f9b6d7 | 2017-12-05 20:59:16 +0000 | [diff] [blame] | 292 | for (const std::string& name : sink->enabled_events()) |
| 293 | RegisterForEvent(name); |
| 294 | } |
| 295 | |
| 296 | void FtraceController::RegisterForEvent(const std::string& name) { |
| 297 | PERFETTO_DCHECK_THREAD(thread_checker_); |
Hector Dearman | 83d9803 | 2017-12-11 16:37:43 +0000 | [diff] [blame] | 298 | const Event* event = table_->GetEventByName(name); |
Primiano Tucci | 4f9b6d7 | 2017-12-05 20:59:16 +0000 | [diff] [blame] | 299 | if (!event) { |
| 300 | PERFETTO_DLOG("Can't enable %s, event not known", name.c_str()); |
| 301 | return; |
| 302 | } |
| 303 | size_t& count = enabled_count_.at(event->ftrace_event_id); |
| 304 | if (count == 0) |
| 305 | ftrace_procfs_->EnableEvent(event->group, event->name); |
| 306 | count += 1; |
| 307 | } |
| 308 | |
| 309 | void FtraceController::UnregisterForEvent(const std::string& name) { |
| 310 | PERFETTO_DCHECK_THREAD(thread_checker_); |
Hector Dearman | 83d9803 | 2017-12-11 16:37:43 +0000 | [diff] [blame] | 311 | const Event* event = table_->GetEventByName(name); |
Primiano Tucci | 4f9b6d7 | 2017-12-05 20:59:16 +0000 | [diff] [blame] | 312 | if (!event) |
| 313 | return; |
| 314 | size_t& count = enabled_count_.at(event->ftrace_event_id); |
| 315 | PERFETTO_CHECK(count > 0); |
| 316 | if (--count == 0) |
| 317 | ftrace_procfs_->DisableEvent(event->group, event->name); |
| 318 | } |
| 319 | |
| 320 | void FtraceController::Unregister(FtraceSink* sink) { |
| 321 | PERFETTO_DCHECK_THREAD(thread_checker_); |
| 322 | size_t removed = sinks_.erase(sink); |
| 323 | PERFETTO_DCHECK(removed == 1); |
Hector Dearman | 5c87a75 | 2017-12-07 12:40:04 +0000 | [diff] [blame] | 324 | |
Primiano Tucci | 4f9b6d7 | 2017-12-05 20:59:16 +0000 | [diff] [blame] | 325 | for (const std::string& name : sink->enabled_events()) |
| 326 | UnregisterForEvent(name); |
Hector Dearman | cb4ba32 | 2018-02-09 14:12:27 +0000 | [diff] [blame^] | 327 | if (RequiresAtrace(sink->config())) |
Hector Dearman | c61e883 | 2018-01-25 12:10:12 +0000 | [diff] [blame] | 328 | StopAtrace(); |
Hector Dearman | 5c87a75 | 2017-12-07 12:40:04 +0000 | [diff] [blame] | 329 | StopIfNeeded(); |
Primiano Tucci | 4f9b6d7 | 2017-12-05 20:59:16 +0000 | [diff] [blame] | 330 | } |
| 331 | |
Hector Dearman | c61e883 | 2018-01-25 12:10:12 +0000 | [diff] [blame] | 332 | void FtraceController::StartAtrace(const FtraceConfig& config) { |
| 333 | PERFETTO_CHECK(atrace_running_ == false); |
| 334 | atrace_running_ = true; |
| 335 | PERFETTO_DLOG("Start atrace..."); |
| 336 | std::vector<std::string> args; |
| 337 | args.push_back("atrace"); // argv0 for exec() |
| 338 | args.push_back("--async_start"); |
| 339 | for (const auto& category : config.atrace_categories()) |
| 340 | args.push_back(category); |
| 341 | if (!config.atrace_apps().empty()) { |
| 342 | args.push_back("-a"); |
| 343 | for (const auto& app : config.atrace_apps()) |
| 344 | args.push_back(app); |
| 345 | } |
| 346 | |
| 347 | PERFETTO_CHECK(RunAtrace(std::move(args))); |
| 348 | PERFETTO_DLOG("...done"); |
| 349 | } |
| 350 | |
| 351 | void FtraceController::StopAtrace() { |
| 352 | PERFETTO_CHECK(atrace_running_ == true); |
| 353 | atrace_running_ = false; |
| 354 | PERFETTO_DLOG("Stop atrace..."); |
| 355 | PERFETTO_CHECK( |
| 356 | RunAtrace(std::vector<std::string>({"atrace", "--async_stop"}))); |
| 357 | PERFETTO_DLOG("...done"); |
| 358 | } |
| 359 | |
Primiano Tucci | 4f9b6d7 | 2017-12-05 20:59:16 +0000 | [diff] [blame] | 360 | FtraceSink::FtraceSink(base::WeakPtr<FtraceController> controller_weak, |
Hector Dearman | c61e883 | 2018-01-25 12:10:12 +0000 | [diff] [blame] | 361 | FtraceConfig config, |
Primiano Tucci | 4f9b6d7 | 2017-12-05 20:59:16 +0000 | [diff] [blame] | 362 | std::unique_ptr<EventFilter> filter, |
| 363 | Delegate* delegate) |
| 364 | : controller_weak_(std::move(controller_weak)), |
Hector Dearman | 6ea67b3 | 2018-02-01 15:45:15 +0000 | [diff] [blame] | 365 | config_(config), |
Primiano Tucci | 4f9b6d7 | 2017-12-05 20:59:16 +0000 | [diff] [blame] | 366 | filter_(std::move(filter)), |
| 367 | delegate_(delegate){}; |
| 368 | |
| 369 | FtraceSink::~FtraceSink() { |
| 370 | if (controller_weak_) |
| 371 | controller_weak_->Unregister(this); |
| 372 | }; |
| 373 | |
| 374 | const std::set<std::string>& FtraceSink::enabled_events() { |
| 375 | return filter_->enabled_names(); |
| 376 | } |
| 377 | |
Primiano Tucci | 4f9b6d7 | 2017-12-05 20:59:16 +0000 | [diff] [blame] | 378 | } // namespace perfetto |