/* * Copyright (C) 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "src/tracing/core/metatrace_writer.h" #include "perfetto/base/logging.h" #include "perfetto/base/task_runner.h" #include "perfetto/ext/tracing/core/trace_writer.h" #include "perfetto/tracing/core/data_source_descriptor.h" #include "protos/perfetto/trace/perfetto/perfetto_metatrace.pbzero.h" #include "protos/perfetto/trace/trace_packet.pbzero.h" namespace perfetto { // static constexpr char MetatraceWriter::kDataSourceName[]; MetatraceWriter::MetatraceWriter() : weak_ptr_factory_(this) {} MetatraceWriter::~MetatraceWriter() { Disable(); } void MetatraceWriter::Enable(base::TaskRunner* task_runner, std::unique_ptr trace_writer, uint32_t tags) { PERFETTO_DCHECK_THREAD(thread_checker_); if (started_) { PERFETTO_DFATAL_OR_ELOG("Metatrace already started from this instance"); return; } task_runner_ = task_runner; trace_writer_ = std::move(trace_writer); auto weak_ptr = weak_ptr_factory_.GetWeakPtr(); bool enabled = metatrace::Enable( [weak_ptr] { if (weak_ptr) weak_ptr->WriteAllAvailableEvents(); }, task_runner, tags); if (!enabled) return; started_ = true; } void MetatraceWriter::Disable() { PERFETTO_DCHECK_THREAD(thread_checker_); if (!started_) return; metatrace::Disable(); started_ = false; trace_writer_.reset(); } void MetatraceWriter::WriteAllAvailableEvents() { PERFETTO_DCHECK_THREAD(thread_checker_); if (!started_) return; for (auto it = metatrace::RingBuffer::GetReadIterator(); it; ++it) { auto type_and_id = it->type_and_id.load(std::memory_order_acquire); if (type_and_id == 0) break; // Stop at the first incomplete event. auto packet = trace_writer_->NewTracePacket(); packet->set_timestamp(it->timestamp_ns()); auto* evt = packet->set_perfetto_metatrace(); uint16_t type = type_and_id & metatrace::Record::kTypeMask; uint16_t id = type_and_id & ~metatrace::Record::kTypeMask; if (type == metatrace::Record::kTypeCounter) { evt->set_counter_id(id); evt->set_counter_value(it->counter_value); } else { evt->set_event_id(id); evt->set_event_duration_ns(it->duration_ns); } evt->set_thread_id(static_cast(it->thread_id)); if (metatrace::RingBuffer::has_overruns()) evt->set_has_overruns(true); } // The |it| destructor will automatically update the read index position in // the meta-trace ring buffer. } void MetatraceWriter::WriteAllAndFlushTraceWriter( std::function callback) { PERFETTO_DCHECK_THREAD(thread_checker_); if (!started_) return; WriteAllAvailableEvents(); trace_writer_->Flush(std::move(callback)); } } // namespace perfetto