Merge "simpleperf: handle monitored processes correctly when a cpu is up."
diff --git a/simpleperf/cmd_record.cpp b/simpleperf/cmd_record.cpp
index e746a9a..7671047 100644
--- a/simpleperf/cmd_record.cpp
+++ b/simpleperf/cmd_record.cpp
@@ -181,9 +181,7 @@
bool DumpKernelSymbol();
bool DumpTracingData();
bool DumpKernelAndModuleMmaps(const perf_event_attr& attr, uint64_t event_id);
- bool DumpThreadCommAndMmaps(const perf_event_attr& attr, uint64_t event_id,
- bool all_threads,
- const std::vector<pid_t>& selected_threads);
+ bool DumpThreadCommAndMmaps(const perf_event_attr& attr, uint64_t event_id);
bool ProcessRecord(Record* record);
bool DumpSymbolForRecord(const SampleRecord& r, bool for_callchain);
void UpdateRecordForEmbeddedElfPath(Record* record);
@@ -209,7 +207,6 @@
double duration_in_sec_;
bool can_dump_kernel_symbols_;
bool dump_symbols_;
- std::vector<pid_t> monitored_threads_;
std::vector<int> cpus_;
EventSelectionSet event_selection_set_;
@@ -255,9 +252,11 @@
return false;
}
}
- if (!system_wide_collection_ && monitored_threads_.empty()) {
+ if (system_wide_collection_) {
+ event_selection_set_.AddMonitoredThreads({-1});
+ } else if (!event_selection_set_.HasMonitoredTarget()) {
if (workload != nullptr) {
- monitored_threads_.push_back(workload->GetPid());
+ event_selection_set_.AddMonitoredProcesses({workload->GetPid()});
event_selection_set_.SetEnableOnExec(true);
} else {
LOG(ERROR)
@@ -267,15 +266,8 @@
}
// 3. Open perf_event_files, create mapped buffers for perf_event_files.
- if (system_wide_collection_) {
- if (!event_selection_set_.OpenEventFilesForCpus(cpus_)) {
- return false;
- }
- } else {
- if (!event_selection_set_.OpenEventFilesForThreadsOnCpus(monitored_threads_,
- cpus_)) {
- return false;
- }
+ if (!event_selection_set_.OpenEventFiles(cpus_)) {
+ return false;
}
if (!event_selection_set_.MmapEventFiles(mmap_page_range_.first,
mmap_page_range_.second)) {
@@ -363,7 +355,6 @@
bool RecordCommand::ParseOptions(const std::vector<std::string>& args,
std::vector<std::string>* non_option_args) {
- std::set<pid_t> tid_set;
size_t i;
for (i = 0; i < args.size() && !args[i].empty() && args[i][0] == '-'; ++i) {
if (args[i] == "-a") {
@@ -509,9 +500,11 @@
if (!NextArgumentOrError(args, &i)) {
return false;
}
- if (!GetValidThreadsFromProcessString(args[i], &tid_set)) {
+ std::set<pid_t> pids;
+ if (!GetValidThreadsFromThreadString(args[i], &pids)) {
return false;
}
+ event_selection_set_.AddMonitoredProcesses(pids);
} else if (args[i] == "--post-unwind") {
post_unwind_ = true;
} else if (args[i] == "--symfs") {
@@ -525,9 +518,11 @@
if (!NextArgumentOrError(args, &i)) {
return false;
}
- if (!GetValidThreadsFromThreadString(args[i], &tid_set)) {
+ std::set<pid_t> tids;
+ if (!GetValidThreadsFromThreadString(args[i], &tids)) {
return false;
}
+ event_selection_set_.AddMonitoredThreads(tids);
} else {
ReportUnknownOption(args, i);
return false;
@@ -559,9 +554,7 @@
}
}
- monitored_threads_.insert(monitored_threads_.end(), tid_set.begin(),
- tid_set.end());
- if (system_wide_collection_ && !monitored_threads_.empty()) {
+ if (system_wide_collection_ && event_selection_set_.HasMonitoredTarget()) {
LOG(ERROR) << "Record system wide and existing processes/threads can't be "
"used at the same time.";
return false;
@@ -643,8 +636,7 @@
if (!DumpKernelAndModuleMmaps(attr, event_id)) {
return false;
}
- if (!DumpThreadCommAndMmaps(attr, event_id, system_wide_collection_,
- monitored_threads_)) {
+ if (!DumpThreadCommAndMmaps(attr, event_id)) {
return false;
}
return true;
@@ -748,19 +740,20 @@
return true;
}
-bool RecordCommand::DumpThreadCommAndMmaps(
- const perf_event_attr& attr, uint64_t event_id, bool all_threads,
- const std::vector<pid_t>& selected_threads) {
+bool RecordCommand::DumpThreadCommAndMmaps(const perf_event_attr& attr,
+ uint64_t event_id) {
std::vector<ThreadComm> thread_comms;
if (!GetThreadComms(&thread_comms)) {
return false;
}
// Decide which processes and threads to dump.
- std::set<pid_t> dump_processes;
- std::set<pid_t> dump_threads;
- for (auto& tid : selected_threads) {
- dump_threads.insert(tid);
+ bool all_threads = system_wide_collection_;
+ std::set<pid_t> dump_threads = event_selection_set_.GetMonitoredThreads();
+ for (const auto& pid : event_selection_set_.GetMonitoredProcesses()) {
+ std::vector<pid_t> tids = GetThreadsInProcess(pid);
+ dump_threads.insert(tids.begin(), tids.end());
}
+ std::set<pid_t> dump_processes;
for (auto& thread : thread_comms) {
if (dump_threads.find(thread.tid) != dump_threads.end()) {
dump_processes.insert(thread.pid);
diff --git a/simpleperf/cmd_stat.cpp b/simpleperf/cmd_stat.cpp
index 728deb2..93054d2 100644
--- a/simpleperf/cmd_stat.cpp
+++ b/simpleperf/cmd_stat.cpp
@@ -312,7 +312,6 @@
bool system_wide_collection_;
bool child_inherit_;
double duration_in_sec_;
- std::vector<pid_t> monitored_threads_;
std::vector<int> cpus_;
EventSelectionSet event_selection_set_;
std::string output_filename_;
@@ -344,9 +343,11 @@
return false;
}
}
- if (!system_wide_collection_ && monitored_threads_.empty()) {
+ if (system_wide_collection_) {
+ event_selection_set_.AddMonitoredThreads({-1});
+ } else if (!event_selection_set_.HasMonitoredTarget()) {
if (workload != nullptr) {
- monitored_threads_.push_back(workload->GetPid());
+ event_selection_set_.AddMonitoredProcesses({workload->GetPid()});
event_selection_set_.SetEnableOnExec(true);
} else {
LOG(ERROR)
@@ -356,21 +357,16 @@
}
// 3. Open perf_event_files.
- if (system_wide_collection_) {
- if (!event_selection_set_.OpenEventFilesForCpus(cpus_)) {
- return false;
- }
- } else {
- std::vector<int> all_cpus = {-1};
- if (!event_selection_set_.OpenEventFilesForThreadsOnCpus(
- monitored_threads_, cpus_.empty() ? all_cpus : cpus_)) {
- return false;
- }
+ if (!system_wide_collection_ && cpus_.empty()) {
+ cpus_.push_back(-1); // Monitor on all cpus.
+ }
+ if (!event_selection_set_.OpenEventFiles(cpus_)) {
+ return false;
}
// 4. Create IOEventLoop and add signal/periodic Events.
IOEventLoop loop;
- if (system_wide_collection_ || !cpus_.empty()) {
+ if (system_wide_collection_ || (!cpus_.empty() && cpus_[0] != -1)) {
if (!event_selection_set_.HandleCpuHotplugEvents(loop, cpus_)) {
return false;
}
@@ -465,16 +461,20 @@
if (!NextArgumentOrError(args, &i)) {
return false;
}
- if (!GetValidThreadsFromProcessString(args[i], &tid_set)) {
+ std::set<pid_t> pids;
+ if (!GetValidThreadsFromThreadString(args[i], &pids)) {
return false;
}
+ event_selection_set_.AddMonitoredProcesses(pids);
} else if (args[i] == "-t") {
if (!NextArgumentOrError(args, &i)) {
return false;
}
- if (!GetValidThreadsFromThreadString(args[i], &tid_set)) {
+ std::set<pid_t> tids;
+ if (!GetValidThreadsFromThreadString(args[i], &tids)) {
return false;
}
+ event_selection_set_.AddMonitoredThreads(tids);
} else if (args[i] == "--verbose") {
verbose_mode_ = true;
} else {
@@ -483,9 +483,7 @@
}
}
- monitored_threads_.insert(monitored_threads_.end(), tid_set.begin(),
- tid_set.end());
- if (system_wide_collection_ && !monitored_threads_.empty()) {
+ if (system_wide_collection_ && event_selection_set_.HasMonitoredTarget()) {
LOG(ERROR) << "Stat system wide and existing processes/threads can't be "
"used at the same time.";
return false;
diff --git a/simpleperf/environment.cpp b/simpleperf/environment.cpp
index 621bc9f..1de8a1e 100644
--- a/simpleperf/environment.cpp
+++ b/simpleperf/environment.cpp
@@ -246,7 +246,7 @@
return false;
}
-static std::vector<pid_t> GetThreadsInProcess(pid_t pid) {
+std::vector<pid_t> GetThreadsInProcess(pid_t pid) {
std::vector<pid_t> result;
std::string task_dirname = android::base::StringPrintf("/proc/%d/task", pid);
for (const auto& name : GetSubDirs(task_dirname)) {
@@ -340,24 +340,6 @@
return GetBuildIdFromNoteFile(notefile, build_id);
}
-bool GetValidThreadsFromProcessString(const std::string& pid_str, std::set<pid_t>* tid_set) {
- std::vector<std::string> strs = android::base::Split(pid_str, ",");
- for (const auto& s : strs) {
- int pid;
- if (!android::base::ParseInt(s.c_str(), &pid, 0)) {
- LOG(ERROR) << "Invalid pid '" << s << "'";
- return false;
- }
- std::vector<pid_t> tids = GetThreadsInProcess(pid);
- if (tids.empty()) {
- LOG(ERROR) << "Non existing process '" << pid << "'";
- return false;
- }
- tid_set->insert(tids.begin(), tids.end());
- }
- return true;
-}
-
bool GetValidThreadsFromThreadString(const std::string& tid_str, std::set<pid_t>* tid_set) {
std::vector<std::string> strs = android::base::Split(tid_str, ",");
for (const auto& s : strs) {
diff --git a/simpleperf/environment.h b/simpleperf/environment.h
index 2f0f59c..176c9ce 100644
--- a/simpleperf/environment.h
+++ b/simpleperf/environment.h
@@ -64,7 +64,7 @@
bool GetKernelBuildId(BuildId* build_id);
bool GetModuleBuildId(const std::string& module_name, BuildId* build_id);
-bool GetValidThreadsFromProcessString(const std::string& pid_str, std::set<pid_t>* tid_set);
+std::vector<pid_t> GetThreadsInProcess(pid_t pid);
bool GetValidThreadsFromThreadString(const std::string& tid_str, std::set<pid_t>* tid_set);
bool GetExecPath(std::string* exec_path);
diff --git a/simpleperf/event_selection_set.cpp b/simpleperf/event_selection_set.cpp
index 9d65ec1..d6b1fe6 100644
--- a/simpleperf/event_selection_set.cpp
+++ b/simpleperf/event_selection_set.cpp
@@ -265,23 +265,6 @@
return true;
}
-bool EventSelectionSet::OpenEventFilesForCpus(const std::vector<int>& cpus) {
- return OpenEventFilesForThreadsOnCpus({-1}, cpus);
-}
-
-bool EventSelectionSet::OpenEventFilesForThreadsOnCpus(
- const std::vector<pid_t>& threads, std::vector<int> cpus) {
- if (!cpus.empty()) {
- // cpus = {-1} means open an event file for all cpus.
- if (!(cpus.size() == 1 && cpus[0] == -1) && !CheckIfCpusOnline(cpus)) {
- return false;
- }
- } else {
- cpus = GetOnlineCpus();
- }
- return OpenEventFiles(threads, cpus);
-}
-
static bool OpenEventFile(EventSelectionGroup& group, pid_t tid, int cpu,
std::string* failed_event_type) {
std::vector<std::unique_ptr<EventFd>> event_fds;
@@ -310,8 +293,27 @@
return true;
}
-bool EventSelectionSet::OpenEventFiles(const std::vector<pid_t>& threads,
- const std::vector<int>& cpus) {
+static std::set<pid_t> PrepareThreads(const std::set<pid_t>& processes,
+ const std::set<pid_t>& threads) {
+ std::set<pid_t> result = threads;
+ for (const auto& pid : processes) {
+ std::vector<pid_t> tids = GetThreadsInProcess(pid);
+ result.insert(tids.begin(), tids.end());
+ }
+ return result;
+}
+
+bool EventSelectionSet::OpenEventFiles(const std::vector<int>& on_cpus) {
+ std::vector<int> cpus = on_cpus;
+ if (!cpus.empty()) {
+ // cpus = {-1} means open an event file for all cpus.
+ if (!(cpus.size() == 1 && cpus[0] == -1) && !CheckIfCpusOnline(cpus)) {
+ return false;
+ }
+ } else {
+ cpus = GetOnlineCpus();
+ }
+ std::set<pid_t> threads = PrepareThreads(processes_, threads_);
for (auto& group : groups_) {
for (const auto& tid : threads) {
size_t success_cpu_count = 0;
@@ -334,7 +336,6 @@
}
}
}
- threads_.insert(threads_.end(), threads.begin(), threads.end());
return true;
}
@@ -545,8 +546,9 @@
bool EventSelectionSet::HandleCpuOnlineEvent(int cpu) {
// We need to start profiling when opening new event files.
SetEnableOnExec(false);
+ std::set<pid_t> threads = PrepareThreads(processes_, threads_);
for (auto& group : groups_) {
- for (const auto& tid : threads_) {
+ for (const auto& tid : threads) {
std::string failed_event_type;
if (!OpenEventFile(group, tid, cpu, &failed_event_type)) {
// If failed to open event files, maybe the cpu has been offlined.
diff --git a/simpleperf/event_selection_set.h b/simpleperf/event_selection_set.h
index 5a2dea4..53c8edd 100644
--- a/simpleperf/event_selection_set.h
+++ b/simpleperf/event_selection_set.h
@@ -97,9 +97,27 @@
void SetInherit(bool enable);
void SetLowWatermark();
- bool OpenEventFilesForCpus(const std::vector<int>& cpus);
- bool OpenEventFilesForThreadsOnCpus(const std::vector<pid_t>& threads,
- std::vector<int> cpus);
+ void AddMonitoredProcesses(const std::set<pid_t>& processes) {
+ processes_.insert(processes.begin(), processes.end());
+ }
+
+ void AddMonitoredThreads(const std::set<pid_t>& threads) {
+ threads_.insert(threads.begin(), threads.end());
+ }
+
+ const std::set<pid_t>& GetMonitoredProcesses() const {
+ return processes_;
+ }
+
+ const std::set<pid_t>& GetMonitoredThreads() const {
+ return threads_;
+ }
+
+ bool HasMonitoredTarget() const {
+ return !processes_.empty() || !threads_.empty();
+ }
+
+ bool OpenEventFiles(const std::vector<int>& on_cpus);
bool ReadCounters(std::vector<CountersInfo>* counters);
bool MmapEventFiles(size_t min_mmap_pages, size_t max_mmap_pages);
bool PrepareToReadMmapEventData(IOEventLoop& loop,
@@ -116,8 +134,6 @@
bool BuildAndCheckEventSelection(const std::string& event_name,
EventSelection* selection);
void UnionSampleType();
- bool OpenEventFiles(const std::vector<pid_t>& threads,
- const std::vector<int>& cpus);
bool MmapEventFiles(size_t mmap_pages, bool report_error);
bool ReadMmapEventDataForFd(EventFd* event_fd);
@@ -129,7 +145,8 @@
const bool for_stat_cmd_;
std::vector<EventSelectionGroup> groups_;
- std::vector<pid_t> threads_;
+ std::set<pid_t> processes_;
+ std::set<pid_t> threads_;
size_t mmap_pages_;
IOEventLoop* loop_;