OSDN Git Service

ANRdaemon: move trace result from /sdcard to /data am: d93aa41807
[android-x86/system-extras.git] / simpleperf / event_selection_set.cpp
index b7fcd58..fad8b1e 100644 (file)
 
 #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"
@@ -43,7 +45,7 @@ bool IsDwarfCallChainSamplingSupported() {
   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);
 }
@@ -81,7 +83,17 @@ void EventSelectionSet::UnionSampleType() {
 
 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;
+    }
   }
 }
 
@@ -154,7 +166,7 @@ bool EventSelectionSet::EnableDwarfCallChainSampling(uint32_t dump_stack_size) {
     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;
@@ -166,18 +178,29 @@ void EventSelectionSet::SetInherit(bool enable) {
   }
 }
 
-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);
 }
@@ -190,6 +213,7 @@ bool EventSelectionSet::OpenEventFiles(const std::vector<pid_t>& threads,
       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;
         }
@@ -207,17 +231,6 @@ bool EventSelectionSet::OpenEventFiles(const std::vector<pid_t>& threads,
   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_) {
@@ -272,7 +285,6 @@ static bool ReadMmapEventDataForFd(std::unique_ptr<EventFd>& event_fd,
       return false;
     }
     *have_data = true;
-    event_fd->DiscardMmapData(size);
   }
   return true;
 }