// Copyright 2021 Google Inc. All rights reserved.
//
// 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 "perf_counters.h"

#include <cstring>
#include <memory>
#include <optional>
#include <vector>

#if defined HAVE_LIBPFM
#include <dirent.h>
#include <fcntl.h>
#include <linux/perf_event.h>
#include <sys/stat.h>

#include "perfmon/pfmlib.h"
#include "perfmon/pfmlib_perf_event.h"
#endif

namespace benchmark {
namespace internal {

#if defined HAVE_LIBPFM

size_t PerfCounterValues::Read(const std::vector<int>& leaders) {
  // Create a pointer for multiple reads
  const size_t bufsize = values_.size() * sizeof(values_[0]);
  char* ptr = reinterpret_cast<char*>(values_.data());
  size_t size = bufsize;
  for (int lead : leaders) {
    auto read_bytes = ::read(lead, ptr, size);
    if (read_bytes >= ssize_t(sizeof(uint64_t))) {
      // Actual data bytes are all bytes minus initial padding
      std::size_t data_bytes =
          static_cast<std::size_t>(read_bytes) - sizeof(uint64_t);
      // This should be very cheap since it's in hot cache
      std::memmove(ptr, ptr + sizeof(uint64_t), data_bytes);
      // Increment our counters
      ptr += data_bytes;
      size -= data_bytes;
    } else {
      int err = errno;
      GetErrorLogInstance() << "Error reading lead " << lead << " errno:" << err
                            << " " << ::strerror(err) << "\n";
      return 0;
    }
  }
  return (bufsize - size) / sizeof(uint64_t);
}

const bool PerfCounters::kSupported = true;

// Initializes libpfm only on the first call.  Returns whether that single
// initialization was successful.
bool PerfCounters::Initialize() {
  // Function-scope static gets initialized only once on first call.
  static const bool success = []() {
    return pfm_initialize() == PFM_SUCCESS;
  }();
  return success;
}

bool PerfCounters::IsCounterSupported(const std::string& name) {
  Initialize();
  perf_event_attr attr;
  std::memset(&attr, 0, sizeof(attr));
  pfm_perf_encode_arg_t arg;
  std::memset(&arg, 0, sizeof(arg));
  arg.attr = &attr;
  const int mode = PFM_PLM3;  // user mode only
  int ret = pfm_get_os_event_encoding(name.c_str(), mode, PFM_OS_PERF_EVENT_EXT,
                                      &arg);
  return (ret == PFM_SUCCESS);
}

static std::optional<std::vector<uint64_t>> QueryCPUPMUTypes() {
  std::vector<uint64_t> types;
  DIR* dir = opendir("/sys/bus/event_source/devices");
  if (!dir) {
    return std::nullopt;
  }
  while (dirent* ent = readdir(dir)) {
    std::string_view name_str = ent->d_name;
    auto node_path = [&](const char* node) {
      return std::string("/sys/bus/event_source/devices/") + ent->d_name + "/" +
             node;
    };
    struct stat st;
    if (name_str == "cpu" || name_str == "cpum_cf" ||
        stat(node_path("cpus").c_str(), &st) == 0 || errno != ENOENT) {
      int type_fd = open(node_path("type").c_str(), O_RDONLY);
      if (type_fd < 0) {
        closedir(dir);
        return std::nullopt;
      }
      char type_str[32] = {};
      ssize_t res = read(type_fd, type_str, sizeof(type_str) - 1);
      close(type_fd);
      if (res < 0) {
        closedir(dir);
        return std::nullopt;
      }
      uint64_t type;
      if (sscanf(type_str, "%" PRIu64, &type) != 1) {
        closedir(dir);
        return std::nullopt;
      }
      types.push_back(type);
    }
  }
  closedir(dir);
  return types;
}

static std::vector<uint64_t> GetPMUTypesForEvent(const perf_event_attr& attr) {
  // Replicate generic hardware events on all CPU PMUs.
  if (attr.type == PERF_TYPE_HARDWARE && attr.config < PERF_COUNT_HW_MAX) {
    if (auto types = QueryCPUPMUTypes()) {
      return *types;
    }
  }
  return {0};
}

PerfCounters PerfCounters::Create(
    const std::vector<std::string>& counter_names) {
  if (!counter_names.empty()) {
    Initialize();
  }

  // Valid counters will populate these arrays but we start empty
  std::vector<std::string> valid_names;
  std::vector<int> counter_ids;
  std::vector<int> leader_ids;

  // Resize to the maximum possible
  valid_names.reserve(counter_names.size());
  counter_ids.reserve(counter_names.size());

  const int kCounterMode = PFM_PLM3;  // user mode only

  // Group leads will be assigned on demand. The idea is that once we cannot
  // create a counter descriptor, the reason is that this group has maxed out
  // so we set the group_id again to -1 and retry - giving the algorithm a
  // chance to create a new group leader to hold the next set of counters.
  int group_id = -1;

  // Loop through all performance counters
  for (size_t i = 0; i < counter_names.size(); ++i) {
    // we are about to push into the valid names vector
    // check if we did not reach the maximum
    if (valid_names.size() == PerfCounterValues::kMaxCounters) {
      // Log a message if we maxed out and stop adding
      GetErrorLogInstance()
          << counter_names.size() << " counters were requested. The maximum is "
          << PerfCounterValues::kMaxCounters << " and " << valid_names.size()
          << " were already added. All remaining counters will be ignored\n";
      // stop the loop and return what we have already
      break;
    }

    // Check if this name is empty
    const auto& name = counter_names[i];
    if (name.empty()) {
      GetErrorLogInstance()
          << "A performance counter name was the empty string\n";
      continue;
    }

    // Here first means first in group, ie the group leader
    const bool is_first = (group_id < 0);

    // This struct will be populated by libpfm from the counter string
    // and then fed into the syscall perf_event_open
    struct perf_event_attr attr {};
    attr.size = sizeof(attr);

    // This is the input struct to libpfm.
    pfm_perf_encode_arg_t arg{};
    arg.attr = &attr;
    const int pfm_get = pfm_get_os_event_encoding(name.c_str(), kCounterMode,
                                                  PFM_OS_PERF_EVENT, &arg);
    if (pfm_get != PFM_SUCCESS) {
      GetErrorLogInstance()
          << "Unknown performance counter name: " << name << "\n";
      continue;
    }

    // We then proceed to populate the remaining fields in our attribute struct
    // Note: the man page for perf_event_create suggests inherit = true and
    // read_format = PERF_FORMAT_GROUP don't work together, but that's not the
    // case.
    attr.disabled = is_first;
    attr.inherit = true;
    attr.pinned = is_first;
    attr.exclude_kernel = true;
    attr.exclude_user = false;
    attr.exclude_hv = true;

    // Read all counters in a group in one read.
    attr.read_format = PERF_FORMAT_GROUP;  //| PERF_FORMAT_TOTAL_TIME_ENABLED |
                                           // PERF_FORMAT_TOTAL_TIME_RUNNING;

    uint64_t base_config = attr.config;
    for (uint64_t pmu : GetPMUTypesForEvent(attr)) {
      attr.config = (pmu << PERF_PMU_TYPE_SHIFT) | base_config;
      int id = -1;
      while (id < 0) {
        static constexpr size_t kNrOfSyscallRetries = 5;
        // Retry syscall as it was interrupted often (b/64774091).
        for (size_t num_retries = 0; num_retries < kNrOfSyscallRetries;
             ++num_retries) {
          id = perf_event_open(&attr, 0, -1, group_id, 0);
          if (id >= 0 || errno != EINTR) {
            break;
          }
        }
        if (id < 0) {
          // If the file descriptor is negative we might have reached a limit
          // in the current group. Set the group_id to -1 and retry
          if (group_id >= 0) {
            // Create a new group
            group_id = -1;
          } else {
            // At this point we have already retried to set a new group id and
            // failed. We then give up.
            break;
          }
        }
      }

      // We failed to get a new file descriptor. We might have reached a hard
      // hardware limit that cannot be resolved even with group multiplexing
      if (id < 0) {
        GetErrorLogInstance() << "***WARNING** Failed to get a file descriptor "
                                 "for performance counter "
                              << name << ". Ignoring\n";

        // We give up on this counter but try to keep going
        // as the others would be fine
        continue;
      }
      if (group_id < 0) {
        // This is a leader, store and assign it to the current file descriptor
        leader_ids.push_back(id);
        group_id = id;
      }
      // This is a valid counter, add it to our descriptor's list
      counter_ids.push_back(id);
      valid_names.push_back(name);
    }
  }

  // Loop through all group leaders activating them
  // There is another option of starting ALL counters in a process but
  // that would be far reaching an intrusion. If the user is using PMCs
  // by themselves then this would have a side effect on them. It is
  // friendlier to loop through all groups individually.
  for (int lead : leader_ids) {
    if (ioctl(lead, PERF_EVENT_IOC_ENABLE) != 0) {
      // This should never happen but if it does, we give up on the
      // entire batch as recovery would be a mess.
      GetErrorLogInstance() << "***WARNING*** Failed to start counters. "
                               "Clearing out all counters.\n";

      // Close all performance counters
      for (int id : counter_ids) {
        ::close(id);
      }

      // Return an empty object so our internal state is still good and
      // the process can continue normally without impact
      return NoCounters();
    }
  }

  return PerfCounters(std::move(valid_names), std::move(counter_ids),
                      std::move(leader_ids));
}

void PerfCounters::CloseCounters() const {
  if (counter_ids_.empty()) {
    return;
  }
  for (int lead : leader_ids_) {
    ioctl(lead, PERF_EVENT_IOC_DISABLE);
  }
  for (int fd : counter_ids_) {
    close(fd);
  }
}
#else   // defined HAVE_LIBPFM
size_t PerfCounterValues::Read(const std::vector<int>&) { return 0; }

const bool PerfCounters::kSupported = false;

bool PerfCounters::Initialize() { return false; }

bool PerfCounters::IsCounterSupported(const std::string&) { return false; }

PerfCounters PerfCounters::Create(
    const std::vector<std::string>& counter_names) {
  if (!counter_names.empty()) {
    GetErrorLogInstance() << "Performance counters not supported.\n";
  }
  return NoCounters();
}

void PerfCounters::CloseCounters() const {}
#endif  // defined HAVE_LIBPFM

PerfCountersMeasurement::PerfCountersMeasurement(
    const std::vector<std::string>& counter_names)
    : start_values_(counter_names.size()), end_values_(counter_names.size()) {
  counters_ = PerfCounters::Create(counter_names);
}

PerfCounters& PerfCounters::operator=(PerfCounters&& other) noexcept {
  if (this != &other) {
    CloseCounters();

    counter_ids_ = std::move(other.counter_ids_);
    leader_ids_ = std::move(other.leader_ids_);
    counter_names_ = std::move(other.counter_names_);
  }
  return *this;
}
}  // namespace internal
}  // namespace benchmark
