summaryrefslogtreecommitdiffstats
path: root/chromium/base/profiler/thread_delegate_win.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/base/profiler/thread_delegate_win.cc')
-rw-r--r--chromium/base/profiler/thread_delegate_win.cc223
1 files changed, 0 insertions, 223 deletions
diff --git a/chromium/base/profiler/thread_delegate_win.cc b/chromium/base/profiler/thread_delegate_win.cc
deleted file mode 100644
index 71ba5aaee47..00000000000
--- a/chromium/base/profiler/thread_delegate_win.cc
+++ /dev/null
@@ -1,223 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/profiler/thread_delegate_win.h"
-
-#include <windows.h>
-#include <winternl.h>
-
-#include "base/debug/alias.h"
-#include "base/logging.h"
-#include "base/profiler/native_unwinder_win.h"
-#include "build/build_config.h"
-
-// IMPORTANT NOTE: Some functions within this implementation are invoked while
-// the target thread is suspended so it must not do any allocation from the
-// heap, including indirectly via use of DCHECK/CHECK or other logging
-// statements. Otherwise this code can deadlock on heap locks acquired by the
-// target thread before it was suspended. These functions are commented with "NO
-// HEAP ALLOCATIONS".
-
-namespace base {
-
-namespace {
-
-// The thread environment block internal type.
-struct TEB {
- NT_TIB Tib;
- // Rest of struct is ignored.
-};
-
-win::ScopedHandle GetThreadHandle(PlatformThreadId thread_id) {
- // TODO(http://crbug.com/947459): Remove the test_handle* CHECKs once we
- // understand which flag is triggering the failure.
-
- DWORD flags = 0;
- base::debug::Alias(&flags);
-
- flags |= THREAD_GET_CONTEXT;
- win::ScopedHandle test_handle1(::OpenThread(flags, FALSE, thread_id));
- CHECK(test_handle1.IsValid());
-
- flags |= THREAD_QUERY_INFORMATION;
- win::ScopedHandle test_handle2(::OpenThread(flags, FALSE, thread_id));
- CHECK(test_handle2.IsValid());
-
- flags |= THREAD_SUSPEND_RESUME;
- win::ScopedHandle handle(::OpenThread(flags, FALSE, thread_id));
- CHECK(handle.IsValid());
- return handle;
-}
-
-// Returns the thread environment block pointer for |thread_handle|.
-const TEB* GetThreadEnvironmentBlock(HANDLE thread_handle) {
- // Define the internal types we need to invoke NtQueryInformationThread.
- enum THREAD_INFORMATION_CLASS { ThreadBasicInformation };
-
- struct CLIENT_ID {
- HANDLE UniqueProcess;
- HANDLE UniqueThread;
- };
-
- struct THREAD_BASIC_INFORMATION {
- NTSTATUS ExitStatus;
- TEB* Teb;
- CLIENT_ID ClientId;
- KAFFINITY AffinityMask;
- LONG Priority;
- LONG BasePriority;
- };
-
- using NtQueryInformationThreadFunction =
- NTSTATUS(WINAPI*)(HANDLE, THREAD_INFORMATION_CLASS, PVOID, ULONG, PULONG);
-
- const auto nt_query_information_thread =
- reinterpret_cast<NtQueryInformationThreadFunction>(::GetProcAddress(
- ::GetModuleHandle(L"ntdll.dll"), "NtQueryInformationThread"));
- if (!nt_query_information_thread)
- return nullptr;
-
- THREAD_BASIC_INFORMATION basic_info = {0};
- NTSTATUS status = nt_query_information_thread(
- thread_handle, ThreadBasicInformation, &basic_info,
- sizeof(THREAD_BASIC_INFORMATION), nullptr);
- if (status != 0)
- return nullptr;
-
- return basic_info.Teb;
-}
-
-// Tests whether |stack_pointer| points to a location in the guard page. NO HEAP
-// ALLOCATIONS.
-bool PointsToGuardPage(uintptr_t stack_pointer) {
- MEMORY_BASIC_INFORMATION memory_info;
- SIZE_T result = ::VirtualQuery(reinterpret_cast<LPCVOID>(stack_pointer),
- &memory_info, sizeof(memory_info));
- return result != 0 && (memory_info.Protect & PAGE_GUARD);
-}
-
-// ScopedDisablePriorityBoost -------------------------------------------------
-
-// Disables priority boost on a thread for the lifetime of the object.
-class ScopedDisablePriorityBoost {
- public:
- ScopedDisablePriorityBoost(HANDLE thread_handle);
- ~ScopedDisablePriorityBoost();
-
- private:
- HANDLE thread_handle_;
- BOOL got_previous_boost_state_;
- BOOL boost_state_was_disabled_;
-
- DISALLOW_COPY_AND_ASSIGN(ScopedDisablePriorityBoost);
-};
-
-// NO HEAP ALLOCATIONS.
-ScopedDisablePriorityBoost::ScopedDisablePriorityBoost(HANDLE thread_handle)
- : thread_handle_(thread_handle),
- got_previous_boost_state_(false),
- boost_state_was_disabled_(false) {
- got_previous_boost_state_ =
- ::GetThreadPriorityBoost(thread_handle_, &boost_state_was_disabled_);
- if (got_previous_boost_state_) {
- // Confusingly, TRUE disables priority boost.
- ::SetThreadPriorityBoost(thread_handle_, TRUE);
- }
-}
-
-ScopedDisablePriorityBoost::~ScopedDisablePriorityBoost() {
- if (got_previous_boost_state_)
- ::SetThreadPriorityBoost(thread_handle_, boost_state_was_disabled_);
-}
-
-} // namespace
-
-// ScopedSuspendThread --------------------------------------------------------
-
-// NO HEAP ALLOCATIONS after ::SuspendThread.
-ThreadDelegateWin::ScopedSuspendThread::ScopedSuspendThread(
- HANDLE thread_handle)
- : thread_handle_(thread_handle),
- was_successful_(::SuspendThread(thread_handle) !=
- static_cast<DWORD>(-1)) {}
-
-// NO HEAP ALLOCATIONS. The CHECK is OK because it provides a more noisy failure
-// mode than deadlocking.
-ThreadDelegateWin::ScopedSuspendThread::~ScopedSuspendThread() {
- if (!was_successful_)
- return;
-
- // Disable the priority boost that the thread would otherwise receive on
- // resume. We do this to avoid artificially altering the dynamics of the
- // executing application any more than we already are by suspending and
- // resuming the thread.
- //
- // Note that this can racily disable a priority boost that otherwise would
- // have been given to the thread, if the thread is waiting on other wait
- // conditions at the time of SuspendThread and those conditions are satisfied
- // before priority boost is reenabled. The measured length of this window is
- // ~100us, so this should occur fairly rarely.
- ScopedDisablePriorityBoost disable_priority_boost(thread_handle_);
- bool resume_thread_succeeded =
- ::ResumeThread(thread_handle_) != static_cast<DWORD>(-1);
- CHECK(resume_thread_succeeded) << "ResumeThread failed: " << GetLastError();
-}
-
-bool ThreadDelegateWin::ScopedSuspendThread::WasSuccessful() const {
- return was_successful_;
-}
-
-// ThreadDelegateWin ----------------------------------------------------------
-
-ThreadDelegateWin::ThreadDelegateWin(PlatformThreadId thread_id)
- : thread_handle_(GetThreadHandle(thread_id)),
- thread_stack_base_address_(reinterpret_cast<uintptr_t>(
- GetThreadEnvironmentBlock(thread_handle_.Get())->Tib.StackBase)) {}
-
-ThreadDelegateWin::~ThreadDelegateWin() = default;
-
-std::unique_ptr<ThreadDelegate::ScopedSuspendThread>
-ThreadDelegateWin::CreateScopedSuspendThread() {
- return std::make_unique<ScopedSuspendThread>(thread_handle_.Get());
-}
-
-// NO HEAP ALLOCATIONS.
-bool ThreadDelegateWin::GetThreadContext(CONTEXT* thread_context) {
- *thread_context = {0};
- thread_context->ContextFlags = CONTEXT_FULL;
- return ::GetThreadContext(thread_handle_.Get(), thread_context) != 0;
-}
-
-// NO HEAP ALLOCATIONS.
-uintptr_t ThreadDelegateWin::GetStackBaseAddress() const {
- return thread_stack_base_address_;
-}
-
-// Tests whether |stack_pointer| points to a location in the guard page. NO HEAP
-// ALLOCATIONS.
-bool ThreadDelegateWin::CanCopyStack(uintptr_t stack_pointer) {
- // Dereferencing a pointer in the guard page in a thread that doesn't own the
- // stack results in a STATUS_GUARD_PAGE_VIOLATION exception and a crash. This
- // occurs very rarely, but reliably over the population.
- return !PointsToGuardPage(stack_pointer);
-}
-
-std::vector<uintptr_t*> ThreadDelegateWin::GetRegistersToRewrite(
- CONTEXT* thread_context) {
- // Return the set of non-volatile registers.
- return {
-#if defined(ARCH_CPU_X86_64)
- &thread_context->R12, &thread_context->R13, &thread_context->R14,
- &thread_context->R15, &thread_context->Rdi, &thread_context->Rsi,
- &thread_context->Rbx, &thread_context->Rbp, &thread_context->Rsp
-#elif defined(ARCH_CPU_ARM64)
- &thread_context->X19, &thread_context->X20, &thread_context->X21,
- &thread_context->X22, &thread_context->X23, &thread_context->X24,
- &thread_context->X25, &thread_context->X26, &thread_context->X27,
- &thread_context->X28, &thread_context->Fp, &thread_context->Lr
-#endif
- };
-}
-
-} // namespace base