/*
 * 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 <string.h>
#include <sys/mman.h>
#include <unistd.h>

#include <new>

#include "Action.h"
#include "Thread.h"
#include "Threads.h"

void* ThreadRunner(void* data) {
  Thread* thread = reinterpret_cast<Thread*>(data);
  while (true) {
    thread->WaitForPending();
    Action* action = thread->GetAction();
    action->Execute(thread->pointers());
    bool end_thread = action->EndThread();
    thread->ClearPending();
    if (end_thread) {
      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\n",
        data_size_, max_threads_);
  }

  if (Thread::ACTION_SIZE < Action::MaxActionSize()) {
    err(1, "Thread action size is too small: ACTION_SIZE %zu, max size %zu\n",
        Thread::ACTION_SIZE, Action::MaxActionSize());
  }

  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_) {
    err(1, "Too many threads created, current max %zu.\n", num_threads_);
  }
  Thread* thread = FindEmptyEntry(tid);
  if (thread == nullptr) {
    err(1, "No empty entries found, current max %zu, num threads %zu\n",
          max_threads_, num_threads_);
  }
  thread->tid_ = tid;
  thread->pointers_ = pointers_;
  if (pthread_create(&thread->thread_id_, nullptr, ThreadRunner, thread) == -1) {
    err(1, "Failed to create thread %d: %s\n", tid, strerror(errno));
  }

  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) {
  pthread_join(thread->thread_id_, nullptr);
  thread->tid_ = 0;
  num_threads_--;
}

void Threads::FinishAll() {
  for (size_t i = 0; i < max_threads_; i++) {
    if (threads_[i].tid_ != 0) {
      threads_[i].CreateAction(0, "thread_done", nullptr);
      threads_[i].SetPending();
      Finish(threads_ + i);
    }
  }
}
