// Copyright 2020 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 <fuchsia/scheduler/cpp/fidl.h>
#include <lib/fdio/spawn.h>
#include <lib/sys/cpp/service_directory.h>
#include <lib/syslog/cpp/macros.h>
#include <lib/zx/eventpair.h>
#include <lib/zx/handle.h>
#include <lib/zx/job.h>
#include <lib/zx/process.h>
#include <lib/zx/time.h>
#include <pthread.h>
#include <zircon/assert.h>
#include <zircon/processargs.h>
#include <zircon/status.h>
#include <zircon/syscalls.h>
#include <zircon/threads.h>

#include <thread>

namespace {

struct State {
  pthread_barrier_t start_barrier;
  pthread_barrier_t stop_barrier;
  const size_t number_of_switches;

  State(uint32_t thread_count, size_t number_of_switches) : number_of_switches(number_of_switches) {
    FX_CHECK(0 == pthread_barrier_init(&start_barrier, nullptr,
                                       thread_count + 1));  // additional thread for main
    FX_CHECK(0 == pthread_barrier_init(&stop_barrier, nullptr,
                                       thread_count + 1));  // additional thread for main
  }
};

class ProfileService {
 public:
  bool Init() {
    std::shared_ptr<sys::ServiceDirectory> svc = sys::ServiceDirectory::CreateFromNamespace();
    if (svc == nullptr) {
      FX_LOGS(ERROR) << "No service directory";
      return false;
    }

    zx_status_t status = svc->Connect(provider_.NewRequest());
    if (status != ZX_OK) {
      FX_LOGS(ERROR) << "Couldn't connect to service: " << zx_status_get_string(status);
      return false;
    }

    return true;
  }

  zx_status_t ApplyAffinityProfile(size_t cpu_num, std::thread* thread_a, std::thread* thread_b) {
    FX_CHECK(cpu_num < 31);
    uint32_t mask = 1 << cpu_num;

    zx::profile profile;
    zx_status_t server_status;
    zx_status_t status = provider_->GetCpuAffinityProfile({mask}, &server_status, &profile);
    if (status != ZX_OK) {
      FX_LOGS(ERROR) << "Failed to contact profile service: " << zx_status_get_string(status);
      return status;
    }
    if (server_status != ZX_OK) {
      FX_LOGS(ERROR) << "Profile service failure: " << zx_status_get_string(server_status);
      return server_status;
    }

    status = HandleFromThread(thread_a)->set_profile(profile, /*options=*/0);
    if (status != ZX_OK) {
      FX_LOGS(ERROR) << "Failed to set profile: " << zx_status_get_string(status);
      return status;
    }

    status = HandleFromThread(thread_b)->set_profile(profile, /*options=*/0);
    if (status != ZX_OK) {
      FX_LOGS(ERROR) << "Failed to set profile: " << zx_status_get_string(status);
      return status;
    }

    return ZX_OK;
  }

 private:
  zx::unowned<zx::thread> HandleFromThread(std::thread* thread) {
    zx_handle_t handle = native_thread_get_zx_handle(thread->native_handle());
    return zx::unowned<zx::thread>(handle);
  }

  fuchsia::scheduler::ProfileProviderSyncPtr provider_;
};

void ThreadPair(size_t cpu_num, State* state, ProfileService* profiles) {
  auto thread_action = [state](zx::eventpair event, bool first) {
    auto wait_val = pthread_barrier_wait(&state->start_barrier);
    FX_CHECK(wait_val == PTHREAD_BARRIER_SERIAL_THREAD || wait_val == 0);

    size_t to_receive = state->number_of_switches;

    if (first) {
      FX_CHECK(ZX_OK == event.signal_peer(0, ZX_USER_SIGNAL_0));
    }

    while (to_receive > 0) {
      FX_CHECK(ZX_OK == event.wait_one(ZX_USER_SIGNAL_0, zx::time::infinite(), nullptr));
      to_receive--;
      FX_CHECK(ZX_OK == event.signal(ZX_USER_SIGNAL_0, 0));
      FX_CHECK(ZX_OK == event.signal_peer(0, ZX_USER_SIGNAL_0));
    }

    wait_val = pthread_barrier_wait(&state->stop_barrier);
    FX_CHECK(wait_val == PTHREAD_BARRIER_SERIAL_THREAD || wait_val == 0);
  };

  zx::eventpair e1, e2;
  FX_CHECK(ZX_OK == zx::eventpair::create(0, &e1, &e2));

  std::thread thread_a(thread_action, std::move(e1), true);
  std::thread thread_b(thread_action, std::move(e2), false);

  FX_CHECK(ZX_OK == profiles->ApplyAffinityProfile(cpu_num, &thread_a, &thread_b));

  thread_a.detach();
  thread_b.detach();
}

}  // namespace

const char kMessage[] = "ping";
const size_t kMessageSize = 4;

int main(int argc, char** argv) {
  zx::channel incoming(zx_take_startup_handle(PA_USER0));

  if (!incoming) {
    printf("ERROR: Invalid incoming handle\n");
    return 1;
  }

  uint32_t cpus = zx_system_get_num_cpus();
  uint64_t number_of_switches = 0;

  // Signal that this process is ready to accept instructions.
  FX_CHECK(ZX_OK == incoming.write(0, kMessage, kMessageSize, nullptr, 0));

  ProfileService profiles;
  FX_CHECK(profiles.Init());

  while (true) {
    // Read the number of context switches to perform.
    FX_CHECK(ZX_OK == incoming.wait_one(ZX_CHANNEL_READABLE | ZX_CHANNEL_PEER_CLOSED,
                                        zx::time::infinite(), nullptr));
    if (ZX_OK != incoming.read(0, &number_of_switches, nullptr, sizeof(number_of_switches), 0,
                               nullptr, nullptr)) {
      break;
    }
    State state(cpus * 2, number_of_switches);

    // Initialize all thread pairs with the state.
    for (size_t i = 0; i < cpus; i++) {
      ThreadPair(i, &state, &profiles);
    }

    // Wait until all threads are ready to start, then signal to the test that we have started.
    auto wait_val = pthread_barrier_wait(&state.start_barrier);
    FX_CHECK(wait_val == PTHREAD_BARRIER_SERIAL_THREAD || wait_val == 0);
    FX_CHECK(ZX_OK == incoming.write(0, kMessage, kMessageSize, nullptr, 0));

    // Wait until all threads have completed, then signal to the test that we have finished.
    wait_val = pthread_barrier_wait(&state.stop_barrier);
    FX_CHECK(wait_val == PTHREAD_BARRIER_SERIAL_THREAD || wait_val == 0);
    FX_CHECK(ZX_OK == incoming.write(0, kMessage, kMessageSize, nullptr, 0));
  }

  return 0;
}
