xref: /freebsd-src/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTMultiCpuDecoder.h (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
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