1 //===-- PerfContextSwitchDecoder.h --======----------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_PERFCONTEXTSWITCHDECODER_H 10 #define LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_PERFCONTEXTSWITCHDECODER_H 11 12 #include "lldb/Utility/TraceIntelPTGDBRemotePackets.h" 13 #include "lldb/lldb-types.h" 14 15 #include "llvm/Support/Error.h" 16 17 #include <vector> 18 19 namespace lldb_private { 20 namespace trace_intel_pt { 21 22 /// This class indicates the time interval in which a thread was running 23 /// continuously on a cpu core. 24 struct ThreadContinuousExecution { 25 26 /// In most cases both the start and end of a continuous execution can be 27 /// accurately recovered from the context switch trace, but in some cases one 28 /// of these endpoints might be guessed or not known at all, due to contention 29 /// problems in the trace or because tracing was interrupted, e.g. with ioctl 30 /// calls, which causes gaps in the trace. Because of that, we identify which 31 /// situation we fall into with the following variants. 32 enum class Variant { 33 /// Both endpoints are known. 34 Complete, 35 /// The end is known and we have a lower bound for the start, i.e. the 36 /// previous execution in the same cpu happens strictly before the hinted 37 /// start. 38 HintedStart, 39 /// The start is known and we have an upper bound for the end, i.e. the next 40 /// execution in the same cpu happens strictly after the hinted end. 41 HintedEnd, 42 /// We only know the start. This might be the last entry of a cpu trace. 43 OnlyStart, 44 /// We only know the end. This might be the first entry or a cpu trace. 45 OnlyEnd, 46 } variant; 47 48 /// \return 49 /// The lowest tsc that we are sure of, i.e. not hinted. 50 uint64_t GetLowestKnownTSC() const; 51 52 /// \return 53 /// The known or hinted start tsc, or 0 if the variant is \a OnlyEnd. 54 uint64_t GetStartTSC() const; 55 56 /// \return 57 /// The known or hinted end tsc, or max \a uint64_t if the variant is \a 58 /// OnlyStart. 59 uint64_t GetEndTSC() const; 60 61 /// Constructors for the different variants of this object 62 /// 63 /// \{ 64 static ThreadContinuousExecution 65 CreateCompleteExecution(lldb::cpu_id_t cpu_id, lldb::tid_t tid, 66 lldb::pid_t pid, uint64_t start, uint64_t end); 67 68 static ThreadContinuousExecution 69 CreateHintedStartExecution(lldb::cpu_id_t cpu_id, lldb::tid_t tid, 70 lldb::pid_t pid, uint64_t hinted_start, 71 uint64_t end); 72 73 static ThreadContinuousExecution 74 CreateHintedEndExecution(lldb::cpu_id_t cpu_id, lldb::tid_t tid, 75 lldb::pid_t pid, uint64_t start, 76 uint64_t hinted_end); 77 78 static ThreadContinuousExecution CreateOnlyEndExecution(lldb::cpu_id_t cpu_id, 79 lldb::tid_t tid, 80 lldb::pid_t pid, 81 uint64_t end); 82 83 static ThreadContinuousExecution 84 CreateOnlyStartExecution(lldb::cpu_id_t cpu_id, lldb::tid_t tid, 85 lldb::pid_t pid, uint64_t start); 86 /// \} 87 88 union { 89 struct { 90 uint64_t start; 91 uint64_t end; 92 } complete; 93 struct { 94 uint64_t start; 95 } only_start; 96 struct { 97 uint64_t end; 98 } only_end; 99 /// The following 'hinted' structures are useful when there are contention 100 /// problems in the trace 101 struct { 102 uint64_t hinted_start; 103 uint64_t end; 104 } hinted_start; 105 struct { 106 uint64_t start; 107 uint64_t hinted_end; 108 } hinted_end; 109 } tscs; 110 111 lldb::cpu_id_t cpu_id; 112 lldb::tid_t tid; 113 lldb::pid_t pid; 114 115 private: 116 /// We keep this constructor private to force the usage of the static named 117 /// constructors. 118 ThreadContinuousExecution(lldb::cpu_id_t cpu_id, lldb::tid_t tid, 119 lldb::pid_t pid) 120 : cpu_id(cpu_id), tid(tid), pid(pid) {} 121 }; 122 123 /// Decodes a context switch trace collected with perf_event_open. 124 /// 125 /// \param[in] data 126 /// The context switch trace in binary format. 127 /// 128 /// \param[i] cpu_id 129 /// The cpu_id where the trace were gotten from. 130 /// 131 /// \param[in] tsc_conversion 132 /// The conversion values used to confert nanoseconds to TSC. 133 /// 134 /// \return 135 /// A list of continuous executions recovered from the raw trace sorted by 136 /// time, or an \a llvm::Error if the data is malformed. 137 llvm::Expected<std::vector<ThreadContinuousExecution>> 138 DecodePerfContextSwitchTrace(llvm::ArrayRef<uint8_t> data, 139 lldb::cpu_id_t cpu_id, 140 const LinuxPerfZeroTscConversion &tsc_conversion); 141 142 } // namespace trace_intel_pt 143 } // namespace lldb_private 144 145 #endif // LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_PERFCONTEXTSWITCHDECODER_H 146