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 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 int64_t thread_timestamp = 0; 74 int64_t thread_instruction_count = 0; 75 int64_t counter_value = 0; 76 std::array<int64_t, 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, 111 uint64_t idx, 112 std::unique_ptr<Json::Value> value) 113 : json_value(std::move(value)), 114 timestamp(ts), 115 packet_idx(idx), 116 type(Type::kJsonValue) {} 117 TimestampedTracePieceTimestampedTracePiece118 TimestampedTracePiece(int64_t ts, 119 uint64_t idx, 120 std::unique_ptr<FuchsiaRecord> fr) 121 : fuchsia_record(std::move(fr)), 122 timestamp(ts), 123 packet_idx(idx), 124 type(Type::kFuchsiaRecord) {} 125 TimestampedTracePieceTimestampedTracePiece126 TimestampedTracePiece(int64_t ts, 127 uint64_t idx, 128 std::unique_ptr<TrackEventData> ted) 129 : track_event_data(std::move(ted)), 130 timestamp(ts), 131 packet_idx(idx), 132 type(Type::kTrackEvent) {} 133 TimestampedTracePieceTimestampedTracePiece134 TimestampedTracePiece(int64_t ts, 135 uint64_t idx, 136 std::unique_ptr<SystraceLine> ted) 137 : systrace_line(std::move(ted)), 138 timestamp(ts), 139 packet_idx(idx), 140 type(Type::kSystraceLine) {} 141 TimestampedTracePieceTimestampedTracePiece142 TimestampedTracePiece(int64_t ts, uint64_t idx, InlineSchedSwitch iss) 143 : sched_switch(std::move(iss)), 144 timestamp(ts), 145 packet_idx(idx), 146 type(Type::kInlineSchedSwitch) {} 147 TimestampedTracePieceTimestampedTracePiece148 TimestampedTracePiece(int64_t ts, uint64_t idx, InlineSchedWaking isw) 149 : sched_waking(std::move(isw)), 150 timestamp(ts), 151 packet_idx(idx), 152 type(Type::kInlineSchedWaking) {} 153 TimestampedTracePieceTimestampedTracePiece154 TimestampedTracePiece(TimestampedTracePiece&& ttp) noexcept { 155 // Adopt |ttp|'s data. We have to use placement-new to fill the fields 156 // because their original values may be uninitialized and thus 157 // move-assignment won't work correctly. 158 switch (ttp.type) { 159 case Type::kInvalid: 160 break; 161 case Type::kFtraceEvent: 162 new (&ftrace_event) FtraceEventData(std::move(ttp.ftrace_event)); 163 break; 164 case Type::kTracePacket: 165 new (&packet_data) TracePacketData(std::move(ttp.packet_data)); 166 break; 167 case Type::kInlineSchedSwitch: 168 new (&sched_switch) InlineSchedSwitch(std::move(ttp.sched_switch)); 169 break; 170 case Type::kInlineSchedWaking: 171 new (&sched_waking) InlineSchedWaking(std::move(ttp.sched_waking)); 172 break; 173 case Type::kJsonValue: 174 new (&json_value) 175 std::unique_ptr<Json::Value>(std::move(ttp.json_value)); 176 break; 177 case Type::kFuchsiaRecord: 178 new (&fuchsia_record) 179 std::unique_ptr<FuchsiaRecord>(std::move(ttp.fuchsia_record)); 180 break; 181 case Type::kTrackEvent: 182 new (&track_event_data) 183 std::unique_ptr<TrackEventData>(std::move(ttp.track_event_data)); 184 break; 185 case Type::kSystraceLine: 186 new (&systrace_line) 187 std::unique_ptr<SystraceLine>(std::move(ttp.systrace_line)); 188 } 189 timestamp = ttp.timestamp; 190 packet_idx = ttp.packet_idx; 191 type = ttp.type; 192 193 // Invalidate |ttp|. 194 ttp.type = Type::kInvalid; 195 } 196 197 TimestampedTracePiece& operator=(TimestampedTracePiece&& ttp) { 198 if (this != &ttp) { 199 // First invoke the destructor and then invoke the move constructor 200 // inline via placement-new to implement move-assignment. 201 this->~TimestampedTracePiece(); 202 new (this) TimestampedTracePiece(std::move(ttp)); 203 } 204 return *this; 205 } 206 207 TimestampedTracePiece(const TimestampedTracePiece&) = delete; 208 TimestampedTracePiece& operator=(const TimestampedTracePiece&) = delete; 209 ~TimestampedTracePieceTimestampedTracePiece210 ~TimestampedTracePiece() { 211 switch (type) { 212 case Type::kInvalid: 213 case Type::kInlineSchedSwitch: 214 case Type::kInlineSchedWaking: 215 break; 216 case Type::kFtraceEvent: 217 ftrace_event.~FtraceEventData(); 218 break; 219 case Type::kTracePacket: 220 packet_data.~TracePacketData(); 221 break; 222 case Type::kJsonValue: 223 json_value.~unique_ptr(); 224 break; 225 case Type::kFuchsiaRecord: 226 fuchsia_record.~unique_ptr(); 227 break; 228 case Type::kTrackEvent: 229 track_event_data.~unique_ptr(); 230 break; 231 case Type::kSystraceLine: 232 systrace_line.~unique_ptr(); 233 break; 234 } 235 } 236 237 // For std::lower_bound(). CompareTimestampedTracePiece238 static inline bool Compare(const TimestampedTracePiece& x, int64_t ts) { 239 return x.timestamp < ts; 240 } 241 242 // For std::sort(). 243 inline bool operator<(const TimestampedTracePiece& o) const { 244 return timestamp < o.timestamp || 245 (timestamp == o.timestamp && packet_idx < o.packet_idx); 246 } 247 248 // Fields ordered for packing. 249 250 // Data for different types of TimestampedTracePiece. 251 union { 252 FtraceEventData ftrace_event; 253 TracePacketData packet_data; 254 InlineSchedSwitch sched_switch; 255 InlineSchedWaking sched_waking; 256 std::unique_ptr<Json::Value> json_value; 257 std::unique_ptr<FuchsiaRecord> fuchsia_record; 258 std::unique_ptr<TrackEventData> track_event_data; 259 std::unique_ptr<SystraceLine> systrace_line; 260 }; 261 262 int64_t timestamp; 263 uint64_t packet_idx; 264 Type type; 265 }; 266 267 } // namespace trace_processor 268 } // namespace perfetto 269 270 #if PERFETTO_BUILDFLAG(PERFETTO_COMPILER_GCC) 271 #pragma GCC diagnostic pop 272 #endif 273 274 #endif // SRC_TRACE_PROCESSOR_TIMESTAMPED_TRACE_PIECE_H_ 275