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

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

Issue 1711763005: 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
49 suspended_(false), 45 suspended_(false),
50 #if defined(USE_X11) 46 #if defined(USE_X11)
51 display_(NULL), 47 display_(NULL),
52 window_(0), 48 window_(0),
53 atom_(None), 49 atom_(None),
54 #endif 50 #endif
55 weak_factory_(this) { 51 weak_factory_(this) {
56 DCHECK(timeout >= 0); 52 DCHECK(timeout >= 0);
57 53
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
72 #if defined(OS_CHROMEOS) 54 #if defined(OS_CHROMEOS)
73 tty_file_ = base::OpenFile(base::FilePath(kTtyFilePath), "r"); 55 tty_file_ = base::OpenFile(base::FilePath(kTtyFilePath), "r");
74 #endif 56 #endif
75 #if defined(USE_X11) 57 #if defined(USE_X11)
76 SetupXServer(); 58 SetupXServer();
77 #endif 59 #endif
78 watched_message_loop_->AddTaskObserver(&task_observer_); 60 watched_message_loop_->AddTaskObserver(&task_observer_);
79 } 61 }
80 62
81 void GpuWatchdogThread::PostAcknowledge() { 63 void GpuWatchdogThread::PostAcknowledge() {
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
117 99
118 void GpuWatchdogThread::GpuWatchdogTaskObserver::DidProcessTask( 100 void GpuWatchdogThread::GpuWatchdogTaskObserver::DidProcessTask(
119 const base::PendingTask& pending_task) { 101 const base::PendingTask& pending_task) {
120 } 102 }
121 103
122 GpuWatchdogThread::~GpuWatchdogThread() { 104 GpuWatchdogThread::~GpuWatchdogThread() {
123 // Verify that the thread was explicitly stopped. If the thread is stopped 105 // Verify that the thread was explicitly stopped. If the thread is stopped
124 // implicitly by the destructor, CleanUp() will not be called. 106 // implicitly by the destructor, CleanUp() will not be called.
125 DCHECK(!weak_factory_.HasWeakPtrs()); 107 DCHECK(!weak_factory_.HasWeakPtrs());
126 108
127 #if defined(OS_WIN)
128 CloseHandle(watched_thread_handle_);
129 #endif
130
131 base::PowerMonitor* power_monitor = base::PowerMonitor::Get(); 109 base::PowerMonitor* power_monitor = base::PowerMonitor::Get();
132 if (power_monitor) 110 if (power_monitor)
133 power_monitor->RemoveObserver(this); 111 power_monitor->RemoveObserver(this);
134 112
135 #if defined(OS_CHROMEOS) 113 #if defined(OS_CHROMEOS)
136 if (tty_file_) 114 if (tty_file_)
137 fclose(tty_file_); 115 fclose(tty_file_);
138 #endif 116 #endif
139 117
140 #if defined(USE_X11) 118 #if defined(USE_X11)
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
179 // Do not create any new termination tasks if one has already been created 157 // Do not create any new termination tasks if one has already been created
180 // or the system is suspended. 158 // or the system is suspended.
181 if (armed_ || suspended_) 159 if (armed_ || suspended_)
182 return; 160 return;
183 161
184 // Must set armed before posting the task. This task might be the only task 162 // Must set armed before posting the task. This task might be the only task
185 // that will activate the TaskObserver on the watched thread and it must not 163 // that will activate the TaskObserver on the watched thread and it must not
186 // miss the false -> true transition. 164 // miss the false -> true transition.
187 armed_ = true; 165 armed_ = true;
188 166
189 #if defined(OS_WIN)
190 arm_cpu_time_ = GetWatchedThreadTime();
191 #endif
192
193 // Immediately after the computer is woken up from being suspended it might 167 // Immediately after the computer is woken up from being suspended it might
194 // be pretty sluggish, so allow some extra time before the next timeout. 168 // be pretty sluggish, so allow some extra time before the next timeout.
195 base::TimeDelta timeout = timeout_ * (after_suspend ? 3 : 1); 169 base::TimeDelta timeout = timeout_ * (after_suspend ? 3 : 1);
196 suspension_timeout_ = base::Time::Now() + timeout * 2; 170 suspension_timeout_ = base::Time::Now() + timeout * 2;
197 171
198 // Post a task to the monitored thread that does nothing but wake up the 172 // Post a task to the monitored thread that does nothing but wake up the
199 // TaskObserver. Any other tasks that are pending on the watched thread will 173 // TaskObserver. Any other tasks that are pending on the watched thread will
200 // also wake up the observer. This simply ensures there is at least one. 174 // also wake up the observer. This simply ensures there is at least one.
201 watched_message_loop_->task_runner()->PostTask(FROM_HERE, 175 watched_message_loop_->task_runner()->PostTask(FROM_HERE,
202 base::Bind(&base::DoNothing)); 176 base::Bind(&base::DoNothing));
203 177
204 // Post a task to the watchdog thread to exit if the monitored thread does 178 // Post a task to the watchdog thread to exit if the monitored thread does
205 // not respond in time. 179 // not respond in time.
206 task_runner()->PostDelayedTask( 180 task_runner()->PostDelayedTask(
207 FROM_HERE, 181 FROM_HERE,
208 base::Bind(&GpuWatchdogThread::DeliberatelyTerminateToRecoverFromHang, 182 base::Bind(&GpuWatchdogThread::DeliberatelyTerminateToRecoverFromHang,
209 weak_factory_.GetWeakPtr()), 183 weak_factory_.GetWeakPtr()),
210 timeout); 184 timeout);
211 } 185 }
212 186
213 // Use the --disable-gpu-watchdog command line switch to disable this. 187 // Use the --disable-gpu-watchdog command line switch to disable this.
214 void GpuWatchdogThread::DeliberatelyTerminateToRecoverFromHang() { 188 void GpuWatchdogThread::DeliberatelyTerminateToRecoverFromHang() {
215 // Should not get here while the system is suspended. 189 // Should not get here while the system is suspended.
216 DCHECK(!suspended_); 190 DCHECK(!suspended_);
217 191
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
233 // If the watchdog woke up significantly behind schedule, disarm and reset 192 // If the watchdog woke up significantly behind schedule, disarm and reset
234 // the watchdog check. This is to prevent the watchdog thread from terminating 193 // the watchdog check. This is to prevent the watchdog thread from terminating
235 // when a machine wakes up from sleep or hibernation, which would otherwise 194 // when a machine wakes up from sleep or hibernation, which would otherwise
236 // appear to be a hang. 195 // appear to be a hang.
237 if (base::Time::Now() > suspension_timeout_) { 196 if (base::Time::Now() > suspension_timeout_) {
238 armed_ = false; 197 armed_ = false;
239 OnCheck(true); 198 OnCheck(true);
240 return; 199 return;
241 } 200 }
242 201
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
363 } 322 }
364 323
365 void GpuWatchdogThread::OnResume() { 324 void GpuWatchdogThread::OnResume() {
366 suspended_ = false; 325 suspended_ = false;
367 326
368 // After resuming jump-start the watchdog again. 327 // After resuming jump-start the watchdog again.
369 armed_ = false; 328 armed_ = false;
370 OnCheck(true); 329 OnCheck(true);
371 } 330 }
372 331
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
406 } // namespace content 332 } // 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