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

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

Issue 5278006: GPU thread acknowledges an armed watchdog every time it returns to the messag... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 10 years, 1 month 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 | Annotate | Revision Log
« no previous file with comments | « chrome/gpu/gpu_watchdog_thread.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 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 #if defined(OS_WIN) 5 #if defined(OS_WIN)
6 #include <windows.h> 6 #include <windows.h>
7 #endif 7 #endif
8 8
9 #include "chrome/gpu/gpu_watchdog_thread.h" 9 #include "chrome/gpu/gpu_watchdog_thread.h"
10 10
11 #include "base/compiler_specific.h" 11 #include "base/compiler_specific.h"
12 #include "build/build_config.h" 12 #include "build/build_config.h"
13 13
14 namespace { 14 namespace {
15 const int64 kCheckPeriod = 2000; 15 const int64 kCheckPeriod = 2000;
16
17 void DoNothing() {
18 }
16 } 19 }
17 20
18 GpuWatchdogThread::GpuWatchdogThread(MessageLoop* watched_message_loop, 21 GpuWatchdogThread::GpuWatchdogThread(MessageLoop* watched_message_loop,
19 int timeout) 22 int timeout)
20 : base::Thread("Watchdog"), 23 : base::Thread("Watchdog"),
21 watched_message_loop_(watched_message_loop), 24 watched_message_loop_(watched_message_loop),
22 timeout_(timeout) { 25 timeout_(timeout),
26 armed_(false),
27 ALLOW_THIS_IN_INITIALIZER_LIST(task_observer_(this)) {
23 DCHECK(watched_message_loop); 28 DCHECK(watched_message_loop);
24 DCHECK(timeout >= 0); 29 DCHECK(timeout >= 0);
30
31 watched_message_loop_->AddTaskObserver(&task_observer_);
25 } 32 }
26 33
27 GpuWatchdogThread::~GpuWatchdogThread() { 34 GpuWatchdogThread::~GpuWatchdogThread() {
28 // Verify that the thread was explicitly stopped. If the thread is stopped 35 // Verify that the thread was explicitly stopped. If the thread is stopped
29 // implicitly by the destructor, CleanUp() will not be called. 36 // implicitly by the destructor, CleanUp() will not be called.
30 DCHECK(!method_factory_.get()); 37 DCHECK(!method_factory_.get());
38
39 watched_message_loop_->RemoveTaskObserver(&task_observer_);
40 }
41
42 void GpuWatchdogThread::PostAcknowledge() {
43 // Called on the monitored thread. Responds with OnAcknowledge. Cannot use
44 // the method factory. Rely on reference counting instead.
45 message_loop()->PostTask(
46 FROM_HERE,
47 NewRunnableMethod(this, &GpuWatchdogThread::OnAcknowledge));
31 } 48 }
32 49
33 void GpuWatchdogThread::Init() { 50 void GpuWatchdogThread::Init() {
34 // The method factory must be created on the watchdog thread. 51 // The method factory must be created on the watchdog thread.
35 method_factory_.reset(new MethodFactory(this)); 52 method_factory_.reset(new MethodFactory(this));
36 53
37 // Schedule the first check. 54 // Schedule the first check.
38 OnCheck(); 55 OnCheck();
39 } 56 }
40 57
41 void GpuWatchdogThread::CleanUp() { 58 void GpuWatchdogThread::CleanUp() {
42 // The method factory must be destroyed on the watchdog thread. 59 // The method factory must be destroyed on the watchdog thread.
43 method_factory_->RevokeAll(); 60 method_factory_->RevokeAll();
44 method_factory_.reset(); 61 method_factory_.reset();
45 62
46 // Prevent any more delayed tasks from being posted. 63 // Prevent any more delayed tasks from being posted.
47 watched_message_loop_ = NULL; 64 watched_message_loop_ = NULL;
48 } 65 }
49 66
67 GpuWatchdogThread::GpuWatchdogTaskObserver::GpuWatchdogTaskObserver(
68 GpuWatchdogThread* watchdog)
69 : watchdog_(watchdog) {
70 }
71
72 GpuWatchdogThread::GpuWatchdogTaskObserver::~GpuWatchdogTaskObserver() {
73 }
74
75 void GpuWatchdogThread::GpuWatchdogTaskObserver::WillProcessTask(
76 const Task* task)
77 {
78 CheckArmed();
79 }
80
81 void GpuWatchdogThread::GpuWatchdogTaskObserver::DidProcessTask(
82 const Task* task)
83 {
84 CheckArmed();
85 }
86
87 void GpuWatchdogThread::GpuWatchdogTaskObserver::CheckArmed()
88 {
89 // Acknowledge the watchdog if it has armed itself. The watchdog will not
90 // change its armed state until it is acknowledged.
91 if (watchdog_->armed()) {
92 watchdog_->PostAcknowledge();
93 }
94 }
95
50 void GpuWatchdogThread::OnAcknowledge() { 96 void GpuWatchdogThread::OnAcknowledge() {
97 // The check has already been acknowledged and another has already been
98 // scheduled by a previous call to OnAcknowledge. It is normal for a
99 // watched thread to see armed_ being true multiple times before
100 // the OnAcknowledge task is run on the watchdog thread.
101 if (!armed_)
102 return;
103
51 // Revoke any pending OnExit. 104 // Revoke any pending OnExit.
52 method_factory_->RevokeAll(); 105 method_factory_->RevokeAll();
106 armed_ = false;
53 107
54 // The monitored thread has responded. Post a task to check it again. 108 // The monitored thread has responded. Post a task to check it again.
55 if (watched_message_loop_) { 109 if (watched_message_loop_) {
56 message_loop()->PostDelayedTask( 110 message_loop()->PostDelayedTask(
57 FROM_HERE, 111 FROM_HERE,
58 method_factory_->NewRunnableMethod(&GpuWatchdogThread::OnCheck), 112 method_factory_->NewRunnableMethod(&GpuWatchdogThread::OnCheck),
59 kCheckPeriod); 113 kCheckPeriod);
60 } 114 }
61 } 115 }
62 116
63 void GpuWatchdogThread::OnCheck() { 117 void GpuWatchdogThread::OnCheck() {
64 if (watched_message_loop_) { 118 if (watched_message_loop_) {
65 // Post a task to the monitored thread that simply responds with a task that 119 // Must set armed before posting the task. This task might be the only task
66 // calls OnAcknowldge. 120 // that will activate the TaskObserver on the watched thread and it must not
121 // miss the false -> true transition.
122 armed_ = true;
123
124 // Post a task to the monitored thread that does nothing but wake up the
125 // TaskObserver. Any other tasks that are pending on the watched thread will
126 // also wake up the observer. This simply ensures there is at least one.
67 watched_message_loop_->PostTask( 127 watched_message_loop_->PostTask(
68 FROM_HERE, 128 FROM_HERE,
69 NewRunnableMethod(this, &GpuWatchdogThread::PostAcknowledge)); 129 NewRunnableFunction(DoNothing));
70 130
71 // Post a task to the watchdog thread to exit if the nmonitored thread does 131 // Post a task to the watchdog thread to exit if the monitored thread does
72 // not respond in time. 132 // not respond in time.
73 message_loop()->PostDelayedTask( 133 message_loop()->PostDelayedTask(
74 FROM_HERE, 134 FROM_HERE,
75 method_factory_->NewRunnableMethod(&GpuWatchdogThread::OnExit), 135 method_factory_->NewRunnableMethod(&GpuWatchdogThread::OnExit),
76 timeout_); 136 timeout_);
77 } 137 }
78 } 138 }
79 139
80 void GpuWatchdogThread::PostAcknowledge() {
81 // Called on the monitored thread. Responds with OnAcknowledge. Cannot use
82 // the method factory. Rely on reference counting instead.
83 message_loop()->PostTask(
84 FROM_HERE,
85 NewRunnableMethod(this, &GpuWatchdogThread::OnAcknowledge));
86 }
87
88 // Use the --disable-gpu-watchdog command line switch to disable this. 140 // Use the --disable-gpu-watchdog command line switch to disable this.
89 void GpuWatchdogThread::OnExit() { 141 void GpuWatchdogThread::OnExit() {
90 // Make sure the timeout period is on the stack before crashing. 142 // Make sure the timeout period is on the stack before crashing.
91 volatile int timeout = timeout_; 143 volatile int timeout = timeout_;
92 144
93 // For minimal developer annoyance, don't keep crashing. 145 // For minimal developer annoyance, don't keep crashing.
94 static bool crashed = false; 146 static bool crashed = false;
95 if (crashed) 147 if (crashed)
96 return; 148 return;
97 149
98 #if defined(OS_WIN) 150 #if defined(OS_WIN)
99 if (IsDebuggerPresent()) 151 if (IsDebuggerPresent())
100 return; 152 return;
101 #endif 153 #endif
102 154
103 LOG(ERROR) << "The GPU process hung. Restarting after " 155 LOG(ERROR) << "The GPU process hung. Restarting after "
104 << timeout_ << " seconds."; 156 << timeout_ << " seconds.";
105 157
106 volatile int* null_pointer = NULL; 158 volatile int* null_pointer = NULL;
107 *null_pointer = timeout; 159 *null_pointer = timeout;
108 160
109 crashed = true; 161 crashed = true;
110 } 162 }
OLDNEW
« no previous file with comments | « chrome/gpu/gpu_watchdog_thread.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698