Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(148)

Side by Side Diff: content/gpu/gpu_watchdog_thread.cc

Issue 22289002: Added suspend/resume detection to the GpuWatchdogThread (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « content/gpu/gpu_watchdog_thread.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #if defined(OS_WIN) 5 #if defined(OS_WIN)
6 #include <windows.h> 6 #include <windows.h>
7 #endif 7 #endif
8 8
9 #include "content/gpu/gpu_watchdog_thread.h" 9 #include "content/gpu/gpu_watchdog_thread.h"
10 10
11 #include "base/bind.h" 11 #include "base/bind.h"
12 #include "base/bind_helpers.h" 12 #include "base/bind_helpers.h"
13 #include "base/command_line.h" 13 #include "base/command_line.h"
14 #include "base/compiler_specific.h" 14 #include "base/compiler_specific.h"
15 #include "base/power_monitor/power_monitor.h"
15 #include "base/process/process.h" 16 #include "base/process/process.h"
16 #include "build/build_config.h" 17 #include "build/build_config.h"
17 #include "content/public/common/content_switches.h" 18 #include "content/public/common/content_switches.h"
18 #include "content/public/common/result_codes.h" 19 #include "content/public/common/result_codes.h"
19 20
20 namespace content { 21 namespace content {
21 namespace { 22 namespace {
22 const int64 kCheckPeriodMs = 2000; 23 const int64 kCheckPeriodMs = 2000;
23 } // namespace 24 } // namespace
24 25
25 GpuWatchdogThread::GpuWatchdogThread(int timeout) 26 GpuWatchdogThread::GpuWatchdogThread(int timeout)
26 : base::Thread("Watchdog"), 27 : base::Thread("Watchdog"),
27 watched_message_loop_(base::MessageLoop::current()), 28 watched_message_loop_(base::MessageLoop::current()),
28 timeout_(base::TimeDelta::FromMilliseconds(timeout)), 29 timeout_(base::TimeDelta::FromMilliseconds(timeout)),
29 armed_(false), 30 armed_(false),
30 #if defined(OS_WIN) 31 #if defined(OS_WIN)
31 watched_thread_handle_(0), 32 watched_thread_handle_(0),
32 arm_cpu_time_(), 33 arm_cpu_time_(),
33 #endif 34 #endif
34 task_observer_(this), 35 task_observer_(this),
35 weak_factory_(this) { 36 weak_factory_(this),
37 suspended_(false) {
36 DCHECK(timeout >= 0); 38 DCHECK(timeout >= 0);
37 39
38 #if defined(OS_WIN) 40 #if defined(OS_WIN)
39 // GetCurrentThread returns a pseudo-handle that cannot be used by one thread 41 // GetCurrentThread returns a pseudo-handle that cannot be used by one thread
40 // to identify another. DuplicateHandle creates a "real" handle that can be 42 // to identify another. DuplicateHandle creates a "real" handle that can be
41 // used for this purpose. 43 // used for this purpose.
42 BOOL result = DuplicateHandle(GetCurrentProcess(), 44 BOOL result = DuplicateHandle(GetCurrentProcess(),
43 GetCurrentThread(), 45 GetCurrentThread(),
44 GetCurrentProcess(), 46 GetCurrentProcess(),
45 &watched_thread_handle_, 47 &watched_thread_handle_,
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
97 99
98 GpuWatchdogThread::~GpuWatchdogThread() { 100 GpuWatchdogThread::~GpuWatchdogThread() {
99 // Verify that the thread was explicitly stopped. If the thread is stopped 101 // Verify that the thread was explicitly stopped. If the thread is stopped
100 // implicitly by the destructor, CleanUp() will not be called. 102 // implicitly by the destructor, CleanUp() will not be called.
101 DCHECK(!weak_factory_.HasWeakPtrs()); 103 DCHECK(!weak_factory_.HasWeakPtrs());
102 104
103 #if defined(OS_WIN) 105 #if defined(OS_WIN)
104 CloseHandle(watched_thread_handle_); 106 CloseHandle(watched_thread_handle_);
105 #endif 107 #endif
106 108
109 base::PowerMonitor* power_monitor = base::PowerMonitor::Get();
110 if (power_monitor)
111 power_monitor->RemoveObserver(this);
112
107 watched_message_loop_->RemoveTaskObserver(&task_observer_); 113 watched_message_loop_->RemoveTaskObserver(&task_observer_);
108 } 114 }
109 115
110 void GpuWatchdogThread::OnAcknowledge() { 116 void GpuWatchdogThread::OnAcknowledge() {
111 // The check has already been acknowledged and another has already been 117 // The check has already been acknowledged and another has already been
112 // scheduled by a previous call to OnAcknowledge. It is normal for a 118 // scheduled by a previous call to OnAcknowledge. It is normal for a
113 // watched thread to see armed_ being true multiple times before 119 // watched thread to see armed_ being true multiple times before
114 // the OnAcknowledge task is run on the watchdog thread. 120 // the OnAcknowledge task is run on the watchdog thread.
115 if (!armed_) 121 if (!armed_)
116 return; 122 return;
117 123
118 // Revoke any pending hang termination. 124 // Revoke any pending hang termination.
119 weak_factory_.InvalidateWeakPtrs(); 125 weak_factory_.InvalidateWeakPtrs();
120 armed_ = false; 126 armed_ = false;
121 127
122 // If it took a long time for the acknowledgement, assume the computer was 128 // If it took a long time for the acknowledgement, assume the computer was
123 // recently suspended. 129 // recently suspended.
124 bool was_suspended = (base::Time::Now() > suspension_timeout_); 130 bool was_suspended = (base::Time::Now() > suspension_timeout_);
125 131
126 // The monitored thread has responded. Post a task to check it again. 132 // The monitored thread has responded. Post a task to check it again.
127 message_loop()->PostDelayedTask( 133 message_loop()->PostDelayedTask(
128 FROM_HERE, 134 FROM_HERE,
129 base::Bind(&GpuWatchdogThread::OnCheck, weak_factory_.GetWeakPtr(), 135 base::Bind(&GpuWatchdogThread::OnCheck, weak_factory_.GetWeakPtr(),
130 was_suspended), 136 was_suspended),
131 base::TimeDelta::FromMilliseconds(kCheckPeriodMs)); 137 base::TimeDelta::FromMilliseconds(kCheckPeriodMs));
132 } 138 }
133 139
134 void GpuWatchdogThread::OnCheck(bool after_suspend) { 140 void GpuWatchdogThread::OnCheck(bool after_suspend) {
135 if (armed_) 141 // Do not create any new termination tasks if one has already been created
142 // or the system is suspended.
143 if (armed_ || suspended_)
136 return; 144 return;
137 145
138 // Must set armed before posting the task. This task might be the only task 146 // Must set armed before posting the task. This task might be the only task
139 // that will activate the TaskObserver on the watched thread and it must not 147 // that will activate the TaskObserver on the watched thread and it must not
140 // miss the false -> true transition. 148 // miss the false -> true transition.
141 armed_ = true; 149 armed_ = true;
142 150
143 #if defined(OS_WIN) 151 #if defined(OS_WIN)
144 arm_cpu_time_ = GetWatchedThreadTime(); 152 arm_cpu_time_ = GetWatchedThreadTime();
145 #endif 153 #endif
(...skipping 15 matching lines...) Expand all
161 message_loop()->PostDelayedTask( 169 message_loop()->PostDelayedTask(
162 FROM_HERE, 170 FROM_HERE,
163 base::Bind( 171 base::Bind(
164 &GpuWatchdogThread::DeliberatelyTerminateToRecoverFromHang, 172 &GpuWatchdogThread::DeliberatelyTerminateToRecoverFromHang,
165 weak_factory_.GetWeakPtr()), 173 weak_factory_.GetWeakPtr()),
166 timeout); 174 timeout);
167 } 175 }
168 176
169 // Use the --disable-gpu-watchdog command line switch to disable this. 177 // Use the --disable-gpu-watchdog command line switch to disable this.
170 void GpuWatchdogThread::DeliberatelyTerminateToRecoverFromHang() { 178 void GpuWatchdogThread::DeliberatelyTerminateToRecoverFromHang() {
179 // Should not get here while system is suspended
Ken Russell (switch to Gerrit) 2013/08/05 22:08:01 Please complete the sentence: "while the system is
180 DCHECK(!suspended_);
181
171 #if defined(OS_WIN) 182 #if defined(OS_WIN)
172 // Defer termination until a certain amount of CPU time has elapsed on the 183 // Defer termination until a certain amount of CPU time has elapsed on the
173 // watched thread. 184 // watched thread.
174 base::TimeDelta time_since_arm = GetWatchedThreadTime() - arm_cpu_time_; 185 base::TimeDelta time_since_arm = GetWatchedThreadTime() - arm_cpu_time_;
175 if (time_since_arm < timeout_) { 186 if (time_since_arm < timeout_) {
176 message_loop()->PostDelayedTask( 187 message_loop()->PostDelayedTask(
177 FROM_HERE, 188 FROM_HERE,
178 base::Bind( 189 base::Bind(
179 &GpuWatchdogThread::DeliberatelyTerminateToRecoverFromHang, 190 &GpuWatchdogThread::DeliberatelyTerminateToRecoverFromHang,
180 weak_factory_.GetWeakPtr()), 191 weak_factory_.GetWeakPtr()),
(...skipping 26 matching lines...) Expand all
207 218
208 LOG(ERROR) << "The GPU process hung. Terminating after " 219 LOG(ERROR) << "The GPU process hung. Terminating after "
209 << timeout_.InMilliseconds() << " ms."; 220 << timeout_.InMilliseconds() << " ms.";
210 221
211 // Deliberately crash the process to create a crash dump. 222 // Deliberately crash the process to create a crash dump.
212 *((volatile int*)0) = 0x1337; 223 *((volatile int*)0) = 0x1337;
213 224
214 terminated = true; 225 terminated = true;
215 } 226 }
216 227
228 void GpuWatchdogThread::AddPowerObserver() {
229 message_loop()->PostTask(
230 FROM_HERE,
231 base::Bind(&GpuWatchdogThread::OnAddPowerObserver, this));
232 }
233
234 void GpuWatchdogThread::OnAddPowerObserver() {
235 base::PowerMonitor* power_monitor = base::PowerMonitor::Get();
236 DCHECK(power_monitor);
237 power_monitor->AddObserver(this);
238 }
239
240 void GpuWatchdogThread::OnSuspend() {
241 suspended_ = true;
242
243 // When suspending force an acknowledgement to cancel any pending termination
244 // tasks.
245 OnAcknowledge();
Ken Russell (switch to Gerrit) 2013/08/05 22:08:01 Is this correct and sufficient? The situation I'm
246 }
247
248 void GpuWatchdogThread::OnResume() {
249 suspended_ = false;
250
251 // After resuming jump-start the watchdog again
252 armed_ = false;
253 OnCheck(true);
Ken Russell (switch to Gerrit) 2013/08/05 22:08:01 Similarly for OnCheck. Per discussion with apatric
254 }
255
217 #if defined(OS_WIN) 256 #if defined(OS_WIN)
218 base::TimeDelta GpuWatchdogThread::GetWatchedThreadTime() { 257 base::TimeDelta GpuWatchdogThread::GetWatchedThreadTime() {
219 FILETIME creation_time; 258 FILETIME creation_time;
220 FILETIME exit_time; 259 FILETIME exit_time;
221 FILETIME user_time; 260 FILETIME user_time;
222 FILETIME kernel_time; 261 FILETIME kernel_time;
223 BOOL result = GetThreadTimes(watched_thread_handle_, 262 BOOL result = GetThreadTimes(watched_thread_handle_,
224 &creation_time, 263 &creation_time,
225 &exit_time, 264 &exit_time,
226 &kernel_time, 265 &kernel_time,
(...skipping 14 matching lines...) Expand all
241 // not increasing. The other is where either the kernel hangs and never 280 // not increasing. The other is where either the kernel hangs and never
242 // returns to user level or where user level code 281 // returns to user level or where user level code
243 // calls into kernel level repeatedly, giving up its quanta before it is 282 // calls into kernel level repeatedly, giving up its quanta before it is
244 // tracked, for example a loop that repeatedly Sleeps. 283 // tracked, for example a loop that repeatedly Sleeps.
245 return base::TimeDelta::FromMilliseconds(static_cast<int64>( 284 return base::TimeDelta::FromMilliseconds(static_cast<int64>(
246 (user_time64.QuadPart + kernel_time64.QuadPart) / 10000)); 285 (user_time64.QuadPart + kernel_time64.QuadPart) / 10000));
247 } 286 }
248 #endif 287 #endif
249 288
250 } // namespace content 289 } // namespace content
OLDNEW
« no previous file with comments | « content/gpu/gpu_watchdog_thread.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698