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

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

Issue 1980263002: GPU Watchdog to check I/O before terminating GPU process (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 6 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
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"
11 #include "base/bind_helpers.h" 11 #include "base/bind_helpers.h"
12 #include "base/command_line.h" 12 #include "base/command_line.h"
13 #include "base/compiler_specific.h" 13 #include "base/compiler_specific.h"
14 #include "base/debug/alias.h" 14 #include "base/debug/alias.h"
15 #include "base/files/file_path.h"
15 #include "base/files/file_util.h" 16 #include "base/files/file_util.h"
16 #include "base/location.h" 17 #include "base/location.h"
17 #include "base/macros.h" 18 #include "base/macros.h"
18 #include "base/power_monitor/power_monitor.h" 19 #include "base/power_monitor/power_monitor.h"
19 #include "base/process/process.h" 20 #include "base/process/process.h"
20 #include "base/single_thread_task_runner.h" 21 #include "base/single_thread_task_runner.h"
21 #include "base/threading/platform_thread.h" 22 #include "base/threading/platform_thread.h"
23 #include "base/timer/elapsed_timer.h"
22 #include "build/build_config.h" 24 #include "build/build_config.h"
25 #include "content/common/gpu_watchdog_utils.h"
23 #include "content/public/common/content_switches.h" 26 #include "content/public/common/content_switches.h"
24 #include "content/public/common/result_codes.h" 27 #include "content/public/common/result_codes.h"
25 28
26 #if defined(OS_WIN) 29 #if defined(OS_WIN)
27 #include <windows.h> 30 #include <windows.h>
28 #endif 31 #endif
29 32
30 namespace content { 33 namespace content {
31 namespace { 34 namespace {
32 #if defined(USE_X11) 35 #if defined(USE_X11)
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
70 FALSE, 73 FALSE,
71 0); 74 0);
72 DCHECK(result); 75 DCHECK(result);
73 #endif 76 #endif
74 77
75 #if defined(USE_X11) 78 #if defined(USE_X11)
76 tty_file_ = base::OpenFile(base::FilePath(kTtyFilePath), "r"); 79 tty_file_ = base::OpenFile(base::FilePath(kTtyFilePath), "r");
77 SetupXServer(); 80 SetupXServer();
78 #endif 81 #endif
79 watched_message_loop_->AddTaskObserver(&task_observer_); 82 watched_message_loop_->AddTaskObserver(&task_observer_);
83
84 #if defined(OS_WIN)
85 // Create a temp file for checking whether I/O is a bottleneck.
86 // This code runs on the main GPU thread before the sandbox is lowered.
87 base::FilePath temp_file_path;
88 if (GetGpuWatchdogTempFile(&temp_file_path)) {
89 // Please note that multiple instances of GPU process may reuse the same
90 // temporary file. That's OK because the file is written to only when
91 // the watchdog gets triggered and about to crash the process. The file
92 // should be deleted when the last handle is closed.
93 temp_file_for_io_checking_.Initialize(
94 temp_file_path, base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_WRITE |
95 base::File::FLAG_DELETE_ON_CLOSE |
96 base::File::FLAG_SHARE_DELETE);
ncarter (slow) 2016/06/09 16:14:43 I imagine that running browsertests in parallel wi
stanisc 2016/06/09 20:52:28 I've tested contention on this file by running two
97 if (!temp_file_for_io_checking_.IsValid()) {
98 LOG(ERROR) << "Couldn't create " << temp_file_path.value().c_str()
99 << ", error: " << temp_file_for_io_checking_.error_details();
100 }
101 }
102 #endif
80 } 103 }
81 104
82 void GpuWatchdogThread::PostAcknowledge() { 105 void GpuWatchdogThread::PostAcknowledge() {
83 // Called on the monitored thread. Responds with OnAcknowledge. Cannot use 106 // Called on the monitored thread. Responds with OnAcknowledge. Cannot use
84 // the method factory. Rely on reference counting instead. 107 // the method factory. Rely on reference counting instead.
85 task_runner()->PostTask(FROM_HERE, 108 task_runner()->PostTask(FROM_HERE,
86 base::Bind(&GpuWatchdogThread::OnAcknowledge, this)); 109 base::Bind(&GpuWatchdogThread::OnAcknowledge, this));
87 } 110 }
88 111
89 void GpuWatchdogThread::CheckArmed() { 112 void GpuWatchdogThread::CheckArmed() {
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
217 240
218 // Post a task to the monitored thread that does nothing but wake up the 241 // Post a task to the monitored thread that does nothing but wake up the
219 // TaskObserver. Any other tasks that are pending on the watched thread will 242 // TaskObserver. Any other tasks that are pending on the watched thread will
220 // also wake up the observer. This simply ensures there is at least one. 243 // also wake up the observer. This simply ensures there is at least one.
221 watched_message_loop_->task_runner()->PostTask(FROM_HERE, 244 watched_message_loop_->task_runner()->PostTask(FROM_HERE,
222 base::Bind(&base::DoNothing)); 245 base::Bind(&base::DoNothing));
223 246
224 // Post a task to the watchdog thread to exit if the monitored thread does 247 // Post a task to the watchdog thread to exit if the monitored thread does
225 // not respond in time. 248 // not respond in time.
226 task_runner()->PostDelayedTask( 249 task_runner()->PostDelayedTask(
227 FROM_HERE, 250 FROM_HERE, base::Bind(&GpuWatchdogThread::BeginTerminating,
228 base::Bind(&GpuWatchdogThread::DeliberatelyTerminateToRecoverFromHang, 251 weak_factory_.GetWeakPtr()),
229 weak_factory_.GetWeakPtr()),
230 timeout); 252 timeout);
231 } 253 }
232 254
233 // Use the --disable-gpu-watchdog command line switch to disable this. 255 void GpuWatchdogThread::BeginTerminating() {
234 void GpuWatchdogThread::DeliberatelyTerminateToRecoverFromHang() {
235 // Should not get here while the system is suspended. 256 // Should not get here while the system is suspended.
236 DCHECK(!suspended_); 257 DCHECK(!suspended_);
237 258
238 #if defined(OS_WIN) 259 #if defined(OS_WIN)
239 // Defer termination until a certain amount of CPU time has elapsed on the 260 // Defer termination until a certain amount of CPU time has elapsed on the
240 // watched thread. 261 // watched thread.
241 base::ThreadTicks current_cpu_time = GetWatchedThreadTime(); 262 base::ThreadTicks current_cpu_time = GetWatchedThreadTime();
242 base::TimeDelta time_since_arm = current_cpu_time - arm_cpu_time_; 263 base::TimeDelta time_since_arm = current_cpu_time - arm_cpu_time_;
243 if (use_thread_cpu_time_ && (time_since_arm < timeout_)) { 264 if (use_thread_cpu_time_ && (time_since_arm < timeout_)) {
244 message_loop()->PostDelayedTask( 265 message_loop()->PostDelayedTask(
245 FROM_HERE, 266 FROM_HERE, base::Bind(&GpuWatchdogThread::BeginTerminating,
246 base::Bind( 267 weak_factory_.GetWeakPtr()),
247 &GpuWatchdogThread::DeliberatelyTerminateToRecoverFromHang,
248 weak_factory_.GetWeakPtr()),
249 timeout_ - time_since_arm); 268 timeout_ - time_since_arm);
250 return; 269 return;
251 } 270 }
271
272 // If the machine is busy with heavy I/O activity this should defer
273 // termination until the I/O queue clears (on the drive that contains
274 // the temp directory).
275 if (temp_file_for_io_checking_.IsValid()) {
276 // Write a few bytes and wait for the write to flush.
277 const char temp_data[32] = {0};
brucedawson 2016/06/09 01:01:13 VC++ still generates sub-optimal code for = {0}. Y
stanisc 2016/06/09 20:52:28 Done.
278 base::ElapsedTimer timer;
279 temp_file_for_io_checking_.Write(0, temp_data, sizeof(temp_data));
280 temp_file_for_io_checking_.Flush();
281 io_check_duration_ = timer.Elapsed();
ncarter (slow) 2016/06/09 16:14:43 Did you intend to use this for anything?
brucedawson 2016/06/09 17:29:05 The io_check_duration_ member will end up in the c
manzagop (departed) 2016/06/09 19:41:54 Drive-by question! Is memory pulled in around regi
ncarter (slow) 2016/06/09 20:11:20 The memory around |*this|, for all stack frames, a
stanisc 2016/06/09 20:52:28 I've added a comment suggested by Bruce. Using cr
282 }
252 #endif 283 #endif
253 284
285 // Post a new task to actually terminate unless an acknowledge from the
286 // watched thread arrives in between.
287 message_loop()->PostTask(
288 FROM_HERE,
289 base::Bind(&GpuWatchdogThread::DeliberatelyTerminateToRecoverFromHang,
290 weak_factory_.GetWeakPtr()));
291 }
292
293 // Use the --disable-gpu-watchdog command line switch to disable this.
294 void GpuWatchdogThread::DeliberatelyTerminateToRecoverFromHang() {
295 // Should not get here while the system is suspended.
296 DCHECK(!suspended_);
297
254 // If the watchdog woke up significantly behind schedule, disarm and reset 298 // If the watchdog woke up significantly behind schedule, disarm and reset
255 // the watchdog check. This is to prevent the watchdog thread from terminating 299 // the watchdog check. This is to prevent the watchdog thread from terminating
256 // when a machine wakes up from sleep or hibernation, which would otherwise 300 // when a machine wakes up from sleep or hibernation, which would otherwise
257 // appear to be a hang. 301 // appear to be a hang.
258 if (base::Time::Now() > suspension_timeout_) { 302 if (base::Time::Now() > suspension_timeout_) {
259 armed_ = false; 303 armed_ = false;
260 OnCheck(true); 304 OnCheck(true);
261 return; 305 return;
262 } 306 }
263 307
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
329 373
330 // Store variables so they're available in crash dumps to help determine the 374 // Store variables so they're available in crash dumps to help determine the
331 // cause of any hang. 375 // cause of any hang.
332 #if defined(OS_WIN) 376 #if defined(OS_WIN)
333 ULONGLONG fire_interrupt_time; 377 ULONGLONG fire_interrupt_time;
334 QueryUnbiasedInterruptTime(&fire_interrupt_time); 378 QueryUnbiasedInterruptTime(&fire_interrupt_time);
335 379
336 // This is the time since the watchdog was armed, in 100ns intervals, 380 // This is the time since the watchdog was armed, in 100ns intervals,
337 // ignoring time where the computer is suspended. 381 // ignoring time where the computer is suspended.
338 ULONGLONG interrupt_delay = fire_interrupt_time - arm_interrupt_time_; 382 ULONGLONG interrupt_delay = fire_interrupt_time - arm_interrupt_time_;
383 base::debug::Alias(&interrupt_delay);
339 384
340 base::debug::Alias(&interrupt_delay); 385 base::ThreadTicks current_cpu_time = GetWatchedThreadTime();
341 base::debug::Alias(&current_cpu_time); 386 base::debug::Alias(&current_cpu_time);
387
388 base::TimeDelta time_since_arm = current_cpu_time - arm_cpu_time_;
342 base::debug::Alias(&time_since_arm); 389 base::debug::Alias(&time_since_arm);
343 390
344 bool using_thread_ticks = base::ThreadTicks::IsSupported(); 391 bool using_thread_ticks = base::ThreadTicks::IsSupported();
345 base::debug::Alias(&using_thread_ticks); 392 base::debug::Alias(&using_thread_ticks);
346 393
347 bool using_high_res_timer = base::Time::IsHighResolutionTimerInUse(); 394 bool using_high_res_timer = base::Time::IsHighResolutionTimerInUse();
348 base::debug::Alias(&using_high_res_timer); 395 base::debug::Alias(&using_high_res_timer);
349 #endif 396 #endif
350 397
351 base::Time current_time = base::Time::Now(); 398 base::Time current_time = base::Time::Now();
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
460 int tty_number; 507 int tty_number;
461 size_t num_res = sscanf(tty_string, "tty%d\n", &tty_number); 508 size_t num_res = sscanf(tty_string, "tty%d\n", &tty_number);
462 if (num_res == 1) 509 if (num_res == 1)
463 return tty_number; 510 return tty_number;
464 } 511 }
465 return -1; 512 return -1;
466 } 513 }
467 #endif 514 #endif
468 515
469 } // namespace content 516 } // namespace content
OLDNEW
« content/common/gpu_watchdog_utils.cc ('K') | « content/gpu/gpu_watchdog_thread.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698