181ad6265SDimitry Andric //===-- PerfContextSwitchDecoder.h --======----------------------*- C++ -*-===// 281ad6265SDimitry Andric // 381ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 481ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 581ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 681ad6265SDimitry Andric // 781ad6265SDimitry Andric //===----------------------------------------------------------------------===// 881ad6265SDimitry Andric 981ad6265SDimitry Andric #ifndef LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_PERFCONTEXTSWITCHDECODER_H 1081ad6265SDimitry Andric #define LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_PERFCONTEXTSWITCHDECODER_H 1181ad6265SDimitry Andric 1281ad6265SDimitry Andric #include "lldb/Utility/TraceIntelPTGDBRemotePackets.h" 1381ad6265SDimitry Andric #include "lldb/lldb-types.h" 1481ad6265SDimitry Andric #include "llvm/Support/Error.h" 15*753f127fSDimitry Andric #include <set> 1681ad6265SDimitry Andric #include <vector> 1781ad6265SDimitry Andric 1881ad6265SDimitry Andric namespace lldb_private { 1981ad6265SDimitry Andric namespace trace_intel_pt { 2081ad6265SDimitry Andric 2181ad6265SDimitry Andric /// This class indicates the time interval in which a thread was running 2281ad6265SDimitry Andric /// continuously on a cpu core. 2381ad6265SDimitry Andric struct ThreadContinuousExecution { 2481ad6265SDimitry Andric 2581ad6265SDimitry Andric /// In most cases both the start and end of a continuous execution can be 2681ad6265SDimitry Andric /// accurately recovered from the context switch trace, but in some cases one 2781ad6265SDimitry Andric /// of these endpoints might be guessed or not known at all, due to contention 2881ad6265SDimitry Andric /// problems in the trace or because tracing was interrupted, e.g. with ioctl 2981ad6265SDimitry Andric /// calls, which causes gaps in the trace. Because of that, we identify which 3081ad6265SDimitry Andric /// situation we fall into with the following variants. 3181ad6265SDimitry Andric enum class Variant { 3281ad6265SDimitry Andric /// Both endpoints are known. 3381ad6265SDimitry Andric Complete, 3481ad6265SDimitry Andric /// The end is known and we have a lower bound for the start, i.e. the 3581ad6265SDimitry Andric /// previous execution in the same cpu happens strictly before the hinted 3681ad6265SDimitry Andric /// start. 3781ad6265SDimitry Andric HintedStart, 3881ad6265SDimitry Andric /// The start is known and we have an upper bound for the end, i.e. the next 3981ad6265SDimitry Andric /// execution in the same cpu happens strictly after the hinted end. 4081ad6265SDimitry Andric HintedEnd, 4181ad6265SDimitry Andric /// We only know the start. This might be the last entry of a cpu trace. 4281ad6265SDimitry Andric OnlyStart, 4381ad6265SDimitry Andric /// We only know the end. This might be the first entry or a cpu trace. 4481ad6265SDimitry Andric OnlyEnd, 4581ad6265SDimitry Andric } variant; 4681ad6265SDimitry Andric 4781ad6265SDimitry Andric /// \return 4881ad6265SDimitry Andric /// The lowest tsc that we are sure of, i.e. not hinted. 4981ad6265SDimitry Andric uint64_t GetLowestKnownTSC() const; 5081ad6265SDimitry Andric 5181ad6265SDimitry Andric /// \return 5281ad6265SDimitry Andric /// The known or hinted start tsc, or 0 if the variant is \a OnlyEnd. 5381ad6265SDimitry Andric uint64_t GetStartTSC() const; 5481ad6265SDimitry Andric 5581ad6265SDimitry Andric /// \return 5681ad6265SDimitry Andric /// The known or hinted end tsc, or max \a uint64_t if the variant is \a 5781ad6265SDimitry Andric /// OnlyStart. 5881ad6265SDimitry Andric uint64_t GetEndTSC() const; 5981ad6265SDimitry Andric 6081ad6265SDimitry Andric /// Constructors for the different variants of this object 6181ad6265SDimitry Andric /// 6281ad6265SDimitry Andric /// \{ 6381ad6265SDimitry Andric static ThreadContinuousExecution 6481ad6265SDimitry Andric CreateCompleteExecution(lldb::cpu_id_t cpu_id, lldb::tid_t tid, 6581ad6265SDimitry Andric lldb::pid_t pid, uint64_t start, uint64_t end); 6681ad6265SDimitry Andric 6781ad6265SDimitry Andric static ThreadContinuousExecution 6881ad6265SDimitry Andric CreateHintedStartExecution(lldb::cpu_id_t cpu_id, lldb::tid_t tid, 6981ad6265SDimitry Andric lldb::pid_t pid, uint64_t hinted_start, 7081ad6265SDimitry Andric uint64_t end); 7181ad6265SDimitry Andric 7281ad6265SDimitry Andric static ThreadContinuousExecution 7381ad6265SDimitry Andric CreateHintedEndExecution(lldb::cpu_id_t cpu_id, lldb::tid_t tid, 7481ad6265SDimitry Andric lldb::pid_t pid, uint64_t start, 7581ad6265SDimitry Andric uint64_t hinted_end); 7681ad6265SDimitry Andric 7781ad6265SDimitry Andric static ThreadContinuousExecution CreateOnlyEndExecution(lldb::cpu_id_t cpu_id, 7881ad6265SDimitry Andric lldb::tid_t tid, 7981ad6265SDimitry Andric lldb::pid_t pid, 8081ad6265SDimitry Andric uint64_t end); 8181ad6265SDimitry Andric 8281ad6265SDimitry Andric static ThreadContinuousExecution 8381ad6265SDimitry Andric CreateOnlyStartExecution(lldb::cpu_id_t cpu_id, lldb::tid_t tid, 8481ad6265SDimitry Andric lldb::pid_t pid, uint64_t start); 8581ad6265SDimitry Andric /// \} 8681ad6265SDimitry Andric 8781ad6265SDimitry Andric union { 8881ad6265SDimitry Andric struct { 8981ad6265SDimitry Andric uint64_t start; 9081ad6265SDimitry Andric uint64_t end; 9181ad6265SDimitry Andric } complete; 9281ad6265SDimitry Andric struct { 9381ad6265SDimitry Andric uint64_t start; 9481ad6265SDimitry Andric } only_start; 9581ad6265SDimitry Andric struct { 9681ad6265SDimitry Andric uint64_t end; 9781ad6265SDimitry Andric } only_end; 9881ad6265SDimitry Andric /// The following 'hinted' structures are useful when there are contention 9981ad6265SDimitry Andric /// problems in the trace 10081ad6265SDimitry Andric struct { 10181ad6265SDimitry Andric uint64_t hinted_start; 10281ad6265SDimitry Andric uint64_t end; 10381ad6265SDimitry Andric } hinted_start; 10481ad6265SDimitry Andric struct { 10581ad6265SDimitry Andric uint64_t start; 10681ad6265SDimitry Andric uint64_t hinted_end; 10781ad6265SDimitry Andric } hinted_end; 10881ad6265SDimitry Andric } tscs; 10981ad6265SDimitry Andric 11081ad6265SDimitry Andric lldb::cpu_id_t cpu_id; 11181ad6265SDimitry Andric lldb::tid_t tid; 11281ad6265SDimitry Andric lldb::pid_t pid; 11381ad6265SDimitry Andric 11481ad6265SDimitry Andric private: 11581ad6265SDimitry Andric /// We keep this constructor private to force the usage of the static named 11681ad6265SDimitry Andric /// constructors. ThreadContinuousExecutionThreadContinuousExecution11781ad6265SDimitry Andric ThreadContinuousExecution(lldb::cpu_id_t cpu_id, lldb::tid_t tid, 11881ad6265SDimitry Andric lldb::pid_t pid) 11981ad6265SDimitry Andric : cpu_id(cpu_id), tid(tid), pid(pid) {} 12081ad6265SDimitry Andric }; 12181ad6265SDimitry Andric 12281ad6265SDimitry Andric /// Decodes a context switch trace collected with perf_event_open. 12381ad6265SDimitry Andric /// 12481ad6265SDimitry Andric /// \param[in] data 12581ad6265SDimitry Andric /// The context switch trace in binary format. 12681ad6265SDimitry Andric /// 12781ad6265SDimitry Andric /// \param[i] cpu_id 12881ad6265SDimitry Andric /// The cpu_id where the trace were gotten from. 12981ad6265SDimitry Andric /// 13081ad6265SDimitry Andric /// \param[in] tsc_conversion 13181ad6265SDimitry Andric /// The conversion values used to confert nanoseconds to TSC. 13281ad6265SDimitry Andric /// 13381ad6265SDimitry Andric /// \return 13481ad6265SDimitry Andric /// A list of continuous executions recovered from the raw trace sorted by 13581ad6265SDimitry Andric /// time, or an \a llvm::Error if the data is malformed. 13681ad6265SDimitry Andric llvm::Expected<std::vector<ThreadContinuousExecution>> 13781ad6265SDimitry Andric DecodePerfContextSwitchTrace(llvm::ArrayRef<uint8_t> data, 13881ad6265SDimitry Andric lldb::cpu_id_t cpu_id, 13981ad6265SDimitry Andric const LinuxPerfZeroTscConversion &tsc_conversion); 14081ad6265SDimitry Andric 141*753f127fSDimitry Andric llvm::Expected<std::vector<uint8_t>> 142*753f127fSDimitry Andric FilterProcessesFromContextSwitchTrace(llvm::ArrayRef<uint8_t> data, 143*753f127fSDimitry Andric const std::set<lldb::pid_t> &pids); 144*753f127fSDimitry Andric 14581ad6265SDimitry Andric } // namespace trace_intel_pt 14681ad6265SDimitry Andric } // namespace lldb_private 14781ad6265SDimitry Andric 14881ad6265SDimitry Andric #endif // LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_PERFCONTEXTSWITCHDECODER_H 149