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