181ad6265SDimitry Andric //===-- TraceIntelPTMultiCpuDecoder.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_TRACEINTELPTMULTICPUDECODER_H 1081ad6265SDimitry Andric #define LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_TRACEINTELPTMULTICPUDECODER_H 1181ad6265SDimitry Andric 1281ad6265SDimitry Andric #include "LibiptDecoder.h" 1381ad6265SDimitry Andric #include "PerfContextSwitchDecoder.h" 1481ad6265SDimitry Andric #include "ThreadDecoder.h" 1581ad6265SDimitry Andric #include "forward-declarations.h" 16*bdd1243dSDimitry Andric #include <optional> 1781ad6265SDimitry Andric 1881ad6265SDimitry Andric namespace lldb_private { 1981ad6265SDimitry Andric namespace trace_intel_pt { 2081ad6265SDimitry Andric 2181ad6265SDimitry Andric /// Class used to decode a multi-cpu Intel PT trace. It assumes that each 2281ad6265SDimitry Andric /// thread could have potentially been executed on different cpu cores. It uses 2381ad6265SDimitry Andric /// a context switch trace per CPU with timestamps to identify which thread owns 2481ad6265SDimitry Andric /// each Intel PT decoded instruction and in which order. It also assumes that 2581ad6265SDimitry Andric /// the Intel PT data and context switches might have gaps in their traces due 2681ad6265SDimitry Andric /// to contention or race conditions. Finally, it assumes that a tid is not 2781ad6265SDimitry Andric /// repeated twice for two different threads because of the shortness of the 2881ad6265SDimitry Andric /// intel pt trace. 2981ad6265SDimitry Andric /// 3081ad6265SDimitry Andric /// This object should be recreated after every stop in the case of live 3181ad6265SDimitry Andric /// processes. 3281ad6265SDimitry Andric class TraceIntelPTMultiCpuDecoder { 3381ad6265SDimitry Andric public: 3481ad6265SDimitry Andric /// \param[in] TraceIntelPT 3581ad6265SDimitry Andric /// The trace object to be decoded 3681ad6265SDimitry Andric TraceIntelPTMultiCpuDecoder(TraceIntelPTSP trace_sp); 3781ad6265SDimitry Andric 3881ad6265SDimitry Andric /// \return 3981ad6265SDimitry Andric /// A \a DecodedThread for the \p thread by decoding its instructions on all 4081ad6265SDimitry Andric /// CPUs, sorted by TSCs. An \a llvm::Error is returned if the decoder 4181ad6265SDimitry Andric /// couldn't be properly set up. 4281ad6265SDimitry Andric llvm::Expected<DecodedThreadSP> Decode(Thread &thread); 4381ad6265SDimitry Andric 4481ad6265SDimitry Andric /// \return 4581ad6265SDimitry Andric /// \b true if the given \p tid is managed by this decoder, regardless of 4681ad6265SDimitry Andric /// whether there's tracing data associated to it or not. 4781ad6265SDimitry Andric bool TracesThread(lldb::tid_t tid) const; 4881ad6265SDimitry Andric 4981ad6265SDimitry Andric /// \return 5081ad6265SDimitry Andric /// The number of continuous executions found for the given \p tid. 5181ad6265SDimitry Andric size_t GetNumContinuousExecutionsForThread(lldb::tid_t tid) const; 5281ad6265SDimitry Andric 5381ad6265SDimitry Andric /// \return 54753f127fSDimitry Andric /// The number of PSB blocks for a given thread in all cores. 55753f127fSDimitry Andric size_t GePSBBlocksCountForThread(lldb::tid_t tid) const; 56753f127fSDimitry Andric 57753f127fSDimitry Andric /// \return 5881ad6265SDimitry Andric /// The total number of continuous executions found across CPUs. 5981ad6265SDimitry Andric size_t GetTotalContinuousExecutionsCount() const; 6081ad6265SDimitry Andric 61753f127fSDimitry Andric /// \return 62753f127fSDimitry Andric /// The number of psb blocks in all cores that couldn't be matched with a 63753f127fSDimitry Andric /// thread execution coming from context switch traces. 64753f127fSDimitry Andric size_t GetUnattributedPSBBlocksCount() const; 65753f127fSDimitry Andric 66753f127fSDimitry Andric /// \return 67753f127fSDimitry Andric /// The total number of PSB blocks in all cores. 68753f127fSDimitry Andric size_t GetTotalPSBBlocksCount() const; 69753f127fSDimitry Andric 70972a253aSDimitry Andric /// \return 71*bdd1243dSDimitry Andric /// The lowest TSC value in this trace if available, \a std::nullopt if 72*bdd1243dSDimitry Andric /// the trace is empty or the trace contains no timing information, or an 73*bdd1243dSDimitry Andric /// \a llvm::Error if it was not possible to set up the decoder. 74*bdd1243dSDimitry Andric llvm::Expected<std::optional<uint64_t>> FindLowestTSC(); 75972a253aSDimitry Andric 7681ad6265SDimitry Andric private: 7781ad6265SDimitry Andric /// Traverse the context switch traces and the basic intel pt continuous 7881ad6265SDimitry Andric /// subtraces and produce a list of continuous executions for each process and 7981ad6265SDimitry Andric /// thread. 8081ad6265SDimitry Andric /// 8181ad6265SDimitry Andric /// See \a DoCorrelateContextSwitchesAndIntelPtTraces. 8281ad6265SDimitry Andric /// 8381ad6265SDimitry Andric /// Any errors are stored in \a m_setup_error. 8481ad6265SDimitry Andric llvm::Error CorrelateContextSwitchesAndIntelPtTraces(); 8581ad6265SDimitry Andric 8681ad6265SDimitry Andric /// Produce a mapping from thread ids to the list of continuos executions with 8781ad6265SDimitry Andric /// their associated intel pt subtraces. 8881ad6265SDimitry Andric llvm::Expected< 8981ad6265SDimitry Andric llvm::DenseMap<lldb::tid_t, std::vector<IntelPTThreadContinousExecution>>> 9081ad6265SDimitry Andric DoCorrelateContextSwitchesAndIntelPtTraces(); 9181ad6265SDimitry Andric 9281ad6265SDimitry Andric TraceIntelPTSP GetTrace(); 9381ad6265SDimitry Andric 9481ad6265SDimitry Andric std::weak_ptr<TraceIntelPT> m_trace_wp; 9581ad6265SDimitry Andric std::set<lldb::tid_t> m_tids; 96*bdd1243dSDimitry Andric std::optional< 9781ad6265SDimitry Andric llvm::DenseMap<lldb::tid_t, std::vector<IntelPTThreadContinousExecution>>> 9881ad6265SDimitry Andric m_continuous_executions_per_thread; 9981ad6265SDimitry Andric llvm::DenseMap<lldb::tid_t, DecodedThreadSP> m_decoded_threads; 100*bdd1243dSDimitry Andric /// This variable will not be std::nullopt if a severe error happened during 101*bdd1243dSDimitry Andric /// the setup of the decoder and we don't want decoding to be reattempted. 102*bdd1243dSDimitry Andric std::optional<std::string> m_setup_error; 103753f127fSDimitry Andric uint64_t m_unattributed_psb_blocks = 0; 104753f127fSDimitry Andric uint64_t m_total_psb_blocks = 0; 10581ad6265SDimitry Andric }; 10681ad6265SDimitry Andric 10781ad6265SDimitry Andric } // namespace trace_intel_pt 10881ad6265SDimitry Andric } // namespace lldb_private 10981ad6265SDimitry Andric 11081ad6265SDimitry Andric #endif // LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_TRACEINTELPTMULTICPUDECODER_H 111