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

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

Issue 1725983002: Revert of Don't measure CPU time in timing out GPU watchdog. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 10 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
« 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 #include "content/gpu/gpu_watchdog_thread.h" 5 #include "content/gpu/gpu_watchdog_thread.h"
6 6
7 #include <errno.h> 7 #include <errno.h>
8 #include <stdint.h> 8 #include <stdint.h>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
(...skipping 24 matching lines...) Expand all
35 const unsigned char text[20] = "check"; 35 const unsigned char text[20] = "check";
36 #endif 36 #endif
37 } // namespace 37 } // namespace
38 38
39 GpuWatchdogThread::GpuWatchdogThread(int timeout) 39 GpuWatchdogThread::GpuWatchdogThread(int timeout)
40 : base::Thread("Watchdog"), 40 : base::Thread("Watchdog"),
41 watched_message_loop_(base::MessageLoop::current()), 41 watched_message_loop_(base::MessageLoop::current()),
42 timeout_(base::TimeDelta::FromMilliseconds(timeout)), 42 timeout_(base::TimeDelta::FromMilliseconds(timeout)),
43 armed_(false), 43 armed_(false),
44 task_observer_(this), 44 task_observer_(this),
45 #if defined(OS_WIN)
46 watched_thread_handle_(0),
47 arm_cpu_time_(),
48 #endif
45 suspended_(false), 49 suspended_(false),
46 #if defined(USE_X11) 50 #if defined(USE_X11)
47 display_(NULL), 51 display_(NULL),
48 window_(0), 52 window_(0),
49 atom_(None), 53 atom_(None),
50 #endif 54 #endif
51 weak_factory_(this) { 55 weak_factory_(this) {
52 DCHECK(timeout >= 0); 56 DCHECK(timeout >= 0);
53 57
58 #if defined(OS_WIN)
59 // GetCurrentThread returns a pseudo-handle that cannot be used by one thread
60 // to identify another. DuplicateHandle creates a "real" handle that can be
61 // used for this purpose.
62 BOOL result = DuplicateHandle(GetCurrentProcess(),
63 GetCurrentThread(),
64 GetCurrentProcess(),
65 &watched_thread_handle_,
66 THREAD_QUERY_INFORMATION,
67 FALSE,
68 0);
69 DCHECK(result);
70 #endif
71
54 #if defined(OS_CHROMEOS) 72 #if defined(OS_CHROMEOS)
55 tty_file_ = base::OpenFile(base::FilePath(kTtyFilePath), "r"); 73 tty_file_ = base::OpenFile(base::FilePath(kTtyFilePath), "r");
56 #endif 74 #endif
57 #if defined(USE_X11) 75 #if defined(USE_X11)
58 SetupXServer(); 76 SetupXServer();
59 #endif 77 #endif
60 watched_message_loop_->AddTaskObserver(&task_observer_); 78 watched_message_loop_->AddTaskObserver(&task_observer_);
61 } 79 }
62 80
63 void GpuWatchdogThread::PostAcknowledge() { 81 void GpuWatchdogThread::PostAcknowledge() {
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
99 117
100 void GpuWatchdogThread::GpuWatchdogTaskObserver::DidProcessTask( 118 void GpuWatchdogThread::GpuWatchdogTaskObserver::DidProcessTask(
101 const base::PendingTask& pending_task) { 119 const base::PendingTask& pending_task) {
102 } 120 }
103 121
104 GpuWatchdogThread::~GpuWatchdogThread() { 122 GpuWatchdogThread::~GpuWatchdogThread() {
105 // Verify that the thread was explicitly stopped. If the thread is stopped 123 // Verify that the thread was explicitly stopped. If the thread is stopped
106 // implicitly by the destructor, CleanUp() will not be called. 124 // implicitly by the destructor, CleanUp() will not be called.
107 DCHECK(!weak_factory_.HasWeakPtrs()); 125 DCHECK(!weak_factory_.HasWeakPtrs());
108 126
127 #if defined(OS_WIN)
128 CloseHandle(watched_thread_handle_);
129 #endif
130
109 base::PowerMonitor* power_monitor = base::PowerMonitor::Get(); 131 base::PowerMonitor* power_monitor = base::PowerMonitor::Get();
110 if (power_monitor) 132 if (power_monitor)
111 power_monitor->RemoveObserver(this); 133 power_monitor->RemoveObserver(this);
112 134
113 #if defined(OS_CHROMEOS) 135 #if defined(OS_CHROMEOS)
114 if (tty_file_) 136 if (tty_file_)
115 fclose(tty_file_); 137 fclose(tty_file_);
116 #endif 138 #endif
117 139
118 #if defined(USE_X11) 140 #if defined(USE_X11)
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
157 // Do not create any new termination tasks if one has already been created 179 // Do not create any new termination tasks if one has already been created
158 // or the system is suspended. 180 // or the system is suspended.
159 if (armed_ || suspended_) 181 if (armed_ || suspended_)
160 return; 182 return;
161 183
162 // Must set armed before posting the task. This task might be the only task 184 // Must set armed before posting the task. This task might be the only task
163 // that will activate the TaskObserver on the watched thread and it must not 185 // that will activate the TaskObserver on the watched thread and it must not
164 // miss the false -> true transition. 186 // miss the false -> true transition.
165 armed_ = true; 187 armed_ = true;
166 188
189 #if defined(OS_WIN)
190 arm_cpu_time_ = GetWatchedThreadTime();
191 #endif
192
167 // Immediately after the computer is woken up from being suspended it might 193 // Immediately after the computer is woken up from being suspended it might
168 // be pretty sluggish, so allow some extra time before the next timeout. 194 // be pretty sluggish, so allow some extra time before the next timeout.
169 base::TimeDelta timeout = timeout_ * (after_suspend ? 3 : 1); 195 base::TimeDelta timeout = timeout_ * (after_suspend ? 3 : 1);
170 suspension_timeout_ = base::Time::Now() + timeout * 2; 196 suspension_timeout_ = base::Time::Now() + timeout * 2;
171 197
172 // Post a task to the monitored thread that does nothing but wake up the 198 // Post a task to the monitored thread that does nothing but wake up the
173 // TaskObserver. Any other tasks that are pending on the watched thread will 199 // TaskObserver. Any other tasks that are pending on the watched thread will
174 // also wake up the observer. This simply ensures there is at least one. 200 // also wake up the observer. This simply ensures there is at least one.
175 watched_message_loop_->task_runner()->PostTask(FROM_HERE, 201 watched_message_loop_->task_runner()->PostTask(FROM_HERE,
176 base::Bind(&base::DoNothing)); 202 base::Bind(&base::DoNothing));
177 203
178 // Post a task to the watchdog thread to exit if the monitored thread does 204 // Post a task to the watchdog thread to exit if the monitored thread does
179 // not respond in time. 205 // not respond in time.
180 task_runner()->PostDelayedTask( 206 task_runner()->PostDelayedTask(
181 FROM_HERE, 207 FROM_HERE,
182 base::Bind(&GpuWatchdogThread::DeliberatelyTerminateToRecoverFromHang, 208 base::Bind(&GpuWatchdogThread::DeliberatelyTerminateToRecoverFromHang,
183 weak_factory_.GetWeakPtr()), 209 weak_factory_.GetWeakPtr()),
184 timeout); 210 timeout);
185 } 211 }
186 212
187 // Use the --disable-gpu-watchdog command line switch to disable this. 213 // Use the --disable-gpu-watchdog command line switch to disable this.
188 void GpuWatchdogThread::DeliberatelyTerminateToRecoverFromHang() { 214 void GpuWatchdogThread::DeliberatelyTerminateToRecoverFromHang() {
189 // Should not get here while the system is suspended. 215 // Should not get here while the system is suspended.
190 DCHECK(!suspended_); 216 DCHECK(!suspended_);
191 217
218 #if defined(OS_WIN)
219 // Defer termination until a certain amount of CPU time has elapsed on the
220 // watched thread.
221 base::TimeDelta time_since_arm = GetWatchedThreadTime() - arm_cpu_time_;
222 if (time_since_arm < timeout_) {
223 message_loop()->PostDelayedTask(
224 FROM_HERE,
225 base::Bind(
226 &GpuWatchdogThread::DeliberatelyTerminateToRecoverFromHang,
227 weak_factory_.GetWeakPtr()),
228 timeout_ - time_since_arm);
229 return;
230 }
231 #endif
232
192 // If the watchdog woke up significantly behind schedule, disarm and reset 233 // If the watchdog woke up significantly behind schedule, disarm and reset
193 // the watchdog check. This is to prevent the watchdog thread from terminating 234 // the watchdog check. This is to prevent the watchdog thread from terminating
194 // when a machine wakes up from sleep or hibernation, which would otherwise 235 // when a machine wakes up from sleep or hibernation, which would otherwise
195 // appear to be a hang. 236 // appear to be a hang.
196 if (base::Time::Now() > suspension_timeout_) { 237 if (base::Time::Now() > suspension_timeout_) {
197 armed_ = false; 238 armed_ = false;
198 OnCheck(true); 239 OnCheck(true);
199 return; 240 return;
200 } 241 }
201 242
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
322 } 363 }
323 364
324 void GpuWatchdogThread::OnResume() { 365 void GpuWatchdogThread::OnResume() {
325 suspended_ = false; 366 suspended_ = false;
326 367
327 // After resuming jump-start the watchdog again. 368 // After resuming jump-start the watchdog again.
328 armed_ = false; 369 armed_ = false;
329 OnCheck(true); 370 OnCheck(true);
330 } 371 }
331 372
373 #if defined(OS_WIN)
374 base::TimeDelta GpuWatchdogThread::GetWatchedThreadTime() {
375 FILETIME creation_time;
376 FILETIME exit_time;
377 FILETIME user_time;
378 FILETIME kernel_time;
379 BOOL result = GetThreadTimes(watched_thread_handle_,
380 &creation_time,
381 &exit_time,
382 &kernel_time,
383 &user_time);
384 DCHECK(result);
385
386 ULARGE_INTEGER user_time64;
387 user_time64.HighPart = user_time.dwHighDateTime;
388 user_time64.LowPart = user_time.dwLowDateTime;
389
390 ULARGE_INTEGER kernel_time64;
391 kernel_time64.HighPart = kernel_time.dwHighDateTime;
392 kernel_time64.LowPart = kernel_time.dwLowDateTime;
393
394 // Time is reported in units of 100 nanoseconds. Kernel and user time are
395 // summed to deal with to kinds of hangs. One is where the GPU process is
396 // stuck in user level, never calling into the kernel and kernel time is
397 // not increasing. The other is where either the kernel hangs and never
398 // returns to user level or where user level code
399 // calls into kernel level repeatedly, giving up its quanta before it is
400 // tracked, for example a loop that repeatedly Sleeps.
401 return base::TimeDelta::FromMilliseconds(static_cast<int64_t>(
402 (user_time64.QuadPart + kernel_time64.QuadPart) / 10000));
403 }
404 #endif
405
332 } // namespace content 406 } // 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