/*
 * Copyright (C) 2017 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 "src/traced/probes/ftrace/ftrace_controller.h"

#include <fcntl.h>
#include <poll.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/utsname.h>
#include <sys/wait.h>
#include <unistd.h>
#include <cstdint>

#include <limits>
#include <memory>
#include <optional>
#include <string>
#include <tuple>
#include <utility>

#include "perfetto/base/build_config.h"
#include "perfetto/base/logging.h"
#include "perfetto/base/time.h"
#include "perfetto/ext/base/file_utils.h"
#include "perfetto/ext/base/metatrace.h"
#include "perfetto/ext/base/scoped_file.h"
#include "perfetto/ext/base/string_utils.h"
#include "perfetto/ext/tracing/core/trace_writer.h"
#include "src/kallsyms/kernel_symbol_map.h"
#include "src/kallsyms/lazy_kernel_symbolizer.h"
#include "src/traced/probes/ftrace/atrace_hal_wrapper.h"
#include "src/traced/probes/ftrace/cpu_reader.h"
#include "src/traced/probes/ftrace/cpu_stats_parser.h"
#include "src/traced/probes/ftrace/event_info.h"
#include "src/traced/probes/ftrace/event_info_constants.h"
#include "src/traced/probes/ftrace/ftrace_config_muxer.h"
#include "src/traced/probes/ftrace/ftrace_config_utils.h"
#include "src/traced/probes/ftrace/ftrace_data_source.h"
#include "src/traced/probes/ftrace/ftrace_metadata.h"
#include "src/traced/probes/ftrace/ftrace_procfs.h"
#include "src/traced/probes/ftrace/ftrace_stats.h"
#include "src/traced/probes/ftrace/proto_translation_table.h"
#include "src/traced/probes/ftrace/vendor_tracepoints.h"

namespace perfetto {
namespace {

constexpr uint32_t kDefaultTickPeriodMs = 100;
constexpr uint32_t kPollBackingTickPeriodMs = 1000;
constexpr uint32_t kMinTickPeriodMs = 1;
constexpr uint32_t kMaxTickPeriodMs = 1000 * 60;
constexpr int kPollRequiredMajorVersion = 6;
constexpr int kPollRequiredMinorVersion = 1;

// Read at most this many pages of data per cpu per read task. If we hit this
// limit on at least one cpu, we stop and repost the read task, letting other
// tasks get some cpu time before continuing reading.
constexpr size_t kMaxPagesPerCpuPerReadTick = 256;  // 1 MB per cpu

bool WriteToFile(const char* path, const char* str) {
  auto fd = base::OpenFile(path, O_WRONLY);
  if (!fd)
    return false;
  const size_t str_len = strlen(str);
  return base::WriteAll(*fd, str, str_len) == static_cast<ssize_t>(str_len);
}

bool ClearFile(const char* path) {
  auto fd = base::OpenFile(path, O_WRONLY | O_TRUNC);
  return !!fd;
}

std::optional<int64_t> ReadFtraceNowTs(const base::ScopedFile& cpu_stats_fd) {
  PERFETTO_CHECK(cpu_stats_fd);

  char buf[512];
  ssize_t res = PERFETTO_EINTR(pread(*cpu_stats_fd, buf, sizeof(buf) - 1, 0));
  if (res <= 0)
    return std::nullopt;
  buf[res] = '\0';

  FtraceCpuStats stats{};
  DumpCpuStats(buf, &stats);
  return static_cast<int64_t>(stats.now_ts * 1000 * 1000 * 1000);
}

std::map<std::string, std::vector<GroupAndName>> GetAtraceVendorEvents(
    FtraceProcfs* tracefs) {
#if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
  if (base::FileExists(vendor_tracepoints::kCategoriesFile)) {
    std::map<std::string, std::vector<GroupAndName>> vendor_evts;
    base::Status status =
        vendor_tracepoints::DiscoverAccessibleVendorTracepointsWithFile(
            vendor_tracepoints::kCategoriesFile, &vendor_evts, tracefs);
    if (!status.ok()) {
      PERFETTO_ELOG("Cannot load vendor categories: %s", status.c_message());
    }
    return vendor_evts;
  } else {
    AtraceHalWrapper hal;
    return vendor_tracepoints::DiscoverVendorTracepointsWithHal(&hal, tracefs);
  }
#else
  base::ignore_result(tracefs);
  return {};
#endif
}

struct AndroidGkiVersion {
  uint64_t version = 0;
  uint64_t patch_level = 0;
  uint64_t sub_level = 0;
  uint64_t release = 0;
  uint64_t kmi_gen = 0;
};

#define ANDROID_GKI_UNAME_FMT \
  "%" PRIu64 ".%" PRIu64 ".%" PRIu64 "-android%" PRIu64 "-%" PRIu64

std::optional<AndroidGkiVersion> ParseAndroidGkiVersion(const char* s) {
  AndroidGkiVersion v = {};
  if (sscanf(s, ANDROID_GKI_UNAME_FMT, &v.version, &v.patch_level, &v.sub_level,
             &v.release, &v.kmi_gen) != 5) {
    return std::nullopt;
  }
  return v;
}

}  // namespace

// Method of last resort to reset ftrace state.
// We don't know what state the rest of the system and process is so as far
// as possible avoid allocations.
bool HardResetFtraceState() {
  for (const char* const* item = FtraceProcfs::kTracingPaths; *item; ++item) {
    std::string prefix(*item);
    PERFETTO_CHECK(base::EndsWith(prefix, "/"));
    bool res = true;
    res &= WriteToFile((prefix + "tracing_on").c_str(), "0");
    res &= WriteToFile((prefix + "buffer_size_kb").c_str(), "4");
    // Not checking success because these files might not be accessible on
    // older or release builds of Android:
    WriteToFile((prefix + "events/enable").c_str(), "0");
    WriteToFile((prefix + "events/raw_syscalls/filter").c_str(), "0");
    WriteToFile((prefix + "current_tracer").c_str(), "nop");
    res &= ClearFile((prefix + "trace").c_str());
    if (res)
      return true;
  }
  return false;
}

// static
std::unique_ptr<FtraceController> FtraceController::Create(
    base::TaskRunner* runner,
    Observer* observer) {
  std::unique_ptr<FtraceProcfs> ftrace_procfs =
      FtraceProcfs::CreateGuessingMountPoint("");
  if (!ftrace_procfs)
    return nullptr;

  std::unique_ptr<ProtoTranslationTable> table = ProtoTranslationTable::Create(
      ftrace_procfs.get(), GetStaticEventInfo(), GetStaticCommonFieldsInfo());
  if (!table)
    return nullptr;

  auto atrace_wrapper = std::make_unique<AtraceWrapperImpl>();

  std::map<std::string, std::vector<GroupAndName>> vendor_evts =
      GetAtraceVendorEvents(ftrace_procfs.get());

  SyscallTable syscalls = SyscallTable::FromCurrentArch();

  auto muxer = std::make_unique<FtraceConfigMuxer>(
      ftrace_procfs.get(), atrace_wrapper.get(), table.get(),
      std::move(syscalls), vendor_evts);
  return std::unique_ptr<FtraceController>(new FtraceController(
      std::move(ftrace_procfs), std::move(table), std::move(atrace_wrapper),
      std::move(muxer), runner, observer));
}

FtraceController::FtraceController(
    std::unique_ptr<FtraceProcfs> ftrace_procfs,
    std::unique_ptr<ProtoTranslationTable> table,
    std::unique_ptr<AtraceWrapper> atrace_wrapper,
    std::unique_ptr<FtraceConfigMuxer> muxer,
    base::TaskRunner* task_runner,
    Observer* observer)
    : task_runner_(task_runner),
      observer_(observer),
      atrace_wrapper_(std::move(atrace_wrapper)),
      primary_(std::move(ftrace_procfs), std::move(table), std::move(muxer)),
      weak_factory_(this) {}

FtraceController::~FtraceController() {
  while (!data_sources_.empty()) {
    RemoveDataSource(*data_sources_.begin());
  }
  PERFETTO_DCHECK(data_sources_.empty());
  PERFETTO_DCHECK(primary_.started_data_sources.empty());
  PERFETTO_DCHECK(primary_.cpu_readers.empty());
  PERFETTO_DCHECK(secondary_instances_.empty());
}

uint64_t FtraceController::NowMs() const {
  return static_cast<uint64_t>(base::GetWallTimeMs().count());
}

template <typename F>
void FtraceController::ForEachInstance(F fn) {
  fn(&primary_);
  for (auto& kv : secondary_instances_) {
    fn(kv.second.get());
  }
}

void FtraceController::StartIfNeeded(FtraceInstanceState* instance,
                                     const std::string& instance_name) {
  if (buffer_watermark_support_ == PollSupport::kUntested) {
    buffer_watermark_support_ = VerifyKernelSupportForBufferWatermark();
  }

  // If instance is already active, then at most we need to update the buffer
  // poll callbacks. The periodic |ReadTick| will pick up any updates to the
  // period the next time it executes.
  if (instance->started_data_sources.size() > 1) {
    UpdateBufferWatermarkWatches(instance, instance_name);
    return;
  }

  // Lazily allocate the memory used for reading & parsing ftrace. In the case
  // of multiple ftrace instances, this might already be valid.
  parsing_mem_.AllocateIfNeeded();

  const auto ftrace_clock = instance->ftrace_config_muxer->ftrace_clock();
  size_t num_cpus = instance->ftrace_procfs->NumberOfCpus();
  PERFETTO_CHECK(instance->cpu_readers.empty());
  instance->cpu_readers.reserve(num_cpus);
  for (size_t cpu = 0; cpu < num_cpus; cpu++) {
    instance->cpu_readers.emplace_back(
        cpu, instance->ftrace_procfs->OpenPipeForCpu(cpu),
        instance->table.get(), &symbolizer_, ftrace_clock,
        &ftrace_clock_snapshot_);
  }

  // Special case for primary instance: if not using the boot clock, take
  // manual clock snapshots so that the trace parser can do a best effort
  // conversion back to boot. This is primarily for old kernels that predate
  // boot support, and therefore default to "global" clock.
  if (instance == &primary_ &&
      ftrace_clock != protos::pbzero::FtraceClock::FTRACE_CLOCK_UNSPECIFIED) {
    cpu_zero_stats_fd_ = primary_.ftrace_procfs->OpenCpuStats(0 /* cpu */);
    MaybeSnapshotFtraceClock();
  }

  // Set up poll callbacks for the buffers if requested by at least one DS.
  UpdateBufferWatermarkWatches(instance, instance_name);

  // Start a new repeating read task (even if there is already one posted due
  // to a different ftrace instance). Any old tasks will stop due to generation
  // checks.
  auto generation = ++tick_generation_;
  auto tick_period_ms = GetTickPeriodMs();
  auto weak_this = weak_factory_.GetWeakPtr();
  task_runner_->PostDelayedTask(
      [weak_this, generation] {
        if (weak_this)
          weak_this->ReadTick(generation);
      },
      tick_period_ms - (NowMs() % tick_period_ms));
}

// We handle the ftrace buffers in a repeating task (ReadTick). On a given tick,
// we iterate over all per-cpu buffers, parse their contents, and then write out
// the serialized packets. This is handled by |CpuReader| instances, which
// attempt to read from their respective per-cpu buffer fd until they catch up
// to the head of the buffer, or hit a transient error.
//
// The readers work in batches of |kParsingBufferSizePages| pages for cache
// locality, and to limit memory usage.
//
// However, the reading happens on the primary thread, shared with the rest of
// the service (including ipc). If there is a lot of ftrace data to read, we
// want to yield to the event loop, re-enqueueing a continuation task at the end
// of the immediate queue (letting other enqueued tasks to run before
// continuing). Therefore we introduce |kMaxPagesPerCpuPerReadTick|.
void FtraceController::ReadTick(int generation) {
  metatrace::ScopedEvent evt(metatrace::TAG_FTRACE,
                             metatrace::FTRACE_READ_TICK);
  if (generation != tick_generation_ || GetStartedDataSourcesCount() == 0) {
    return;
  }
  MaybeSnapshotFtraceClock();

  // Read all per-cpu buffers.
  bool all_cpus_done = ReadPassForInstance(&primary_);
  ForEachInstance([&](FtraceInstanceState* instance) {
    all_cpus_done &= ReadPassForInstance(instance);
  });
  observer_->OnFtraceDataWrittenIntoDataSourceBuffers();

  auto weak_this = weak_factory_.GetWeakPtr();
  if (!all_cpus_done) {
    PERFETTO_DLOG("Reposting immediate ReadTick as there's more work.");
    task_runner_->PostTask([weak_this, generation] {
      if (weak_this)
        weak_this->ReadTick(generation);
    });
  } else {
    // Done until next period.
    auto tick_period_ms = GetTickPeriodMs();
    task_runner_->PostDelayedTask(
        [weak_this, generation] {
          if (weak_this)
            weak_this->ReadTick(generation);
        },
        tick_period_ms - (NowMs() % tick_period_ms));
  }

#if PERFETTO_DCHECK_IS_ON()
  // OnFtraceDataWrittenIntoDataSourceBuffers() is supposed to clear
  // all metadata, including the |kernel_addrs| map for symbolization.
  ForEachInstance([&](FtraceInstanceState* instance) {
    for (FtraceDataSource* ds : instance->started_data_sources) {
      FtraceMetadata* ftrace_metadata = ds->mutable_metadata();
      PERFETTO_DCHECK(ftrace_metadata->kernel_addrs.empty());
      PERFETTO_DCHECK(ftrace_metadata->last_kernel_addr_index_written == 0);
    }
  });
#endif
}

bool FtraceController::ReadPassForInstance(FtraceInstanceState* instance) {
  if (instance->started_data_sources.empty())
    return true;

  bool all_cpus_done = true;
  for (size_t i = 0; i < instance->cpu_readers.size(); i++) {
    size_t max_pages = kMaxPagesPerCpuPerReadTick;
    size_t pages_read = instance->cpu_readers[i].ReadCycle(
        &parsing_mem_, max_pages, instance->started_data_sources);
    PERFETTO_DCHECK(pages_read <= max_pages);
    if (pages_read == max_pages) {
      all_cpus_done = false;
    }
  }
  return all_cpus_done;
}

uint32_t FtraceController::GetTickPeriodMs() {
  if (data_sources_.empty())
    return kDefaultTickPeriodMs;
  uint32_t kUnsetPeriod = std::numeric_limits<uint32_t>::max();
  uint32_t min_period_ms = kUnsetPeriod;
  bool using_poll = true;
  ForEachInstance([&](FtraceInstanceState* instance) {
    using_poll &= instance->buffer_watches_posted;
    for (FtraceDataSource* ds : instance->started_data_sources) {
      if (ds->config().has_drain_period_ms()) {
        min_period_ms = std::min(min_period_ms, ds->config().drain_period_ms());
      }
    }
  });

  // None of the active data sources requested an explicit tick period.
  // The historical default is 100ms, but if we know that all instances are also
  // using buffer watermark polling, we can raise it. We don't disable the tick
  // entirely as it spreads the read work more evenly, and ensures procfs
  // scrapes of seen TIDs are not too stale.
  if (min_period_ms == kUnsetPeriod) {
    return using_poll ? kPollBackingTickPeriodMs : kDefaultTickPeriodMs;
  }

  if (min_period_ms < kMinTickPeriodMs || min_period_ms > kMaxTickPeriodMs) {
    PERFETTO_LOG(
        "drain_period_ms was %u should be between %u and %u. "
        "Falling back onto a default.",
        min_period_ms, kMinTickPeriodMs, kMaxTickPeriodMs);
    return kDefaultTickPeriodMs;
  }
  return min_period_ms;
}

void FtraceController::UpdateBufferWatermarkWatches(
    FtraceInstanceState* instance,
    const std::string& instance_name) {
  PERFETTO_DCHECK(buffer_watermark_support_ != PollSupport::kUntested);
  if (buffer_watermark_support_ == PollSupport::kUnsupported)
    return;

  bool requested_poll = false;
  for (const FtraceDataSource* ds : instance->started_data_sources) {
    requested_poll |= ds->config().has_drain_buffer_percent();
  }

  if (!requested_poll || instance->buffer_watches_posted)
    return;

  auto weak_this = weak_factory_.GetWeakPtr();
  for (size_t i = 0; i < instance->cpu_readers.size(); i++) {
    int fd = instance->cpu_readers[i].RawBufferFd();
    task_runner_->AddFileDescriptorWatch(fd, [weak_this, instance_name, i] {
      if (weak_this)
        weak_this->OnBufferPastWatermark(instance_name, i,
                                         /*repoll_watermark=*/true);
    });
  }
  instance->buffer_watches_posted = true;
}

void FtraceController::RemoveBufferWatermarkWatches(
    FtraceInstanceState* instance) {
  if (!instance->buffer_watches_posted)
    return;

  for (size_t i = 0; i < instance->cpu_readers.size(); i++) {
    int fd = instance->cpu_readers[i].RawBufferFd();
    task_runner_->RemoveFileDescriptorWatch(fd);
  }
  instance->buffer_watches_posted = false;
}

// TODO(rsavitski): consider calling OnFtraceData only if we're not reposting
// a continuation. It's a tradeoff between procfs scrape freshness and urgency
// to drain ftrace kernel buffers.
void FtraceController::OnBufferPastWatermark(std::string instance_name,
                                             size_t cpu,
                                             bool repoll_watermark) {
  metatrace::ScopedEvent evt(metatrace::TAG_FTRACE,
                             metatrace::FTRACE_CPU_BUFFER_WATERMARK);

  // Instance might have been stopped before this callback runs.
  FtraceInstanceState* instance = GetInstance(instance_name);
  if (!instance || cpu >= instance->cpu_readers.size())
    return;

  // Repoll all per-cpu buffers with zero timeout to confirm that at least
  // one is still past the watermark. This might not be true if a different
  // callback / readtick / flush did a read pass before this callback reached
  // the front of the task runner queue.
  if (repoll_watermark) {
    size_t num_cpus = instance->cpu_readers.size();
    std::vector<struct pollfd> pollfds(num_cpus);
    for (size_t i = 0; i < num_cpus; i++) {
      pollfds[i].fd = instance->cpu_readers[i].RawBufferFd();
      pollfds[i].events = POLLIN;
    }
    int r = PERFETTO_EINTR(poll(pollfds.data(), num_cpus, 0));
    if (r < 0) {
      PERFETTO_DPLOG("poll failed");
      return;
    } else if (r == 0) {  // no buffers below the watermark -> we're done.
      return;
    }
    // Count the number of readable fds, as some poll results might be POLLERR,
    // as seen in cases with offlined cores. It's still fine to attempt reading
    // from those buffers as CpuReader will handle the ENODEV.
    bool has_readable_fd = false;
    for (size_t i = 0; i < num_cpus; i++) {
      has_readable_fd |= (pollfds[i].revents & POLLIN);
    }
    if (!has_readable_fd) {
      return;
    }
  }

  MaybeSnapshotFtraceClock();
  bool all_cpus_done = ReadPassForInstance(instance);
  observer_->OnFtraceDataWrittenIntoDataSourceBuffers();
  if (!all_cpus_done) {
    // More data to be read, but we want to let other task_runner tasks to run.
    // Repost a continuation task.
    auto weak_this = weak_factory_.GetWeakPtr();
    task_runner_->PostTask([weak_this, instance_name, cpu] {
      if (weak_this)
        weak_this->OnBufferPastWatermark(instance_name, cpu,
                                         /*repoll_watermark=*/false);
    });
  }
}

void FtraceController::Flush(FlushRequestID flush_id) {
  metatrace::ScopedEvent evt(metatrace::TAG_FTRACE,
                             metatrace::FTRACE_CPU_FLUSH);

  ForEachInstance([&](FtraceInstanceState* instance) {  // for clang-format
    FlushForInstance(instance);
  });
  observer_->OnFtraceDataWrittenIntoDataSourceBuffers();

  ForEachInstance([&](FtraceInstanceState* instance) {
    for (FtraceDataSource* ds : instance->started_data_sources) {
      ds->OnFtraceFlushComplete(flush_id);
    }
  });
}

void FtraceController::FlushForInstance(FtraceInstanceState* instance) {
  if (instance->started_data_sources.empty())
    return;

  // Read all cpus in one go, limiting the per-cpu read amount to make sure we
  // don't get stuck chasing the writer if there's a very high bandwidth of
  // events.
  size_t max_pages = instance->ftrace_config_muxer->GetPerCpuBufferSizePages();
  for (size_t i = 0; i < instance->cpu_readers.size(); i++) {
    instance->cpu_readers[i].ReadCycle(&parsing_mem_, max_pages,
                                       instance->started_data_sources);
  }
}

// We are not implicitly flushing on Stop. The tracing service is supposed to
// ask for an explicit flush before stopping, unless it needs to perform a
// non-graceful stop.
void FtraceController::StopIfNeeded(FtraceInstanceState* instance) {
  if (!instance->started_data_sources.empty())
    return;

  RemoveBufferWatermarkWatches(instance);
  instance->cpu_readers.clear();
  if (instance == &primary_) {
    cpu_zero_stats_fd_.reset();
  }
  // Muxer cannot change the current_tracer until we close the trace pipe fds
  // (i.e. per_cpu). Hence an explicit request here.
  instance->ftrace_config_muxer->ResetCurrentTracer();

  DestroyIfUnusedSeconaryInstance(instance);

  // Clean up global state if done with all data sources.
  if (!data_sources_.empty())
    return;

  if (!retain_ksyms_on_stop_) {
    symbolizer_.Destroy();
  }
  retain_ksyms_on_stop_ = false;

  // Note: might have never been allocated if data sources were rejected.
  parsing_mem_.Release();
}

bool FtraceController::AddDataSource(FtraceDataSource* data_source) {
  if (!ValidConfig(data_source->config()))
    return false;

  FtraceInstanceState* instance =
      GetOrCreateInstance(data_source->config().instance_name());
  if (!instance)
    return false;

  // note: from this point onwards, need to not leak a possibly created
  // instance if returning early.

  FtraceConfigId config_id = next_cfg_id_++;
  if (!instance->ftrace_config_muxer->SetupConfig(
          config_id, data_source->config(),
          data_source->mutable_setup_errors())) {
    DestroyIfUnusedSeconaryInstance(instance);
    return false;
  }

  const FtraceDataSourceConfig* ds_config =
      instance->ftrace_config_muxer->GetDataSourceConfig(config_id);
  auto it_and_inserted = data_sources_.insert(data_source);
  PERFETTO_DCHECK(it_and_inserted.second);
  data_source->Initialize(config_id, ds_config);
  return true;
}

bool FtraceController::StartDataSource(FtraceDataSource* data_source) {
  PERFETTO_DCHECK(data_sources_.count(data_source) > 0);

  FtraceConfigId config_id = data_source->config_id();
  PERFETTO_CHECK(config_id);
  const std::string& instance_name = data_source->config().instance_name();
  FtraceInstanceState* instance = GetOrCreateInstance(instance_name);
  PERFETTO_CHECK(instance);

  if (!instance->ftrace_config_muxer->ActivateConfig(config_id))
    return false;
  instance->started_data_sources.insert(data_source);
  StartIfNeeded(instance, instance_name);

  // Parse kernel symbols if required by the config. This can be an expensive
  // operation (cpu-bound for 500ms+), so delay the StartDataSource
  // acknowledgement until after we're done. This lets a consumer wait for the
  // expensive work to be done by waiting on the "all data sources started"
  // fence. This helps isolate the effects of the cpu-bound work on
  // frequency scaling of cpus when recording benchmarks (b/236143653).
  // Note that we're already recording data into the kernel ftrace
  // buffers while doing the symbol parsing.
  if (data_source->config().symbolize_ksyms()) {
    symbolizer_.GetOrCreateKernelSymbolMap();
    // If at least one config sets the KSYMS_RETAIN flag, keep the ksysm map
    // around in StopIfNeeded().
    const auto KRET = FtraceConfig::KSYMS_RETAIN;
    retain_ksyms_on_stop_ |= data_source->config().ksyms_mem_policy() == KRET;
  }

  return true;
}

void FtraceController::RemoveDataSource(FtraceDataSource* data_source) {
  size_t removed = data_sources_.erase(data_source);
  if (!removed)
    return;  // can happen if AddDataSource failed

  FtraceInstanceState* instance =
      GetOrCreateInstance(data_source->config().instance_name());
  PERFETTO_CHECK(instance);

  instance->ftrace_config_muxer->RemoveConfig(data_source->config_id());
  instance->started_data_sources.erase(data_source);
  StopIfNeeded(instance);
}

void FtraceController::DumpFtraceStats(FtraceDataSource* data_source,
                                       FtraceStats* stats_out) {
  FtraceInstanceState* instance =
      GetInstance(data_source->config().instance_name());
  PERFETTO_DCHECK(instance);
  if (!instance)
    return;

  DumpAllCpuStats(instance->ftrace_procfs.get(), stats_out);
  if (symbolizer_.is_valid()) {
    auto* symbol_map = symbolizer_.GetOrCreateKernelSymbolMap();
    stats_out->kernel_symbols_parsed =
        static_cast<uint32_t>(symbol_map->num_syms());
    stats_out->kernel_symbols_mem_kb =
        static_cast<uint32_t>(symbol_map->size_bytes() / 1024);
  }
}

void FtraceController::MaybeSnapshotFtraceClock() {
  if (!cpu_zero_stats_fd_)
    return;

  auto ftrace_clock = primary_.ftrace_config_muxer->ftrace_clock();
  PERFETTO_DCHECK(ftrace_clock != protos::pbzero::FTRACE_CLOCK_UNSPECIFIED);

  // Snapshot the boot clock *before* reading CPU stats so that
  // two clocks are as close togher as possible (i.e. if it was the
  // other way round, we'd skew by the const of string parsing).
  ftrace_clock_snapshot_.boot_clock_ts = base::GetBootTimeNs().count();

  // A value of zero will cause this snapshot to be skipped.
  ftrace_clock_snapshot_.ftrace_clock_ts =
      ReadFtraceNowTs(cpu_zero_stats_fd_).value_or(0);
}

FtraceController::PollSupport
FtraceController::VerifyKernelSupportForBufferWatermark() {
  struct utsname uts = {};
  if (uname(&uts) < 0 || strcmp(uts.sysname, "Linux") != 0)
    return PollSupport::kUnsupported;
  if (!PollSupportedOnKernelVersion(uts.release))
    return PollSupport::kUnsupported;

  // buffer_percent exists and is writable
  auto* tracefs = primary_.ftrace_procfs.get();
  uint32_t current = tracefs->ReadBufferPercent();
  if (!tracefs->SetBufferPercent(current ? current : 50)) {
    return PollSupport::kUnsupported;
  }

  // Polling on per_cpu/cpu0/trace_pipe_raw doesn't return errors.
  base::ScopedFile fd = tracefs->OpenPipeForCpu(0);
  struct pollfd pollset = {};
  pollset.fd = fd.get();
  pollset.events = POLLIN;
  int r = PERFETTO_EINTR(poll(&pollset, 1, 0));
  if (r < 0 || (r > 0 && (pollset.revents & POLLERR))) {
    return PollSupport::kUnsupported;
  }
  return PollSupport::kSupported;
}

// Check kernel version since the poll implementation has historical bugs.
// We're looking for at least 6.1 for the following:
//   42fb0a1e84ff tracing/ring-buffer: Have polling block on watermark
// Otherwise the poll will wake us up as soon as a single byte is in the
// buffer. A more conservative check would look for 6.6 for an extra fix that
// reduces excessive kernel-space wakeups:
//   1e0cb399c765 ring-buffer: Update "shortest_full" in polling
// However that doesn't break functionality, so we'll still use poll if
// requested by the config.
// static
bool FtraceController::PollSupportedOnKernelVersion(const char* uts_release) {
  int major = 0, minor = 0;
  if (sscanf(uts_release, "%d.%d", &major, &minor) != 2) {
    return false;
  }
  if (major < kPollRequiredMajorVersion ||
      (major == kPollRequiredMajorVersion &&
       minor < kPollRequiredMinorVersion)) {
    // Android: opportunistically detect a few select GKI kernels that are known
    // to have the fixes. Note: 6.1 and 6.6 GKIs are already covered by the
    // outer check.
    std::optional<AndroidGkiVersion> gki = ParseAndroidGkiVersion(uts_release);
    if (!gki.has_value())
      return false;
    // android13-5.10.197 or higher sublevel:
    //   ef47f25e98de ring-buffer: Update "shortest_full" in polling
    // android13-5.15.133 and
    // android14-5.15.133 or higher sublevel:
    //   b5d00cd7db66 ring-buffer: Update "shortest_full" in polling
    bool gki_patched =
        (gki->release == 13 && gki->version == 5 && gki->patch_level == 10 &&
         gki->sub_level >= 197) ||
        ((gki->release == 13 || gki->release == 14) && gki->version == 5 &&
         gki->patch_level == 15 && gki->sub_level >= 133);
    return gki_patched;
  }
  return true;
}

size_t FtraceController::GetStartedDataSourcesCount() {
  size_t cnt = 0;
  ForEachInstance([&](FtraceInstanceState* instance) {
    cnt += instance->started_data_sources.size();
  });
  return cnt;
}

FtraceController::FtraceInstanceState::FtraceInstanceState(
    std::unique_ptr<FtraceProcfs> ft,
    std::unique_ptr<ProtoTranslationTable> ptt,
    std::unique_ptr<FtraceConfigMuxer> fcm)
    : ftrace_procfs(std::move(ft)),
      table(std::move(ptt)),
      ftrace_config_muxer(std::move(fcm)) {}

FtraceController::FtraceInstanceState* FtraceController::GetOrCreateInstance(
    const std::string& instance_name) {
  FtraceInstanceState* maybe_existing = GetInstance(instance_name);
  if (maybe_existing)
    return maybe_existing;

  PERFETTO_DCHECK(!instance_name.empty());
  std::unique_ptr<FtraceInstanceState> instance =
      CreateSecondaryInstance(instance_name);
  if (!instance)
    return nullptr;

  auto it_and_inserted = secondary_instances_.emplace(
      std::piecewise_construct, std::forward_as_tuple(instance_name),
      std::forward_as_tuple(std::move(instance)));
  PERFETTO_CHECK(it_and_inserted.second);
  return it_and_inserted.first->second.get();
}

FtraceController::FtraceInstanceState* FtraceController::GetInstance(
    const std::string& instance_name) {
  if (instance_name.empty())
    return &primary_;

  auto it = secondary_instances_.find(instance_name);
  return it != secondary_instances_.end() ? it->second.get() : nullptr;
}

void FtraceController::DestroyIfUnusedSeconaryInstance(
    FtraceInstanceState* instance) {
  if (instance == &primary_)
    return;
  for (auto it = secondary_instances_.begin(); it != secondary_instances_.end();
       ++it) {
    if (it->second.get() == instance &&
        instance->ftrace_config_muxer->GetDataSourcesCount() == 0) {
      // no data sources left referencing this secondary instance
      secondary_instances_.erase(it);
      return;
    }
  }
  PERFETTO_FATAL("Bug in ftrace instance lifetimes");
}

std::unique_ptr<FtraceController::FtraceInstanceState>
FtraceController::CreateSecondaryInstance(const std::string& instance_name) {
  std::optional<std::string> instance_path = AbsolutePathForInstance(
      primary_.ftrace_procfs->GetRootPath(), instance_name);
  if (!instance_path.has_value()) {
    PERFETTO_ELOG("Invalid ftrace instance name: \"%s\"",
                  instance_name.c_str());
    return nullptr;
  }

  auto ftrace_procfs = FtraceProcfs::Create(*instance_path);
  if (!ftrace_procfs) {
    PERFETTO_ELOG("Failed to create ftrace procfs for \"%s\"",
                  instance_path->c_str());
    return nullptr;
  }

  auto table = ProtoTranslationTable::Create(
      ftrace_procfs.get(), GetStaticEventInfo(), GetStaticCommonFieldsInfo());
  if (!table) {
    PERFETTO_ELOG("Failed to create proto translation table for \"%s\"",
                  instance_path->c_str());
    return nullptr;
  }

  // secondary instances don't support atrace and vendor tracepoint HAL
  std::map<std::string, std::vector<GroupAndName>> vendor_evts;

  auto syscalls = SyscallTable::FromCurrentArch();

  auto muxer = std::make_unique<FtraceConfigMuxer>(
      ftrace_procfs.get(), atrace_wrapper_.get(), table.get(),
      std::move(syscalls), vendor_evts,
      /* secondary_instance= */ true);
  return std::make_unique<FtraceInstanceState>(
      std::move(ftrace_procfs), std::move(table), std::move(muxer));
}

// TODO(rsavitski): we want to eventually add support for the default
// (primary_) tracefs path to be an instance itself, at which point we'll need
// to be careful to distinguish the tracefs mount point from the default
// instance path.
// static
std::optional<std::string> FtraceController::AbsolutePathForInstance(
    const std::string& tracefs_root,
    const std::string& raw_cfg_name) {
  if (base::Contains(raw_cfg_name, '/') ||
      base::StartsWith(raw_cfg_name, "..")) {
    return std::nullopt;
  }

  // ARM64 pKVM hypervisor tracing emulates an instance, but is not under
  // instances/, we special-case that name for now.
  if (raw_cfg_name == "hyp") {
    std::string hyp_path = tracefs_root + "hyp/";
    PERFETTO_LOG(
        "Config specified reserved \"hyp\" instance name, using %s for events.",
        hyp_path.c_str());
    return std::make_optional(hyp_path);
  }

  return tracefs_root + "instances/" + raw_cfg_name + "/";
}

FtraceController::Observer::~Observer() = default;

}  // namespace perfetto
