xref: /openbsd-src/gnu/llvm/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTMultiCpuDecoder.h (revision f6aab3d83b51b91c24247ad2c2573574de475a82)
1*f6aab3d8Srobert //===-- TraceIntelPTMultiCpuDecoder.h ---------------------------*- C++ -*-===//
2*f6aab3d8Srobert //
3*f6aab3d8Srobert // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*f6aab3d8Srobert // See https://llvm.org/LICENSE.txt for license information.
5*f6aab3d8Srobert // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*f6aab3d8Srobert //
7*f6aab3d8Srobert //===----------------------------------------------------------------------===//
8*f6aab3d8Srobert 
9*f6aab3d8Srobert #ifndef LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_TRACEINTELPTMULTICPUDECODER_H
10*f6aab3d8Srobert #define LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_TRACEINTELPTMULTICPUDECODER_H
11*f6aab3d8Srobert 
12*f6aab3d8Srobert #include "LibiptDecoder.h"
13*f6aab3d8Srobert #include "PerfContextSwitchDecoder.h"
14*f6aab3d8Srobert #include "ThreadDecoder.h"
15*f6aab3d8Srobert #include "forward-declarations.h"
16*f6aab3d8Srobert #include <optional>
17*f6aab3d8Srobert 
18*f6aab3d8Srobert namespace lldb_private {
19*f6aab3d8Srobert namespace trace_intel_pt {
20*f6aab3d8Srobert 
21*f6aab3d8Srobert /// Class used to decode a multi-cpu Intel PT trace. It assumes that each
22*f6aab3d8Srobert /// thread could have potentially been executed on different cpu cores. It uses
23*f6aab3d8Srobert /// a context switch trace per CPU with timestamps to identify which thread owns
24*f6aab3d8Srobert /// each Intel PT decoded instruction and in which order. It also assumes that
25*f6aab3d8Srobert /// the Intel PT data and context switches might have gaps in their traces due
26*f6aab3d8Srobert /// to contention or race conditions. Finally, it assumes that a tid is not
27*f6aab3d8Srobert /// repeated twice for two different threads because of the shortness of the
28*f6aab3d8Srobert /// intel pt trace.
29*f6aab3d8Srobert ///
30*f6aab3d8Srobert /// This object should be recreated after every stop in the case of live
31*f6aab3d8Srobert /// processes.
32*f6aab3d8Srobert class TraceIntelPTMultiCpuDecoder {
33*f6aab3d8Srobert public:
34*f6aab3d8Srobert   /// \param[in] TraceIntelPT
35*f6aab3d8Srobert   ///   The trace object to be decoded
36*f6aab3d8Srobert   TraceIntelPTMultiCpuDecoder(TraceIntelPTSP trace_sp);
37*f6aab3d8Srobert 
38*f6aab3d8Srobert   /// \return
39*f6aab3d8Srobert   ///   A \a DecodedThread for the \p thread by decoding its instructions on all
40*f6aab3d8Srobert   ///   CPUs, sorted by TSCs. An \a llvm::Error is returned if the decoder
41*f6aab3d8Srobert   ///   couldn't be properly set up.
42*f6aab3d8Srobert   llvm::Expected<DecodedThreadSP> Decode(Thread &thread);
43*f6aab3d8Srobert 
44*f6aab3d8Srobert   /// \return
45*f6aab3d8Srobert   ///   \b true if the given \p tid is managed by this decoder, regardless of
46*f6aab3d8Srobert   ///   whether there's tracing data associated to it or not.
47*f6aab3d8Srobert   bool TracesThread(lldb::tid_t tid) const;
48*f6aab3d8Srobert 
49*f6aab3d8Srobert   /// \return
50*f6aab3d8Srobert   ///   The number of continuous executions found for the given \p tid.
51*f6aab3d8Srobert   size_t GetNumContinuousExecutionsForThread(lldb::tid_t tid) const;
52*f6aab3d8Srobert 
53*f6aab3d8Srobert   /// \return
54*f6aab3d8Srobert   ///   The number of PSB blocks for a given thread in all cores.
55*f6aab3d8Srobert   size_t GePSBBlocksCountForThread(lldb::tid_t tid) const;
56*f6aab3d8Srobert 
57*f6aab3d8Srobert   /// \return
58*f6aab3d8Srobert   ///   The total number of continuous executions found across CPUs.
59*f6aab3d8Srobert   size_t GetTotalContinuousExecutionsCount() const;
60*f6aab3d8Srobert 
61*f6aab3d8Srobert   /// \return
62*f6aab3d8Srobert   ///   The number of psb blocks in all cores that couldn't be matched with a
63*f6aab3d8Srobert   ///   thread execution coming from context switch traces.
64*f6aab3d8Srobert   size_t GetUnattributedPSBBlocksCount() const;
65*f6aab3d8Srobert 
66*f6aab3d8Srobert   /// \return
67*f6aab3d8Srobert   ///   The total number of PSB blocks in all cores.
68*f6aab3d8Srobert   size_t GetTotalPSBBlocksCount() const;
69*f6aab3d8Srobert 
70*f6aab3d8Srobert   /// \return
71*f6aab3d8Srobert   ///     The lowest TSC value in this trace if available, \a std::nullopt if
72*f6aab3d8Srobert   ///     the trace is empty or the trace contains no timing information, or an
73*f6aab3d8Srobert   ///     \a llvm::Error if it was not possible to set up the decoder.
74*f6aab3d8Srobert   llvm::Expected<std::optional<uint64_t>> FindLowestTSC();
75*f6aab3d8Srobert 
76*f6aab3d8Srobert private:
77*f6aab3d8Srobert   /// Traverse the context switch traces and the basic intel pt continuous
78*f6aab3d8Srobert   /// subtraces and produce a list of continuous executions for each process and
79*f6aab3d8Srobert   /// thread.
80*f6aab3d8Srobert   ///
81*f6aab3d8Srobert   /// See \a DoCorrelateContextSwitchesAndIntelPtTraces.
82*f6aab3d8Srobert   ///
83*f6aab3d8Srobert   /// Any errors are stored in \a m_setup_error.
84*f6aab3d8Srobert   llvm::Error CorrelateContextSwitchesAndIntelPtTraces();
85*f6aab3d8Srobert 
86*f6aab3d8Srobert   /// Produce a mapping from thread ids to the list of continuos executions with
87*f6aab3d8Srobert   /// their associated intel pt subtraces.
88*f6aab3d8Srobert   llvm::Expected<
89*f6aab3d8Srobert       llvm::DenseMap<lldb::tid_t, std::vector<IntelPTThreadContinousExecution>>>
90*f6aab3d8Srobert   DoCorrelateContextSwitchesAndIntelPtTraces();
91*f6aab3d8Srobert 
92*f6aab3d8Srobert   TraceIntelPTSP GetTrace();
93*f6aab3d8Srobert 
94*f6aab3d8Srobert   std::weak_ptr<TraceIntelPT> m_trace_wp;
95*f6aab3d8Srobert   std::set<lldb::tid_t> m_tids;
96*f6aab3d8Srobert   std::optional<
97*f6aab3d8Srobert       llvm::DenseMap<lldb::tid_t, std::vector<IntelPTThreadContinousExecution>>>
98*f6aab3d8Srobert       m_continuous_executions_per_thread;
99*f6aab3d8Srobert   llvm::DenseMap<lldb::tid_t, DecodedThreadSP> m_decoded_threads;
100*f6aab3d8Srobert   /// This variable will not be std::nullopt if a severe error happened during
101*f6aab3d8Srobert   /// the setup of the decoder and we don't want decoding to be reattempted.
102*f6aab3d8Srobert   std::optional<std::string> m_setup_error;
103*f6aab3d8Srobert   uint64_t m_unattributed_psb_blocks = 0;
104*f6aab3d8Srobert   uint64_t m_total_psb_blocks = 0;
105*f6aab3d8Srobert };
106*f6aab3d8Srobert 
107*f6aab3d8Srobert } // namespace trace_intel_pt
108*f6aab3d8Srobert } // namespace lldb_private
109*f6aab3d8Srobert 
110*f6aab3d8Srobert #endif // LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_TRACEINTELPTMULTICPUDECODER_H
111