• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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