chromium/gpu/ipc/service/gpu_watchdog_thread.cc

// 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 "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() {}

// static
std::unique_ptr<GpuWatchdogThread> GpuWatchdogThread::Create(
    bool start_backgrounded,
    base::TimeDelta timeout,
    int restart_factor,
    bool is_test_mode,
    const std::string& thread_name) {}

// static
std::unique_ptr<GpuWatchdogThread> GpuWatchdogThread::Create(
    bool start_backgrounded,
    bool software_rendering,
    const std::string& thread_name) {}

// static
std::unique_ptr<GpuWatchdogThread> GpuWatchdogThread::Create(
    bool start_backgrounded,
    const GpuWatchdogThread* existing_watchdog,
    const std::string& thread_name) {}

// Android Chrome goes to the background. Called from the gpu io thread.
void GpuWatchdogThread::OnBackgrounded() {}

// Android Chrome goes to the foreground. Called from the gpu io thread.
void GpuWatchdogThread::OnForegrounded() {}

// Called from the gpu thread when gpu init has completed.
void GpuWatchdogThread::OnInitComplete() {}

// Called from the gpu thread in viz::GpuServiceImpl::~GpuServiceImpl().
// After this, no Disarm() will be called before the watchdog thread is
// destroyed. If this destruction takes too long, the watchdog timeout
// will be triggered.
void GpuWatchdogThread::OnGpuProcessTearDown() {}

// Called from the watched gpu thread.
void GpuWatchdogThread::PauseWatchdog() {}

// Called from the watched gpu thread.
void GpuWatchdogThread::ResumeWatchdog() {}

// Running on the watchdog thread.
// On Linux, Init() will be called twice for Sandbox Initialization. The
// watchdog is stopped and then restarted in StartSandboxLinux(). Everything
// should be the same and continue after the second init().
void GpuWatchdogThread::Init() {}

// Running on the watchdog thread.
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) {}

// Power Suspends. Running on the watchdog thread.
void GpuWatchdogThread::OnSuspend() {}

// Power Resumes. Running on the watchdog thread.
void GpuWatchdogThread::OnResume() {}

// Running on the watchdog thread.
// Call AddPowerSuspendObserver on the watchdog thread so that OnSuspend() and
// OnResume() will be called on this thread.
void GpuWatchdogThread::AddPowerObserver() {}

// Running on the watchdog thread.
void GpuWatchdogThread::RestartWatchdogTimeoutTask(
    PauseResumeSource source_of_request) {}

void GpuWatchdogThread::StopWatchdogTimeoutTask(
    PauseResumeSource source_of_request) {}

// On the watchdog thread only.
void GpuWatchdogThread::UpdateInitializationFlag() {}

// Called from the watched gpu thread.
// The watchdog is armed only in these three functions -
// GpuWatchdogThread(), WillProcessTask(), and OnGpuProcessTearDown()
void GpuWatchdogThread::Arm() {}

void GpuWatchdogThread::Disarm() {}

void GpuWatchdogThread::InProgress() {}

bool GpuWatchdogThread::IsArmed() {}

base::subtle::Atomic32 GpuWatchdogThread::ReadArmDisarmCounter() {}

// Running on the watchdog thread.
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()) {
    // Note: GetForThread() might return bogus results if running on different
    // CPUs between two calls.
    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();

    // Need to bit_cast to fix alignment, then divide by 10 to convert
    // 100-nanoseconds to microseconds.
    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) {
    // This is the start of allowing more thread time. Only record it once for
    // all following timeouts on the same detected gpu hang, so we know this
    // is equivalent one crash in our crash reports.
    GpuWatchdogTimeoutHistogram(GpuWatchdogTimeoutEvent::kMoreThreadTime);
  } else {
    if (count_of_more_gpu_thread_time_allowed_ > 0) {
      if (no_gpu_hang_detected) {
        // If count_of_more_gpu_thread_time_allowed_ > 0, we know extra time was
        // extended in the previous OnWatchdogTimeout(). Now we find gpu makes
        // progress. Record this case.
        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() {}

// For gpu testing only. Return whether a GPU hang was detected or not.
bool GpuWatchdogThread::IsGpuHangDetectedForTesting() {}

}  // namespace gpu