| 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.
|
|
|