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