//===-- memprof_thread.cpp -----------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file is a part of MemProfiler, a memory profiler.
//
// Thread-related code.
//===----------------------------------------------------------------------===//
#include "memprof_thread.h"
#include "memprof_allocator.h"
#include "memprof_interceptors.h"
#include "memprof_mapping.h"
#include "memprof_stack.h"
#include "sanitizer_common/sanitizer_common.h"
#include "sanitizer_common/sanitizer_placement_new.h"
#include "sanitizer_common/sanitizer_stackdepot.h"
#include "sanitizer_common/sanitizer_tls_get_addr.h"

namespace __memprof {

// MemprofThreadContext implementation.

void MemprofThreadContext::OnCreated(void *arg) {
  CreateThreadContextArgs *args = static_cast<CreateThreadContextArgs *>(arg);
  if (args->stack)
    stack_id = StackDepotPut(*args->stack);
  thread = args->thread;
  thread->set_context(this);
}

void MemprofThreadContext::OnFinished() {
  // Drop the link to the MemprofThread object.
  thread = nullptr;
}

static ALIGNED(16) char thread_registry_placeholder[sizeof(ThreadRegistry)];
static ThreadRegistry *memprof_thread_registry;

static Mutex mu_for_thread_context;
static LowLevelAllocator allocator_for_thread_context;

static ThreadContextBase *GetMemprofThreadContext(u32 tid) {
  Lock lock(&mu_for_thread_context);
  return new (allocator_for_thread_context) MemprofThreadContext(tid);
}

ThreadRegistry &memprofThreadRegistry() {
  static bool initialized;
  // Don't worry about thread_safety - this should be called when there is
  // a single thread.
  if (!initialized) {
    // Never reuse MemProf threads: we store pointer to MemprofThreadContext
    // in TSD and can't reliably tell when no more TSD destructors will
    // be called. It would be wrong to reuse MemprofThreadContext for another
    // thread before all TSD destructors will be called for it.
    memprof_thread_registry = new (thread_registry_placeholder)
        ThreadRegistry(GetMemprofThreadContext);
    initialized = true;
  }
  return *memprof_thread_registry;
}

MemprofThreadContext *GetThreadContextByTidLocked(u32 tid) {
  return static_cast<MemprofThreadContext *>(
      memprofThreadRegistry().GetThreadLocked(tid));
}

// MemprofThread implementation.

MemprofThread *MemprofThread::Create(thread_callback_t start_routine, void *arg,
                                     u32 parent_tid, StackTrace *stack,
                                     bool detached) {
  uptr PageSize = GetPageSizeCached();
  uptr size = RoundUpTo(sizeof(MemprofThread), PageSize);
  MemprofThread *thread = (MemprofThread *)MmapOrDie(size, __func__);
  thread->start_routine_ = start_routine;
  thread->arg_ = arg;
  MemprofThreadContext::CreateThreadContextArgs args = {thread, stack};
  memprofThreadRegistry().CreateThread(*reinterpret_cast<uptr *>(thread),
                                       detached, parent_tid, &args);

  return thread;
}

void MemprofThread::TSDDtor(void *tsd) {
  MemprofThreadContext *context = (MemprofThreadContext *)tsd;
  VReport(1, "T%d TSDDtor\n", context->tid);
  if (context->thread)
    context->thread->Destroy();
}

void MemprofThread::Destroy() {
  int tid = this->tid();
  VReport(1, "T%d exited\n", tid);

  malloc_storage().CommitBack();
  memprofThreadRegistry().FinishThread(tid);
  FlushToDeadThreadStats(&stats_);
  uptr size = RoundUpTo(sizeof(MemprofThread), GetPageSizeCached());
  UnmapOrDie(this, size);
  DTLS_Destroy();
}

inline MemprofThread::StackBounds MemprofThread::GetStackBounds() const {
  if (stack_bottom_ >= stack_top_)
    return {0, 0};
  return {stack_bottom_, stack_top_};
}

uptr MemprofThread::stack_top() { return GetStackBounds().top; }

uptr MemprofThread::stack_bottom() { return GetStackBounds().bottom; }

uptr MemprofThread::stack_size() {
  const auto bounds = GetStackBounds();
  return bounds.top - bounds.bottom;
}

void MemprofThread::Init(const InitOptions *options) {
  CHECK_EQ(this->stack_size(), 0U);
  SetThreadStackAndTls(options);
  if (stack_top_ != stack_bottom_) {
    CHECK_GT(this->stack_size(), 0U);
    CHECK(AddrIsInMem(stack_bottom_));
    CHECK(AddrIsInMem(stack_top_ - 1));
  }
  int local = 0;
  VReport(1, "T%d: stack [%p,%p) size 0x%zx; local=%p\n", tid(),
          (void *)stack_bottom_, (void *)stack_top_, stack_top_ - stack_bottom_,
          (void *)&local);
}

thread_return_t
MemprofThread::ThreadStart(tid_t os_id,
                           atomic_uintptr_t *signal_thread_is_registered) {
  Init();
  memprofThreadRegistry().StartThread(tid(), os_id, ThreadType::Regular,
                                      nullptr);
  if (signal_thread_is_registered)
    atomic_store(signal_thread_is_registered, 1, memory_order_release);

  if (!start_routine_) {
    // start_routine_ == 0 if we're on the main thread or on one of the
    // OS X libdispatch worker threads. But nobody is supposed to call
    // ThreadStart() for the worker threads.
    CHECK_EQ(tid(), 0);
    return 0;
  }

  return start_routine_(arg_);
}

MemprofThread *CreateMainThread() {
  MemprofThread *main_thread = MemprofThread::Create(
      /* start_routine */ nullptr, /* arg */ nullptr, /* parent_tid */ kMainTid,
      /* stack */ nullptr, /* detached */ true);
  SetCurrentThread(main_thread);
  main_thread->ThreadStart(internal_getpid(),
                           /* signal_thread_is_registered */ nullptr);
  return main_thread;
}

// This implementation doesn't use the argument, which is just passed down
// from the caller of Init (which see, above).  It's only there to support
// OS-specific implementations that need more information passed through.
void MemprofThread::SetThreadStackAndTls(const InitOptions *options) {
  DCHECK_EQ(options, nullptr);
  uptr tls_size = 0;
  uptr stack_size = 0;
  GetThreadStackAndTls(tid() == kMainTid, &stack_bottom_, &stack_size,
                       &tls_begin_, &tls_size);
  stack_top_ = stack_bottom_ + stack_size;
  tls_end_ = tls_begin_ + tls_size;
  dtls_ = DTLS_Get();

  if (stack_top_ != stack_bottom_) {
    int local;
    CHECK(AddrIsInStack((uptr)&local));
  }
}

bool MemprofThread::AddrIsInStack(uptr addr) {
  const auto bounds = GetStackBounds();
  return addr >= bounds.bottom && addr < bounds.top;
}

MemprofThread *GetCurrentThread() {
  MemprofThreadContext *context =
      reinterpret_cast<MemprofThreadContext *>(TSDGet());
  if (!context)
    return nullptr;
  return context->thread;
}

void SetCurrentThread(MemprofThread *t) {
  CHECK(t->context());
  VReport(2, "SetCurrentThread: %p for thread %p\n", (void *)t->context(),
          (void *)GetThreadSelf());
  // Make sure we do not reset the current MemprofThread.
  CHECK_EQ(0, TSDGet());
  TSDSet(t->context());
  CHECK_EQ(t->context(), TSDGet());
}

u32 GetCurrentTidOrInvalid() {
  MemprofThread *t = GetCurrentThread();
  return t ? t->tid() : kInvalidTid;
}

void EnsureMainThreadIDIsCorrect() {
  MemprofThreadContext *context =
      reinterpret_cast<MemprofThreadContext *>(TSDGet());
  if (context && (context->tid == kMainTid))
    context->os_id = GetTid();
}
} // namespace __memprof
