/*
 * Copyright (C) 2020 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 <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#include <atomic>
#include <condition_variable>
#include <iterator>
#include <mutex>
#include <thread>
#include <vector>

#include "perfetto/base/logging.h"
#include "perfetto/base/time.h"
#include "perfetto/ext/base/getopt.h"
#include "perfetto/ext/base/optional.h"
#include "perfetto/ext/base/string_utils.h"
#include "perfetto/profiling/memory/heap_profile.h"

namespace {

void EnabledCallback(void*, const AHeapProfileEnableCallbackInfo*);

std::atomic<bool> done;
std::atomic<uint64_t> allocs{0};

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wglobal-constructors"
#pragma GCC diagnostic ignored "-Wexit-time-destructors"
std::mutex g_wake_up_mutex;
std::condition_variable g_wake_up_cv;
uint64_t g_rate = 0;

uint32_t g_heap_id = AHeapProfile_registerHeap(
    AHeapInfo_setEnabledCallback(AHeapInfo_create("test_heap"),
                                 EnabledCallback,
                                 nullptr));

#pragma GCC diagnostic pop

void EnabledCallback(void*, const AHeapProfileEnableCallbackInfo* info) {
  std::lock_guard<std::mutex> l(g_wake_up_mutex);
  g_rate = AHeapProfileEnableCallbackInfo_getSamplingInterval(info);
  g_wake_up_cv.notify_all();
}

uint64_t ScrambleAllocId(uint64_t alloc_id, uint32_t thread_idx) {
  return thread_idx | (~alloc_id << 24);
}

void Thread(uint32_t thread_idx, uint64_t pending_allocs) {
  PERFETTO_CHECK(thread_idx < 1 << 24);
  uint64_t alloc_id = 0;
  size_t thread_allocs = 0;
  while (!done.load(std::memory_order_relaxed)) {
    AHeapProfile_reportAllocation(g_heap_id,
                                  ScrambleAllocId(alloc_id, thread_idx), 1);
    if (alloc_id > pending_allocs)
      AHeapProfile_reportFree(
          g_heap_id, ScrambleAllocId(alloc_id - pending_allocs, thread_idx));
    alloc_id++;
    thread_allocs++;
  }
  allocs.fetch_add(thread_allocs, std::memory_order_relaxed);
}

}  // namespace

int main(int argc, char** argv) {
  if (argc != 4) {
    PERFETTO_FATAL("%s NUMBER_THREADS RUNTIME_MS PENDING_ALLOCS", argv[0]);
  }

  perfetto::base::Optional<uint64_t> opt_no_threads =
      perfetto::base::CStringToUInt64(argv[1]);
  if (!opt_no_threads) {
    PERFETTO_FATAL("Invalid number of threads: %s", argv[1]);
  }
  uint64_t no_threads = *opt_no_threads;

  perfetto::base::Optional<uint64_t> opt_runtime_ms =
      perfetto::base::CStringToUInt64(argv[2]);
  if (!opt_runtime_ms) {
    PERFETTO_FATAL("Invalid runtime: %s", argv[2]);
  }
  uint64_t runtime_ms = *opt_runtime_ms;

  perfetto::base::Optional<uint64_t> opt_pending_allocs =
      perfetto::base::CStringToUInt64(argv[3]);
  if (!opt_runtime_ms) {
    PERFETTO_FATAL("Invalid number of pending allocs: %s", argv[3]);
  }
  uint64_t pending_allocs = *opt_pending_allocs;

  std::unique_lock<std::mutex> l(g_wake_up_mutex);
  g_wake_up_cv.wait(l, [] { return g_rate > 0; });

  perfetto::base::TimeMillis end =
      perfetto::base::GetWallTimeMs() + perfetto::base::TimeMillis(runtime_ms);
  std::vector<std::thread> threads;
  for (size_t i = 0; i < static_cast<size_t>(no_threads); ++i)
    threads.emplace_back(Thread, i, pending_allocs);

  perfetto::base::TimeMillis current = perfetto::base::GetWallTimeMs();
  while (current < end) {
    usleep(useconds_t((end - current).count()) * 1000);
    current = perfetto::base::GetWallTimeMs();
  }

  done.store(true, std::memory_order_relaxed);

  for (std::thread& th : threads)
    th.join();

  printf("%" PRIu64 ",%" PRIu64 ",%" PRIu64 ",%" PRIu64 ",%" PRIu64 "\n",
         no_threads, runtime_ms, pending_allocs, g_rate,
         allocs.load(std::memory_order_relaxed));
  return 0;
}
