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