// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "garnet/lib/perfmon/controller.h"

#include <fuchsia/perfmon/cpu/cpp/fidl.h>
#include <lib/fdio/directory.h>
#include <lib/syslog/cpp/macros.h>
#include <sys/stat.h>

#include <fbl/algorithm.h>

#include "garnet/lib/perfmon/config_impl.h"
#include "garnet/lib/perfmon/controller_impl.h"
#include "garnet/lib/perfmon/device_reader.h"
#include "garnet/lib/perfmon/properties_impl.h"
#include "src/lib/fxl/strings/string_printf.h"

namespace perfmon {

// Shorten some long FIDL names.
using FidlPerfmonAllocation = ::fuchsia::perfmon::cpu::Allocation;

const char kPerfMonDev[] = "/dev/sys/cpu-trace/perfmon";

static uint32_t RoundUpToPages(uint32_t value) {
  uint32_t size = fbl::round_up(value, Controller::kPageSize);
  FX_DCHECK(size & ~(Controller::kPageSize - 1));
  return size >> Controller::kLog2PageSize;
}

static uint32_t GetBufferSizeInPages(CollectionMode mode, uint32_t requested_size_in_pages) {
  switch (mode) {
    case CollectionMode::kSample:
      return requested_size_in_pages;
    case CollectionMode::kTally: {
      // For tally mode we just need something large enough to hold
      // the header + records for each event.
      unsigned num_events = kMaxNumEvents;
      uint32_t size = (sizeof(BufferHeader) + num_events * sizeof(ValueRecord));
      return RoundUpToPages(size);
    }
    default:
      __UNREACHABLE;
  }
}

bool Controller::IsSupported() {
  // The device path isn't present if it's not supported.
  struct stat stat_buffer;
  if (stat(kPerfMonDev, &stat_buffer) != 0)
    return false;
  return S_ISCHR(stat_buffer.st_mode);
}

bool Controller::GetProperties(Properties* props) {
  ::fuchsia::perfmon::cpu::ControllerSyncPtr controller_ptr;
  zx_status_t status =
      fdio_service_connect(kPerfMonDev, controller_ptr.NewRequest().TakeChannel().release());
  if (status != ZX_OK) {
    FX_LOGS(ERROR) << "Error connecting to " << kPerfMonDev << ": " << status;
    return false;
  }

  FidlPerfmonProperties properties;
  status = controller_ptr->GetProperties(&properties);
  if (status != ZX_OK) {
    FX_LOGS(ERROR) << "Failed to get properties: " << status;
    return false;
  }

  internal::FidlToPerfmonProperties(properties, props);
  return true;
}

static bool Initialize(::fuchsia::perfmon::cpu::ControllerSyncPtr* controller_ptr,
                       uint32_t num_traces, uint32_t buffer_size_in_pages) {
  FidlPerfmonAllocation allocation;
  allocation.num_buffers = num_traces;
  allocation.buffer_size_in_pages = buffer_size_in_pages;
  FX_VLOGS(2) << fxl::StringPrintf("num_buffers=%u, buffer_size_in_pages=0x%x", num_traces,
                                   buffer_size_in_pages);

  ::fuchsia::perfmon::cpu::Controller_Initialize_Result result;
  zx_status_t status = (*controller_ptr)->Initialize(allocation, &result);
  if (status != ZX_OK) {
    FX_LOGS(ERROR) << "Initialize failed: status=" << status;
    return false;
  }
  if (result.is_err() && result.err() != ZX_ERR_BAD_STATE) {
    FX_LOGS(ERROR) << "Initialize failed: error=" << result.err();
    return false;
  }

  // TODO(dje): If we get BAD_STATE, a previous run may have crashed without
  // resetting the device. The device doesn't reset itself on close yet.
  if (result.is_err()) {
    FX_DCHECK(result.err() == ZX_ERR_BAD_STATE);
    FX_VLOGS(2) << "Got BAD_STATE trying to initialize a trace,"
                << " resetting device and trying again";
    status = (*controller_ptr)->Stop();
    if (status != ZX_OK) {
      FX_VLOGS(2) << "Stopping device failed: status=" << status;
      return false;
    }
    status = (*controller_ptr)->Terminate();
    if (status != ZX_OK) {
      FX_VLOGS(2) << "Terminating previous trace failed: status=" << status;
      return false;
    }
    status = (*controller_ptr)->Initialize(allocation, &result);
    if (status != ZX_OK) {
      FX_LOGS(ERROR) << "Initialize try #2 failed: status=" << status;
      return false;
    }
    if (result.is_err()) {
      FX_LOGS(ERROR) << "Initialize try #2 failed: error=" << result.err();
      return false;
    }
    FX_VLOGS(2) << "Second Initialize attempt succeeded";
  }

  return true;
}

bool Controller::Create(uint32_t buffer_size_in_pages, const Config config,
                        std::unique_ptr<Controller>* out_controller) {
  if (buffer_size_in_pages > kMaxBufferSizeInPages) {
    FX_LOGS(ERROR) << "Buffer size is too large, max " << kMaxBufferSizeInPages << " pages";
    return false;
  }

  ::fuchsia::perfmon::cpu::ControllerSyncPtr controller_ptr;
  zx_status_t status =
      fdio_service_connect(kPerfMonDev, controller_ptr.NewRequest().TakeChannel().release());
  if (status != ZX_OK) {
    FX_LOGS(ERROR) << "Error connecting to " << kPerfMonDev << ": " << status;
    return false;
  }

  CollectionMode mode = config.GetMode();
  uint32_t num_traces = zx_system_get_num_cpus();
  // For "tally" mode we only need a small fixed amount, so toss what the
  // caller provided and use our own value.
  uint32_t actual_buffer_size_in_pages = GetBufferSizeInPages(mode, buffer_size_in_pages);

  if (!Initialize(&controller_ptr, num_traces, actual_buffer_size_in_pages)) {
    return false;
  }

  out_controller->reset(new internal::ControllerImpl(std::move(controller_ptr), num_traces,
                                                     buffer_size_in_pages, std::move(config)));
  return true;
}

}  // namespace perfmon
