1 /*
2  * Copyright (C) 2019 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 "src/tracing/core/metatrace_writer.h"
18 
19 #include "perfetto/base/logging.h"
20 #include "perfetto/base/task_runner.h"
21 #include "perfetto/ext/tracing/core/trace_writer.h"
22 #include "perfetto/tracing/core/data_source_descriptor.h"
23 
24 #include "protos/perfetto/trace/perfetto/perfetto_metatrace.pbzero.h"
25 #include "protos/perfetto/trace/trace_packet.pbzero.h"
26 
27 namespace perfetto {
28 
29 // static
30 constexpr char MetatraceWriter::kDataSourceName[];
31 
MetatraceWriter()32 MetatraceWriter::MetatraceWriter() : weak_ptr_factory_(this) {}
33 
~MetatraceWriter()34 MetatraceWriter::~MetatraceWriter() {
35   Disable();
36 }
37 
Enable(base::TaskRunner * task_runner,std::unique_ptr<TraceWriter> trace_writer,uint32_t tags)38 void MetatraceWriter::Enable(base::TaskRunner* task_runner,
39                              std::unique_ptr<TraceWriter> trace_writer,
40                              uint32_t tags) {
41   PERFETTO_DCHECK_THREAD(thread_checker_);
42   if (started_) {
43     PERFETTO_DFATAL_OR_ELOG("Metatrace already started from this instance");
44     return;
45   }
46   task_runner_ = task_runner;
47   trace_writer_ = std::move(trace_writer);
48   auto weak_ptr = weak_ptr_factory_.GetWeakPtr();
49   bool enabled = metatrace::Enable(
50       [weak_ptr] {
51         if (weak_ptr)
52           weak_ptr->WriteAllAvailableEvents();
53       },
54       task_runner, tags);
55   if (!enabled)
56     return;
57   started_ = true;
58 }
59 
Disable()60 void MetatraceWriter::Disable() {
61   PERFETTO_DCHECK_THREAD(thread_checker_);
62   if (!started_)
63     return;
64   metatrace::Disable();
65   started_ = false;
66   trace_writer_.reset();
67 }
68 
WriteAllAvailableEvents()69 void MetatraceWriter::WriteAllAvailableEvents() {
70   PERFETTO_DCHECK_THREAD(thread_checker_);
71   if (!started_)
72     return;
73   for (auto it = metatrace::RingBuffer::GetReadIterator(); it; ++it) {
74     auto type_and_id = it->type_and_id.load(std::memory_order_acquire);
75     if (type_and_id == 0)
76       break;  // Stop at the first incomplete event.
77 
78     auto packet = trace_writer_->NewTracePacket();
79     packet->set_timestamp(it->timestamp_ns());
80     auto* evt = packet->set_perfetto_metatrace();
81     uint16_t type = type_and_id & metatrace::Record::kTypeMask;
82     uint16_t id = type_and_id & ~metatrace::Record::kTypeMask;
83     if (type == metatrace::Record::kTypeCounter) {
84       evt->set_counter_id(id);
85       evt->set_counter_value(it->counter_value);
86     } else {
87       evt->set_event_id(id);
88       evt->set_event_duration_ns(it->duration_ns);
89     }
90 
91     evt->set_thread_id(static_cast<uint32_t>(it->thread_id));
92 
93     if (metatrace::RingBuffer::has_overruns())
94       evt->set_has_overruns(true);
95   }
96   // The |it| destructor will automatically update the read index position in
97   // the meta-trace ring buffer.
98 }
99 
WriteAllAndFlushTraceWriter(std::function<void ()> callback)100 void MetatraceWriter::WriteAllAndFlushTraceWriter(
101     std::function<void()> callback) {
102   PERFETTO_DCHECK_THREAD(thread_checker_);
103   if (!started_)
104     return;
105   WriteAllAvailableEvents();
106   trace_writer_->Flush(std::move(callback));
107 }
108 
109 }  // namespace perfetto
110