// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/threading/platform_thread_win.h"

#include <stddef.h>

#include <string>

#include "base/allocator/partition_allocator/partition_alloc_buildflags.h"
#include "base/debug/alias.h"
#include "base/debug/crash_logging.h"
#include "base/debug/profiler.h"
#include "base/feature_list.h"
#include "base/logging.h"
#include "base/memory/raw_ptr.h"
#include "base/metrics/histogram_macros.h"
#include "base/process/memory.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/scoped_blocking_call.h"
#include "base/threading/scoped_thread_priority.h"
#include "base/threading/thread_id_name_manager.h"
#include "base/threading/thread_restrictions.h"
#include "base/threading/threading_features.h"
#include "base/time/time_override.h"
#include "base/win/scoped_handle.h"
#include "base/win/windows_version.h"
#include "build/build_config.h"

#include <windows.h>

#if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) && BUILDFLAG(USE_STARSCAN)
#include "base/allocator/partition_allocator/starscan/pcscan.h"
#include "base/allocator/partition_allocator/starscan/stack/stack.h"
#endif

namespace base {

BASE_FEATURE(kUseThreadPriorityLowest,
             "UseThreadPriorityLowest",
             base::FEATURE_DISABLED_BY_DEFAULT);
BASE_FEATURE(kAboveNormalCompositingBrowserWin,
             "AboveNormalCompositingBrowserWin",
             base::FEATURE_DISABLED_BY_DEFAULT);

namespace {

// Flag used to set thread priority to |THREAD_PRIORITY_LOWEST| for
// |kUseThreadPriorityLowest| Feature.
std::atomic<bool> g_use_thread_priority_lowest{false};
// Flag used to map Compositing ThreadType |THREAD_PRIORITY_ABOVE_NORMAL| on the
// UI thread for |kAboveNormalCompositingBrowserWin| Feature.
std::atomic<bool> g_above_normal_compositing_browser{false};

// These values are sometimes returned by ::GetThreadPriority().
constexpr int kWinDisplayPriority1 = 5;
constexpr int kWinDisplayPriority2 = 6;

// The information on how to set the thread name comes from
// a MSDN article: http://msdn2.microsoft.com/en-us/library/xcb2z8hs.aspx
const DWORD kVCThreadNameException = 0x406D1388;

typedef struct tagTHREADNAME_INFO {
  DWORD dwType;  // Must be 0x1000.
  LPCSTR szName;  // Pointer to name (in user addr space).
  DWORD dwThreadID;  // Thread ID (-1=caller thread).
  DWORD dwFlags;  // Reserved for future use, must be zero.
} THREADNAME_INFO;

// The SetThreadDescription API was brought in version 1607 of Windows 10.
typedef HRESULT(WINAPI* SetThreadDescription)(HANDLE hThread,
                                              PCWSTR lpThreadDescription);

// This function has try handling, so it is separated out of its caller.
void SetNameInternal(PlatformThreadId thread_id, const char* name) {
  THREADNAME_INFO info;
  info.dwType = 0x1000;
  info.szName = name;
  info.dwThreadID = thread_id;
  info.dwFlags = 0;

  __try {
    RaiseException(kVCThreadNameException, 0, sizeof(info) / sizeof(ULONG_PTR),
                   reinterpret_cast<ULONG_PTR*>(&info));
  } __except (EXCEPTION_EXECUTE_HANDLER) {
  }
}

struct ThreadParams {
  raw_ptr<PlatformThread::Delegate> delegate;
  bool joinable;
  ThreadType thread_type;
  MessagePumpType message_pump_type;
};

DWORD __stdcall ThreadFunc(void* params) {
  ThreadParams* thread_params = static_cast<ThreadParams*>(params);
  PlatformThread::Delegate* delegate = thread_params->delegate;
  if (!thread_params->joinable)
    base::DisallowSingleton();

  if (thread_params->thread_type != ThreadType::kDefault)
    internal::SetCurrentThreadType(thread_params->thread_type,
                                   thread_params->message_pump_type);

  // Retrieve a copy of the thread handle to use as the key in the
  // thread name mapping.
  PlatformThreadHandle::Handle platform_handle;
  BOOL did_dup = DuplicateHandle(GetCurrentProcess(),
                                GetCurrentThread(),
                                GetCurrentProcess(),
                                &platform_handle,
                                0,
                                FALSE,
                                DUPLICATE_SAME_ACCESS);

#if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) && BUILDFLAG(USE_STARSCAN)
  partition_alloc::internal::PCScan::NotifyThreadCreated(
      partition_alloc::internal::GetStackPointer());
#endif

  win::ScopedHandle scoped_platform_handle;

  if (did_dup) {
    scoped_platform_handle.Set(platform_handle);
    ThreadIdNameManager::GetInstance()->RegisterThread(
        scoped_platform_handle.get(), PlatformThread::CurrentId());
  }

  delete thread_params;
  delegate->ThreadMain();

  if (did_dup) {
    ThreadIdNameManager::GetInstance()->RemoveName(scoped_platform_handle.get(),
                                                   PlatformThread::CurrentId());
  }

#if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) && BUILDFLAG(USE_STARSCAN)
  partition_alloc::internal::PCScan::NotifyThreadDestroyed();
#endif

  // Ensure thread priority is at least NORMAL before initiating thread
  // destruction. Thread destruction on Windows holds the LdrLock while
  // performing TLS destruction which causes hangs if performed at background
  // priority (priority inversion) (see: http://crbug.com/1096203).
  if (::GetThreadPriority(::GetCurrentThread()) < THREAD_PRIORITY_NORMAL)
    PlatformThread::SetCurrentThreadType(ThreadType::kDefault);

  return 0;
}

// CreateThreadInternal() matches PlatformThread::CreateWithType(), except
// that |out_thread_handle| may be nullptr, in which case a non-joinable thread
// is created.
bool CreateThreadInternal(size_t stack_size,
                          PlatformThread::Delegate* delegate,
                          PlatformThreadHandle* out_thread_handle,
                          ThreadType thread_type,
                          MessagePumpType message_pump_type) {
  unsigned int flags = 0;
  if (stack_size > 0) {
    flags = STACK_SIZE_PARAM_IS_A_RESERVATION;
#if defined(ARCH_CPU_32_BITS)
  } else {
    // The process stack size is increased to give spaces to |RendererMain| in
    // |chrome/BUILD.gn|, but keep the default stack size of other threads to
    // 1MB for the address space pressure.
    flags = STACK_SIZE_PARAM_IS_A_RESERVATION;
    static BOOL is_wow64 = -1;
    if (is_wow64 == -1 && !IsWow64Process(GetCurrentProcess(), &is_wow64))
      is_wow64 = FALSE;
    // When is_wow64 is set that means we are running on 64-bit Windows and we
    // get 4 GiB of address space. In that situation we can afford to use 1 MiB
    // of address space for stacks. When running on 32-bit Windows we only get
    // 2 GiB of address space so we need to conserve. Typically stack usage on
    // these threads is only about 100 KiB.
    if (is_wow64)
      stack_size = 1024 * 1024;
    else
      stack_size = 512 * 1024;
#endif
  }

  ThreadParams* params = new ThreadParams;
  params->delegate = delegate;
  params->joinable = out_thread_handle != nullptr;
  params->thread_type = thread_type;
  params->message_pump_type = message_pump_type;

  // Using CreateThread here vs _beginthreadex makes thread creation a bit
  // faster and doesn't require the loader lock to be available.  Our code will
  // have to work running on CreateThread() threads anyway, since we run code on
  // the Windows thread pool, etc.  For some background on the difference:
  // http://www.microsoft.com/msj/1099/win32/win321099.aspx
  void* thread_handle =
      ::CreateThread(nullptr, stack_size, ThreadFunc, params, flags, nullptr);

  if (!thread_handle) {
    DWORD last_error = ::GetLastError();

    switch (last_error) {
      case ERROR_NOT_ENOUGH_MEMORY:
      case ERROR_OUTOFMEMORY:
      case ERROR_COMMITMENT_LIMIT:
        TerminateBecauseOutOfMemory(stack_size);
        break;

      default:
        static auto* last_error_crash_key = debug::AllocateCrashKeyString(
            "create_thread_last_error", debug::CrashKeySize::Size32);
        debug::SetCrashKeyString(last_error_crash_key,
                                 base::NumberToString(last_error));
        break;
    }

    delete params;
    return false;
  }

  if (out_thread_handle)
    *out_thread_handle = PlatformThreadHandle(thread_handle);
  else
    CloseHandle(thread_handle);
  return true;
}

}  // namespace

namespace internal {

void AssertMemoryPriority(HANDLE thread, int memory_priority) {
#if DCHECK_IS_ON()
  static const auto get_thread_information_fn =
      reinterpret_cast<decltype(&::GetThreadInformation)>(::GetProcAddress(
          ::GetModuleHandle(L"Kernel32.dll"), "GetThreadInformation"));

  DCHECK(get_thread_information_fn);

  MEMORY_PRIORITY_INFORMATION memory_priority_information = {};
  DCHECK(get_thread_information_fn(thread, ::ThreadMemoryPriority,
                                   &memory_priority_information,
                                   sizeof(memory_priority_information)));

  DCHECK_EQ(memory_priority,
            static_cast<int>(memory_priority_information.MemoryPriority));
#endif
}

}  // namespace internal

// static
PlatformThreadId PlatformThread::CurrentId() {
  return ::GetCurrentThreadId();
}

// static
PlatformThreadRef PlatformThread::CurrentRef() {
  return PlatformThreadRef(::GetCurrentThreadId());
}

// static
PlatformThreadHandle PlatformThread::CurrentHandle() {
  return PlatformThreadHandle(::GetCurrentThread());
}

// static
void PlatformThread::YieldCurrentThread() {
  ::Sleep(0);
}

// static
void PlatformThread::Sleep(TimeDelta duration) {
  // When measured with a high resolution clock, Sleep() sometimes returns much
  // too early. We may need to call it repeatedly to get the desired duration.
  // PlatformThread::Sleep doesn't support mock-time, so this always uses
  // real-time.
  const TimeTicks end = subtle::TimeTicksNowIgnoringOverride() + duration;
  for (TimeTicks now = subtle::TimeTicksNowIgnoringOverride(); now < end;
       now = subtle::TimeTicksNowIgnoringOverride()) {
    ::Sleep(static_cast<DWORD>((end - now).InMillisecondsRoundedUp()));
  }
}

// static
void PlatformThread::SetName(const std::string& name) {
  ThreadIdNameManager::GetInstance()->SetName(name);

  // The SetThreadDescription API works even if no debugger is attached.
  static auto set_thread_description_func =
      reinterpret_cast<SetThreadDescription>(::GetProcAddress(
          ::GetModuleHandle(L"Kernel32.dll"), "SetThreadDescription"));
  if (set_thread_description_func) {
    set_thread_description_func(::GetCurrentThread(),
                                base::UTF8ToWide(name).c_str());
  }

  // The debugger needs to be around to catch the name in the exception.  If
  // there isn't a debugger, we are just needlessly throwing an exception.
  if (!::IsDebuggerPresent())
    return;

  SetNameInternal(CurrentId(), name.c_str());
}

// static
const char* PlatformThread::GetName() {
  return ThreadIdNameManager::GetInstance()->GetName(CurrentId());
}

// static
bool PlatformThread::CreateWithType(size_t stack_size,
                                    Delegate* delegate,
                                    PlatformThreadHandle* thread_handle,
                                    ThreadType thread_type,
                                    MessagePumpType pump_type_hint) {
  DCHECK(thread_handle);
  return CreateThreadInternal(stack_size, delegate, thread_handle, thread_type,
                              pump_type_hint);
}

// static
bool PlatformThread::CreateNonJoinable(size_t stack_size, Delegate* delegate) {
  return CreateNonJoinableWithType(stack_size, delegate, ThreadType::kDefault);
}

// static
bool PlatformThread::CreateNonJoinableWithType(size_t stack_size,
                                               Delegate* delegate,
                                               ThreadType thread_type,
                                               MessagePumpType pump_type_hint) {
  return CreateThreadInternal(stack_size, delegate, nullptr /* non-joinable */,
                              thread_type, pump_type_hint);
}

// static
void PlatformThread::Join(PlatformThreadHandle thread_handle) {
  DCHECK(thread_handle.platform_handle());

  DWORD thread_id = 0;
  thread_id = ::GetThreadId(thread_handle.platform_handle());
  DWORD last_error = 0;
  if (!thread_id)
    last_error = ::GetLastError();

  // Record information about the exiting thread in case joining hangs.
  base::debug::Alias(&thread_id);
  base::debug::Alias(&last_error);

  base::internal::ScopedBlockingCallWithBaseSyncPrimitives scoped_blocking_call(
      FROM_HERE, base::BlockingType::MAY_BLOCK);

  // Wait for the thread to exit.  It should already have terminated but make
  // sure this assumption is valid.
  CHECK_EQ(WAIT_OBJECT_0,
           WaitForSingleObject(thread_handle.platform_handle(), INFINITE));
  CloseHandle(thread_handle.platform_handle());
}

// static
void PlatformThread::Detach(PlatformThreadHandle thread_handle) {
  CloseHandle(thread_handle.platform_handle());
}

// static
bool PlatformThread::CanChangeThreadType(ThreadType from, ThreadType to) {
  return true;
}

namespace {

void SetCurrentThreadPriority(ThreadType thread_type,
                              MessagePumpType pump_type_hint) {
  if (thread_type == ThreadType::kCompositing &&
      pump_type_hint == MessagePumpType::UI &&
      !g_above_normal_compositing_browser) {
    // Ignore kCompositing thread type for UI thread as Windows has a
    // priority boost mechanism. See
    // https://docs.microsoft.com/en-us/windows/win32/procthread/priority-boosts
    return;
  }

  PlatformThreadHandle::Handle thread_handle =
      PlatformThread::CurrentHandle().platform_handle();

  if (!g_use_thread_priority_lowest && thread_type != ThreadType::kBackground) {
    // Exit background mode if the new priority is not BACKGROUND. This is a
    // no-op if not in background mode.
    ::SetThreadPriority(thread_handle, THREAD_MODE_BACKGROUND_END);
    // We used to DCHECK that memory priority is MEMORY_PRIORITY_NORMAL here,
    // but found that it is not always the case (e.g. in the installer).
    // crbug.com/1340578#c2
  }

  int desired_priority = THREAD_PRIORITY_ERROR_RETURN;
  switch (thread_type) {
    case ThreadType::kBackground:
      // Using THREAD_MODE_BACKGROUND_BEGIN instead of THREAD_PRIORITY_LOWEST
      // improves input latency and navigation time. See
      // https://docs.google.com/document/d/16XrOwuwTwKWdgPbcKKajTmNqtB4Am8TgS9GjbzBYLc0
      //
      // MSDN recommends THREAD_MODE_BACKGROUND_BEGIN for threads that perform
      // background work, as it reduces disk and memory priority in addition to
      // CPU priority.
      desired_priority =
          g_use_thread_priority_lowest.load(std::memory_order_relaxed)
              ? THREAD_PRIORITY_LOWEST
              : THREAD_MODE_BACKGROUND_BEGIN;
      break;
    case ThreadType::kUtility:
      desired_priority = THREAD_PRIORITY_BELOW_NORMAL;
      break;
    case ThreadType::kResourceEfficient:
    case ThreadType::kDefault:
      desired_priority = THREAD_PRIORITY_NORMAL;
      break;
    case ThreadType::kCompositing:
    case ThreadType::kDisplayCritical:
      desired_priority = THREAD_PRIORITY_ABOVE_NORMAL;
      break;
    case ThreadType::kRealtimeAudio:
      desired_priority = THREAD_PRIORITY_TIME_CRITICAL;
      break;
  }
  DCHECK_NE(desired_priority, THREAD_PRIORITY_ERROR_RETURN);

  [[maybe_unused]] const BOOL success =
      ::SetThreadPriority(thread_handle, desired_priority);
  DPLOG_IF(ERROR, !success)
      << "Failed to set thread priority to " << desired_priority;

  if (!g_use_thread_priority_lowest && thread_type == ThreadType::kBackground) {
    // In a background process, THREAD_MODE_BACKGROUND_BEGIN lowers the memory
    // and I/O priorities but not the CPU priority (kernel bug?). Use
    // THREAD_PRIORITY_LOWEST to also lower the CPU priority.
    // https://crbug.com/901483
    if (PlatformThread::GetCurrentThreadPriorityForTest() !=
        ThreadPriorityForTest::kBackground) {
      ::SetThreadPriority(thread_handle, THREAD_PRIORITY_LOWEST);
      // We used to DCHECK that memory priority is MEMORY_PRIORITY_VERY_LOW
      // here, but found that it is not always the case (e.g. in the installer).
      // crbug.com/1340578#c2
    }
  }
}

void SetCurrentThreadQualityOfService(ThreadType thread_type) {
  // QoS and power throttling were introduced in Win10 1709
  if (win::GetVersion() < win::Version::WIN10_RS3) {
    return;
  }

  static const auto set_thread_information_fn =
      reinterpret_cast<decltype(&::SetThreadInformation)>(::GetProcAddress(
          ::GetModuleHandle(L"kernel32.dll"), "SetThreadInformation"));
  DCHECK(set_thread_information_fn);

  bool desire_ecoqos = false;
  switch (thread_type) {
    case ThreadType::kBackground:
    case ThreadType::kUtility:
    case ThreadType::kResourceEfficient:
      desire_ecoqos = true;
      break;
    case ThreadType::kDefault:
    case ThreadType::kCompositing:
    case ThreadType::kDisplayCritical:
    case ThreadType::kRealtimeAudio:
      desire_ecoqos = false;
      break;
  }

  THREAD_POWER_THROTTLING_STATE thread_power_throttling_state{
      .Version = THREAD_POWER_THROTTLING_CURRENT_VERSION,
      .ControlMask =
          desire_ecoqos ? THREAD_POWER_THROTTLING_EXECUTION_SPEED : 0ul,
      .StateMask =
          desire_ecoqos ? THREAD_POWER_THROTTLING_EXECUTION_SPEED : 0ul,
  };
  [[maybe_unused]] const BOOL success = set_thread_information_fn(
      ::GetCurrentThread(), ::ThreadPowerThrottling,
      &thread_power_throttling_state, sizeof(thread_power_throttling_state));
  DPLOG_IF(ERROR, !success)
      << "Failed to set EcoQoS to " << std::boolalpha << desire_ecoqos;
}

}  // namespace

namespace internal {

void SetCurrentThreadTypeImpl(ThreadType thread_type,
                              MessagePumpType pump_type_hint) {
  SetCurrentThreadPriority(thread_type, pump_type_hint);
  SetCurrentThreadQualityOfService(thread_type);
}

}  // namespace internal

// static
ThreadPriorityForTest PlatformThread::GetCurrentThreadPriorityForTest() {
  static_assert(
      THREAD_PRIORITY_IDLE < 0,
      "THREAD_PRIORITY_IDLE is >= 0 and will incorrectly cause errors.");
  static_assert(
      THREAD_PRIORITY_LOWEST < 0,
      "THREAD_PRIORITY_LOWEST is >= 0 and will incorrectly cause errors.");
  static_assert(THREAD_PRIORITY_BELOW_NORMAL < 0,
                "THREAD_PRIORITY_BELOW_NORMAL is >= 0 and will incorrectly "
                "cause errors.");
  static_assert(
      THREAD_PRIORITY_NORMAL == 0,
      "The logic below assumes that THREAD_PRIORITY_NORMAL is zero. If it is "
      "not, ThreadPriorityForTest::kBackground may be incorrectly detected.");
  static_assert(THREAD_PRIORITY_ABOVE_NORMAL >= 0,
                "THREAD_PRIORITY_ABOVE_NORMAL is < 0 and will incorrectly be "
                "translated to ThreadPriorityForTest::kBackground.");
  static_assert(THREAD_PRIORITY_HIGHEST >= 0,
                "THREAD_PRIORITY_HIGHEST is < 0 and will incorrectly be "
                "translated to ThreadPriorityForTest::kBackground.");
  static_assert(THREAD_PRIORITY_TIME_CRITICAL >= 0,
                "THREAD_PRIORITY_TIME_CRITICAL is < 0 and will incorrectly be "
                "translated to ThreadPriorityForTest::kBackground.");
  static_assert(THREAD_PRIORITY_ERROR_RETURN >= 0,
                "THREAD_PRIORITY_ERROR_RETURN is < 0 and will incorrectly be "
                "translated to ThreadPriorityForTest::kBackground.");

  const int priority =
      ::GetThreadPriority(PlatformThread::CurrentHandle().platform_handle());

  // Negative values represent a background priority. We have observed -3, -4,
  // -6 when THREAD_MODE_BACKGROUND_* is used. THREAD_PRIORITY_IDLE,
  // THREAD_PRIORITY_LOWEST and THREAD_PRIORITY_BELOW_NORMAL are other possible
  // negative values.
  if (priority < THREAD_PRIORITY_BELOW_NORMAL)
    return ThreadPriorityForTest::kBackground;

  switch (priority) {
    case THREAD_PRIORITY_BELOW_NORMAL:
      return ThreadPriorityForTest::kUtility;
    case THREAD_PRIORITY_NORMAL:
      return ThreadPriorityForTest::kNormal;
    case kWinDisplayPriority1:
      [[fallthrough]];
    case kWinDisplayPriority2:
      return ThreadPriorityForTest::kDisplay;
    case THREAD_PRIORITY_ABOVE_NORMAL:
    case THREAD_PRIORITY_HIGHEST:
      return ThreadPriorityForTest::kDisplay;
    case THREAD_PRIORITY_TIME_CRITICAL:
      return ThreadPriorityForTest::kRealtimeAudio;
    case THREAD_PRIORITY_ERROR_RETURN:
      DPCHECK(false) << "::GetThreadPriority error";
  }

  NOTREACHED() << "::GetThreadPriority returned " << priority << ".";
  return ThreadPriorityForTest::kNormal;
}

void InitializePlatformThreadFeatures() {
  g_use_thread_priority_lowest.store(
      FeatureList::IsEnabled(kUseThreadPriorityLowest),
      std::memory_order_relaxed);
  g_above_normal_compositing_browser.store(
      FeatureList::IsEnabled(kAboveNormalCompositingBrowserWin),
      std::memory_order_relaxed);
}

// static
size_t PlatformThread::GetDefaultThreadStackSize() {
  return 0;
}

}  // namespace base
