[Lldb-commits] [lldb] b8d1776 - [trace][intelpt] Support system-wide tracing [2] - Add a dummy --per-core-tracing option
Walter Erquinigo via lldb-commits
lldb-commits at lists.llvm.org
Mon May 9 16:05:34 PDT 2022
Author: Walter Erquinigo
Date: 2022-05-09T16:05:26-07:00
New Revision: b8d1776fc58d56af30d446386788e377d25dd512
URL: https://github.com/llvm/llvm-project/commit/b8d1776fc58d56af30d446386788e377d25dd512
DIFF: https://github.com/llvm/llvm-project/commit/b8d1776fc58d56af30d446386788e377d25dd512.diff
LOG: [trace][intelpt] Support system-wide tracing [2] - Add a dummy --per-core-tracing option
This updates the documentation of the gdb-remote protocol, as well as the help messages, to include the new --per-core-tracing option.
Differential Revision: https://reviews.llvm.org/D124640
Added:
Modified:
lldb/docs/lldb-gdb-remote.txt
lldb/include/lldb/Utility/TraceIntelPTGDBRemotePackets.h
lldb/packages/Python/lldbsuite/test/tools/intelpt/intelpt_testcase.py
lldb/source/Plugins/Process/Linux/IntelPTCollector.cpp
lldb/source/Plugins/Trace/intel-pt/CommandObjectTraceStartIntelPT.cpp
lldb/source/Plugins/Trace/intel-pt/CommandObjectTraceStartIntelPT.h
lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.cpp
lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.h
lldb/source/Plugins/Trace/intel-pt/TraceIntelPTConstants.h
lldb/source/Plugins/Trace/intel-pt/TraceIntelPTOptions.td
lldb/source/Utility/TraceIntelPTGDBRemotePackets.cpp
lldb/test/API/commands/trace/TestTraceStartStop.py
lldb/test/API/commands/trace/multiple-threads/TestTraceStartStopMultipleThreads.py
Removed:
################################################################################
diff --git a/lldb/docs/lldb-gdb-remote.txt b/lldb/docs/lldb-gdb-remote.txt
index 545fbb46ae242..50a47ccf50bfb 100644
--- a/lldb/docs/lldb-gdb-remote.txt
+++ b/lldb/docs/lldb-gdb-remote.txt
@@ -283,7 +283,7 @@ read packet: {"name":<name>, "description":<description>}/E<error code>;AAAAAAAA
// Tracing technology name, e.g. intel-pt, arm-coresight.
//
// /* thread tracing only */
-// "tids": [<decimal integer>],
+// "tids"?: [<decimal integer>],
// Individual threads to trace.
//
// ... other parameters specific to the provided tracing type
@@ -298,16 +298,25 @@ read packet: {"name":<name>, "description":<description>}/E<error code>;AAAAAAAA
// INTEL-PT
// intel-pt supports both "thread tracing" and "process tracing".
//
-// "Process tracing" is implemented by tracing each thread individually, but
-// managed by the same "process trace" instance.
-// Each actual thread trace, either from "process tracing" or "thread tracing",
+// "Process tracing" is implemented in two
diff erent ways. If the
+// "perCoreTracing" option is false, then each thread is traced individually
+// but managed by the same "process trace" instance. This means that the
+// amount of trace buffers used is proportional to the number of running
+// threads. This is the recommended option unless the number of threads is
+// huge. If "perCoreTracing" is true, then each cpu core is traced invidually
+// instead of each thread, which uses a fixed number of trace buffers, but
+// might result in less data available for less frequent threads. See
+// "perCoreTracing" below for more information.
+//
+// Each actual trace buffer, either from "process tracing" or "thread tracing",
// is stored in an in-memory circular buffer, which keeps the most recent data.
//
// Additional params in the input schema:
// {
-// "threadBufferSize": <decimal integer>,
-// Trace buffer size per thread in bytes. It must be a power of 2
-// greater than or equal to 4096 (2^12) bytes.
+// "traceBufferSize": <decimal integer>,
+// Size in bytes used by each individual per-thread or per-core trace
+// buffer. It must be a power of 2 greater than or equal to 4096 (2^12)
+// bytes.
//
// "enableTsc": <boolean>,
// Whether to enable TSC timestamps or not. This is supported on
@@ -342,15 +351,35 @@ read packet: {"name":<name>, "description":<description>}/E<error code>;AAAAAAAA
// 0 if supported.
//
// /* process tracing only */
+// "perCoreTracing": <boolean>
+// Instead of having an individual trace buffer per thread, this option
+// triggers the collection on a per cpu core basis. This effectively
+// traces the entire activity on all cores. At decoding time, in order
+// to correctly associate a decoded instruction with a thread, the
+// context switch trace of each core is needed, as well as a record per
+// cpu indicating which thread was running on each core when tracing
+// started. These secondary traces are correlated with the intel-pt
+// trace by comparing TSC timestamps.
+//
+// This option forces the capture of TSC timestamps (see "enableTsc").
+//
+// Note: This option can't be used simulatenously with any other trace
+// sessions because of its system-wide nature.
+//
+// /* process tracing only */
// "processBufferSizeLimit": <decimal integer>,
// Maximum total buffer size per process in bytes.
// This limit applies to the sum of the sizes of all trace buffers for
// the current process, excluding the ones started with "thread tracing".
//
-// Whenever a thread is attempted to be traced due to "process tracing"
-// and the limit would be reached, the process is stopped with a
-// "tracing" reason along with a meaningful description, so that the
-// user can retrace the process if needed.
+// If "perCoreTracing" is false, whenever a thread is attempted to be
+// traced due to "process tracing" and the limit would be reached, the
+// process is stopped with a "tracing" reason along with a meaningful
+// description, so that the user can retrace the process if needed.
+//
+// If "perCoreTracing" is true, then starting the system-wide trace
+// session fails if all the individual per-core trace buffers require
+// in total more memory that the limit impossed by this parameter.
// }
//
// Notes:
diff --git a/lldb/include/lldb/Utility/TraceIntelPTGDBRemotePackets.h b/lldb/include/lldb/Utility/TraceIntelPTGDBRemotePackets.h
index 294b0205af452..d331b18c4ae70 100644
--- a/lldb/include/lldb/Utility/TraceIntelPTGDBRemotePackets.h
+++ b/lldb/include/lldb/Utility/TraceIntelPTGDBRemotePackets.h
@@ -28,20 +28,23 @@ struct IntelPTDataKinds {
/// \{
struct TraceIntelPTStartRequest : TraceStartRequest {
/// Size in bytes to use for each thread's trace buffer.
- int64_t threadBufferSize;
+ int64_t trace_buffer_size;
/// Whether to enable TSC
- bool enableTsc;
+ bool enable_tsc;
/// PSB packet period
- llvm::Optional<int64_t> psbPeriod;
+ llvm::Optional<int64_t> psb_period;
/// Required when doing "process tracing".
///
/// Limit in bytes on all the thread traces started by this "process trace"
/// instance. When a thread is about to be traced and the limit would be hit,
/// then a "tracing" stop event is triggered.
- llvm::Optional<int64_t> processBufferSizeLimit;
+ llvm::Optional<int64_t> process_buffer_size_limit;
+
+ /// Whether to have a trace buffer per thread or per cpu core.
+ llvm::Optional<bool> per_core_tracing;
};
bool fromJSON(const llvm::json::Value &value, TraceIntelPTStartRequest &packet,
diff --git a/lldb/packages/Python/lldbsuite/test/tools/intelpt/intelpt_testcase.py b/lldb/packages/Python/lldbsuite/test/tools/intelpt/intelpt_testcase.py
index a2f63bc88bd10..9f1b6bab2f86b 100644
--- a/lldb/packages/Python/lldbsuite/test/tools/intelpt/intelpt_testcase.py
+++ b/lldb/packages/Python/lldbsuite/test/tools/intelpt/intelpt_testcase.py
@@ -45,37 +45,38 @@ def assertSBError(self, sberror, error=False):
else:
self.assertSuccess(sberror)
- def createConfiguration(self, threadBufferSize=None,
+ def createConfiguration(self, traceBufferSize=None,
processBufferSizeLimit=None, enableTsc=False,
- psbPeriod=None):
+ psbPeriod=None, perCoreTracing=False):
obj = {}
if processBufferSizeLimit is not None:
obj["processBufferSizeLimit"] = processBufferSizeLimit
- if threadBufferSize is not None:
- obj["threadBufferSize"] = threadBufferSize
+ if traceBufferSize is not None:
+ obj["traceBufferSize"] = traceBufferSize
if psbPeriod is not None:
obj["psbPeriod"] = psbPeriod
obj["enableTsc"] = enableTsc
+ obj["perCoreTracing"] = perCoreTracing
configuration = lldb.SBStructuredData()
configuration.SetFromJSON(json.dumps(obj))
return configuration
def traceStartThread(self, thread=None, error=False, substrs=None,
- threadBufferSize=None, enableTsc=False, psbPeriod=None):
+ traceBufferSize=None, enableTsc=False, psbPeriod=None):
if self.USE_SB_API:
trace = self.getTraceOrCreate()
thread = thread if thread is not None else self.thread()
configuration = self.createConfiguration(
- threadBufferSize=threadBufferSize, enableTsc=enableTsc,
+ traceBufferSize=traceBufferSize, enableTsc=enableTsc,
psbPeriod=psbPeriod)
self.assertSBError(trace.Start(thread, configuration), error)
else:
command = "thread trace start"
if thread is not None:
command += " " + str(thread.GetIndexID())
- if threadBufferSize is not None:
- command += " -s " + str(threadBufferSize)
+ if traceBufferSize is not None:
+ command += " -s " + str(traceBufferSize)
if enableTsc:
command += " --tsc"
if psbPeriod is not None:
@@ -83,12 +84,13 @@ def traceStartThread(self, thread=None, error=False, substrs=None,
self.expect(command, error=error, substrs=substrs)
def traceStartProcess(self, processBufferSizeLimit=None, error=False,
- substrs=None, enableTsc=False, psbPeriod=None):
+ substrs=None, enableTsc=False, psbPeriod=None,
+ perCoreTracing=False):
if self.USE_SB_API:
trace = self.getTraceOrCreate()
configuration = self.createConfiguration(
processBufferSizeLimit=processBufferSizeLimit, enableTsc=enableTsc,
- psbPeriod=psbPeriod)
+ psbPeriod=psbPeriod, perCoreTracing=perCoreTracing)
self.assertSBError(trace.Start(configuration), error=error)
else:
command = "process trace start"
@@ -98,6 +100,8 @@ def traceStartProcess(self, processBufferSizeLimit=None, error=False,
command += " --tsc"
if psbPeriod is not None:
command += " --psb-period " + str(psbPeriod)
+ if perCoreTracing:
+ command += " --per-core-tracing"
self.expect(command, error=error, substrs=substrs)
def traceStopProcess(self):
diff --git a/lldb/source/Plugins/Process/Linux/IntelPTCollector.cpp b/lldb/source/Plugins/Process/Linux/IntelPTCollector.cpp
index e2303b37eb883..bcb270c9fae74 100644
--- a/lldb/source/Plugins/Process/Linux/IntelPTCollector.cpp
+++ b/lldb/source/Plugins/Process/Linux/IntelPTCollector.cpp
@@ -443,8 +443,8 @@ Error IntelPTThreadTraceCollection::TraceStart(
"Thread %" PRIu64 " already traced", tid);
Expected<IntelPTThreadTraceUP> trace_up = IntelPTThreadTrace::Create(
- m_pid, tid, request.threadBufferSize, request.enableTsc,
- request.psbPeriod.map([](int64_t period) { return (size_t)period; }));
+ m_pid, tid, request.trace_buffer_size, request.enable_tsc,
+ request.psb_period.map([](int64_t period) { return (size_t)period; }));
if (!trace_up)
return trace_up.takeError();
@@ -490,8 +490,9 @@ Error IntelPTProcessTrace::TraceStop(lldb::tid_t tid) {
}
Error IntelPTProcessTrace::TraceStart(lldb::tid_t tid) {
- if (m_thread_traces.GetTotalBufferSize() + m_tracing_params.threadBufferSize >
- static_cast<size_t>(*m_tracing_params.processBufferSizeLimit))
+ if (m_thread_traces.GetTotalBufferSize() +
+ m_tracing_params.trace_buffer_size >
+ static_cast<size_t>(*m_tracing_params.process_buffer_size_limit))
return createStringError(
inconvertibleErrorCode(),
"Thread %" PRIu64 " can't be traced as the process trace size limit "
@@ -548,6 +549,10 @@ Error IntelPTCollector::TraceStart(
inconvertibleErrorCode(),
"Process currently traced. Stop process tracing first");
}
+ if (request.per_core_tracing.getValueOr(false)) {
+ return createStringError(inconvertibleErrorCode(),
+ "Per-core tracing is not supported.");
+ }
m_process_trace = IntelPTProcessTrace(m_pid, request);
Error error = Error::success();
diff --git a/lldb/source/Plugins/Trace/intel-pt/CommandObjectTraceStartIntelPT.cpp b/lldb/source/Plugins/Trace/intel-pt/CommandObjectTraceStartIntelPT.cpp
index 5650af657c5e4..bd3017f8f09be 100644
--- a/lldb/source/Plugins/Trace/intel-pt/CommandObjectTraceStartIntelPT.cpp
+++ b/lldb/source/Plugins/Trace/intel-pt/CommandObjectTraceStartIntelPT.cpp
@@ -32,13 +32,13 @@ Status CommandObjectThreadTraceStartIntelPT::CommandOptions::SetOptionValue(
switch (short_option) {
case 's': {
- int64_t thread_buffer_size;
- if (option_arg.empty() || option_arg.getAsInteger(0, thread_buffer_size) ||
- thread_buffer_size < 0)
+ int64_t trace_buffer_size;
+ if (option_arg.empty() || option_arg.getAsInteger(0, trace_buffer_size) ||
+ trace_buffer_size < 0)
error.SetErrorStringWithFormat("invalid integer value for option '%s'",
option_arg.str().c_str());
else
- m_thread_buffer_size = thread_buffer_size;
+ m_trace_buffer_size = trace_buffer_size;
break;
}
case 't': {
@@ -63,7 +63,7 @@ Status CommandObjectThreadTraceStartIntelPT::CommandOptions::SetOptionValue(
void CommandObjectThreadTraceStartIntelPT::CommandOptions::
OptionParsingStarting(ExecutionContext *execution_context) {
- m_thread_buffer_size = kDefaultThreadBufferSize;
+ m_trace_buffer_size = kDefaultTraceBufferSize;
m_enable_tsc = kDefaultEnableTscValue;
m_psb_period = kDefaultPsbPeriod;
}
@@ -76,7 +76,7 @@ CommandObjectThreadTraceStartIntelPT::CommandOptions::GetDefinitions() {
bool CommandObjectThreadTraceStartIntelPT::DoExecuteOnThreads(
Args &command, CommandReturnObject &result,
llvm::ArrayRef<lldb::tid_t> tids) {
- if (Error err = m_trace.Start(tids, m_options.m_thread_buffer_size,
+ if (Error err = m_trace.Start(tids, m_options.m_trace_buffer_size,
m_options.m_enable_tsc, m_options.m_psb_period))
result.SetError(Status(std::move(err)));
else
@@ -98,13 +98,13 @@ Status CommandObjectProcessTraceStartIntelPT::CommandOptions::SetOptionValue(
switch (short_option) {
case 's': {
- int64_t thread_buffer_size;
- if (option_arg.empty() || option_arg.getAsInteger(0, thread_buffer_size) ||
- thread_buffer_size < 0)
+ int64_t trace_buffer_size;
+ if (option_arg.empty() || option_arg.getAsInteger(0, trace_buffer_size) ||
+ trace_buffer_size < 0)
error.SetErrorStringWithFormat("invalid integer value for option '%s'",
option_arg.str().c_str());
else
- m_thread_buffer_size = thread_buffer_size;
+ m_trace_buffer_size = trace_buffer_size;
break;
}
case 'l': {
@@ -122,6 +122,10 @@ Status CommandObjectProcessTraceStartIntelPT::CommandOptions::SetOptionValue(
m_enable_tsc = true;
break;
}
+ case 'c': {
+ m_per_core_tracing = true;
+ break;
+ }
case 'p': {
int64_t psb_period;
if (option_arg.empty() || option_arg.getAsInteger(0, psb_period) ||
@@ -140,10 +144,11 @@ Status CommandObjectProcessTraceStartIntelPT::CommandOptions::SetOptionValue(
void CommandObjectProcessTraceStartIntelPT::CommandOptions::
OptionParsingStarting(ExecutionContext *execution_context) {
- m_thread_buffer_size = kDefaultThreadBufferSize;
+ m_trace_buffer_size = kDefaultTraceBufferSize;
m_process_buffer_size_limit = kDefaultProcessBufferSizeLimit;
m_enable_tsc = kDefaultEnableTscValue;
m_psb_period = kDefaultPsbPeriod;
+ m_per_core_tracing = kDefaultPerCoreTracing;
}
llvm::ArrayRef<OptionDefinition>
@@ -153,9 +158,10 @@ CommandObjectProcessTraceStartIntelPT::CommandOptions::GetDefinitions() {
bool CommandObjectProcessTraceStartIntelPT::DoExecute(
Args &command, CommandReturnObject &result) {
- if (Error err = m_trace.Start(m_options.m_thread_buffer_size,
+ if (Error err = m_trace.Start(m_options.m_trace_buffer_size,
m_options.m_process_buffer_size_limit,
- m_options.m_enable_tsc, m_options.m_psb_period))
+ m_options.m_enable_tsc, m_options.m_psb_period,
+ m_options.m_per_core_tracing))
result.SetError(Status(std::move(err)));
else
result.SetStatus(eReturnStatusSuccessFinishResult);
diff --git a/lldb/source/Plugins/Trace/intel-pt/CommandObjectTraceStartIntelPT.h b/lldb/source/Plugins/Trace/intel-pt/CommandObjectTraceStartIntelPT.h
index 2f3d53a864067..bb505905e1548 100644
--- a/lldb/source/Plugins/Trace/intel-pt/CommandObjectTraceStartIntelPT.h
+++ b/lldb/source/Plugins/Trace/intel-pt/CommandObjectTraceStartIntelPT.h
@@ -31,7 +31,7 @@ class CommandObjectThreadTraceStartIntelPT
llvm::ArrayRef<OptionDefinition> GetDefinitions() override;
- size_t m_thread_buffer_size;
+ size_t m_trace_buffer_size;
bool m_enable_tsc;
llvm::Optional<size_t> m_psb_period;
};
@@ -74,10 +74,11 @@ class CommandObjectProcessTraceStartIntelPT : public CommandObjectParsed {
llvm::ArrayRef<OptionDefinition> GetDefinitions() override;
- size_t m_thread_buffer_size;
+ size_t m_trace_buffer_size;
size_t m_process_buffer_size_limit;
bool m_enable_tsc;
llvm::Optional<size_t> m_psb_period;
+ bool m_per_core_tracing;
};
CommandObjectProcessTraceStartIntelPT(TraceIntelPT &trace,
@@ -85,10 +86,14 @@ class CommandObjectProcessTraceStartIntelPT : public CommandObjectParsed {
: CommandObjectParsed(
interpreter, "process trace start",
"Start tracing this process with intel-pt, including future "
- "threads. "
- "This is implemented by tracing each thread independently. "
+ "threads. If --per-core-tracing is not provided, this traces each "
+ "thread independently, thus using a trace buffer per thread. "
"Threads traced with the \"thread trace start\" command are left "
- "unaffected ant not retraced.",
+ "unaffected ant not retraced. This is the recommended option "
+ "unless the number of threads is huge. If --per-core-tracing is "
+ "passed, each cpu core is traced instead of each thread, which "
+ "uses a fixed number of trace buffers, but might result in less "
+ "data available for less frequent threads.",
"process trace start [<intel-pt-options>]",
lldb::eCommandRequiresProcess | lldb::eCommandTryTargetAPILock |
lldb::eCommandProcessMustBeLaunched |
diff --git a/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.cpp b/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.cpp
index 394963a263084..9bd1e3c605a17 100644
--- a/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.cpp
+++ b/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.cpp
@@ -271,101 +271,79 @@ bool TraceIntelPT::IsTraced(lldb::tid_t tid) {
// documentation file. Similarly, it should match the CLI help messages of the
// TraceIntelPTOptions.td file.
const char *TraceIntelPT::GetStartConfigurationHelp() {
- return R"(Parameters:
+ static Optional<std::string> message;
+ if (!message) {
+ message.emplace(formatv(R"(Parameters:
- Note: If a parameter is not specified, a default value will be used.
+ See the jLLDBTraceStart section in lldb/docs/lldb-gdb-remote.txt for a
+ description of each parameter below.
- - int threadBufferSize (defaults to 4096 bytes):
+ - int traceBufferSize (defaults to {0} bytes):
[process and thread tracing]
- Trace size in bytes per thread. It must be a power of 2 greater
- than or equal to 4096 (2^12). The trace is circular keeping the
- the most recent data.
- - boolean enableTsc (default to false):
+ - boolean enableTsc (default to {1}):
[process and thread tracing]
- Whether to use enable TSC timestamps or not. This is supported on
- all devices that support intel-pt.
- - psbPeriod (defaults to null):
+ - int psbPeriod (defaults to {2}):
[process and thread tracing]
- This value defines the period in which PSB packets will be generated.
- A PSB packet is a synchronization packet that contains a TSC
- timestamp and the current absolute instruction pointer.
- This parameter can only be used if
-
- /sys/bus/event_source/devices/intel_pt/caps/psb_cyc
-
- is 1. Otherwise, the PSB period will be defined by the processor.
-
- If supported, valid values for this period can be found in
-
- /sys/bus/event_source/devices/intel_pt/caps/psb_periods
-
- which contains a hexadecimal number, whose bits represent
- valid values e.g. if bit 2 is set, then value 2 is valid.
-
- The psb_period value is converted to the approximate number of
- raw trace bytes between PSB packets as:
-
- 2 ^ (value + 11)
-
- e.g. value 3 means 16KiB between PSB packets. Defaults to 0 if
- supported.
-
- - int processBufferSizeLimit (defaults to 500 MB):
+ - boolean perCoreTracing (default to {3}):
[process tracing only]
- Maximum total trace size per process in bytes. This limit applies
- to the sum of the sizes of all thread traces of this process,
- excluding the ones created explicitly with "thread tracing".
- Whenever a thread is attempted to be traced due to this command
- and the limit would be reached, the process is stopped with a
- "processor trace" reason, so that the user can retrace the process
- if needed.)";
+
+ - int processBufferSizeLimit (defaults to {4} MiB):
+ [process tracing only])",
+ kDefaultTraceBufferSize, kDefaultEnableTscValue,
+ kDefaultPsbPeriod, kDefaultPerCoreTracing,
+ kDefaultProcessBufferSizeLimit / 1024 / 1024));
+ }
+ return message->c_str();
}
-Error TraceIntelPT::Start(size_t thread_buffer_size,
+Error TraceIntelPT::Start(size_t trace_buffer_size,
size_t total_buffer_size_limit, bool enable_tsc,
- Optional<size_t> psb_period) {
+ Optional<size_t> psb_period, bool per_core_tracing) {
TraceIntelPTStartRequest request;
- request.threadBufferSize = thread_buffer_size;
- request.processBufferSizeLimit = total_buffer_size_limit;
- request.enableTsc = enable_tsc;
- request.psbPeriod = psb_period.map([](size_t val) { return (int64_t)val; });
+ request.trace_buffer_size = trace_buffer_size;
+ request.process_buffer_size_limit = total_buffer_size_limit;
+ request.enable_tsc = enable_tsc;
+ request.psb_period = psb_period.map([](size_t val) { return (int64_t)val; });
request.type = GetPluginName().str();
+ request.per_core_tracing = per_core_tracing;
return Trace::Start(toJSON(request));
}
Error TraceIntelPT::Start(StructuredData::ObjectSP configuration) {
- size_t thread_buffer_size = kDefaultThreadBufferSize;
+ size_t trace_buffer_size = kDefaultTraceBufferSize;
size_t process_buffer_size_limit = kDefaultProcessBufferSizeLimit;
bool enable_tsc = kDefaultEnableTscValue;
Optional<size_t> psb_period = kDefaultPsbPeriod;
+ bool per_core_tracing = kDefaultPerCoreTracing;
if (configuration) {
if (StructuredData::Dictionary *dict = configuration->GetAsDictionary()) {
- dict->GetValueForKeyAsInteger("threadBufferSize", thread_buffer_size);
+ dict->GetValueForKeyAsInteger("traceBufferSize", trace_buffer_size);
dict->GetValueForKeyAsInteger("processBufferSizeLimit",
process_buffer_size_limit);
dict->GetValueForKeyAsBoolean("enableTsc", enable_tsc);
dict->GetValueForKeyAsInteger("psbPeriod", psb_period);
+ dict->GetValueForKeyAsBoolean("perCoreTracing", per_core_tracing);
} else {
return createStringError(inconvertibleErrorCode(),
"configuration object is not a dictionary");
}
}
- return Start(thread_buffer_size, process_buffer_size_limit, enable_tsc,
- psb_period);
+ return Start(trace_buffer_size, process_buffer_size_limit, enable_tsc,
+ psb_period, per_core_tracing);
}
llvm::Error TraceIntelPT::Start(llvm::ArrayRef<lldb::tid_t> tids,
- size_t thread_buffer_size, bool enable_tsc,
+ size_t trace_buffer_size, bool enable_tsc,
Optional<size_t> psb_period) {
TraceIntelPTStartRequest request;
- request.threadBufferSize = thread_buffer_size;
- request.enableTsc = enable_tsc;
- request.psbPeriod = psb_period.map([](size_t val) { return (int64_t)val; });
+ request.trace_buffer_size = trace_buffer_size;
+ request.enable_tsc = enable_tsc;
+ request.psb_period = psb_period.map([](size_t val) { return (int64_t)val; });
request.type = GetPluginName().str();
request.tids.emplace();
for (lldb::tid_t tid : tids)
@@ -375,13 +353,13 @@ llvm::Error TraceIntelPT::Start(llvm::ArrayRef<lldb::tid_t> tids,
Error TraceIntelPT::Start(llvm::ArrayRef<lldb::tid_t> tids,
StructuredData::ObjectSP configuration) {
- size_t thread_buffer_size = kDefaultThreadBufferSize;
+ size_t trace_buffer_size = kDefaultTraceBufferSize;
bool enable_tsc = kDefaultEnableTscValue;
Optional<size_t> psb_period = kDefaultPsbPeriod;
if (configuration) {
if (StructuredData::Dictionary *dict = configuration->GetAsDictionary()) {
- dict->GetValueForKeyAsInteger("threadBufferSize", thread_buffer_size);
+ dict->GetValueForKeyAsInteger("traceBufferSize", trace_buffer_size);
dict->GetValueForKeyAsBoolean("enableTsc", enable_tsc);
dict->GetValueForKeyAsInteger("psbPeriod", psb_period);
} else {
@@ -390,7 +368,7 @@ Error TraceIntelPT::Start(llvm::ArrayRef<lldb::tid_t> tids,
}
}
- return Start(tids, thread_buffer_size, enable_tsc, psb_period);
+ return Start(tids, trace_buffer_size, enable_tsc, psb_period);
}
Error TraceIntelPT::OnThreadBufferRead(lldb::tid_t tid,
diff --git a/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.h b/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.h
index f8f60da7f52ce..d5e8c93c2ba39 100644
--- a/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.h
+++ b/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.h
@@ -84,27 +84,31 @@ class TraceIntelPT : public Trace {
/// Start tracing a live process.
///
- /// \param[in] thread_buffer_size
+ /// More information on the parameters below can be found in the
+ /// jLLDBTraceStart section in lldb/docs/lldb-gdb-remote.txt.
+ ///
+ /// \param[in] trace_buffer_size
/// Trace size per thread in bytes.
///
/// \param[in] total_buffer_size_limit
/// Maximum total trace size per process in bytes.
- /// More information in TraceIntelPT::GetStartConfigurationHelp().
///
/// \param[in] enable_tsc
/// Whether to use enable TSC timestamps or not.
- /// More information in TraceIntelPT::GetStartConfigurationHelp().
///
/// \param[in] psb_period
- ///
/// This value defines the period in which PSB packets will be generated.
- /// More information in TraceIntelPT::GetStartConfigurationHelp();
+ ///
+ /// \param[in] per_core_tracing
+ /// This value defines whether to have a trace buffer per thread or per
+ /// cpu core.
///
/// \return
/// \a llvm::Error::success if the operation was successful, or
/// \a llvm::Error otherwise.
- llvm::Error Start(size_t thread_buffer_size, size_t total_buffer_size_limit,
- bool enable_tsc, llvm::Optional<size_t> psb_period);
+ llvm::Error Start(size_t trace_buffer_size, size_t total_buffer_size_limit,
+ bool enable_tsc, llvm::Optional<size_t> psb_period,
+ bool m_per_core_tracing);
/// \copydoc Trace::Start
llvm::Error Start(StructuredData::ObjectSP configuration =
@@ -112,25 +116,25 @@ class TraceIntelPT : public Trace {
/// Start tracing live threads.
///
+ /// More information on the parameters below can be found in the
+ /// jLLDBTraceStart section in lldb/docs/lldb-gdb-remote.txt.
+ ///
/// \param[in] tids
/// Threads to trace.
///
- /// \param[in] thread_buffer_size
- /// Trace size per thread in bytes.
+ /// \param[in] trace_buffer_size
+ /// Trace size per thread or per core in bytes.
///
/// \param[in] enable_tsc
/// Whether to use enable TSC timestamps or not.
- /// More information in TraceIntelPT::GetStartConfigurationHelp().
///
/// \param[in] psb_period
- ///
/// This value defines the period in which PSB packets will be generated.
- /// More information in TraceIntelPT::GetStartConfigurationHelp().
///
/// \return
/// \a llvm::Error::success if the operation was successful, or
/// \a llvm::Error otherwise.
- llvm::Error Start(llvm::ArrayRef<lldb::tid_t> tids, size_t thread_buffer_size,
+ llvm::Error Start(llvm::ArrayRef<lldb::tid_t> tids, size_t trace_buffer_size,
bool enable_tsc, llvm::Optional<size_t> psb_period);
/// \copydoc Trace::Start
diff --git a/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTConstants.h b/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTConstants.h
index c2bc1b57b2bd2..501fc3013f60c 100644
--- a/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTConstants.h
+++ b/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTConstants.h
@@ -16,10 +16,11 @@
namespace lldb_private {
namespace trace_intel_pt {
-const size_t kDefaultThreadBufferSize = 4 * 1024; // 4KB
+const size_t kDefaultTraceBufferSize = 4 * 1024; // 4KB
const size_t kDefaultProcessBufferSizeLimit = 5 * 1024 * 1024; // 500MB
const bool kDefaultEnableTscValue = false;
const llvm::Optional<size_t> kDefaultPsbPeriod = llvm::None;
+const bool kDefaultPerCoreTracing = false;
} // namespace trace_intel_pt
} // namespace lldb_private
diff --git a/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTOptions.td b/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTOptions.td
index 714a13b6e5e02..2583f8f4b2f4a 100644
--- a/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTOptions.td
+++ b/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTOptions.td
@@ -35,12 +35,24 @@ let Command = "thread trace start intel pt" in {
}
let Command = "process trace start intel pt" in {
- def process_trace_start_intel_pt_thread_size: Option<"thread-size", "s">,
+ def process_trace_start_intel_pt_buffer_size: Option<"buffer-size", "s">,
Group<1>,
Arg<"Value">,
- Desc<"Trace size in bytes per thread. It must be a power of 2 greater "
- "than or equal to 4096 (2^12). The trace is circular keeping "
- "the most recent data. Defaults to 4096 bytes.">;
+ Desc<"Size in bytes used by each individual per-thread or per-core trace "
+ "buffer. It must be a power of 2 greater than or equal to 4096 (2^12) "
+ "bytes.">;
+ def process_trace_start_intel_pt_per_core_tracing:
+ Option<"per-core-tracing", "c">,
+ Group<1>,
+ Desc<"Instead of having an individual trace buffer per thread, which uses "
+ "a number trace buffers proportional to the number of running "
+ "threads, this option triggers the collection on a per cpu core "
+ "basis. This effectively traces the entire activity on all cores "
+ "using a limited amount of trace buffers regardless of the number of "
+ "threads. This might cause data loss for less frequent threads. This "
+ "option forces the capture of TSC timestamps (see --tsc). Also, this "
+ "option can't be used simulatenously with any other trace sessions "
+ "because of its system-wide nature.">;
def process_trace_start_intel_pt_process_size_limit: Option<"total-size-limit", "l">,
Group<1>,
Arg<"Value">,
diff --git a/lldb/source/Utility/TraceIntelPTGDBRemotePackets.cpp b/lldb/source/Utility/TraceIntelPTGDBRemotePackets.cpp
index bd450bb0721c9..746e034e88de7 100644
--- a/lldb/source/Utility/TraceIntelPTGDBRemotePackets.cpp
+++ b/lldb/source/Utility/TraceIntelPTGDBRemotePackets.cpp
@@ -20,29 +20,27 @@ bool fromJSON(const json::Value &value, TraceIntelPTStartRequest &packet,
Path path) {
ObjectMapper o(value, path);
if (!o || !fromJSON(value, (TraceStartRequest &)packet, path) ||
- !o.map("enableTsc", packet.enableTsc) ||
- !o.map("psbPeriod", packet.psbPeriod) ||
- !o.map("threadBufferSize", packet.threadBufferSize) ||
- !o.map("processBufferSizeLimit", packet.processBufferSizeLimit))
- return false;
- if (packet.tids && packet.processBufferSizeLimit) {
- path.report("processBufferSizeLimit must be provided");
- return false;
- }
- if (!packet.tids && !packet.processBufferSizeLimit) {
- path.report("processBufferSizeLimit must not be provided");
+ !o.map("enableTsc", packet.enable_tsc) ||
+ !o.map("psbPeriod", packet.psb_period) ||
+ !o.map("traceBufferSize", packet.trace_buffer_size))
return false;
+
+ if (packet.IsProcessTracing()) {
+ if (!o.map("processBufferSizeLimit", packet.process_buffer_size_limit) ||
+ !o.map("perCoreTracing", packet.per_core_tracing))
+ return false;
}
return true;
}
json::Value toJSON(const TraceIntelPTStartRequest &packet) {
json::Value base = toJSON((const TraceStartRequest &)packet);
- base.getAsObject()->try_emplace("threadBufferSize", packet.threadBufferSize);
- base.getAsObject()->try_emplace("processBufferSizeLimit",
- packet.processBufferSizeLimit);
- base.getAsObject()->try_emplace("psbPeriod", packet.psbPeriod);
- base.getAsObject()->try_emplace("enableTsc", packet.enableTsc);
+ json::Object &obj = *base.getAsObject();
+ obj.try_emplace("traceBufferSize", packet.trace_buffer_size);
+ obj.try_emplace("processBufferSizeLimit", packet.process_buffer_size_limit);
+ obj.try_emplace("psbPeriod", packet.psb_period);
+ obj.try_emplace("enableTsc", packet.enable_tsc);
+ obj.try_emplace("perCoreTracing", packet.per_core_tracing);
return base;
}
diff --git a/lldb/test/API/commands/trace/TestTraceStartStop.py b/lldb/test/API/commands/trace/TestTraceStartStop.py
index 765e3e829f1c5..294ba96cf013e 100644
--- a/lldb/test/API/commands/trace/TestTraceStartStop.py
+++ b/lldb/test/API/commands/trace/TestTraceStartStop.py
@@ -35,18 +35,18 @@ def testStartSessionWithWrongSize(self):
self.expect("r")
self.traceStartThread(
- error=True, threadBufferSize=2000,
+ error=True, traceBufferSize=2000,
substrs=["The trace buffer size must be a power of 2", "It was 2000"])
self.traceStartThread(
- error=True, threadBufferSize=5000,
+ error=True, traceBufferSize=5000,
substrs=["The trace buffer size must be a power of 2", "It was 5000"])
self.traceStartThread(
- error=True, threadBufferSize=0,
+ error=True, traceBufferSize=0,
substrs=["The trace buffer size must be a power of 2", "It was 0"])
- self.traceStartThread(threadBufferSize=1048576)
+ self.traceStartThread(traceBufferSize=1048576)
@skipIf(oslist=no_match(['linux']), archs=no_match(['i386', 'x86_64']))
def testSBAPIHelp(self):
@@ -55,7 +55,7 @@ def testSBAPIHelp(self):
self.expect("r")
help = self.getTraceOrCreate().GetStartConfigurationHelp()
- self.assertIn("threadBufferSize", help)
+ self.assertIn("traceBufferSize", help)
self.assertIn("processBufferSizeLimit", help)
@skipIf(oslist=no_match(['linux']), archs=no_match(['i386', 'x86_64']))
diff --git a/lldb/test/API/commands/trace/multiple-threads/TestTraceStartStopMultipleThreads.py b/lldb/test/API/commands/trace/multiple-threads/TestTraceStartStopMultipleThreads.py
index 4b7fbc9f388de..6bfe83192bd58 100644
--- a/lldb/test/API/commands/trace/multiple-threads/TestTraceStartStopMultipleThreads.py
+++ b/lldb/test/API/commands/trace/multiple-threads/TestTraceStartStopMultipleThreads.py
@@ -152,3 +152,17 @@ def testStartMultipleLiveThreadsWithSmallTotalLimit(self):
self.expect("c", substrs=['Thread', "can't be traced"])
self.traceStopProcess()
+
+ @skipIf(oslist=no_match(['linux']), archs=no_match(['i386', 'x86_64']))
+ @testSBAPIAndCommands
+ def testStartPerCoreSession(self):
+ self.build()
+ exe = self.getBuildArtifact("a.out")
+ self.dbg.CreateTarget(exe)
+
+ self.expect("b main")
+ self.expect("r")
+
+ self.traceStartProcess(
+ error=True, perCoreTracing=True,
+ substrs=["Per-core tracing is not supported"])
More information about the lldb-commits
mailing list