summaryrefslogtreecommitdiff
path: root/simpleperf
diff options
context:
space:
mode:
authorYabin Cui <yabinc@google.com>2024-05-08 21:28:54 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2024-05-08 21:28:54 +0000
commit88815e57fb998bbdc92bc3acad91a12d6755c904 (patch)
treed9f08a11df1cb0fe825a4777a1cb38c7cf878f4a /simpleperf
parent10ea6cc8b454565df086dad5f05c7ff29661880a (diff)
parent7a59f85e59772f2de6315195bffc3290ec730b83 (diff)
downloadextras-88815e57fb998bbdc92bc3acad91a12d6755c904.tar.gz
Merge changes Ib892aeea,I1b5f2b85,I449517fb,I6583aebc into main
* changes: simpleperf: Delay processing ETM data until the buffer is half full simpleperf: Rotate the last cpu disabling ETM events simpleperf: Flush ETM data at the end of recording simpleperf: Enable ETM events after create aux buffer
Diffstat (limited to 'simpleperf')
-rw-r--r--simpleperf/RecordReadThread.cpp12
-rw-r--r--simpleperf/RecordReadThread.h1
-rw-r--r--simpleperf/cmd_record.cpp17
-rw-r--r--simpleperf/event_selection_set.cpp70
-rw-r--r--simpleperf/event_selection_set.h6
5 files changed, 103 insertions, 3 deletions
diff --git a/simpleperf/RecordReadThread.cpp b/simpleperf/RecordReadThread.cpp
index 2ab61278..2d034bc1 100644
--- a/simpleperf/RecordReadThread.cpp
+++ b/simpleperf/RecordReadThread.cpp
@@ -408,6 +408,7 @@ bool RecordReadThread::HandleAddEventFds(IOEventLoop& loop,
success = false;
break;
}
+ has_etm_events_ = true;
}
cpu_map[fd->Cpu()] = fd;
} else {
@@ -620,6 +621,9 @@ void RecordReadThread::PushRecordToRecordBuffer(KernelRecordReader* kernel_recor
}
void RecordReadThread::ReadAuxDataFromKernelBuffer(bool* has_data) {
+ if (!has_etm_events_) {
+ return;
+ }
for (auto& reader : kernel_record_readers_) {
EventFd* event_fd = reader.GetEventFd();
if (event_fd->HasAuxBuffer()) {
@@ -659,6 +663,14 @@ void RecordReadThread::ReadAuxDataFromKernelBuffer(bool* has_data) {
}
bool RecordReadThread::SendDataNotificationToMainThread() {
+ if (has_etm_events_) {
+ // For ETM recording, the default buffer size is large enough to hold ETM data for several
+ // seconds. To reduce impact of processing ETM data (especially when --decode-etm is used),
+ // delay processing ETM data until the buffer is half full.
+ if (record_buffer_.GetFreeSize() >= record_buffer_.size() / 2) {
+ return true;
+ }
+ }
if (!has_data_notification_.load(std::memory_order_relaxed)) {
has_data_notification_ = true;
char unused = 0;
diff --git a/simpleperf/RecordReadThread.h b/simpleperf/RecordReadThread.h
index c104b083..893f8234 100644
--- a/simpleperf/RecordReadThread.h
+++ b/simpleperf/RecordReadThread.h
@@ -211,6 +211,7 @@ class RecordReadThread {
std::unique_ptr<std::thread> read_thread_;
std::vector<KernelRecordReader> kernel_record_readers_;
pid_t exclude_pid_ = -1;
+ bool has_etm_events_ = false;
std::unordered_set<EventFd*> event_fds_disabled_by_kernel_;
diff --git a/simpleperf/cmd_record.cpp b/simpleperf/cmd_record.cpp
index 40582045..d57c3422 100644
--- a/simpleperf/cmd_record.cpp
+++ b/simpleperf/cmd_record.cpp
@@ -631,7 +631,7 @@ bool RecordCommand::PrepareRecording(Workload* workload) {
} else {
need_to_check_targets = true;
}
- if (delay_in_ms_ != 0) {
+ if (delay_in_ms_ != 0 || event_selection_set_.HasAuxTrace()) {
event_selection_set_.SetEnableCondition(false, false);
}
@@ -755,6 +755,12 @@ bool RecordCommand::PrepareRecording(Workload* workload) {
}
}
if (event_selection_set_.HasAuxTrace()) {
+ // ETM events can only be enabled successfully after MmapEventFiles().
+ if (delay_in_ms_ == 0 && !event_selection_set_.IsEnabledOnExec()) {
+ if (!event_selection_set_.EnableETMEvents()) {
+ return false;
+ }
+ }
// ETM data is dumped to kernel buffer only when there is no thread traced by ETM. It happens
// either when all monitored threads are scheduled off cpu, or when all etm perf events are
// disabled.
@@ -762,8 +768,7 @@ bool RecordCommand::PrepareRecording(Workload* workload) {
// makes less than expected data, especially in system wide recording. So add a periodic event
// to flush etm data by temporarily disable all perf events.
auto etm_flush = [this]() {
- return event_selection_set_.SetEnableEvents(false) &&
- event_selection_set_.SetEnableEvents(true);
+ return event_selection_set_.DisableETMEvents() && event_selection_set_.EnableETMEvents();
};
if (!loop->AddPeriodicEvent(SecondToTimeval(kDefaultEtmDataFlushPeriodInSec), etm_flush)) {
return false;
@@ -800,6 +805,12 @@ bool RecordCommand::DoRecording(Workload* workload) {
return false;
}
time_stat_.stop_recording_time = GetSystemClock();
+ if (event_selection_set_.HasAuxTrace()) {
+ // Disable ETM events to flush the last ETM data.
+ if (!event_selection_set_.DisableETMEvents()) {
+ return false;
+ }
+ }
if (!event_selection_set_.SyncKernelBuffer()) {
return false;
}
diff --git a/simpleperf/event_selection_set.cpp b/simpleperf/event_selection_set.cpp
index c75f8049..1a7cdef8 100644
--- a/simpleperf/event_selection_set.cpp
+++ b/simpleperf/event_selection_set.cpp
@@ -233,6 +233,8 @@ bool EventSelectionSet::BuildAndCheckEventSelection(const std::string& event_nam
// enabling/disabling etm devices. So don't adjust frequency by default.
selection->event_attr.freq = 0;
selection->event_attr.sample_period = 1;
+ // An ETM event can't be enabled without mmap aux buffer. So disable it by default.
+ selection->event_attr.disabled = 1;
} else {
selection->event_attr.freq = 1;
// Set default sample freq here may print msg "Adjust sample freq to max allowed sample
@@ -461,6 +463,17 @@ void EventSelectionSet::SetEnableCondition(bool enable_on_open, bool enable_on_e
}
}
+bool EventSelectionSet::IsEnabledOnExec() const {
+ for (const auto& group : groups_) {
+ for (const auto& selection : group.selections) {
+ if (!selection.event_attr.enable_on_exec) {
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
void EventSelectionSet::SampleIdAll() {
for (auto& group : groups_) {
for (auto& selection : group.selections) {
@@ -939,4 +952,61 @@ bool EventSelectionSet::SetEnableEvents(bool enable) {
return true;
}
+bool EventSelectionSet::EnableETMEvents() {
+ for (auto& group : groups_) {
+ for (auto& sel : group.selections) {
+ if (!sel.event_type_modifier.event_type.IsEtmEvent()) {
+ continue;
+ }
+ for (auto& fd : sel.event_fds) {
+ if (!fd->SetEnableEvent(true)) {
+ return false;
+ }
+ }
+ }
+ }
+ return true;
+}
+
+bool EventSelectionSet::DisableETMEvents() {
+ for (auto& group : groups_) {
+ for (auto& sel : group.selections) {
+ if (!sel.event_type_modifier.event_type.IsEtmEvent()) {
+ continue;
+ }
+ // When using ETR, ETM data is flushed to the aux buffer of the last cpu disabling ETM events.
+ // To avoid overflowing the aux buffer for one cpu, rotate the last cpu disabling ETM events.
+ if (etm_event_cpus_.empty()) {
+ for (const auto& fd : sel.event_fds) {
+ etm_event_cpus_.insert(fd->Cpu());
+ }
+ if (etm_event_cpus_.empty()) {
+ continue;
+ }
+ etm_event_cpus_it_ = etm_event_cpus_.begin();
+ }
+ int last_disabled_cpu = *etm_event_cpus_it_;
+ if (++etm_event_cpus_it_ == etm_event_cpus_.end()) {
+ etm_event_cpus_it_ = etm_event_cpus_.begin();
+ }
+
+ for (auto& fd : sel.event_fds) {
+ if (fd->Cpu() != last_disabled_cpu) {
+ if (!fd->SetEnableEvent(false)) {
+ return false;
+ }
+ }
+ }
+ for (auto& fd : sel.event_fds) {
+ if (fd->Cpu() == last_disabled_cpu) {
+ if (!fd->SetEnableEvent(false)) {
+ return false;
+ }
+ }
+ }
+ }
+ }
+ return true;
+}
+
} // namespace simpleperf
diff --git a/simpleperf/event_selection_set.h b/simpleperf/event_selection_set.h
index e046035b..a892d51e 100644
--- a/simpleperf/event_selection_set.h
+++ b/simpleperf/event_selection_set.h
@@ -122,6 +122,7 @@ class EventSelectionSet {
std::map<int, size_t> GetHardwareCountersForCpus() const;
void SetEnableCondition(bool enable_on_open, bool enable_on_exec);
+ bool IsEnabledOnExec() const;
void SampleIdAll();
// Only set sample rate for events that haven't set sample rate.
void SetSampleRateForNewEvents(const SampleRate& rate);
@@ -179,6 +180,8 @@ class EventSelectionSet {
double check_interval_in_sec = DEFAULT_PERIOD_TO_CHECK_MONITORED_TARGETS_IN_SEC);
bool SetEnableEvents(bool enable);
+ bool EnableETMEvents();
+ bool DisableETMEvents();
private:
struct EventSelection {
@@ -232,6 +235,9 @@ class EventSelectionSet {
std::optional<SampleRate> sample_rate_;
std::optional<std::vector<int>> cpus_;
+ std::set<int> etm_event_cpus_;
+ std::set<int>::const_iterator etm_event_cpus_it_;
+
DISALLOW_COPY_AND_ASSIGN(EventSelectionSet);
};