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