blob: 8d121a6b760715315ec82fc5822e40b5b0dfff2e (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
|
/*
* 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 {
MetatraceWriter::MetatraceWriter() : weak_ptr_factory_(this) {}
MetatraceWriter::~MetatraceWriter() {
Disable();
}
void MetatraceWriter::Enable(base::TaskRunner* task_runner,
std::unique_ptr<TraceWriter> 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<uint32_t>(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<void()> callback) {
PERFETTO_DCHECK_THREAD(thread_checker_);
if (!started_)
return;
WriteAllAvailableEvents();
trace_writer_->Flush(std::move(callback));
}
} // namespace perfetto
|