• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 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 #ifndef SRC_TRACE_PROCESSOR_TIMESTAMPED_TRACE_PIECE_H_
18 #define SRC_TRACE_PROCESSOR_TIMESTAMPED_TRACE_PIECE_H_
19 
20 #include "perfetto/base/build_config.h"
21 #include "perfetto/trace_processor/basic_types.h"
22 #include "src/trace_processor/importers/common/trace_blob_view.h"
23 #include "src/trace_processor/importers/fuchsia/fuchsia_record.h"
24 #include "src/trace_processor/importers/json/json_utils.h"
25 #include "src/trace_processor/importers/proto/packet_sequence_state.h"
26 #include "src/trace_processor/importers/systrace/systrace_line.h"
27 #include "src/trace_processor/storage/trace_storage.h"
28 #include "src/trace_processor/types/trace_processor_context.h"
29 
30 // GCC can't figure out the relationship between TimestampedTracePiece's type
31 // and the union, and thus thinks that we may be moving or destroying
32 // uninitialized data in the move constructors / destructors. Disable those
33 // warnings for TimestampedTracePiece and the types it contains.
34 #if PERFETTO_BUILDFLAG(PERFETTO_COMPILER_GCC)
35 #pragma GCC diagnostic push
36 #pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
37 #endif
38 
39 namespace perfetto {
40 namespace trace_processor {
41 
42 struct InlineSchedSwitch {
43   int64_t prev_state;
44   int32_t next_pid;
45   int32_t next_prio;
46   StringId next_comm;
47 };
48 
49 struct InlineSchedWaking {
50   int32_t pid;
51   int32_t target_cpu;
52   int32_t prio;
53   StringId comm;
54 };
55 
56 struct TracePacketData {
57   TraceBlobView packet;
58   std::shared_ptr<PacketSequenceStateGeneration> sequence_state;
59 };
60 
61 struct FtraceEventData {
62   TraceBlobView event;
63   std::shared_ptr<PacketSequenceStateGeneration> sequence_state;
64 };
65 
66 struct TrackEventData : public TracePacketData {
TrackEventDataTrackEventData67   TrackEventData(TraceBlobView pv,
68                  std::shared_ptr<PacketSequenceStateGeneration> generation)
69       : TracePacketData{std::move(pv), std::move(generation)} {}
70 
71   static constexpr size_t kMaxNumExtraCounters = 8;
72 
73   base::Optional<int64_t> thread_timestamp;
74   base::Optional<int64_t> thread_instruction_count;
75   double counter_value = 0;
76   std::array<double, kMaxNumExtraCounters> extra_counter_values = {};
77 };
78 
79 // A TimestampedTracePiece is (usually a reference to) a piece of a trace that
80 // is sorted by TraceSorter.
81 struct TimestampedTracePiece {
82   enum class Type {
83     kInvalid = 0,
84     kFtraceEvent,
85     kTracePacket,
86     kInlineSchedSwitch,
87     kInlineSchedWaking,
88     kJsonValue,
89     kFuchsiaRecord,
90     kTrackEvent,
91     kSystraceLine,
92   };
93 
TimestampedTracePieceTimestampedTracePiece94   TimestampedTracePiece(
95       int64_t ts,
96       uint64_t idx,
97       TraceBlobView tbv,
98       std::shared_ptr<PacketSequenceStateGeneration> sequence_state)
99       : packet_data{std::move(tbv), std::move(sequence_state)},
100         timestamp(ts),
101         packet_idx(idx),
102         type(Type::kTracePacket) {}
103 
TimestampedTracePieceTimestampedTracePiece104   TimestampedTracePiece(int64_t ts, uint64_t idx, FtraceEventData fed)
105       : ftrace_event(std::move(fed)),
106         timestamp(ts),
107         packet_idx(idx),
108         type(Type::kFtraceEvent) {}
109 
TimestampedTracePieceTimestampedTracePiece110   TimestampedTracePiece(int64_t ts, uint64_t idx, std::string value)
111       : json_value(std::move(value)),
112         timestamp(ts),
113         packet_idx(idx),
114         type(Type::kJsonValue) {}
115 
TimestampedTracePieceTimestampedTracePiece116   TimestampedTracePiece(int64_t ts,
117                         uint64_t idx,
118                         std::unique_ptr<FuchsiaRecord> fr)
119       : fuchsia_record(std::move(fr)),
120         timestamp(ts),
121         packet_idx(idx),
122         type(Type::kFuchsiaRecord) {}
123 
TimestampedTracePieceTimestampedTracePiece124   TimestampedTracePiece(int64_t ts,
125                         uint64_t idx,
126                         std::unique_ptr<TrackEventData> ted)
127       : track_event_data(std::move(ted)),
128         timestamp(ts),
129         packet_idx(idx),
130         type(Type::kTrackEvent) {}
131 
TimestampedTracePieceTimestampedTracePiece132   TimestampedTracePiece(int64_t ts,
133                         uint64_t idx,
134                         std::unique_ptr<SystraceLine> ted)
135       : systrace_line(std::move(ted)),
136         timestamp(ts),
137         packet_idx(idx),
138         type(Type::kSystraceLine) {}
139 
TimestampedTracePieceTimestampedTracePiece140   TimestampedTracePiece(int64_t ts, uint64_t idx, InlineSchedSwitch iss)
141       : sched_switch(std::move(iss)),
142         timestamp(ts),
143         packet_idx(idx),
144         type(Type::kInlineSchedSwitch) {}
145 
TimestampedTracePieceTimestampedTracePiece146   TimestampedTracePiece(int64_t ts, uint64_t idx, InlineSchedWaking isw)
147       : sched_waking(std::move(isw)),
148         timestamp(ts),
149         packet_idx(idx),
150         type(Type::kInlineSchedWaking) {}
151 
TimestampedTracePieceTimestampedTracePiece152   TimestampedTracePiece(TimestampedTracePiece&& ttp) noexcept {
153     // Adopt |ttp|'s data. We have to use placement-new to fill the fields
154     // because their original values may be uninitialized and thus
155     // move-assignment won't work correctly.
156     switch (ttp.type) {
157       case Type::kInvalid:
158         break;
159       case Type::kFtraceEvent:
160         new (&ftrace_event) FtraceEventData(std::move(ttp.ftrace_event));
161         break;
162       case Type::kTracePacket:
163         new (&packet_data) TracePacketData(std::move(ttp.packet_data));
164         break;
165       case Type::kInlineSchedSwitch:
166         new (&sched_switch) InlineSchedSwitch(std::move(ttp.sched_switch));
167         break;
168       case Type::kInlineSchedWaking:
169         new (&sched_waking) InlineSchedWaking(std::move(ttp.sched_waking));
170         break;
171       case Type::kJsonValue:
172         new (&json_value) std::string(std::move(ttp.json_value));
173         break;
174       case Type::kFuchsiaRecord:
175         new (&fuchsia_record)
176             std::unique_ptr<FuchsiaRecord>(std::move(ttp.fuchsia_record));
177         break;
178       case Type::kTrackEvent:
179         new (&track_event_data)
180             std::unique_ptr<TrackEventData>(std::move(ttp.track_event_data));
181         break;
182       case Type::kSystraceLine:
183         new (&systrace_line)
184             std::unique_ptr<SystraceLine>(std::move(ttp.systrace_line));
185     }
186     timestamp = ttp.timestamp;
187     packet_idx = ttp.packet_idx;
188     type = ttp.type;
189 
190     // Invalidate |ttp|.
191     ttp.type = Type::kInvalid;
192   }
193 
194   TimestampedTracePiece& operator=(TimestampedTracePiece&& ttp) {
195     if (this != &ttp) {
196       // First invoke the destructor and then invoke the move constructor
197       // inline via placement-new to implement move-assignment.
198       this->~TimestampedTracePiece();
199       new (this) TimestampedTracePiece(std::move(ttp));
200     }
201     return *this;
202   }
203 
204   TimestampedTracePiece(const TimestampedTracePiece&) = delete;
205   TimestampedTracePiece& operator=(const TimestampedTracePiece&) = delete;
206 
~TimestampedTracePieceTimestampedTracePiece207   ~TimestampedTracePiece() {
208     switch (type) {
209       case Type::kInvalid:
210       case Type::kInlineSchedSwitch:
211       case Type::kInlineSchedWaking:
212         break;
213       case Type::kFtraceEvent:
214         ftrace_event.~FtraceEventData();
215         break;
216       case Type::kTracePacket:
217         packet_data.~TracePacketData();
218         break;
219       case Type::kJsonValue:
220         json_value.~basic_string();
221         break;
222       case Type::kFuchsiaRecord:
223         fuchsia_record.~unique_ptr();
224         break;
225       case Type::kTrackEvent:
226         track_event_data.~unique_ptr();
227         break;
228       case Type::kSystraceLine:
229         systrace_line.~unique_ptr();
230         break;
231     }
232   }
233 
234   // For std::lower_bound().
CompareTimestampedTracePiece235   static inline bool Compare(const TimestampedTracePiece& x, int64_t ts) {
236     return x.timestamp < ts;
237   }
238 
239   // For std::sort().
240   inline bool operator<(const TimestampedTracePiece& o) const {
241     return timestamp < o.timestamp ||
242            (timestamp == o.timestamp && packet_idx < o.packet_idx);
243   }
244 
245   // Fields ordered for packing.
246 
247   // Data for different types of TimestampedTracePiece.
248   union {
249     FtraceEventData ftrace_event;
250     TracePacketData packet_data;
251     InlineSchedSwitch sched_switch;
252     InlineSchedWaking sched_waking;
253     std::string json_value;
254     std::unique_ptr<FuchsiaRecord> fuchsia_record;
255     std::unique_ptr<TrackEventData> track_event_data;
256     std::unique_ptr<SystraceLine> systrace_line;
257   };
258 
259   int64_t timestamp;
260   uint64_t packet_idx;
261   Type type;
262 };
263 
264 }  // namespace trace_processor
265 }  // namespace perfetto
266 
267 #if PERFETTO_BUILDFLAG(PERFETTO_COMPILER_GCC)
268 #pragma GCC diagnostic pop
269 #endif
270 
271 #endif  // SRC_TRACE_PROCESSOR_TIMESTAMPED_TRACE_PIECE_H_
272