/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "event_selection_set.h"

#include <algorithm>
#include <atomic>
#include <thread>
#include <unordered_map>

#include <android-base/logging.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>

#include "ETMRecorder.h"
#include "IOEventLoop.h"
#include "RecordReadThread.h"
#include "environment.h"
#include "event_attr.h"
#include "event_type.h"
#include "perf_regs.h"
#include "tracing.h"
#include "utils.h"

namespace simpleperf {

using android::base::StringPrintf;

bool IsBranchSamplingSupported() {
  const EventType* type = FindEventTypeByName("BR_INST_RETIRED.NEAR_TAKEN");
  if (type == nullptr) {
    return false;
  }
  perf_event_attr attr = CreateDefaultPerfEventAttr(*type);
  attr.sample_type |= PERF_SAMPLE_BRANCH_STACK;
  attr.branch_sample_type = PERF_SAMPLE_BRANCH_ANY;
  return IsEventAttrSupported(attr, type->name);
}

bool IsDwarfCallChainSamplingSupported() {
  if (auto version = GetKernelVersion(); version && version.value() >= std::make_pair(3, 18)) {
    // Skip test on kernel >= 3.18, which has all patches needed to support dwarf callchain.
    return true;
  }
  const EventType* type = FindEventTypeByName("cpu-clock");
  if (type == nullptr) {
    return false;
  }
  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(GetTargetArch());
  attr.sample_stack_user = 8192;
  return IsEventAttrSupported(attr, type->name);
}

bool IsDumpingRegsForTracepointEventsSupported() {
  if (auto version = GetKernelVersion(); version && version.value() >= std::make_pair(4, 2)) {
    // Kernel >= 4.2 has patch "5b09a094f2 arm64: perf: Fix callchain parse error with kernel
    // tracepoint events". So no need to test.
    return true;
  }
  const EventType* event_type = FindEventTypeByName("sched:sched_switch", false);
  if (event_type == nullptr) {
    return false;
  }
  std::atomic<bool> done(false);
  std::atomic<pid_t> thread_id(0);
  std::thread thread([&]() {
    thread_id = gettid();
    while (!done) {
      usleep(1);
    }
    usleep(1);  // Make a sched out to generate one sample.
  });
  while (thread_id == 0) {
    usleep(1);
  }
  perf_event_attr attr = CreateDefaultPerfEventAttr(*event_type);
  attr.freq = 0;
  attr.sample_period = 1;
  std::unique_ptr<EventFd> event_fd =
      EventFd::OpenEventFile(attr, thread_id, -1, nullptr, event_type->name);
  if (event_fd == nullptr || !event_fd->CreateMappedBuffer(4, true)) {
    done = true;
    thread.join();
    return false;
  }
  done = true;
  thread.join();

  // There are small chances that we don't see samples immediately after joining the thread on
  // cuttlefish, probably due to data synchronization between cpus. To avoid flaky tests, use a
  // loop to wait for samples.
  for (int timeout = 0; timeout < 1000; timeout++) {
    std::vector<char> buffer = event_fd->GetAvailableMmapData();
    std::vector<std::unique_ptr<Record>> records =
        ReadRecordsFromBuffer(attr, buffer.data(), buffer.size());
    for (auto& r : records) {
      if (r->type() == PERF_RECORD_SAMPLE) {
        auto& record = *static_cast<SampleRecord*>(r.get());
        return record.ip_data.ip != 0;
      }
    }
    usleep(1);
  }
  return false;
}

bool IsSettingClockIdSupported() {
  // Do the real check only once and keep the result in a static variable.
  static int is_supported = -1;
  if (is_supported == -1) {
    is_supported = 0;
    if (auto version = GetKernelVersion(); version && version.value() >= std::make_pair(4, 1)) {
      // Kernel >= 4.1 has patch "34f43927 perf: Add per event clockid support". So no need to test.
      is_supported = 1;
    } else if (const EventType* type = FindEventTypeByName("cpu-clock"); type != nullptr) {
      // Check if the kernel supports setting clockid, which was added in kernel 4.0. Just check
      // with one clockid is enough. Because all needed clockids were supported before kernel 4.0.
      perf_event_attr attr = CreateDefaultPerfEventAttr(*type);
      attr.use_clockid = 1;
      attr.clockid = CLOCK_MONOTONIC;
      is_supported = IsEventAttrSupported(attr, type->name) ? 1 : 0;
    }
  }
  return is_supported;
}

bool IsMmap2Supported() {
  if (auto version = GetKernelVersion(); version && version.value() >= std::make_pair(3, 12)) {
    // Kernel >= 3.12 has patch "13d7a2410 perf: Add attr->mmap2 attribute to an event". So no need
    // to test.
    return true;
  }
  const EventType* type = FindEventTypeByName("cpu-clock");
  if (type == nullptr) {
    return false;
  }
  perf_event_attr attr = CreateDefaultPerfEventAttr(*type);
  attr.mmap2 = 1;
  return IsEventAttrSupported(attr, type->name);
}

bool IsHardwareEventSupported() {
  const EventType* type = FindEventTypeByName("cpu-cycles");
  if (type == nullptr) {
    return false;
  }
  perf_event_attr attr = CreateDefaultPerfEventAttr(*type);
  return IsEventAttrSupported(attr, type->name);
}

bool IsSwitchRecordSupported() {
  // Kernel >= 4.3 has patch "45ac1403f perf: Add PERF_RECORD_SWITCH to indicate context switches".
  auto version = GetKernelVersion();
  return version && version.value() >= std::make_pair(4, 3);
}

std::string AddrFilter::ToString() const {
  switch (type) {
    case FILE_RANGE:
      return StringPrintf("filter 0x%" PRIx64 "/0x%" PRIx64 "@%s", addr, size, file_path.c_str());
    case AddrFilter::FILE_START:
      return StringPrintf("start 0x%" PRIx64 "@%s", addr, file_path.c_str());
    case AddrFilter::FILE_STOP:
      return StringPrintf("stop 0x%" PRIx64 "@%s", addr, file_path.c_str());
    case AddrFilter::KERNEL_RANGE:
      return StringPrintf("filter 0x%" PRIx64 "/0x%" PRIx64, addr, size);
    case AddrFilter::KERNEL_START:
      return StringPrintf("start 0x%" PRIx64, addr);
    case AddrFilter::KERNEL_STOP:
      return StringPrintf("stop 0x%" PRIx64, addr);
  }
}

EventSelectionSet::EventSelectionSet(bool for_stat_cmd)
    : for_stat_cmd_(for_stat_cmd), loop_(new IOEventLoop) {}

EventSelectionSet::~EventSelectionSet() {}

bool EventSelectionSet::BuildAndCheckEventSelection(const std::string& event_name, bool first_event,
                                                    EventSelection* selection) {
  std::unique_ptr<EventTypeAndModifier> event_type = ParseEventType(event_name);
  if (event_type == nullptr) {
    return false;
  }
  if (for_stat_cmd_) {
    if (event_type->event_type.name == "cpu-clock" || event_type->event_type.name == "task-clock") {
      if (event_type->exclude_user || event_type->exclude_kernel) {
        LOG(ERROR) << "Modifier u and modifier k used in event type " << event_type->event_type.name
                   << " are not supported by the kernel.";
        return false;
      }
    }
  }
  selection->event_type_modifier = *event_type;
  selection->event_attr = CreateDefaultPerfEventAttr(event_type->event_type);
  selection->event_attr.exclude_user = event_type->exclude_user;
  selection->event_attr.exclude_kernel = event_type->exclude_kernel;
  selection->event_attr.exclude_hv = event_type->exclude_hv;
  selection->event_attr.exclude_host = event_type->exclude_host;
  selection->event_attr.exclude_guest = event_type->exclude_guest;
  selection->event_attr.precise_ip = event_type->precise_ip;
  if (IsEtmEventType(event_type->event_type.type)) {
    auto& etm_recorder = ETMRecorder::GetInstance();
    if (auto result = etm_recorder.CheckEtmSupport(); !result.ok()) {
      LOG(ERROR) << result.error();
      return false;
    }
    ETMRecorder::GetInstance().SetEtmPerfEventAttr(&selection->event_attr);
    // The kernel (rb_allocate_aux) allocates high order of pages based on aux_watermark.
    // To avoid that, use aux_watermark <= 1 page size.
    selection->event_attr.aux_watermark = 4096;
  }
  bool set_default_sample_freq = false;
  if (!for_stat_cmd_) {
    if (event_type->event_type.type == PERF_TYPE_TRACEPOINT) {
      selection->event_attr.freq = 0;
      selection->event_attr.sample_period = DEFAULT_SAMPLE_PERIOD_FOR_TRACEPOINT_EVENT;
    } else if (IsEtmEventType(event_type->event_type.type)) {
      // ETM recording has no sample frequency to adjust. Using sample frequency only wastes time
      // 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
      // freq". But this is misleading. Because default sample freq may not be the final sample
      // freq we use. So use minimum sample freq (1) here.
      selection->event_attr.sample_freq = 1;
      set_default_sample_freq = true;
    }
    // We only need to dump mmap and comm records for the first event type. Because all event types
    // are monitoring the same processes.
    if (first_event) {
      selection->event_attr.mmap = 1;
      selection->event_attr.comm = 1;
      if (IsMmap2Supported()) {
        selection->event_attr.mmap2 = 1;
      }
    }
  }
  // PMU events are provided by kernel, so they should be supported
  if (!event_type->event_type.IsPmuEvent() &&
      !IsEventAttrSupported(selection->event_attr, selection->event_type_modifier.name)) {
    LOG(ERROR) << "Event type '" << event_type->name << "' is not supported on the device";
    return false;
  }
  if (set_default_sample_freq) {
    selection->event_attr.sample_freq = DEFAULT_SAMPLE_FREQ_FOR_NONTRACEPOINT_EVENT;
  }

  selection->event_fds.clear();

  for (const auto& group : groups_) {
    for (const auto& sel : group.selections) {
      if (sel.event_type_modifier.name == selection->event_type_modifier.name) {
        LOG(ERROR) << "Event type '" << sel.event_type_modifier.name << "' appears more than once";
        return false;
      }
    }
  }
  return true;
}

bool EventSelectionSet::AddEventType(const std::string& event_name) {
  return AddEventGroup(std::vector<std::string>(1, event_name));
}

bool EventSelectionSet::AddEventType(const std::string& event_name, const SampleRate& sample_rate) {
  if (!AddEventGroup(std::vector<std::string>(1, event_name))) {
    return false;
  }
  SetSampleRateForGroup(groups_.back(), sample_rate);
  return true;
}

bool EventSelectionSet::AddEventGroup(const std::vector<std::string>& event_names) {
  EventSelectionGroup group;
  bool first_event = groups_.empty();
  bool first_in_group = true;
  for (const auto& event_name : event_names) {
    EventSelection selection;
    if (!BuildAndCheckEventSelection(event_name, first_event, &selection)) {
      return false;
    }
    if (IsEtmEventType(selection.event_attr.type)) {
      has_aux_trace_ = true;
    }
    if (first_in_group) {
      auto& event_type = selection.event_type_modifier.event_type;
      if (event_type.IsPmuEvent()) {
        selection.allowed_cpus = event_type.GetPmuCpumask();
      }
    }
    first_event = false;
    first_in_group = false;
    group.selections.emplace_back(std::move(selection));
  }
  if (sample_rate_) {
    SetSampleRateForGroup(group, sample_rate_.value());
  }
  if (cpus_) {
    group.cpus = cpus_.value();
  }
  groups_.emplace_back(std::move(group));
  UnionSampleType();
  return true;
}

bool EventSelectionSet::AddCounters(const std::vector<std::string>& event_names) {
  CHECK(!groups_.empty());
  if (groups_.size() > 1) {
    LOG(ERROR) << "Failed to add counters. Only one event group is allowed.";
    return false;
  }
  for (const auto& event_name : event_names) {
    EventSelection selection;
    if (!BuildAndCheckEventSelection(event_name, false, &selection)) {
      return false;
    }
    // Use a big sample_period to avoid getting samples for added counters.
    selection.event_attr.freq = 0;
    selection.event_attr.sample_period = INFINITE_SAMPLE_PERIOD;
    selection.event_attr.inherit = 0;
    groups_[0].selections.emplace_back(std::move(selection));
  }
  // Add counters in each sample.
  for (auto& selection : groups_[0].selections) {
    selection.event_attr.sample_type |= PERF_SAMPLE_READ;
    selection.event_attr.read_format |= PERF_FORMAT_GROUP;
  }
  return true;
}

std::vector<const EventType*> EventSelectionSet::GetEvents() const {
  std::vector<const EventType*> result;
  for (const auto& group : groups_) {
    for (const auto& selection : group.selections) {
      result.push_back(&selection.event_type_modifier.event_type);
    }
  }
  return result;
}

std::vector<const EventType*> EventSelectionSet::GetTracepointEvents() const {
  std::vector<const EventType*> result;
  for (const auto& group : groups_) {
    for (const auto& selection : group.selections) {
      if (selection.event_type_modifier.event_type.type == PERF_TYPE_TRACEPOINT) {
        result.push_back(&selection.event_type_modifier.event_type);
      }
    }
  }
  return result;
}

bool EventSelectionSet::ExcludeKernel() const {
  for (const auto& group : groups_) {
    for (const auto& selection : group.selections) {
      if (!selection.event_type_modifier.exclude_kernel) {
        return false;
      }
    }
  }
  return true;
}

EventAttrIds EventSelectionSet::GetEventAttrWithId() const {
  EventAttrIds result;
  for (const auto& group : groups_) {
    for (const auto& selection : group.selections) {
      std::vector<uint64_t> ids;
      for (const auto& fd : selection.event_fds) {
        ids.push_back(fd->Id());
      }
      result.resize(result.size() + 1);
      result.back().attr = selection.event_attr;
      result.back().ids = std::move(ids);
    }
  }
  return result;
}

std::unordered_map<uint64_t, std::string> EventSelectionSet::GetEventNamesById() const {
  std::unordered_map<uint64_t, std::string> result;
  for (const auto& group : groups_) {
    for (const auto& selection : group.selections) {
      for (const auto& fd : selection.event_fds) {
        result[fd->Id()] = selection.event_type_modifier.name;
      }
    }
  }
  return result;
}

std::unordered_map<uint64_t, int> EventSelectionSet::GetCpusById() const {
  std::unordered_map<uint64_t, int> result;
  for (const auto& group : groups_) {
    for (const auto& selection : group.selections) {
      for (const auto& fd : selection.event_fds) {
        result[fd->Id()] = fd->Cpu();
      }
    }
  }
  return result;
}

std::map<int, size_t> EventSelectionSet::GetHardwareCountersForCpus() const {
  std::map<int, size_t> cpu_map;
  std::vector<int> online_cpus = GetOnlineCpus();

  for (const auto& group : groups_) {
    size_t hardware_events = 0;
    for (const auto& selection : group.selections) {
      if (selection.event_type_modifier.event_type.IsHardwareEvent()) {
        hardware_events++;
      }
    }
    const std::vector<int>* pcpus = group.cpus.empty() ? &online_cpus : &group.cpus;
    for (int cpu : *pcpus) {
      cpu_map[cpu] += hardware_events;
    }
  }
  return cpu_map;
}

// Union the sample type of different event attrs can make reading sample
// records in perf.data easier.
void EventSelectionSet::UnionSampleType() {
  uint64_t sample_type = 0;
  for (const auto& group : groups_) {
    for (const auto& selection : group.selections) {
      sample_type |= selection.event_attr.sample_type;
    }
  }
  for (auto& group : groups_) {
    for (auto& selection : group.selections) {
      selection.event_attr.sample_type = sample_type;
    }
  }
}

void EventSelectionSet::SetEnableCondition(bool enable_on_open, bool enable_on_exec) {
  for (auto& group : groups_) {
    for (auto& selection : group.selections) {
      selection.event_attr.disabled = !enable_on_open;
      selection.event_attr.enable_on_exec = enable_on_exec;
    }
  }
}

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) {
      selection.event_attr.sample_id_all = 1;
    }
  }
}

void EventSelectionSet::SetSampleRateForNewEvents(const SampleRate& rate) {
  sample_rate_ = rate;
  for (auto& group : groups_) {
    if (!group.set_sample_rate) {
      SetSampleRateForGroup(group, rate);
    }
  }
}

void EventSelectionSet::SetCpusForNewEvents(const std::vector<int>& cpus) {
  cpus_ = cpus;
  for (auto& group : groups_) {
    if (group.cpus.empty()) {
      group.cpus = cpus_.value();
    }
  }
}

void EventSelectionSet::SetSampleRateForGroup(EventSelectionSet::EventSelectionGroup& group,
                                              const SampleRate& rate) {
  group.set_sample_rate = true;
  for (auto& selection : group.selections) {
    if (rate.UseFreq()) {
      selection.event_attr.freq = 1;
      selection.event_attr.sample_freq = rate.sample_freq;
    } else {
      selection.event_attr.freq = 0;
      selection.event_attr.sample_period = rate.sample_period;
    }
  }
}

bool EventSelectionSet::SetBranchSampling(uint64_t branch_sample_type) {
  if (branch_sample_type != 0 &&
      (branch_sample_type & (PERF_SAMPLE_BRANCH_ANY | PERF_SAMPLE_BRANCH_ANY_CALL |
                             PERF_SAMPLE_BRANCH_ANY_RETURN | PERF_SAMPLE_BRANCH_IND_CALL)) == 0) {
    LOG(ERROR) << "Invalid branch_sample_type: 0x" << std::hex << branch_sample_type;
    return false;
  }
  if (branch_sample_type != 0 && !IsBranchSamplingSupported()) {
    LOG(ERROR) << "branch stack sampling is not supported on this device.";
    return false;
  }
  for (auto& group : groups_) {
    for (auto& selection : group.selections) {
      perf_event_attr& attr = selection.event_attr;
      if (branch_sample_type != 0) {
        attr.sample_type |= PERF_SAMPLE_BRANCH_STACK;
      } else {
        attr.sample_type &= ~PERF_SAMPLE_BRANCH_STACK;
      }
      attr.branch_sample_type = branch_sample_type;
    }
  }
  return true;
}

void EventSelectionSet::EnableFpCallChainSampling() {
  for (auto& group : groups_) {
    for (auto& selection : group.selections) {
      selection.event_attr.sample_type |= PERF_SAMPLE_CALLCHAIN;
    }
  }
}

bool EventSelectionSet::EnableDwarfCallChainSampling(uint32_t dump_stack_size) {
  if (!IsDwarfCallChainSamplingSupported()) {
    LOG(ERROR) << "dwarf callchain sampling is not supported on this device.";
    return false;
  }
  for (auto& group : groups_) {
    for (auto& selection : group.selections) {
      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(GetMachineArch());
      selection.event_attr.sample_stack_user = dump_stack_size;
    }
  }
  return true;
}

void EventSelectionSet::SetInherit(bool enable) {
  for (auto& group : groups_) {
    for (auto& selection : group.selections) {
      selection.event_attr.inherit = (enable ? 1 : 0);
    }
  }
}

void EventSelectionSet::SetClockId(int clock_id) {
  for (auto& group : groups_) {
    for (auto& selection : group.selections) {
      selection.event_attr.use_clockid = 1;
      selection.event_attr.clockid = clock_id;
    }
  }
}

bool EventSelectionSet::NeedKernelSymbol() const {
  return !ExcludeKernel();
}

void EventSelectionSet::SetRecordNotExecutableMaps(bool record) {
  // We only need to dump non-executable mmap records for the first event type.
  groups_[0].selections[0].event_attr.mmap_data = record ? 1 : 0;
}

bool EventSelectionSet::RecordNotExecutableMaps() const {
  return groups_[0].selections[0].event_attr.mmap_data == 1;
}

void EventSelectionSet::EnableSwitchRecord() {
  groups_[0].selections[0].event_attr.context_switch = 1;
}

void EventSelectionSet::WakeupPerSample() {
  for (auto& group : groups_) {
    for (auto& selection : group.selections) {
      selection.event_attr.watermark = 0;
      selection.event_attr.wakeup_events = 1;
    }
  }
}

bool EventSelectionSet::SetTracepointFilter(const std::string& filter) {
  // 1. Find the tracepoint event to set filter.
  EventSelection* selection = nullptr;
  if (!groups_.empty()) {
    auto& group = groups_.back();
    if (group.selections.size() == 1) {
      if (group.selections[0].event_attr.type == PERF_TYPE_TRACEPOINT) {
        selection = &group.selections[0];
      }
    }
  }
  if (selection == nullptr) {
    LOG(ERROR) << "No tracepoint event before filter: " << filter;
    return false;
  }

  // 2. Check the format of the filter.
  bool use_quote = false;
  // Quotes are needed for string operands in kernel >= 4.19, probably after patch "tracing: Rewrite
  // filter logic to be simpler and faster".
  if (auto version = GetKernelVersion(); version && version.value() >= std::make_pair(4, 19)) {
    use_quote = true;
  }

  FieldNameSet used_fields;
  auto adjusted_filter = AdjustTracepointFilter(filter, use_quote, &used_fields);
  if (!adjusted_filter) {
    return false;
  }

  // 3. Check if used fields are available in the tracepoint event.
  auto& event_type = selection->event_type_modifier.event_type;
  if (auto opt_fields = GetFieldNamesForTracepointEvent(event_type); opt_fields) {
    FieldNameSet& fields = opt_fields.value();
    for (const auto& field : used_fields) {
      if (fields.find(field) == fields.end()) {
        LOG(ERROR) << "field name " << field << " used in \"" << filter << "\" doesn't exist in "
                   << event_type.name << ". Available fields are "
                   << android::base::Join(fields, ",");
        return false;
      }
    }
  }

  // 4. Connect the filter to the event.
  selection->tracepoint_filter = adjusted_filter.value();
  return true;
}

bool EventSelectionSet::OpenEventFilesOnGroup(EventSelectionGroup& group, pid_t tid, int cpu,
                                              std::string* failed_event_type) {
  std::vector<std::unique_ptr<EventFd>> event_fds;
  // Given a tid and cpu, events on the same group should be all opened
  // successfully or all failed to open.
  EventFd* group_fd = nullptr;
  for (auto& selection : group.selections) {
    std::unique_ptr<EventFd> event_fd = EventFd::OpenEventFile(
        selection.event_attr, tid, cpu, group_fd, selection.event_type_modifier.name, false);
    if (!event_fd) {
      *failed_event_type = selection.event_type_modifier.name;
      return false;
    }
    LOG(VERBOSE) << "OpenEventFile for " << event_fd->Name();
    event_fds.emplace_back(std::move(event_fd));
    if (group_fd == nullptr) {
      group_fd = event_fds.back().get();
    }
  }
  for (size_t i = 0; i < group.selections.size(); ++i) {
    group.selections[i].event_fds.emplace_back(std::move(event_fds[i]));
  }
  return true;
}

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 (auto& pid : processes) {
    std::vector<pid_t> tids = GetThreadsInProcess(pid);
    result.insert(tids.begin(), tids.end());
  }
  return result;
}

bool EventSelectionSet::OpenEventFiles() {
  std::vector<int> online_cpus = GetOnlineCpus();

  auto check_if_cpus_online = [&](const std::vector<int>& cpus) {
    if (cpus.size() == 1 && cpus[0] == -1) {
      return true;
    }
    for (int 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;
  };

  std::set<pid_t> threads = PrepareThreads(processes_, threads_);
  for (auto& group : groups_) {
    const std::vector<int>* pcpus = &group.cpus;
    if (!group.selections[0].allowed_cpus.empty()) {
      // override cpu list if event's PMU has a cpumask as those PMUs are
      // agnostic to cpu and it's meaningless to specify cpus for them.
      pcpus = &group.selections[0].allowed_cpus;
    }
    if (pcpus->empty()) {
      pcpus = &online_cpus;
    } else if (!check_if_cpus_online(*pcpus)) {
      return false;
    }

    size_t success_count = 0;
    std::string failed_event_type;
    for (const auto tid : threads) {
      for (const auto& cpu : *pcpus) {
        if (OpenEventFilesOnGroup(group, tid, cpu, &failed_event_type)) {
          success_count++;
        }
      }
    }
    // We can't guarantee to open perf event file successfully for each thread on each cpu.
    // Because threads may exit between PrepareThreads() and OpenEventFilesOnGroup(), and
    // cpus may be offlined between GetOnlineCpus() and OpenEventFilesOnGroup().
    // So we only check that we can at least monitor one thread for each event group.
    if (success_count == 0) {
      int error_number = errno;
      PLOG(ERROR) << "failed to open perf event file for event_type " << failed_event_type;
      if (error_number == EMFILE) {
        LOG(ERROR) << "Please increase hard limit of open file numbers.";
      }
      return false;
    }
  }
  return ApplyFilters();
}

bool EventSelectionSet::ApplyFilters() {
  return ApplyAddrFilters() && ApplyTracepointFilters();
}

bool EventSelectionSet::ApplyAddrFilters() {
  if (addr_filters_.empty()) {
    return true;
  }
  if (!has_aux_trace_) {
    LOG(ERROR) << "addr filters only take effect in cs-etm instruction tracing";
    return false;
  }

  // Check filter count limit.
  size_t required_etm_filter_count = 0;
  for (auto& filter : addr_filters_) {
    // A range filter needs two etm filters.
    required_etm_filter_count +=
        (filter.type == AddrFilter::FILE_RANGE || filter.type == AddrFilter::KERNEL_RANGE) ? 2 : 1;
  }
  size_t etm_filter_count = ETMRecorder::GetInstance().GetAddrFilterPairs() * 2;
  if (etm_filter_count < required_etm_filter_count) {
    LOG(ERROR) << "needed " << required_etm_filter_count << " etm filters, but only "
               << etm_filter_count << " filters are available.";
    return false;
  }

  std::string filter_str;
  for (auto& filter : addr_filters_) {
    if (!filter_str.empty()) {
      filter_str += ',';
    }
    filter_str += filter.ToString();
  }

  for (auto& group : groups_) {
    for (auto& selection : group.selections) {
      if (IsEtmEventType(selection.event_type_modifier.event_type.type)) {
        for (auto& event_fd : selection.event_fds) {
          if (!event_fd->SetFilter(filter_str)) {
            return false;
          }
        }
      }
    }
  }
  return true;
}

bool EventSelectionSet::ApplyTracepointFilters() {
  for (auto& group : groups_) {
    for (auto& selection : group.selections) {
      if (!selection.tracepoint_filter.empty()) {
        for (auto& event_fd : selection.event_fds) {
          if (!event_fd->SetFilter(selection.tracepoint_filter)) {
            return false;
          }
        }
      }
    }
  }
  return true;
}

static bool ReadCounter(EventFd* event_fd, CounterInfo* counter) {
  if (!event_fd->ReadCounter(&counter->counter)) {
    return false;
  }
  counter->tid = event_fd->ThreadId();
  counter->cpu = event_fd->Cpu();
  return true;
}

bool EventSelectionSet::ReadCounters(std::vector<CountersInfo>* counters) {
  counters->clear();
  for (size_t i = 0; i < groups_.size(); ++i) {
    for (auto& selection : groups_[i].selections) {
      CountersInfo counters_info;
      counters_info.group_id = i;
      counters_info.event_name = selection.event_type_modifier.event_type.name;
      counters_info.event_modifier = selection.event_type_modifier.modifier;
      counters_info.counters = selection.hotplugged_counters;
      for (auto& event_fd : selection.event_fds) {
        CounterInfo counter;
        if (!ReadCounter(event_fd.get(), &counter)) {
          return false;
        }
        counters_info.counters.push_back(counter);
      }
      counters->push_back(counters_info);
    }
  }
  return true;
}

bool EventSelectionSet::MmapEventFiles(size_t min_mmap_pages, size_t max_mmap_pages,
                                       size_t aux_buffer_size, size_t record_buffer_size,
                                       bool allow_truncating_samples, bool exclude_perf) {
  record_read_thread_.reset(new simpleperf::RecordReadThread(
      record_buffer_size, groups_[0].selections[0].event_attr, min_mmap_pages, max_mmap_pages,
      aux_buffer_size, allow_truncating_samples, exclude_perf));
  return true;
}

bool EventSelectionSet::PrepareToReadMmapEventData(const std::function<bool(Record*)>& callback) {
  // Prepare record callback function.
  record_callback_ = callback;
  if (!record_read_thread_->RegisterDataCallback(*loop_,
                                                 [this]() { return ReadMmapEventData(true); })) {
    return false;
  }
  std::vector<EventFd*> event_fds;
  for (auto& group : groups_) {
    for (auto& selection : group.selections) {
      for (auto& event_fd : selection.event_fds) {
        event_fds.push_back(event_fd.get());
      }
    }
  }
  return record_read_thread_->AddEventFds(event_fds);
}

bool EventSelectionSet::SyncKernelBuffer() {
  return record_read_thread_->SyncKernelBuffer();
}

// Read records from the RecordBuffer. If with_time_limit is false, read until the RecordBuffer is
// empty, otherwise stop after 100 ms or when the record buffer is empty.
bool EventSelectionSet::ReadMmapEventData(bool with_time_limit) {
  uint64_t start_time_in_ns;
  if (with_time_limit) {
    start_time_in_ns = GetSystemClock();
  }
  std::unique_ptr<Record> r;
  while ((r = record_read_thread_->GetRecord()) != nullptr) {
    if (!record_callback_(r.get())) {
      return false;
    }
    if (with_time_limit && (GetSystemClock() - start_time_in_ns) >= 1e8) {
      break;
    }
  }
  return true;
}

bool EventSelectionSet::FinishReadMmapEventData() {
  return ReadMmapEventData(false);
}

void EventSelectionSet::CloseEventFiles() {
  if (record_read_thread_) {
    record_read_thread_->StopReadThread();
  }
  for (auto& group : groups_) {
    for (auto& event : group.selections) {
      event.event_fds.clear();
    }
  }
}

bool EventSelectionSet::StopWhenNoMoreTargets(double check_interval_in_sec) {
  return loop_->AddPeriodicEvent(SecondToTimeval(check_interval_in_sec),
                                 [&]() { return CheckMonitoredTargets(); });
}

bool EventSelectionSet::CheckMonitoredTargets() {
  if (!HasSampler()) {
    return loop_->ExitLoop();
  }
  for (const auto& tid : threads_) {
    if (IsThreadAlive(tid)) {
      return true;
    }
  }
  for (const auto& pid : processes_) {
    if (IsThreadAlive(pid)) {
      return true;
    }
  }
  return loop_->ExitLoop();
}

bool EventSelectionSet::HasSampler() {
  for (auto& group : groups_) {
    for (auto& sel : group.selections) {
      if (!sel.event_fds.empty()) {
        return true;
      }
    }
  }
  return false;
}

bool EventSelectionSet::SetEnableEvents(bool enable) {
  for (auto& group : groups_) {
    for (auto& sel : group.selections) {
      for (auto& fd : sel.event_fds) {
        if (!fd->SetEnableEvent(enable)) {
          return false;
        }
      }
    }
  }
  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
