//===-- MachThreadList.cpp --------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  Created by Greg Clayton on 6/19/07.
//
//===----------------------------------------------------------------------===//

#include "MachThreadList.h"

#include <inttypes.h>
#include <sys/sysctl.h>

#include "DNBLog.h"
#include "DNBThreadResumeActions.h"
#include "MachProcess.h"

MachThreadList::MachThreadList()
    : m_threads(), m_threads_mutex(PTHREAD_MUTEX_RECURSIVE),
      m_is_64_bit(false) {}

MachThreadList::~MachThreadList() {}

nub_state_t MachThreadList::GetState(nub_thread_t tid) {
  MachThreadSP thread_sp(GetThreadByID(tid));
  if (thread_sp)
    return thread_sp->GetState();
  return eStateInvalid;
}

const char *MachThreadList::GetName(nub_thread_t tid) {
  MachThreadSP thread_sp(GetThreadByID(tid));
  if (thread_sp)
    return thread_sp->GetName();
  return NULL;
}

ThreadInfo::QoS MachThreadList::GetRequestedQoS(nub_thread_t tid,
                                                nub_addr_t tsd,
                                                uint64_t dti_qos_class_index) {
  MachThreadSP thread_sp(GetThreadByID(tid));
  if (thread_sp)
    return thread_sp->GetRequestedQoS(tsd, dti_qos_class_index);
  return ThreadInfo::QoS();
}

nub_addr_t MachThreadList::GetPThreadT(nub_thread_t tid) {
  MachThreadSP thread_sp(GetThreadByID(tid));
  if (thread_sp)
    return thread_sp->GetPThreadT();
  return INVALID_NUB_ADDRESS;
}

nub_addr_t MachThreadList::GetDispatchQueueT(nub_thread_t tid) {
  MachThreadSP thread_sp(GetThreadByID(tid));
  if (thread_sp)
    return thread_sp->GetDispatchQueueT();
  return INVALID_NUB_ADDRESS;
}

nub_addr_t MachThreadList::GetTSDAddressForThread(
    nub_thread_t tid, uint64_t plo_pthread_tsd_base_address_offset,
    uint64_t plo_pthread_tsd_base_offset, uint64_t plo_pthread_tsd_entry_size) {
  MachThreadSP thread_sp(GetThreadByID(tid));
  if (thread_sp)
    return thread_sp->GetTSDAddressForThread(
        plo_pthread_tsd_base_address_offset, plo_pthread_tsd_base_offset,
        plo_pthread_tsd_entry_size);
  return INVALID_NUB_ADDRESS;
}

nub_thread_t MachThreadList::SetCurrentThread(nub_thread_t tid) {
  MachThreadSP thread_sp(GetThreadByID(tid));
  if (thread_sp) {
    m_current_thread = thread_sp;
    return tid;
  }
  return INVALID_NUB_THREAD;
}

bool MachThreadList::GetThreadStoppedReason(
    nub_thread_t tid, struct DNBThreadStopInfo *stop_info) const {
  MachThreadSP thread_sp(GetThreadByID(tid));
  if (thread_sp)
    return thread_sp->GetStopException().GetStopInfo(stop_info);
  return false;
}

bool MachThreadList::GetIdentifierInfo(
    nub_thread_t tid, thread_identifier_info_data_t *ident_info) {
  thread_t mach_port_number = GetMachPortNumberByThreadID(tid);

  mach_msg_type_number_t count = THREAD_IDENTIFIER_INFO_COUNT;
  return ::thread_info(mach_port_number, THREAD_IDENTIFIER_INFO,
                       (thread_info_t)ident_info, &count) == KERN_SUCCESS;
}

void MachThreadList::DumpThreadStoppedReason(nub_thread_t tid) const {
  MachThreadSP thread_sp(GetThreadByID(tid));
  if (thread_sp)
    thread_sp->GetStopException().DumpStopReason();
}

const char *MachThreadList::GetThreadInfo(nub_thread_t tid) const {
  MachThreadSP thread_sp(GetThreadByID(tid));
  if (thread_sp)
    return thread_sp->GetBasicInfoAsString();
  return NULL;
}

MachThreadSP MachThreadList::GetThreadByID(nub_thread_t tid) const {
  PTHREAD_MUTEX_LOCKER(locker, m_threads_mutex);
  MachThreadSP thread_sp;
  const size_t num_threads = m_threads.size();
  for (size_t idx = 0; idx < num_threads; ++idx) {
    if (m_threads[idx]->ThreadID() == tid) {
      thread_sp = m_threads[idx];
      break;
    }
  }
  return thread_sp;
}

MachThreadSP
MachThreadList::GetThreadByMachPortNumber(thread_t mach_port_number) const {
  PTHREAD_MUTEX_LOCKER(locker, m_threads_mutex);
  MachThreadSP thread_sp;
  const size_t num_threads = m_threads.size();
  for (size_t idx = 0; idx < num_threads; ++idx) {
    if (m_threads[idx]->MachPortNumber() == mach_port_number) {
      thread_sp = m_threads[idx];
      break;
    }
  }
  return thread_sp;
}

nub_thread_t
MachThreadList::GetThreadIDByMachPortNumber(thread_t mach_port_number) const {
  PTHREAD_MUTEX_LOCKER(locker, m_threads_mutex);
  MachThreadSP thread_sp;
  const size_t num_threads = m_threads.size();
  for (size_t idx = 0; idx < num_threads; ++idx) {
    if (m_threads[idx]->MachPortNumber() == mach_port_number) {
      return m_threads[idx]->ThreadID();
    }
  }
  return INVALID_NUB_THREAD;
}

thread_t MachThreadList::GetMachPortNumberByThreadID(
    nub_thread_t globally_unique_id) const {
  PTHREAD_MUTEX_LOCKER(locker, m_threads_mutex);
  MachThreadSP thread_sp;
  const size_t num_threads = m_threads.size();
  for (size_t idx = 0; idx < num_threads; ++idx) {
    if (m_threads[idx]->ThreadID() == globally_unique_id) {
      return m_threads[idx]->MachPortNumber();
    }
  }
  return 0;
}

bool MachThreadList::GetRegisterValue(nub_thread_t tid, uint32_t set,
                                      uint32_t reg,
                                      DNBRegisterValue *reg_value) const {
  MachThreadSP thread_sp(GetThreadByID(tid));
  if (thread_sp)
    return thread_sp->GetRegisterValue(set, reg, reg_value);

  return false;
}

bool MachThreadList::SetRegisterValue(nub_thread_t tid, uint32_t set,
                                      uint32_t reg,
                                      const DNBRegisterValue *reg_value) const {
  MachThreadSP thread_sp(GetThreadByID(tid));
  if (thread_sp)
    return thread_sp->SetRegisterValue(set, reg, reg_value);

  return false;
}

nub_size_t MachThreadList::GetRegisterContext(nub_thread_t tid, void *buf,
                                              size_t buf_len) {
  MachThreadSP thread_sp(GetThreadByID(tid));
  if (thread_sp)
    return thread_sp->GetRegisterContext(buf, buf_len);
  return 0;
}

nub_size_t MachThreadList::SetRegisterContext(nub_thread_t tid, const void *buf,
                                              size_t buf_len) {
  MachThreadSP thread_sp(GetThreadByID(tid));
  if (thread_sp)
    return thread_sp->SetRegisterContext(buf, buf_len);
  return 0;
}

uint32_t MachThreadList::SaveRegisterState(nub_thread_t tid) {
  MachThreadSP thread_sp(GetThreadByID(tid));
  if (thread_sp)
    return thread_sp->SaveRegisterState();
  return 0;
}

bool MachThreadList::RestoreRegisterState(nub_thread_t tid, uint32_t save_id) {
  MachThreadSP thread_sp(GetThreadByID(tid));
  if (thread_sp)
    return thread_sp->RestoreRegisterState(save_id);
  return 0;
}

nub_size_t MachThreadList::NumThreads() const {
  PTHREAD_MUTEX_LOCKER(locker, m_threads_mutex);
  return m_threads.size();
}

nub_thread_t MachThreadList::ThreadIDAtIndex(nub_size_t idx) const {
  PTHREAD_MUTEX_LOCKER(locker, m_threads_mutex);
  if (idx < m_threads.size())
    return m_threads[idx]->ThreadID();
  return INVALID_NUB_THREAD;
}

nub_thread_t MachThreadList::CurrentThreadID() {
  MachThreadSP thread_sp;
  CurrentThread(thread_sp);
  if (thread_sp.get())
    return thread_sp->ThreadID();
  return INVALID_NUB_THREAD;
}

bool MachThreadList::NotifyException(MachException::Data &exc) {
  MachThreadSP thread_sp(GetThreadByMachPortNumber(exc.thread_port));
  if (thread_sp) {
    thread_sp->NotifyException(exc);
    return true;
  }
  return false;
}

void MachThreadList::Clear() {
  PTHREAD_MUTEX_LOCKER(locker, m_threads_mutex);
  m_threads.clear();
}

uint32_t
MachThreadList::UpdateThreadList(MachProcess *process, bool update,
                                 MachThreadList::collection *new_threads) {
  // locker will keep a mutex locked until it goes out of scope
  DNBLogThreadedIf(LOG_THREAD, "MachThreadList::UpdateThreadList (pid = %4.4x, "
                               "update = %u) process stop count = %u",
                   process->ProcessID(), update, process->StopCount());
  PTHREAD_MUTEX_LOCKER(locker, m_threads_mutex);

  if (process->StopCount() == 0) {
    int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, process->ProcessID()};
    struct kinfo_proc processInfo;
    size_t bufsize = sizeof(processInfo);
    if (sysctl(mib, (unsigned)(sizeof(mib) / sizeof(int)), &processInfo,
               &bufsize, NULL, 0) == 0 &&
        bufsize > 0) {
      if (processInfo.kp_proc.p_flag & P_LP64)
        m_is_64_bit = true;
    }
#if defined(__i386__) || defined(__x86_64__)
    if (m_is_64_bit)
      DNBArchProtocol::SetArchitecture(CPU_TYPE_X86_64);
    else
      DNBArchProtocol::SetArchitecture(CPU_TYPE_I386);
#elif defined(__arm__) || defined(__arm64__) || defined(__aarch64__)
    if (m_is_64_bit)
      DNBArchProtocol::SetArchitecture(CPU_TYPE_ARM64);
    else
      DNBArchProtocol::SetArchitecture(CPU_TYPE_ARM);
#endif
  }

  if (m_threads.empty() || update) {
    thread_array_t thread_list = NULL;
    mach_msg_type_number_t thread_list_count = 0;
    task_t task = process->Task().TaskPort();
    DNBError err(::task_threads(task, &thread_list, &thread_list_count),
                 DNBError::MachKernel);

    if (DNBLogCheckLogBit(LOG_THREAD) || err.Fail())
      err.LogThreaded("::task_threads ( task = 0x%4.4x, thread_list => %p, "
                      "thread_list_count => %u )",
                      task, thread_list, thread_list_count);

    if (err.Status() == KERN_SUCCESS && thread_list_count > 0) {
      MachThreadList::collection currThreads;
      size_t idx;
      // Iterator through the current thread list and see which threads
      // we already have in our list (keep them), which ones we don't
      // (add them), and which ones are not around anymore (remove them).
      for (idx = 0; idx < thread_list_count; ++idx) {
        const thread_t mach_port_num = thread_list[idx];

        uint64_t unique_thread_id =
            MachThread::GetGloballyUniqueThreadIDForMachPortID(mach_port_num);
        MachThreadSP thread_sp(GetThreadByID(unique_thread_id));
        if (thread_sp) {
          // Keep the existing thread class
          currThreads.push_back(thread_sp);
        } else {
          // We don't have this thread, lets add it.
          thread_sp.reset(new MachThread(process, m_is_64_bit, unique_thread_id,
                                         mach_port_num));

          // Add the new thread regardless of its is user ready state...
          // Make sure the thread is ready to be displayed and shown to users
          // before we add this thread to our list...
          if (thread_sp->IsUserReady()) {
            if (new_threads)
              new_threads->push_back(thread_sp);

            currThreads.push_back(thread_sp);
          }
        }
      }

      m_threads.swap(currThreads);
      m_current_thread.reset();

      // Free the vm memory given to us by ::task_threads()
      vm_size_t thread_list_size =
          (vm_size_t)(thread_list_count * sizeof(thread_t));
      ::vm_deallocate(::mach_task_self(), (vm_address_t)thread_list,
                      thread_list_size);
    }
  }
  return static_cast<uint32_t>(m_threads.size());
}

void MachThreadList::CurrentThread(MachThreadSP &thread_sp) {
  // locker will keep a mutex locked until it goes out of scope
  PTHREAD_MUTEX_LOCKER(locker, m_threads_mutex);
  if (m_current_thread.get() == NULL) {
    // Figure out which thread is going to be our current thread.
    // This is currently done by finding the first thread in the list
    // that has a valid exception.
    const size_t num_threads = m_threads.size();
    for (uint32_t idx = 0; idx < num_threads; ++idx) {
      if (m_threads[idx]->GetStopException().IsValid()) {
        m_current_thread = m_threads[idx];
        break;
      }
    }
  }
  thread_sp = m_current_thread;
}

void MachThreadList::Dump() const {
  PTHREAD_MUTEX_LOCKER(locker, m_threads_mutex);
  const size_t num_threads = m_threads.size();
  for (uint32_t idx = 0; idx < num_threads; ++idx) {
    m_threads[idx]->Dump(idx);
  }
}

void MachThreadList::ProcessWillResume(
    MachProcess *process, const DNBThreadResumeActions &thread_actions) {
  PTHREAD_MUTEX_LOCKER(locker, m_threads_mutex);

  // Update our thread list, because sometimes libdispatch or the kernel
  // will spawn threads while a task is suspended.
  MachThreadList::collection new_threads;

  // First figure out if we were planning on running only one thread, and if so
  // force that thread to resume.
  bool run_one_thread;
  nub_thread_t solo_thread = INVALID_NUB_THREAD;
  if (thread_actions.GetSize() > 0 &&
      thread_actions.NumActionsWithState(eStateStepping) +
              thread_actions.NumActionsWithState(eStateRunning) ==
          1) {
    run_one_thread = true;
    const DNBThreadResumeAction *action_ptr = thread_actions.GetFirst();
    size_t num_actions = thread_actions.GetSize();
    for (size_t i = 0; i < num_actions; i++, action_ptr++) {
      if (action_ptr->state == eStateStepping ||
          action_ptr->state == eStateRunning) {
        solo_thread = action_ptr->tid;
        break;
      }
    }
  } else
    run_one_thread = false;

  UpdateThreadList(process, true, &new_threads);

  DNBThreadResumeAction resume_new_threads = {-1U, eStateRunning, 0,
                                              INVALID_NUB_ADDRESS};
  // If we are planning to run only one thread, any new threads should be
  // suspended.
  if (run_one_thread)
    resume_new_threads.state = eStateSuspended;

  const size_t num_new_threads = new_threads.size();
  const size_t num_threads = m_threads.size();
  for (uint32_t idx = 0; idx < num_threads; ++idx) {
    MachThread *thread = m_threads[idx].get();
    bool handled = false;
    for (uint32_t new_idx = 0; new_idx < num_new_threads; ++new_idx) {
      if (thread == new_threads[new_idx].get()) {
        thread->ThreadWillResume(&resume_new_threads);
        handled = true;
        break;
      }
    }

    if (!handled) {
      const DNBThreadResumeAction *thread_action =
          thread_actions.GetActionForThread(thread->ThreadID(), true);
      // There must always be a thread action for every thread.
      assert(thread_action);
      bool others_stopped = false;
      if (solo_thread == thread->ThreadID())
        others_stopped = true;
      thread->ThreadWillResume(thread_action, others_stopped);
    }
  }

  if (new_threads.size()) {
    for (uint32_t idx = 0; idx < num_new_threads; ++idx) {
      DNBLogThreadedIf(
          LOG_THREAD, "MachThreadList::ProcessWillResume (pid = %4.4x) "
                      "stop-id=%u, resuming newly discovered thread: "
                      "0x%8.8" PRIx64 ", thread-is-user-ready=%i)",
          process->ProcessID(), process->StopCount(),
          new_threads[idx]->ThreadID(), new_threads[idx]->IsUserReady());
    }
  }
}

uint32_t MachThreadList::ProcessDidStop(MachProcess *process) {
  PTHREAD_MUTEX_LOCKER(locker, m_threads_mutex);
  // Update our thread list
  const uint32_t num_threads = UpdateThreadList(process, true);
  for (uint32_t idx = 0; idx < num_threads; ++idx) {
    m_threads[idx]->ThreadDidStop();
  }
  return num_threads;
}

//----------------------------------------------------------------------
// Check each thread in our thread list to see if we should notify our
// client of the current halt in execution.
//
// Breakpoints can have callback functions associated with them than
// can return true to stop, or false to continue executing the inferior.
//
// RETURNS
//    true if we should stop and notify our clients
//    false if we should resume our child process and skip notification
//----------------------------------------------------------------------
bool MachThreadList::ShouldStop(bool &step_more) {
  PTHREAD_MUTEX_LOCKER(locker, m_threads_mutex);
  uint32_t should_stop = false;
  const size_t num_threads = m_threads.size();
  for (uint32_t idx = 0; !should_stop && idx < num_threads; ++idx) {
    should_stop = m_threads[idx]->ShouldStop(step_more);
  }
  return should_stop;
}

void MachThreadList::NotifyBreakpointChanged(const DNBBreakpoint *bp) {
  PTHREAD_MUTEX_LOCKER(locker, m_threads_mutex);
  const size_t num_threads = m_threads.size();
  for (uint32_t idx = 0; idx < num_threads; ++idx) {
    m_threads[idx]->NotifyBreakpointChanged(bp);
  }
}

uint32_t
MachThreadList::EnableHardwareBreakpoint(const DNBBreakpoint *bp) const {
  if (bp != NULL) {
    const size_t num_threads = m_threads.size();
    for (uint32_t idx = 0; idx < num_threads; ++idx)
      m_threads[idx]->EnableHardwareBreakpoint(bp);
  }
  return INVALID_NUB_HW_INDEX;
}

bool MachThreadList::DisableHardwareBreakpoint(const DNBBreakpoint *bp) const {
  if (bp != NULL) {
    const size_t num_threads = m_threads.size();
    for (uint32_t idx = 0; idx < num_threads; ++idx)
      m_threads[idx]->DisableHardwareBreakpoint(bp);
  }
  return false;
}

// DNBWatchpointSet() -> MachProcess::CreateWatchpoint() ->
// MachProcess::EnableWatchpoint()
// -> MachThreadList::EnableHardwareWatchpoint().
uint32_t
MachThreadList::EnableHardwareWatchpoint(const DNBBreakpoint *wp) const {
  uint32_t hw_index = INVALID_NUB_HW_INDEX;
  if (wp != NULL) {
    PTHREAD_MUTEX_LOCKER(locker, m_threads_mutex);
    const size_t num_threads = m_threads.size();
    // On Mac OS X we have to prime the control registers for new threads.  We
    // do this
    // using the control register data for the first thread, for lack of a
    // better way of choosing.
    bool also_set_on_task = true;
    for (uint32_t idx = 0; idx < num_threads; ++idx) {
      if ((hw_index = m_threads[idx]->EnableHardwareWatchpoint(
               wp, also_set_on_task)) == INVALID_NUB_HW_INDEX) {
        // We know that idx failed for some reason.  Let's rollback the
        // transaction for [0, idx).
        for (uint32_t i = 0; i < idx; ++i)
          m_threads[i]->RollbackTransForHWP();
        return INVALID_NUB_HW_INDEX;
      }
      also_set_on_task = false;
    }
    // Notify each thread to commit the pending transaction.
    for (uint32_t idx = 0; idx < num_threads; ++idx)
      m_threads[idx]->FinishTransForHWP();
  }
  return hw_index;
}

bool MachThreadList::DisableHardwareWatchpoint(const DNBBreakpoint *wp) const {
  if (wp != NULL) {
    PTHREAD_MUTEX_LOCKER(locker, m_threads_mutex);
    const size_t num_threads = m_threads.size();

    // On Mac OS X we have to prime the control registers for new threads.  We
    // do this
    // using the control register data for the first thread, for lack of a
    // better way of choosing.
    bool also_set_on_task = true;
    for (uint32_t idx = 0; idx < num_threads; ++idx) {
      if (!m_threads[idx]->DisableHardwareWatchpoint(wp, also_set_on_task)) {
        // We know that idx failed for some reason.  Let's rollback the
        // transaction for [0, idx).
        for (uint32_t i = 0; i < idx; ++i)
          m_threads[i]->RollbackTransForHWP();
        return false;
      }
      also_set_on_task = false;
    }
    // Notify each thread to commit the pending transaction.
    for (uint32_t idx = 0; idx < num_threads; ++idx)
      m_threads[idx]->FinishTransForHWP();

    return true;
  }
  return false;
}

uint32_t MachThreadList::NumSupportedHardwareWatchpoints() const {
  PTHREAD_MUTEX_LOCKER(locker, m_threads_mutex);
  const size_t num_threads = m_threads.size();
  // Use an arbitrary thread to retrieve the number of supported hardware
  // watchpoints.
  if (num_threads)
    return m_threads[0]->NumSupportedHardwareWatchpoints();
  return 0;
}

uint32_t MachThreadList::GetThreadIndexForThreadStoppedWithSignal(
    const int signo) const {
  PTHREAD_MUTEX_LOCKER(locker, m_threads_mutex);
  uint32_t should_stop = false;
  const size_t num_threads = m_threads.size();
  for (uint32_t idx = 0; !should_stop && idx < num_threads; ++idx) {
    if (m_threads[idx]->GetStopException().SoftSignal() == signo)
      return idx;
  }
  return UINT32_MAX;
}
