Index: chrome/gpu/gpu_watchdog_thread.cc |
=================================================================== |
--- chrome/gpu/gpu_watchdog_thread.cc (revision 67048) |
+++ chrome/gpu/gpu_watchdog_thread.cc (working copy) |
@@ -13,23 +13,40 @@ |
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() { |
// The method factory must be created on the watchdog thread. |
method_factory_.reset(new MethodFactory(this)); |
@@ -47,9 +64,46 @@ |
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::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::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. |