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