1//===-- PerfContextSwitchDecoder.h --======----------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_PERFCONTEXTSWITCHDECODER_H
10#define LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_PERFCONTEXTSWITCHDECODER_H
11
12#include "lldb/Utility/TraceIntelPTGDBRemotePackets.h"
13#include "lldb/lldb-types.h"
14#include "llvm/Support/Error.h"
15#include <set>
16#include <vector>
17
18namespace lldb_private {
19namespace trace_intel_pt {
20
21/// This class indicates the time interval in which a thread was running
22/// continuously on a cpu core.
23struct ThreadContinuousExecution {
24
25 /// In most cases both the start and end of a continuous execution can be
26 /// accurately recovered from the context switch trace, but in some cases one
27 /// of these endpoints might be guessed or not known at all, due to contention
28 /// problems in the trace or because tracing was interrupted, e.g. with ioctl
29 /// calls, which causes gaps in the trace. Because of that, we identify which
30 /// situation we fall into with the following variants.
31 enum class Variant {
32 /// Both endpoints are known.
33 Complete,
34 /// The end is known and we have a lower bound for the start, i.e. the
35 /// previous execution in the same cpu happens strictly before the hinted
36 /// start.
37 HintedStart,
38 /// The start is known and we have an upper bound for the end, i.e. the next
39 /// execution in the same cpu happens strictly after the hinted end.
40 HintedEnd,
41 /// We only know the start. This might be the last entry of a cpu trace.
42 OnlyStart,
43 /// We only know the end. This might be the first entry or a cpu trace.
44 OnlyEnd,
45 } variant;
46
47 /// \return
48 /// The lowest tsc that we are sure of, i.e. not hinted.
49 uint64_t GetLowestKnownTSC() const;
50
51 /// \return
52 /// The known or hinted start tsc, or 0 if the variant is \a OnlyEnd.
53 uint64_t GetStartTSC() const;
54
55 /// \return
56 /// The known or hinted end tsc, or max \a uint64_t if the variant is \a
57 /// OnlyStart.
58 uint64_t GetEndTSC() const;
59
60 /// Constructors for the different variants of this object
61 ///
62 /// \{
63 static ThreadContinuousExecution
64 CreateCompleteExecution(lldb::cpu_id_t cpu_id, lldb::tid_t tid,
65 lldb::pid_t pid, uint64_t start, uint64_t end);
66
67 static ThreadContinuousExecution
68 CreateHintedStartExecution(lldb::cpu_id_t cpu_id, lldb::tid_t tid,
69 lldb::pid_t pid, uint64_t hinted_start,
70 uint64_t end);
71
72 static ThreadContinuousExecution
73 CreateHintedEndExecution(lldb::cpu_id_t cpu_id, lldb::tid_t tid,
74 lldb::pid_t pid, uint64_t start,
75 uint64_t hinted_end);
76
77 static ThreadContinuousExecution CreateOnlyEndExecution(lldb::cpu_id_t cpu_id,
78 lldb::tid_t tid,
79 lldb::pid_t pid,
80 uint64_t end);
81
82 static ThreadContinuousExecution
83 CreateOnlyStartExecution(lldb::cpu_id_t cpu_id, lldb::tid_t tid,
84 lldb::pid_t pid, uint64_t start);
85 /// \}
86
87 union {
88 struct {
89 uint64_t start;
90 uint64_t end;
91 } complete;
92 struct {
93 uint64_t start;
94 } only_start;
95 struct {
96 uint64_t end;
97 } only_end;
98 /// The following 'hinted' structures are useful when there are contention
99 /// problems in the trace
100 struct {
101 uint64_t hinted_start;
102 uint64_t end;
103 } hinted_start;
104 struct {
105 uint64_t start;
106 uint64_t hinted_end;
107 } hinted_end;
108 } tscs;
109
110 lldb::cpu_id_t cpu_id;
111 lldb::tid_t tid;
112 lldb::pid_t pid;
113
114private:
115 /// We keep this constructor private to force the usage of the static named
116 /// constructors.
117 ThreadContinuousExecution(lldb::cpu_id_t cpu_id, lldb::tid_t tid,
118 lldb::pid_t pid)
119 : cpu_id(cpu_id), tid(tid), pid(pid) {}
120};
121
122/// Decodes a context switch trace collected with perf_event_open.
123///
124/// \param[in] data
125/// The context switch trace in binary format.
126///
127/// \param[i] cpu_id
128/// The cpu_id where the trace were gotten from.
129///
130/// \param[in] tsc_conversion
131/// The conversion values used to confert nanoseconds to TSC.
132///
133/// \return
134/// A list of continuous executions recovered from the raw trace sorted by
135/// time, or an \a llvm::Error if the data is malformed.
136llvm::Expected<std::vector<ThreadContinuousExecution>>
137DecodePerfContextSwitchTrace(llvm::ArrayRef<uint8_t> data,
138 lldb::cpu_id_t cpu_id,
139 const LinuxPerfZeroTscConversion &tsc_conversion);
140
141llvm::Expected<std::vector<uint8_t>>
142FilterProcessesFromContextSwitchTrace(llvm::ArrayRef<uint8_t> data,
143 const std::set<lldb::pid_t> &pids);
144
145} // namespace trace_intel_pt
146} // namespace lldb_private
147
148#endif // LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_PERFCONTEXTSWITCHDECODER_H
149

source code of lldb/source/Plugins/Trace/intel-pt/PerfContextSwitchDecoder.h