// 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 <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/logging.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
