summaryrefslogtreecommitdiffstats
path: root/chrome/gpu/gpu_watchdog_thread.cc
diff options
context:
space:
mode:
authorapatrick@chromium.org <apatrick@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-11-24 00:07:43 +0000
committerapatrick@chromium.org <apatrick@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-11-24 00:07:43 +0000
commit49eab48f99690ce17378ad65229b80496656993b (patch)
tree30babf6c295ddf58aea644782cd8d674a85fd493 /chrome/gpu/gpu_watchdog_thread.cc
parent96af6d4d2ea59c487a866ba6fc844c801f4c80f9 (diff)
downloadchromium_src-49eab48f99690ce17378ad65229b80496656993b.zip
chromium_src-49eab48f99690ce17378ad65229b80496656993b.tar.gz
chromium_src-49eab48f99690ce17378ad65229b80496656993b.tar.bz2
GPU thread acknowledges an armed watchdog every time it returns to the message loop.
It used to only acknowledge upon receiving a particular kind of Task from the watchdog, which could potentially be delayed by other Tasks. TEST=WebGL locally, check recovery from about:gpuhang locally, try BUG=none Review URL: http://codereview.chromium.org/5278006 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@67184 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/gpu/gpu_watchdog_thread.cc')
-rw-r--r--chrome/gpu/gpu_watchdog_thread.cc78
1 files changed, 65 insertions, 13 deletions
diff --git a/chrome/gpu/gpu_watchdog_thread.cc b/chrome/gpu/gpu_watchdog_thread.cc
index e262c79..36f7e6b 100644
--- a/chrome/gpu/gpu_watchdog_thread.cc
+++ b/chrome/gpu/gpu_watchdog_thread.cc
@@ -13,21 +13,38 @@
namespace {
const int64 kCheckPeriod = 2000;
+
+void DoNothing() {
+}
}
GpuWatchdogThread::GpuWatchdogThread(MessageLoop* watched_message_loop,
int timeout)
: base::Thread("Watchdog"),
watched_message_loop_(watched_message_loop),
- timeout_(timeout) {
+ timeout_(timeout),
+ armed_(false),
+ ALLOW_THIS_IN_INITIALIZER_LIST(task_observer_(this)) {
DCHECK(watched_message_loop);
DCHECK(timeout >= 0);
+
+ watched_message_loop_->AddTaskObserver(&task_observer_);
}
GpuWatchdogThread::~GpuWatchdogThread() {
// Verify that the thread was explicitly stopped. If the thread is stopped
// implicitly by the destructor, CleanUp() will not be called.
DCHECK(!method_factory_.get());
+
+ watched_message_loop_->RemoveTaskObserver(&task_observer_);
+}
+
+void GpuWatchdogThread::PostAcknowledge() {
+ // Called on the monitored thread. Responds with OnAcknowledge. Cannot use
+ // the method factory. Rely on reference counting instead.
+ message_loop()->PostTask(
+ FROM_HERE,
+ NewRunnableMethod(this, &GpuWatchdogThread::OnAcknowledge));
}
void GpuWatchdogThread::Init() {
@@ -47,9 +64,46 @@ void GpuWatchdogThread::CleanUp() {
watched_message_loop_ = NULL;
}
+GpuWatchdogThread::GpuWatchdogTaskObserver::GpuWatchdogTaskObserver(
+ GpuWatchdogThread* watchdog)
+ : watchdog_(watchdog) {
+}
+
+GpuWatchdogThread::GpuWatchdogTaskObserver::~GpuWatchdogTaskObserver() {
+}
+
+void GpuWatchdogThread::GpuWatchdogTaskObserver::WillProcessTask(
+ const Task* task)
+{
+ CheckArmed();
+}
+
+void GpuWatchdogThread::GpuWatchdogTaskObserver::DidProcessTask(
+ const Task* task)
+{
+ CheckArmed();
+}
+
+void GpuWatchdogThread::GpuWatchdogTaskObserver::CheckArmed()
+{
+ // Acknowledge the watchdog if it has armed itself. The watchdog will not
+ // change its armed state until it is acknowledged.
+ if (watchdog_->armed()) {
+ watchdog_->PostAcknowledge();
+ }
+}
+
void GpuWatchdogThread::OnAcknowledge() {
+ // The check has already been acknowledged and another has already been
+ // scheduled by a previous call to OnAcknowledge. It is normal for a
+ // watched thread to see armed_ being true multiple times before
+ // the OnAcknowledge task is run on the watchdog thread.
+ if (!armed_)
+ return;
+
// Revoke any pending OnExit.
method_factory_->RevokeAll();
+ armed_ = false;
// The monitored thread has responded. Post a task to check it again.
if (watched_message_loop_) {
@@ -62,13 +116,19 @@ void GpuWatchdogThread::OnAcknowledge() {
void GpuWatchdogThread::OnCheck() {
if (watched_message_loop_) {
- // Post a task to the monitored thread that simply responds with a task that
- // calls OnAcknowldge.
+ // Must set armed before posting the task. This task might be the only task
+ // that will activate the TaskObserver on the watched thread and it must not
+ // miss the false -> true transition.
+ armed_ = true;
+
+ // Post a task to the monitored thread that does nothing but wake up the
+ // TaskObserver. Any other tasks that are pending on the watched thread will
+ // also wake up the observer. This simply ensures there is at least one.
watched_message_loop_->PostTask(
FROM_HERE,
- NewRunnableMethod(this, &GpuWatchdogThread::PostAcknowledge));
+ NewRunnableFunction(DoNothing));
- // Post a task to the watchdog thread to exit if the nmonitored thread does
+ // Post a task to the watchdog thread to exit if the monitored thread does
// not respond in time.
message_loop()->PostDelayedTask(
FROM_HERE,
@@ -77,14 +137,6 @@ void GpuWatchdogThread::OnCheck() {
}
}
-void GpuWatchdogThread::PostAcknowledge() {
- // Called on the monitored thread. Responds with OnAcknowledge. Cannot use
- // the method factory. Rely on reference counting instead.
- message_loop()->PostTask(
- FROM_HERE,
- NewRunnableMethod(this, &GpuWatchdogThread::OnAcknowledge));
-}
-
// Use the --disable-gpu-watchdog command line switch to disable this.
void GpuWatchdogThread::OnExit() {
// Make sure the timeout period is on the stack before crashing.