diff options
author | jbauman <jbauman@chromium.org> | 2016-02-23 12:40:05 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-02-23 20:41:21 +0000 |
commit | 227bc7768e3ee84665b387fa65a01b7b41357218 (patch) | |
tree | 10a8e08d9fd4ca4dbd1599a248266b65a619e9af /content/gpu | |
parent | eb218f428d64fd3e54380e32e5660e51bcabcb5a (diff) | |
download | chromium_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.cc | 74 | ||||
-rw-r--r-- | content/gpu/gpu_watchdog_thread.h | 9 |
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_; |