• 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/fuchsia/fuchsia_record.h"
23 #include "src/trace_processor/importers/json/json_utils.h"
24 #include "src/trace_processor/importers/proto/packet_sequence_state.h"
25 #include "src/trace_processor/importers/systrace/systrace_line.h"
26 #include "src/trace_processor/storage/trace_storage.h"
27 #include "src/trace_processor/trace_blob_view.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 
59   PacketSequenceStateGeneration* sequence_state;
60 };
61 
62 struct TrackEventData : public TracePacketData {
TrackEventDataTrackEventData63   TrackEventData(TraceBlobView pv, PacketSequenceStateGeneration* generation)
64       : TracePacketData{std::move(pv), generation} {}
65 
66   static constexpr size_t kMaxNumExtraCounters = 8;
67 
68   int64_t thread_timestamp = 0;
69   int64_t thread_instruction_count = 0;
70   int64_t counter_value = 0;
71   std::array<int64_t, kMaxNumExtraCounters> extra_counter_values = {};
72 };
73 
74 // A TimestampedTracePiece is (usually a reference to) a piece of a trace that
75 // is sorted by TraceSorter.
76 struct TimestampedTracePiece {
77   enum class Type {
78     kInvalid = 0,
79     kFtraceEvent,
80     kTracePacket,
81     kInlineSchedSwitch,
82     kInlineSchedWaking,
83     kJsonValue,
84     kFuchsiaRecord,
85     kTrackEvent,
86     kSystraceLine,
87   };
88 
TimestampedTracePieceTimestampedTracePiece89   TimestampedTracePiece(int64_t ts,
90                         uint64_t idx,
91                         TraceBlobView tbv,
92                         PacketSequenceStateGeneration* sequence_state)
93       : packet_data{std::move(tbv), sequence_state},
94         timestamp(ts),
95         packet_idx(idx),
96         type(Type::kTracePacket) {}
97 
TimestampedTracePieceTimestampedTracePiece98   TimestampedTracePiece(int64_t ts, uint64_t idx, TraceBlobView tbv)
99       : ftrace_event(std::move(tbv)),
100         timestamp(ts),
101         packet_idx(idx),
102         type(Type::kFtraceEvent) {}
103 
TimestampedTracePieceTimestampedTracePiece104   TimestampedTracePiece(int64_t ts,
105                         uint64_t idx,
106                         std::unique_ptr<Json::Value> value)
107       : json_value(std::move(value)),
108         timestamp(ts),
109         packet_idx(idx),
110         type(Type::kJsonValue) {}
111 
TimestampedTracePieceTimestampedTracePiece112   TimestampedTracePiece(int64_t ts,
113                         uint64_t idx,
114                         std::unique_ptr<FuchsiaRecord> fr)
115       : fuchsia_record(std::move(fr)),
116         timestamp(ts),
117         packet_idx(idx),
118         type(Type::kFuchsiaRecord) {}
119 
TimestampedTracePieceTimestampedTracePiece120   TimestampedTracePiece(int64_t ts,
121                         uint64_t idx,
122                         std::unique_ptr<TrackEventData> ted)
123       : track_event_data(std::move(ted)),
124         timestamp(ts),
125         packet_idx(idx),
126         type(Type::kTrackEvent) {}
127 
TimestampedTracePieceTimestampedTracePiece128   TimestampedTracePiece(int64_t ts,
129                         uint64_t idx,
130                         std::unique_ptr<SystraceLine> ted)
131       : systrace_line(std::move(ted)),
132         timestamp(ts),
133         packet_idx(idx),
134         type(Type::kSystraceLine) {}
135 
TimestampedTracePieceTimestampedTracePiece136   TimestampedTracePiece(int64_t ts, uint64_t idx, InlineSchedSwitch iss)
137       : sched_switch(std::move(iss)),
138         timestamp(ts),
139         packet_idx(idx),
140         type(Type::kInlineSchedSwitch) {}
141 
TimestampedTracePieceTimestampedTracePiece142   TimestampedTracePiece(int64_t ts, uint64_t idx, InlineSchedWaking isw)
143       : sched_waking(std::move(isw)),
144         timestamp(ts),
145         packet_idx(idx),
146         type(Type::kInlineSchedWaking) {}
147 
TimestampedTracePieceTimestampedTracePiece148   TimestampedTracePiece(TimestampedTracePiece&& ttp) noexcept {
149     // Adopt |ttp|'s data. We have to use placement-new to fill the fields
150     // because their original values may be uninitialized and thus
151     // move-assignment won't work correctly.
152     switch (ttp.type) {
153       case Type::kInvalid:
154         break;
155       case Type::kFtraceEvent:
156         new (&ftrace_event) TraceBlobView(std::move(ttp.ftrace_event));
157         break;
158       case Type::kTracePacket:
159         new (&packet_data) TracePacketData(std::move(ttp.packet_data));
160         break;
161       case Type::kInlineSchedSwitch:
162         new (&sched_switch) InlineSchedSwitch(std::move(ttp.sched_switch));
163         break;
164       case Type::kInlineSchedWaking:
165         new (&sched_waking) InlineSchedWaking(std::move(ttp.sched_waking));
166         break;
167       case Type::kJsonValue:
168         new (&json_value)
169             std::unique_ptr<Json::Value>(std::move(ttp.json_value));
170         break;
171       case Type::kFuchsiaRecord:
172         new (&fuchsia_record)
173             std::unique_ptr<FuchsiaRecord>(std::move(ttp.fuchsia_record));
174         break;
175       case Type::kTrackEvent:
176         new (&track_event_data)
177             std::unique_ptr<TrackEventData>(std::move(ttp.track_event_data));
178         break;
179       case Type::kSystraceLine:
180         new (&systrace_line)
181             std::unique_ptr<SystraceLine>(std::move(ttp.systrace_line));
182     }
183     timestamp = ttp.timestamp;
184     packet_idx = ttp.packet_idx;
185     type = ttp.type;
186 
187     // Invalidate |ttp|.
188     ttp.type = Type::kInvalid;
189   }
190 
191   TimestampedTracePiece& operator=(TimestampedTracePiece&& ttp) {
192     if (this != &ttp) {
193       // First invoke the destructor and then invoke the move constructor
194       // inline via placement-new to implement move-assignment.
195       this->~TimestampedTracePiece();
196       new (this) TimestampedTracePiece(std::move(ttp));
197     }
198     return *this;
199   }
200 
201   TimestampedTracePiece(const TimestampedTracePiece&) = delete;
202   TimestampedTracePiece& operator=(const TimestampedTracePiece&) = delete;
203 
~TimestampedTracePieceTimestampedTracePiece204   ~TimestampedTracePiece() {
205     switch (type) {
206       case Type::kInvalid:
207       case Type::kInlineSchedSwitch:
208       case Type::kInlineSchedWaking:
209         break;
210       case Type::kFtraceEvent:
211         ftrace_event.~TraceBlobView();
212         break;
213       case Type::kTracePacket:
214         packet_data.~TracePacketData();
215         break;
216       case Type::kJsonValue:
217         json_value.~unique_ptr();
218         break;
219       case Type::kFuchsiaRecord:
220         fuchsia_record.~unique_ptr();
221         break;
222       case Type::kTrackEvent:
223         track_event_data.~unique_ptr();
224         break;
225       case Type::kSystraceLine:
226         systrace_line.~unique_ptr();
227         break;
228     }
229   }
230 
231   // For std::lower_bound().
CompareTimestampedTracePiece232   static inline bool Compare(const TimestampedTracePiece& x, int64_t ts) {
233     return x.timestamp < ts;
234   }
235 
236   // For std::sort().
237   inline bool operator<(const TimestampedTracePiece& o) const {
238     return timestamp < o.timestamp ||
239            (timestamp == o.timestamp && packet_idx < o.packet_idx);
240   }
241 
242   // Fields ordered for packing.
243 
244   // Data for different types of TimestampedTracePiece.
245   union {
246     TraceBlobView ftrace_event;
247     TracePacketData packet_data;
248     InlineSchedSwitch sched_switch;
249     InlineSchedWaking sched_waking;
250     std::unique_ptr<Json::Value> json_value;
251     std::unique_ptr<FuchsiaRecord> fuchsia_record;
252     std::unique_ptr<TrackEventData> track_event_data;
253     std::unique_ptr<SystraceLine> systrace_line;
254   };
255 
256   int64_t timestamp;
257   uint64_t packet_idx;
258   Type type;
259 };
260 
261 }  // namespace trace_processor
262 }  // namespace perfetto
263 
264 #if PERFETTO_BUILDFLAG(PERFETTO_COMPILER_GCC)
265 #pragma GCC diagnostic pop
266 #endif
267 
268 #endif  // SRC_TRACE_PROCESSOR_TIMESTAMPED_TRACE_PIECE_H_
269