Simpleperf: support child inherit option.

In order to support child inherit option, also change the way to open event
files for threads on all cpus in record command.

Bug: 19483574
Change-Id: I0765e9ec90841c1f762490de3dd24ad37b0cc619
diff --git a/simpleperf/cmd_record.cpp b/simpleperf/cmd_record.cpp
index b59dcdc..001066c 100644
--- a/simpleperf/cmd_record.cpp
+++ b/simpleperf/cmd_record.cpp
@@ -82,6 +82,8 @@
             "                   k: only when the branch target is in the kernel\n"
             "                 This option requires at least one branch type among any,\n"
             "                 any_call, any_ret, ind_call.\n"
+            "    --no-inherit\n"
+            "                 Don't record created child threads/processes.\n"
             "    -o record_file_name    Set record file name, default is perf.data.\n"
             "    -p pid1,pid2,...\n"
             "                 Record events on existing processes. Mutually exclusive with -a.\n"
@@ -92,6 +94,7 @@
         system_wide_collection_(false),
         branch_sampling_(0),
         callchain_sampling_(false),
+        child_inherit_(true),
         perf_mmap_pages_(256),
         record_filename_("perf.data") {
     signaled = false;
@@ -118,10 +121,11 @@
   uint64_t sample_period_;  // Sample once when 'sample_period_' events occur.
 
   bool system_wide_collection_;
-  std::vector<pid_t> monitored_threads_;
   uint64_t branch_sampling_;
-  std::unique_ptr<EventTypeAndModifier> measured_event_type_modifier_;
   bool callchain_sampling_;
+  bool child_inherit_;
+  std::vector<pid_t> monitored_threads_;
+  std::unique_ptr<EventTypeAndModifier> measured_event_type_modifier_;
   EventSelectionSet event_selection_set_;
 
   // mmap pages used by each perf event file, should be power of 2.
@@ -173,7 +177,7 @@
       return false;
     }
   } else {
-    if (!event_selection_set_.OpenEventFilesForThreads(monitored_threads_)) {
+    if (!event_selection_set_.OpenEventFilesForThreadsOnAllCpus(monitored_threads_)) {
       return false;
     }
   }
@@ -282,6 +286,8 @@
         }
         branch_sampling_ |= it->second;
       }
+    } else if (args[i] == "--no-inherit") {
+      child_inherit_ = false;
     } else if (args[i] == "-o") {
       if (!NextArgumentOrError(args, &i)) {
         return false;
@@ -346,6 +352,7 @@
   if (callchain_sampling_) {
     event_selection_set_.EnableCallChainSampling();
   }
+  event_selection_set_.SetInherit(child_inherit_);
   return true;
 }
 
diff --git a/simpleperf/cmd_stat.cpp b/simpleperf/cmd_stat.cpp
index cba2873..83a4a3f 100644
--- a/simpleperf/cmd_stat.cpp
+++ b/simpleperf/cmd_stat.cpp
@@ -57,13 +57,16 @@
                 "                 how the event should be monitored. Possible modifiers are:\n"
                 "                   u - monitor user space events only\n"
                 "                   k - monitor kernel space events only\n"
+                "    --no-inherit\n"
+                "                 Don't stat created child threads/processes.\n"
                 "    -p pid1,pid2,...\n"
                 "                 Stat events on existing processes. Mutually exclusive with -a.\n"
                 "    -t tid1,tid2,...\n"
                 "                 Stat events on existing threads. Mutually exclusive with -a.\n"
                 "    --verbose    Show result in verbose mode.\n"),
         verbose_mode_(false),
-        system_wide_collection_(false) {
+        system_wide_collection_(false),
+        child_inherit_(true) {
     signaled = false;
     signal_handler_register_.reset(
         new SignalHandlerRegister({SIGCHLD, SIGINT, SIGTERM}, signal_handler));
@@ -75,33 +78,34 @@
   bool ParseOptions(const std::vector<std::string>& args, std::vector<std::string>* non_option_args);
   bool AddMeasuredEventType(const std::string& event_type_name, bool report_unsupported_type = true);
   bool AddDefaultMeasuredEventTypes();
+  void SetEventSelection();
   bool ShowCounters(const std::map<const EventType*, std::vector<PerfCounter>>& counters_map,
                     std::chrono::steady_clock::duration counting_duration);
 
-  std::vector<std::pair<std::string, EventType>> measured_event_types_;
-  EventSelectionSet event_selection_set_;
   bool verbose_mode_;
   bool system_wide_collection_;
+  bool child_inherit_;
   std::vector<pid_t> monitored_threads_;
+  std::vector<std::pair<std::string, EventTypeAndModifier>> measured_event_types_;
+  EventSelectionSet event_selection_set_;
 
   std::unique_ptr<SignalHandlerRegister> signal_handler_register_;
 };
 
 bool StatCommand::Run(const std::vector<std::string>& args) {
-  // 1. Parse options.
+  // 1. Parse options, and use default measured event types if not given.
   std::vector<std::string> workload_args;
   if (!ParseOptions(args, &workload_args)) {
     return false;
   }
-
-  // 2. Add default measured event types.
-  if (event_selection_set_.Empty()) {
+  if (measured_event_types_.empty()) {
     if (!AddDefaultMeasuredEventTypes()) {
       return false;
     }
   }
+  SetEventSelection();
 
-  // 3. Create workload.
+  // 2. Create workload.
   std::unique_ptr<Workload> workload;
   if (!workload_args.empty()) {
     workload = Workload::CreateWorkload(workload_args);
@@ -119,7 +123,7 @@
     }
   }
 
-  // 4. Open perf_event_files.
+  // 3. Open perf_event_files.
   if (system_wide_collection_) {
     if (!event_selection_set_.OpenEventFilesForAllCpus()) {
       return false;
@@ -130,7 +134,7 @@
     }
   }
 
-  // 5. Count events while workload running.
+  // 4. Count events while workload running.
   auto start_time = std::chrono::steady_clock::now();
   if (!event_selection_set_.GetEnableOnExec()) {
     if (!event_selection_set_.EnableEvents()) {
@@ -145,7 +149,7 @@
   }
   auto end_time = std::chrono::steady_clock::now();
 
-  // 6. Read and print counters.
+  // 5. Read and print counters.
   std::map<const EventType*, std::vector<PerfCounter>> counters_map;
   if (!event_selection_set_.ReadCounters(&counters_map)) {
     return false;
@@ -173,6 +177,8 @@
           return false;
         }
       }
+    } else if (args[i] == "--no-inherit") {
+      child_inherit_ = false;
     } else if (args[i] == "-p") {
       if (!NextArgumentOrError(args, &i)) {
         return false;
@@ -217,8 +223,7 @@
   if (event_type_modifier == nullptr) {
     return false;
   }
-  measured_event_types_.push_back(std::make_pair(event_type_name, event_type_modifier->event_type));
-  event_selection_set_.AddEventType(*event_type_modifier);
+  measured_event_types_.push_back(std::make_pair(event_type_name, *event_type_modifier));
   return true;
 }
 
@@ -227,13 +232,20 @@
     // It is not an error when some event types in the default list are not supported by the kernel.
     AddMeasuredEventType(name, false);
   }
-  if (event_selection_set_.Empty()) {
+  if (measured_event_types_.empty()) {
     LOG(ERROR) << "Failed to add any supported default measured types";
     return false;
   }
   return true;
 }
 
+void StatCommand::SetEventSelection() {
+  for (auto& pair : measured_event_types_) {
+    event_selection_set_.AddEventType(pair.second);
+  }
+  event_selection_set_.SetInherit(child_inherit_);
+}
+
 bool StatCommand::ShowCounters(
     const std::map<const EventType*, std::vector<PerfCounter>>& counters_map,
     std::chrono::steady_clock::duration counting_duration) {
@@ -271,7 +283,7 @@
     }
     std::string event_type_name;
     for (auto& pair : measured_event_types_) {
-      if (pair.second.name == event_type->name) {
+      if (pair.second.event_type.name == event_type->name) {
         event_type_name = pair.first;
       }
     }
diff --git a/simpleperf/event_selection_set.cpp b/simpleperf/event_selection_set.cpp
index e89a19f..0f23c14 100644
--- a/simpleperf/event_selection_set.cpp
+++ b/simpleperf/event_selection_set.cpp
@@ -17,6 +17,7 @@
 #include "event_selection_set.h"
 
 #include <base/logging.h>
+#include <base/stringprintf.h>
 
 #include "environment.h"
 #include "event_attr.h"
@@ -113,37 +114,48 @@
   }
 }
 
+void EventSelectionSet::SetInherit(bool enable) {
+  for (auto& selection : selections_) {
+    selection.event_attr.inherit = (enable ? 1 : 0);
+  }
+}
+
 bool EventSelectionSet::OpenEventFilesForAllCpus() {
+  return OpenEventFilesForThreadsOnAllCpus({-1});
+}
+
+bool EventSelectionSet::OpenEventFilesForThreads(const std::vector<pid_t>& threads) {
+  return OpenEventFiles(threads, {-1});
+}
+
+bool EventSelectionSet::OpenEventFilesForThreadsOnAllCpus(const std::vector<pid_t>& threads) {
   std::vector<int> cpus = GetOnlineCpus();
   if (cpus.empty()) {
     return false;
   }
-  for (auto& selection : selections_) {
-    for (auto& cpu : cpus) {
-      auto event_fd = EventFd::OpenEventFile(selection.event_attr, -1, cpu);
-      if (event_fd != nullptr) {
-        selection.event_fds.push_back(std::move(event_fd));
-      }
-    }
-    // As the online cpus can be enabled or disabled at runtime, we may not open event file for
-    // all cpus successfully. But we should open at least one cpu successfully.
-    if (selection.event_fds.empty()) {
-      PLOG(ERROR) << "failed to open perf event file for event_type " << selection.event_type.name
-                  << " on all cpus";
-      return false;
-    }
-  }
-  return true;
+  return OpenEventFiles(threads, cpus);
 }
 
-bool EventSelectionSet::OpenEventFilesForThreads(const std::vector<pid_t>& threads) {
+bool EventSelectionSet::OpenEventFiles(const std::vector<pid_t>& threads,
+                                       const std::vector<int>& cpus) {
   for (auto& selection : selections_) {
     for (auto& tid : threads) {
-      auto event_fd = EventFd::OpenEventFile(selection.event_attr, tid, -1);
-      if (event_fd == nullptr) {
+      size_t open_per_thread = 0;
+      for (auto& cpu : cpus) {
+        auto event_fd = EventFd::OpenEventFile(selection.event_attr, tid, cpu);
+        if (event_fd != nullptr) {
+          selection.event_fds.push_back(std::move(event_fd));
+          ++open_per_thread;
+        }
+      }
+      // As the online cpus can be enabled or disabled at runtime, we may not open event file for
+      // all cpus successfully. But we should open at least one cpu successfully.
+      if (open_per_thread == 0) {
+        PLOG(ERROR) << "failed to open perf event file for event_type " << selection.event_type.name
+                    << " for "
+                    << (tid == -1 ? "all threads" : android::base::StringPrintf(" thread %d", tid));
         return false;
       }
-      selection.event_fds.push_back(std::move(event_fd));
     }
   }
   return true;
diff --git a/simpleperf/event_selection_set.h b/simpleperf/event_selection_set.h
index 6f7f8f4..adf3440 100644
--- a/simpleperf/event_selection_set.h
+++ b/simpleperf/event_selection_set.h
@@ -55,9 +55,11 @@
   void SetSamplePeriod(uint64_t sample_period);
   bool SetBranchSampling(uint64_t branch_sample_type);
   void EnableCallChainSampling();
+  void SetInherit(bool enable);
 
   bool OpenEventFilesForAllCpus();
   bool OpenEventFilesForThreads(const std::vector<pid_t>& threads);
+  bool OpenEventFilesForThreadsOnAllCpus(const std::vector<pid_t>& threads);
   bool EnableEvents();
   bool ReadCounters(std::map<const EventType*, std::vector<PerfCounter>>* counters_map);
   void PreparePollForEventFiles(std::vector<pollfd>* pollfds);
@@ -69,6 +71,8 @@
   const std::vector<std::unique_ptr<EventFd>>& FindEventFdsByType(const EventType& event_type);
 
  private:
+  bool OpenEventFiles(const std::vector<pid_t>& threads, const std::vector<int>& cpus);
+
   struct EventSelection {
     EventType event_type;
     perf_event_attr event_attr;