/*
 * Copyright (C) 2015 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 <err.h>
#include <errno.h>
#include <pthread.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <unistd.h>

#include <new>

#include <memory_trace/MemoryTrace.h>

#include "Alloc.h"
#include "Pointers.h"
#include "Thread.h"
#include "Threads.h"

void* ThreadRunner(void* data) {
  Thread* thread = reinterpret_cast<Thread*>(data);
  while (true) {
    thread->WaitForPending();
    const memory_trace::Entry& entry = thread->GetEntry();
    thread->AddTimeNsecs(AllocExecute(entry, thread->pointers()));
    bool thread_done = entry.type == memory_trace::THREAD_DONE;
    thread->ClearPending();
    if (thread_done) {
      break;
    }
  }
  return nullptr;
}

Threads::Threads(Pointers* pointers, size_t max_threads)
    : pointers_(pointers), max_threads_(max_threads) {
  size_t pagesize = getpagesize();
  data_size_ = (max_threads_ * sizeof(Thread) + pagesize - 1) & ~(pagesize - 1);
  max_threads_ = data_size_ / sizeof(Thread);

  void* memory = mmap(nullptr, data_size_, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
  if (memory == MAP_FAILED) {
    err(1, "Failed to map in memory for Threads: map size %zu, max threads %zu", data_size_,
        max_threads_);
  }

  threads_ = new (memory) Thread[max_threads_];
}

Threads::~Threads() {
  if (threads_) {
    munmap(threads_, data_size_);
    threads_ = nullptr;
    data_size_ = 0;
  }
}

Thread* Threads::CreateThread(pid_t tid) {
  if (num_threads_ == max_threads_) {
    errx(1, "Too many threads created, current max %zu", num_threads_);
  }
  Thread* thread = FindEmptyEntry(tid);
  if (thread == nullptr) {
    errx(1, "No empty entries found, current max %zu, num threads %zu", max_threads_, num_threads_);
  }
  thread->tid_ = tid;
  thread->pointers_ = pointers_;
  thread->total_time_nsecs_ = 0;
  if ((errno = pthread_create(&thread->thread_id_, nullptr, ThreadRunner, thread)) != 0) {
    err(1, "Failed to create thread %d", tid);
  }

  num_threads_++;
  return thread;
}

Thread* Threads::FindThread(pid_t tid) {
  size_t index = GetHashEntry(tid);
  for (size_t entries = num_threads_; entries != 0;) {
    pid_t cur_tid = threads_[index].tid_;
    if (cur_tid == tid) {
      return threads_ + index;
    }
    if (cur_tid != 0) {
      entries--;
    }
    if (++index == max_threads_) {
      index = 0;
    }
  }
  return nullptr;
}

void Threads::WaitForAllToQuiesce() {
  for (size_t i = 0, threads = 0; threads < num_threads_; i++) {
    pid_t cur_tid = threads_[i].tid_;
    if (cur_tid != 0) {
      threads++;
      threads_[i].WaitForReady();
    }
  }
}

size_t Threads::GetHashEntry(pid_t tid) {
  return tid % max_threads_;
}

Thread* Threads::FindEmptyEntry(pid_t tid) {
  size_t index = GetHashEntry(tid);
  for (size_t entries = 0; entries < max_threads_; entries++) {
    if (threads_[index].tid_ == 0) {
      return threads_ + index;
    }
    if (++index == max_threads_) {
      index = 0;
    }
  }
  return nullptr;
}

void Threads::Finish(Thread* thread) {
  int ret = pthread_join(thread->thread_id_, nullptr);
  if (ret != 0) {
    err(1, "pthread_join failed");
  }
  total_time_nsecs_ += thread->total_time_nsecs_;
  thread->tid_ = 0;
  num_threads_--;
}

void Threads::FinishAll() {
  memory_trace::Entry thread_done = {.type = memory_trace::THREAD_DONE};
  for (size_t i = 0; i < max_threads_; i++) {
    if (threads_[i].tid_ != 0) {
      threads_[i].SetEntry(&thread_done);
      threads_[i].SetPending();
      Finish(threads_ + i);
    }
  }
}
