#include "gpu/ipc/service/gpu_watchdog_thread.h"
#include <memory>
#include <string>
#include <utility>
#include "base/atomicops.h"
#include "base/bit_cast.h"
#include "base/command_line.h"
#include "base/debug/alias.h"
#include "base/debug/dump_without_crashing.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/native_library.h"
#include "base/numerics/safe_conversions.h"
#include "base/power_monitor/power_monitor.h"
#include "base/process/process.h"
#include "base/strings/string_number_conversions.h"
#include "base/system/sys_info.h"
#include "base/task/current_thread.h"
#include "base/threading/platform_thread.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "gpu/config/gpu_crash_keys.h"
#include "gpu/config/gpu_switches.h"
#include "gpu/ipc/common/result_codes.h"
namespace gpu {
base::TimeDelta GetGpuWatchdogTimeout(bool software_rendering) { … }
GpuWatchdogThread::GpuWatchdogThread(base::TimeDelta timeout,
int restart_factor,
bool is_test_mode,
const std::string& thread_name)
: … { … }
GpuWatchdogThread::~GpuWatchdogThread() { … }
std::unique_ptr<GpuWatchdogThread> GpuWatchdogThread::Create(
bool start_backgrounded,
base::TimeDelta timeout,
int restart_factor,
bool is_test_mode,
const std::string& thread_name) { … }
std::unique_ptr<GpuWatchdogThread> GpuWatchdogThread::Create(
bool start_backgrounded,
bool software_rendering,
const std::string& thread_name) { … }
std::unique_ptr<GpuWatchdogThread> GpuWatchdogThread::Create(
bool start_backgrounded,
const GpuWatchdogThread* existing_watchdog,
const std::string& thread_name) { … }
void GpuWatchdogThread::OnBackgrounded() { … }
void GpuWatchdogThread::OnForegrounded() { … }
void GpuWatchdogThread::OnInitComplete() { … }
void GpuWatchdogThread::OnGpuProcessTearDown() { … }
void GpuWatchdogThread::PauseWatchdog() { … }
void GpuWatchdogThread::ResumeWatchdog() { … }
void GpuWatchdogThread::Init() { … }
void GpuWatchdogThread::CleanUp() { … }
void GpuWatchdogThread::ReportProgress() { … }
void GpuWatchdogThread::WillProcessTask(const base::PendingTask& pending_task,
bool was_blocked_or_low_priority) { … }
void GpuWatchdogThread::DidProcessTask(const base::PendingTask& pending_task) { … }
void GpuWatchdogThread::OnSuspend() { … }
void GpuWatchdogThread::OnResume() { … }
void GpuWatchdogThread::AddPowerObserver() { … }
void GpuWatchdogThread::RestartWatchdogTimeoutTask(
PauseResumeSource source_of_request) { … }
void GpuWatchdogThread::StopWatchdogTimeoutTask(
PauseResumeSource source_of_request) { … }
void GpuWatchdogThread::UpdateInitializationFlag() { … }
void GpuWatchdogThread::Arm() { … }
void GpuWatchdogThread::Disarm() { … }
void GpuWatchdogThread::InProgress() { … }
bool GpuWatchdogThread::IsArmed() { … }
base::subtle::Atomic32 GpuWatchdogThread::ReadArmDisarmCounter() { … }
void GpuWatchdogThread::OnWatchdogTimeout() { … }
void GpuWatchdogThread::ContinueWithNextWatchdogTimeoutTask() { … }
bool GpuWatchdogThread::SlowWatchdogThread() { … }
bool GpuWatchdogThread::WatchedThreadNeedsMoreThreadTime(
bool no_gpu_hang_detected) { … }
#if BUILDFLAG(IS_WIN)
base::ThreadTicks GpuWatchdogThread::GetWatchedThreadTime() {
DCHECK(watched_thread_handle_);
if (base::ThreadTicks::IsSupported()) {
return base::ThreadTicks::GetForThread(
base::PlatformThreadHandle(watched_thread_handle_));
} else {
FILETIME creation_time;
FILETIME exit_time;
FILETIME kernel_time;
FILETIME user_time;
BOOL result = GetThreadTimes(watched_thread_handle_, &creation_time,
&exit_time, &kernel_time, &user_time);
if (!result)
return base::ThreadTicks();
int64_t user_time_us = base::bit_cast<int64_t, FILETIME>(user_time) / 10;
int64_t kernel_time_us =
base::bit_cast<int64_t, FILETIME>(kernel_time) / 10;
return base::ThreadTicks() +
base::Microseconds(user_time_us + kernel_time_us);
}
}
#endif
void GpuWatchdogThread::DeliberatelyTerminateToRecoverFromHang() { … }
void GpuWatchdogThread::GpuWatchdogThreadEventHistogram(
GpuWatchdogThreadEvent thread_event) { … }
void GpuWatchdogThread::GpuWatchdogTimeoutHistogram(
GpuWatchdogTimeoutEvent timeout_event) { … }
#if BUILDFLAG(IS_WIN)
void GpuWatchdogThread::WatchedThreadNeedsMoreThreadTimeHistogram(
bool no_gpu_hang_detected,
bool start_of_more_thread_time) {
if (start_of_more_thread_time) {
GpuWatchdogTimeoutHistogram(GpuWatchdogTimeoutEvent::kMoreThreadTime);
} else {
if (count_of_more_gpu_thread_time_allowed_ > 0) {
if (no_gpu_hang_detected) {
GpuWatchdogTimeoutHistogram(
GpuWatchdogTimeoutEvent::kProgressAfterMoreThreadTime);
} else if (count_of_more_gpu_thread_time_allowed_ >=
kMaxCountOfMoreGpuThreadTimeAllowed) {
GpuWatchdogTimeoutHistogram(
GpuWatchdogTimeoutEvent::kLessThanFullThreadTimeAfterCapped);
}
}
}
}
#endif
bool GpuWatchdogThread::WithinOneMinFromPowerResumed() { … }
bool GpuWatchdogThread::WithinOneMinFromForegrounded() { … }
#if BUILDFLAG(IS_LINUX) && !BUILDFLAG(IS_CASTOS)
void GpuWatchdogThread::UpdateActiveTTY() { … }
#endif
bool GpuWatchdogThread::ContinueOnNonHostX11ServerTty() { … }
bool GpuWatchdogThread::IsGpuHangDetectedForTesting() { … }
}