1 /*
2 * Copyright (C) 2020 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/tracing/internal/interceptor_trace_writer.h"
18
19 #include "perfetto/ext/tracing/core/trace_writer.h"
20
21 namespace perfetto {
22 namespace internal {
23
24 // static
25 std::atomic<uint32_t> InterceptorTraceWriter::next_sequence_id_{};
26
InterceptorTraceWriter(std::unique_ptr<InterceptorBase::ThreadLocalState> tls,InterceptorBase::TracePacketCallback packet_callback,DataSourceStaticState * static_state,uint32_t instance_index)27 InterceptorTraceWriter::InterceptorTraceWriter(
28 std::unique_ptr<InterceptorBase::ThreadLocalState> tls,
29 InterceptorBase::TracePacketCallback packet_callback,
30 DataSourceStaticState* static_state,
31 uint32_t instance_index)
32 : tls_(std::move(tls)),
33 packet_callback_(std::move(packet_callback)),
34 static_state_(static_state),
35 instance_index_(instance_index),
36 sequence_id_(++next_sequence_id_) {}
37
38 InterceptorTraceWriter::~InterceptorTraceWriter() = default;
39
40 protozero::MessageHandle<protos::pbzero::TracePacket>
NewTracePacket()41 InterceptorTraceWriter::NewTracePacket() {
42 Flush();
43 auto packet = TraceWriter::TracePacketHandle(cur_packet_.get());
44 packet->set_trusted_packet_sequence_id(sequence_id_);
45 return packet;
46 }
47
Flush(std::function<void ()> callback)48 void InterceptorTraceWriter::Flush(std::function<void()> callback) {
49 if (!cur_packet_.empty()) {
50 InterceptorBase::TracePacketCallbackArgs args{};
51 args.static_state = static_state_;
52 args.instance_index = instance_index_;
53 args.tls = tls_.get();
54
55 const auto& slices = cur_packet_.GetSlices();
56 if (slices.size() == 1) {
57 // Fast path: the current packet fits into a single slice.
58 auto slice_range = slices.begin()->GetUsedRange();
59 args.packet_data = protozero::ConstBytes{
60 slice_range.begin,
61 static_cast<size_t>(slice_range.end - slice_range.begin)};
62 bytes_written_ += static_cast<uint64_t>(args.packet_data.size);
63 packet_callback_(std::move(args));
64 } else {
65 // Fallback: stitch together multiple slices.
66 auto stitched_data = cur_packet_.SerializeAsArray();
67 args.packet_data =
68 protozero::ConstBytes{stitched_data.data(), stitched_data.size()};
69 bytes_written_ += static_cast<uint64_t>(stitched_data.size());
70 packet_callback_(std::move(args));
71 }
72 cur_packet_.Reset();
73 }
74 if (callback)
75 callback();
76 }
77
written() const78 uint64_t InterceptorTraceWriter::written() const {
79 return bytes_written_;
80 }
81
82 } // namespace internal
83 } // namespace perfetto
84