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