OLD | NEW |
---|---|
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_util.h" | 15 #include "base/files/file_util.h" |
16 #include "base/location.h" | 16 #include "base/location.h" |
17 #include "base/macros.h" | 17 #include "base/macros.h" |
18 #include "base/power_monitor/power_monitor.h" | 18 #include "base/power_monitor/power_monitor.h" |
19 #include "base/process/process.h" | 19 #include "base/process/process.h" |
20 #include "base/single_thread_task_runner.h" | 20 #include "base/single_thread_task_runner.h" |
21 #include "base/threading/platform_thread.h" | |
21 #include "build/build_config.h" | 22 #include "build/build_config.h" |
22 #include "content/public/common/content_switches.h" | 23 #include "content/public/common/content_switches.h" |
23 #include "content/public/common/result_codes.h" | 24 #include "content/public/common/result_codes.h" |
24 | 25 |
25 #if defined(OS_WIN) | 26 #if defined(OS_WIN) |
26 #include <windows.h> | 27 #include <windows.h> |
27 #endif | 28 #endif |
28 | 29 |
29 namespace content { | 30 namespace content { |
30 namespace { | 31 namespace { |
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
236 } | 237 } |
237 | 238 |
238 // Use the --disable-gpu-watchdog command line switch to disable this. | 239 // Use the --disable-gpu-watchdog command line switch to disable this. |
239 void GpuWatchdogThread::DeliberatelyTerminateToRecoverFromHang() { | 240 void GpuWatchdogThread::DeliberatelyTerminateToRecoverFromHang() { |
240 // Should not get here while the system is suspended. | 241 // Should not get here while the system is suspended. |
241 DCHECK(!suspended_); | 242 DCHECK(!suspended_); |
242 | 243 |
243 #if defined(OS_WIN) | 244 #if defined(OS_WIN) |
244 // Defer termination until a certain amount of CPU time has elapsed on the | 245 // Defer termination until a certain amount of CPU time has elapsed on the |
245 // watched thread. | 246 // watched thread. |
246 base::TimeDelta time_since_arm = GetWatchedThreadTime() - arm_cpu_time_; | 247 base::TimeDelta time_since_arm = GetWatchedThreadTime() - arm_cpu_time_; |
fdoray
2016/04/21 21:08:38
ThreadTicks::Now() returns a null ThreadTicks befo
stanisc
2016/04/22 01:11:45
I think it should be fine for GetWatchedThreadTime
| |
247 if (use_thread_cpu_time_ && (time_since_arm < timeout_)) { | 248 if (use_thread_cpu_time_ && (time_since_arm < timeout_)) { |
248 message_loop()->PostDelayedTask( | 249 message_loop()->PostDelayedTask( |
249 FROM_HERE, | 250 FROM_HERE, |
250 base::Bind( | 251 base::Bind( |
251 &GpuWatchdogThread::DeliberatelyTerminateToRecoverFromHang, | 252 &GpuWatchdogThread::DeliberatelyTerminateToRecoverFromHang, |
252 weak_factory_.GetWeakPtr()), | 253 weak_factory_.GetWeakPtr()), |
253 timeout_ - time_since_arm); | 254 timeout_ - time_since_arm); |
254 return; | 255 return; |
255 } | 256 } |
256 #endif | 257 #endif |
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
414 suspended_ = false; | 415 suspended_ = false; |
415 resume_time_ = base::Time::Now(); | 416 resume_time_ = base::Time::Now(); |
416 | 417 |
417 // After resuming jump-start the watchdog again. | 418 // After resuming jump-start the watchdog again. |
418 armed_ = false; | 419 armed_ = false; |
419 OnCheck(true); | 420 OnCheck(true); |
420 } | 421 } |
421 | 422 |
422 #if defined(OS_WIN) | 423 #if defined(OS_WIN) |
423 base::TimeDelta GpuWatchdogThread::GetWatchedThreadTime() { | 424 base::TimeDelta GpuWatchdogThread::GetWatchedThreadTime() { |
424 FILETIME creation_time; | 425 if (base::ThreadTicks::IsSupported()) { |
425 FILETIME exit_time; | 426 // Convert ThreadTicks::Now() to TimeDelta. |
426 FILETIME user_time; | 427 return base::ThreadTicks::Now( |
427 FILETIME kernel_time; | 428 base::PlatformThreadHandle(watched_thread_handle_)) - |
428 BOOL result = GetThreadTimes(watched_thread_handle_, | 429 base::ThreadTicks(); |
fdoray
2016/04/21 21:08:37
Ideally, you would store a ThreadTicks and compute
stanisc
2016/04/22 01:11:45
Yes, it seems like a good idea for this method to
| |
429 &creation_time, | |
430 &exit_time, | |
431 &kernel_time, | |
432 &user_time); | |
433 DCHECK(result); | |
434 | 430 |
435 ULARGE_INTEGER user_time64; | 431 } else { |
436 user_time64.HighPart = user_time.dwHighDateTime; | 432 // Use GetThreadTimes as a backup mechanism. |
437 user_time64.LowPart = user_time.dwLowDateTime; | 433 FILETIME creation_time; |
434 FILETIME exit_time; | |
435 FILETIME user_time; | |
436 FILETIME kernel_time; | |
437 BOOL result = GetThreadTimes(watched_thread_handle_, &creation_time, | |
438 &exit_time, &kernel_time, &user_time); | |
439 DCHECK(result); | |
438 | 440 |
439 ULARGE_INTEGER kernel_time64; | 441 ULARGE_INTEGER user_time64; |
440 kernel_time64.HighPart = kernel_time.dwHighDateTime; | 442 user_time64.HighPart = user_time.dwHighDateTime; |
441 kernel_time64.LowPart = kernel_time.dwLowDateTime; | 443 user_time64.LowPart = user_time.dwLowDateTime; |
442 | 444 |
443 // Time is reported in units of 100 nanoseconds. Kernel and user time are | 445 ULARGE_INTEGER kernel_time64; |
444 // summed to deal with to kinds of hangs. One is where the GPU process is | 446 kernel_time64.HighPart = kernel_time.dwHighDateTime; |
445 // stuck in user level, never calling into the kernel and kernel time is | 447 kernel_time64.LowPart = kernel_time.dwLowDateTime; |
446 // not increasing. The other is where either the kernel hangs and never | 448 |
447 // returns to user level or where user level code | 449 // Time is reported in units of 100 nanoseconds. Kernel and user time are |
448 // calls into kernel level repeatedly, giving up its quanta before it is | 450 // summed to deal with to kinds of hangs. One is where the GPU process is |
449 // tracked, for example a loop that repeatedly Sleeps. | 451 // stuck in user level, never calling into the kernel and kernel time is |
450 return base::TimeDelta::FromMilliseconds(static_cast<int64_t>( | 452 // not increasing. The other is where either the kernel hangs and never |
451 (user_time64.QuadPart + kernel_time64.QuadPart) / 10000)); | 453 // returns to user level or where user level code |
454 // calls into kernel level repeatedly, giving up its quanta before it is | |
455 // tracked, for example a loop that repeatedly Sleeps. | |
456 return base::TimeDelta::FromMilliseconds(static_cast<int64_t>( | |
457 (user_time64.QuadPart + kernel_time64.QuadPart) / 10000)); | |
458 } | |
452 } | 459 } |
453 #endif | 460 #endif |
454 | 461 |
455 } // namespace content | 462 } // namespace content |
OLD | NEW |