#include "event_selection_set.h"
-#include <base/logging.h>
-#include <base/stringprintf.h>
+#include <poll.h>
+
+#include <android-base/logging.h>
+#include <android-base/stringprintf.h>
#include "environment.h"
#include "event_attr.h"
perf_event_attr attr = CreateDefaultPerfEventAttr(*type);
attr.sample_type |= PERF_SAMPLE_CALLCHAIN | PERF_SAMPLE_REGS_USER | PERF_SAMPLE_STACK_USER;
attr.exclude_callchain_user = 1;
- attr.sample_regs_user = GetSupportedRegMask();
+ attr.sample_regs_user = GetSupportedRegMask(GetBuildArch());
attr.sample_stack_user = 8192;
return IsEventAttrSupportedByKernel(attr);
}
void EventSelectionSet::SetEnableOnExec(bool enable) {
for (auto& selection : selections_) {
- selection.event_attr.enable_on_exec = (enable ? 1 : 0);
+ // If sampling is enabled on exec, then it is disabled at startup, otherwise
+ // it should be enabled at startup. Don't use ioctl(PERF_EVENT_IOC_ENABLE)
+ // to enable it after perf_event_open(). Because some android kernels can't
+ // handle ioctl() well when cpu-hotplug happens. See http://b/25193162.
+ if (enable) {
+ selection.event_attr.enable_on_exec = 1;
+ selection.event_attr.disabled = 1;
+ } else {
+ selection.event_attr.enable_on_exec = 0;
+ selection.event_attr.disabled = 0;
+ }
}
}
selection.event_attr.sample_type |=
PERF_SAMPLE_CALLCHAIN | PERF_SAMPLE_REGS_USER | PERF_SAMPLE_STACK_USER;
selection.event_attr.exclude_callchain_user = 1;
- selection.event_attr.sample_regs_user = GetSupportedRegMask();
+ selection.event_attr.sample_regs_user = GetSupportedRegMask(GetBuildArch());
selection.event_attr.sample_stack_user = dump_stack_size;
}
return true;
}
}
-bool EventSelectionSet::OpenEventFilesForAllCpus() {
- return OpenEventFilesForThreadsOnAllCpus({-1});
+static bool CheckIfCpusOnline(const std::vector<int>& cpus) {
+ std::vector<int> online_cpus = GetOnlineCpus();
+ for (const auto& cpu : cpus) {
+ if (std::find(online_cpus.begin(), online_cpus.end(), cpu) == online_cpus.end()) {
+ LOG(ERROR) << "cpu " << cpu << " is not online.";
+ return false;
+ }
+ }
+ return true;
}
-bool EventSelectionSet::OpenEventFilesForThreads(const std::vector<pid_t>& threads) {
- return OpenEventFiles(threads, {-1});
+bool EventSelectionSet::OpenEventFilesForCpus(const std::vector<int>& cpus) {
+ return OpenEventFilesForThreadsOnCpus({-1}, cpus);
}
-bool EventSelectionSet::OpenEventFilesForThreadsOnAllCpus(const std::vector<pid_t>& threads) {
- std::vector<int> cpus = GetOnlineCpus();
- if (cpus.empty()) {
- return false;
+bool EventSelectionSet::OpenEventFilesForThreadsOnCpus(const std::vector<pid_t>& threads,
+ std::vector<int> cpus) {
+ if (!cpus.empty()) {
+ if (!CheckIfCpusOnline(cpus)) {
+ return false;
+ }
+ } else {
+ cpus = GetOnlineCpus();
}
return OpenEventFiles(threads, cpus);
}
for (auto& cpu : cpus) {
auto event_fd = EventFd::OpenEventFile(selection.event_attr, tid, cpu);
if (event_fd != nullptr) {
+ LOG(VERBOSE) << "OpenEventFile for tid " << tid << ", cpu " << cpu;
selection.event_fds.push_back(std::move(event_fd));
++open_per_thread;
}
return true;
}
-bool EventSelectionSet::EnableEvents() {
- for (auto& selection : selections_) {
- for (auto& event_fd : selection.event_fds) {
- if (!event_fd->EnableEvent()) {
- return false;
- }
- }
- }
- return true;
-}
-
bool EventSelectionSet::ReadCounters(std::vector<CountersInfo>* counters) {
counters->clear();
for (auto& selection : selections_) {
return false;
}
*have_data = true;
- event_fd->DiscardMmapData(size);
}
return true;
}