summaryrefslogtreecommitdiffstats
path: root/content/gpu
diff options
context:
space:
mode:
authorjbauman <jbauman@chromium.org>2016-02-23 12:40:05 -0800
committerCommit bot <commit-bot@chromium.org>2016-02-23 20:41:21 +0000
commit227bc7768e3ee84665b387fa65a01b7b41357218 (patch)
tree10a8e08d9fd4ca4dbd1599a248266b65a619e9af /content/gpu
parenteb218f428d64fd3e54380e32e5660e51bcabcb5a (diff)
downloadchromium_src-227bc7768e3ee84665b387fa65a01b7b41357218.zip
chromium_src-227bc7768e3ee84665b387fa65a01b7b41357218.tar.gz
chromium_src-227bc7768e3ee84665b387fa65a01b7b41357218.tar.bz2
Revert of Don't measure CPU time in timing out GPU watchdog. (patchset #1 id:1 of https://codereview.chromium.org/1711763005/ )
Reason for revert: Too many hangs are caused by slow startup: BUG=589175 Original issue's description: > Don't measure CPU time in timing out GPU watchdog. > > It's possible for the main thread to hang on a GPU event or waiting for the OS, so if CPU usage is required for timing out the watchdog then it's possible it'll never time out. > > Just remove the code that checks for CPU time. Time lost due to suspend/resume events should be handled by the PowerMonitor, and this code seems to work on other platforms without issues. > > BUG=588342 > > Committed: https://crrev.com/ae57b78041762268e1898c165e33b904477433bb > Cr-Commit-Position: refs/heads/master@{#376867} TBR=kbr@chromium.org # Skipping CQ checks because original CL landed less than 1 days ago. NOPRESUBMIT=true NOTREECHECKS=true NOTRY=true BUG=588342 Review URL: https://codereview.chromium.org/1725983002 Cr-Commit-Position: refs/heads/master@{#377076}
Diffstat (limited to 'content/gpu')
-rw-r--r--content/gpu/gpu_watchdog_thread.cc74
-rw-r--r--content/gpu/gpu_watchdog_thread.h9
2 files changed, 83 insertions, 0 deletions
diff --git a/content/gpu/gpu_watchdog_thread.cc b/content/gpu/gpu_watchdog_thread.cc
index 22982db..4cfde4f 100644
--- a/content/gpu/gpu_watchdog_thread.cc
+++ b/content/gpu/gpu_watchdog_thread.cc
@@ -42,6 +42,10 @@ GpuWatchdogThread::GpuWatchdogThread(int timeout)
timeout_(base::TimeDelta::FromMilliseconds(timeout)),
armed_(false),
task_observer_(this),
+#if defined(OS_WIN)
+ watched_thread_handle_(0),
+ arm_cpu_time_(),
+#endif
suspended_(false),
#if defined(USE_X11)
display_(NULL),
@@ -51,6 +55,20 @@ GpuWatchdogThread::GpuWatchdogThread(int timeout)
weak_factory_(this) {
DCHECK(timeout >= 0);
+#if defined(OS_WIN)
+ // GetCurrentThread returns a pseudo-handle that cannot be used by one thread
+ // to identify another. DuplicateHandle creates a "real" handle that can be
+ // used for this purpose.
+ BOOL result = DuplicateHandle(GetCurrentProcess(),
+ GetCurrentThread(),
+ GetCurrentProcess(),
+ &watched_thread_handle_,
+ THREAD_QUERY_INFORMATION,
+ FALSE,
+ 0);
+ DCHECK(result);
+#endif
+
#if defined(OS_CHROMEOS)
tty_file_ = base::OpenFile(base::FilePath(kTtyFilePath), "r");
#endif
@@ -106,6 +124,10 @@ GpuWatchdogThread::~GpuWatchdogThread() {
// implicitly by the destructor, CleanUp() will not be called.
DCHECK(!weak_factory_.HasWeakPtrs());
+#if defined(OS_WIN)
+ CloseHandle(watched_thread_handle_);
+#endif
+
base::PowerMonitor* power_monitor = base::PowerMonitor::Get();
if (power_monitor)
power_monitor->RemoveObserver(this);
@@ -164,6 +186,10 @@ void GpuWatchdogThread::OnCheck(bool after_suspend) {
// miss the false -> true transition.
armed_ = true;
+#if defined(OS_WIN)
+ arm_cpu_time_ = GetWatchedThreadTime();
+#endif
+
// Immediately after the computer is woken up from being suspended it might
// be pretty sluggish, so allow some extra time before the next timeout.
base::TimeDelta timeout = timeout_ * (after_suspend ? 3 : 1);
@@ -189,6 +215,21 @@ void GpuWatchdogThread::DeliberatelyTerminateToRecoverFromHang() {
// Should not get here while the system is suspended.
DCHECK(!suspended_);
+#if defined(OS_WIN)
+ // Defer termination until a certain amount of CPU time has elapsed on the
+ // watched thread.
+ base::TimeDelta time_since_arm = GetWatchedThreadTime() - arm_cpu_time_;
+ if (time_since_arm < timeout_) {
+ message_loop()->PostDelayedTask(
+ FROM_HERE,
+ base::Bind(
+ &GpuWatchdogThread::DeliberatelyTerminateToRecoverFromHang,
+ weak_factory_.GetWeakPtr()),
+ timeout_ - time_since_arm);
+ return;
+ }
+#endif
+
// If the watchdog woke up significantly behind schedule, disarm and reset
// the watchdog check. This is to prevent the watchdog thread from terminating
// when a machine wakes up from sleep or hibernation, which would otherwise
@@ -329,4 +370,37 @@ void GpuWatchdogThread::OnResume() {
OnCheck(true);
}
+#if defined(OS_WIN)
+base::TimeDelta GpuWatchdogThread::GetWatchedThreadTime() {
+ FILETIME creation_time;
+ FILETIME exit_time;
+ FILETIME user_time;
+ FILETIME kernel_time;
+ BOOL result = GetThreadTimes(watched_thread_handle_,
+ &creation_time,
+ &exit_time,
+ &kernel_time,
+ &user_time);
+ DCHECK(result);
+
+ ULARGE_INTEGER user_time64;
+ user_time64.HighPart = user_time.dwHighDateTime;
+ user_time64.LowPart = user_time.dwLowDateTime;
+
+ ULARGE_INTEGER kernel_time64;
+ kernel_time64.HighPart = kernel_time.dwHighDateTime;
+ kernel_time64.LowPart = kernel_time.dwLowDateTime;
+
+ // Time is reported in units of 100 nanoseconds. Kernel and user time are
+ // summed to deal with to kinds of hangs. One is where the GPU process is
+ // stuck in user level, never calling into the kernel and kernel time is
+ // not increasing. The other is where either the kernel hangs and never
+ // returns to user level or where user level code
+ // calls into kernel level repeatedly, giving up its quanta before it is
+ // tracked, for example a loop that repeatedly Sleeps.
+ return base::TimeDelta::FromMilliseconds(static_cast<int64_t>(
+ (user_time64.QuadPart + kernel_time64.QuadPart) / 10000));
+}
+#endif
+
} // namespace content
diff --git a/content/gpu/gpu_watchdog_thread.h b/content/gpu/gpu_watchdog_thread.h
index 9be3a39..4370d83 100644
--- a/content/gpu/gpu_watchdog_thread.h
+++ b/content/gpu/gpu_watchdog_thread.h
@@ -88,11 +88,20 @@ class GpuWatchdogThread : public base::Thread,
void OnSuspend() override;
void OnResume() override;
+#if defined(OS_WIN)
+ base::TimeDelta GetWatchedThreadTime();
+#endif
+
base::MessageLoop* watched_message_loop_;
base::TimeDelta timeout_;
volatile bool armed_;
GpuWatchdogTaskObserver task_observer_;
+#if defined(OS_WIN)
+ void* watched_thread_handle_;
+ base::TimeDelta arm_cpu_time_;
+#endif
+
// Time after which it's assumed that the computer has been suspended since
// the task was posted.
base::Time suspension_timeout_;