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