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

Side by Side Diff: chrome/browser/metrics/tracking_synchronizer.cc

Issue 8588023: Collect profiler stats from browser child processes. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 9 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
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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 "chrome/browser/metrics/tracking_synchronizer.h" 5 #include "chrome/browser/metrics/tracking_synchronizer.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/json/json_reader.h" 8 #include "base/json/json_reader.h"
9 #include "base/json/json_writer.h" 9 #include "base/json/json_writer.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
11 #include "base/metrics/histogram.h" 11 #include "base/metrics/histogram.h"
12 #include "base/threading/thread.h" 12 #include "base/threading/thread.h"
13 #include "base/tracked_objects.h" 13 #include "base/tracked_objects.h"
14 #include "chrome/browser/ui/webui/tracing_ui.h" 14 #include "chrome/browser/ui/webui/tracing_ui.h"
15 #include "chrome/common/chrome_constants.h" 15 #include "chrome/common/chrome_constants.h"
16 #include "chrome/common/render_messages.h" 16 #include "chrome/common/render_messages.h"
17 #include "content/browser/browser_child_process_host.h"
18 #include "content/browser/profiler_controller.h"
19 #include "content/common/child_process_info.h"
20 #include "content/common/child_process_messages.h"
17 #include "content/public/browser/browser_thread.h" 21 #include "content/public/browser/browser_thread.h"
18 #include "content/public/browser/render_process_host.h" 22 #include "content/public/browser/render_process_host.h"
19 23
20 using base::TimeTicks; 24 using base::TimeTicks;
21 using content::BrowserThread; 25 using content::BrowserThread;
22 26
23 namespace chrome_browser_metrics { 27 namespace chrome_browser_metrics {
24 28
25 // Negative numbers are never used as sequence numbers. We explicitly pick a 29 // Negative numbers are never used as sequence numbers. We explicitly pick a
26 // negative number that is "so negative" that even when we add one (as is done 30 // negative number that is "so negative" that even when we add one (as is done
27 // when we generated the next sequence number) that it will still be negative. 31 // when we generated the next sequence number) that it will still be negative.
28 // We have code that handles wrapping around on an overflow into negative 32 // We have code that handles wrapping around on an overflow into negative
29 // territory. 33 // territory.
30 static const int kNeverUsableSequenceNumber = -2; 34 static const int kNeverUsableSequenceNumber = -2;
31 35
32 TrackingSynchronizer::TrackingSynchronizer() 36 TrackingSynchronizer::TrackingSynchronizer()
33 : last_used_sequence_number_(kNeverUsableSequenceNumber) { 37 : last_used_sequence_number_(kNeverUsableSequenceNumber) {
34 DCHECK(tracking_synchronizer_ == NULL); 38 DCHECK(tracking_synchronizer_ == NULL);
35 tracking_synchronizer_ = this; 39 tracking_synchronizer_ = this;
40 ProfilerController::GetInstance()->RegisterSubscriber(this);
36 } 41 }
37 42
38 TrackingSynchronizer::~TrackingSynchronizer() { 43 TrackingSynchronizer::~TrackingSynchronizer() {
44 ProfilerController::GetInstance()->CancelSubscriber(this);
39 // Just in case we have any pending tasks, clear them out. 45 // Just in case we have any pending tasks, clear them out.
40 while (!outstanding_requests_.empty()) { 46 while (!outstanding_requests_.empty()) {
41 RequestContextMap::iterator it = outstanding_requests_.begin(); 47 RequestContextMap::iterator it = outstanding_requests_.begin();
42 delete it->second; 48 delete it->second;
43 outstanding_requests_.erase(it); 49 outstanding_requests_.erase(it);
44 } 50 }
45 51
46 tracking_synchronizer_ = NULL; 52 tracking_synchronizer_ = NULL;
47 } 53 }
48 54
49 // static 55 // static
50 TrackingSynchronizer* TrackingSynchronizer::CurrentSynchronizer() { 56 void TrackingSynchronizer::FetchProfilerDataAsynchronously(
51 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
52 DCHECK(tracking_synchronizer_ != NULL);
53 return tracking_synchronizer_;
54 }
55
56 // static
57 void TrackingSynchronizer::FetchTrackingDataAsynchronously(
58 const base::WeakPtr<ProfilerUI>& callback_object) { 57 const base::WeakPtr<ProfilerUI>& callback_object) {
59 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 58 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
60 59
61 TrackingSynchronizer* current_synchronizer = CurrentSynchronizer(); 60 TrackingSynchronizer* current_synchronizer = CurrentSynchronizer();
62 if (current_synchronizer == NULL) { 61 if (current_synchronizer == NULL) {
63 // System teardown is happening. 62 // System teardown is happening.
64 return; 63 return;
65 } 64 }
66 65
67 int sequence_number = current_synchronizer->RegisterAndNotifyAllProcesses( 66 int sequence_number = current_synchronizer->RegisterAndNotifyAllProcesses(
68 callback_object); 67 callback_object);
69 68
70 // Post a task that would be called after waiting for wait_time. This acts 69 // Post a task that would be called after waiting for wait_time. This acts
71 // as a watchdog, to cancel the requests for non-responsive processes. 70 // as a watchdog, to cancel the requests for non-responsive processes.
72 BrowserThread::PostDelayedTask( 71 BrowserThread::PostDelayedTask(
73 BrowserThread::UI, FROM_HERE, 72 BrowserThread::UI, FROM_HERE,
74 NewRunnableMethod( 73 NewRunnableMethod(
75 current_synchronizer, 74 current_synchronizer,
76 &TrackingSynchronizer::ForceTrackingSynchronizationDoneCallback, 75 &TrackingSynchronizer::ForceProfilerSynchronizationDoneCallback,
77 sequence_number), 76 sequence_number),
78 60000); 77 60000);
79 } 78 }
80 79
81 // static 80 // static
82 void TrackingSynchronizer::SetTrackingStatus(bool enable) { 81 void TrackingSynchronizer::SetProfilerStatus(bool enable) {
83 // To iterate over all processes, or to send messages to the hosts, we need 82 // To iterate over all processes, or to send messages to the hosts, we need
84 // to be on the UI thread. 83 // to be on the UI thread.
85 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 84 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
86 85
87 for (content::RenderProcessHost::iterator it( 86 for (content::RenderProcessHost::iterator it(
88 content::RenderProcessHost::AllHostsIterator()); 87 content::RenderProcessHost::AllHostsIterator());
89 !it.IsAtEnd(); it.Advance()) { 88 !it.IsAtEnd(); it.Advance()) {
90 content::RenderProcessHost* render_process_host = it.GetCurrentValue(); 89 content::RenderProcessHost* render_process_host = it.GetCurrentValue();
91 DCHECK(render_process_host); 90 DCHECK(render_process_host);
92 // Ignore processes that don't have a connection, such as crashed tabs. 91 // Ignore processes that don't have a connection, such as crashed tabs.
93 if (!render_process_host->HasConnection()) 92 if (!render_process_host->HasConnection())
94 continue; 93 continue;
95 94
96 render_process_host->Send(new ChromeViewMsg_SetTrackingStatus(enable)); 95 render_process_host->Send(new ChromeViewMsg_SetProfilerStatus(enable));
97 } 96 }
97
98 BrowserThread::PostTask(
99 BrowserThread::IO, FROM_HERE,
100 base::Bind(
101 &TrackingSynchronizer::SetProfilerStatusInChildProcesses, enable));
98 } 102 }
99 103
100 // static 104 // static
101 void TrackingSynchronizer::IsTrackingEnabled(int process_id) { 105 void TrackingSynchronizer::IsProfilerEnabledForRenderer(
106 int renderer_process_id) {
102 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 107 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
103 // To find the process, or to send messages to the hosts, we need to be on the 108 // To find the process, or to send messages to the hosts, we need to be on the
104 // UI thread. 109 // UI thread.
105 BrowserThread::PostTask( 110 BrowserThread::PostTask(
106 BrowserThread::UI, FROM_HERE, 111 BrowserThread::UI, FROM_HERE,
107 base::Bind( 112 base::Bind(
108 &TrackingSynchronizer::SetTrackingStatusInProcess, process_id)); 113 &TrackingSynchronizer::SendRendererSetProfilerStatusOnUI,
114 renderer_process_id));
109 } 115 }
110 116
111 // static 117 // static
112 void TrackingSynchronizer::SetTrackingStatusInProcess(int process_id) { 118 void TrackingSynchronizer::OnRendererProfilerDatatCollected(
119 int sequence_number,
120 const std::string& profiler_data) {
121 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
122 BrowserThread::PostTask(
123 BrowserThread::UI, FROM_HERE,
124 base::Bind(&TrackingSynchronizer::OnRendererProfilerDatatCollectedOnUI,
125 sequence_number,
126 profiler_data));
127 }
128
129 void TrackingSynchronizer::OnBrowserChildProfilerDataCollected(
130 int sequence_number,
131 const std::string& profiler_data) {
132 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
133
134 base::Value* value =
135 base::JSONReader().JsonToValue(profiler_data, false, true);
136 DCHECK(value->GetType() == base::Value::TYPE_DICTIONARY);
137 base::DictionaryValue* dictionary_value =
138 static_cast<DictionaryValue*>(value);
139
140 DecrementPendingProcessesAndSendDataOnIO(sequence_number, dictionary_value);
141 }
142
143 void TrackingSynchronizer::OnIsProfilerEnabledForChildProcess(
144 base::ProcessId child_process_id) {
145 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
113 // To find the process, or to send messages to the hosts, we need to be on the 146 // To find the process, or to send messages to the hosts, we need to be on the
114 // UI thread. 147 // IO thread. We post a task to set the status.
115 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 148 BrowserThread::PostTask(
116 149 BrowserThread::IO, FROM_HERE,
117 bool enable = tracked_objects::ThreadData::tracking_status(); 150 base::Bind(
118 151 &TrackingSynchronizer::SendChildSetProfilerStatusOnIO,
119 content::RenderProcessHost* process = 152 child_process_id));
120 content::RenderProcessHost::FromID(process_id);
121 // Ignore processes that don't have a connection, such as crashed tabs.
122 if (!process || !process->HasConnection())
123 return;
124 process->Send(new ChromeViewMsg_SetTrackingStatus(enable));
125 } 153 }
126 154
127 // static 155 // static
128 void TrackingSynchronizer::DeserializeTrackingList( 156 TrackingSynchronizer* TrackingSynchronizer::CurrentSynchronizer() {
129 int sequence_number,
130 const std::string& tracking_data,
131 ChildProcessInfo::ProcessType process_type) {
132 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
133 BrowserThread::PostTask(
134 BrowserThread::UI, FROM_HERE,
135 base::Bind(
136 &TrackingSynchronizer::DeserializeTrackingListOnUI,
137 sequence_number, tracking_data, process_type));
138 }
139
140 // static
141 void TrackingSynchronizer::DeserializeTrackingListOnUI(
142 int sequence_number,
143 const std::string& tracking_data,
144 ChildProcessInfo::ProcessType process_type) {
145 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 157 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
146 158 DCHECK(tracking_synchronizer_ != NULL);
147 TrackingSynchronizer* current_synchronizer = CurrentSynchronizer(); 159 return tracking_synchronizer_;
148 if (current_synchronizer == NULL)
149 return;
150
151 base::Value* value =
152 base::JSONReader().JsonToValue(tracking_data, false, true);
153 DCHECK(value->GetType() == base::Value::TYPE_DICTIONARY);
154 base::DictionaryValue* dictionary_value =
155 static_cast<DictionaryValue*>(value);
156 dictionary_value->SetString(
157 "process_type", ChildProcessInfo::GetTypeNameInEnglish(process_type));
158
159 current_synchronizer->DecrementPendingProcessesAndSendData(
160 sequence_number, dictionary_value);
161 } 160 }
162 161
163 int TrackingSynchronizer::RegisterAndNotifyAllProcesses( 162 int TrackingSynchronizer::RegisterAndNotifyAllProcesses(
164 const base::WeakPtr<ProfilerUI>& callback_object) { 163 const base::WeakPtr<ProfilerUI>& callback_object) {
165 // To iterate over all processes, or to send messages to the hosts, we need 164 // To iterate over all processes, or to send messages to the hosts, we need
166 // to be on the UI thread. 165 // to be on the UI thread.
167 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 166 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
168 167
169 int sequence_number = GetNextAvailableSequenceNumber(); 168 int sequence_number = GetNextAvailableSequenceNumber();
170 169
171 // Initialize processes_pending with one because we are going to send 170 // ui_processes_pending is initialized to 1 to send browser's data.
172 // browser's ThreadData. 171 // io_processes_pending is initialized to 1 for browser child processes.
172 // threads_pending is set to 2 to wait for data from UI thread (for renderer
173 // processes) and IO thread (for browser child processes).
173 RequestContext* request = new RequestContext( 174 RequestContext* request = new RequestContext(
174 callback_object, sequence_number, 1, TimeTicks::Now()); 175 callback_object, sequence_number, 1, 1, 2, TimeTicks::Now());
175 outstanding_requests_[sequence_number] = request; 176 outstanding_requests_[sequence_number] = request;
176 177
177 DCHECK_GT(request->processes_pending_, 0); 178 NotifyAllRendererProcesses(request);
179
180 BrowserThread::PostTask(
181 BrowserThread::IO, FROM_HERE,
182 base::Bind(
183 &TrackingSynchronizer::NotifyAllChildProcesses,
184 base::Unretained(this), request));
185
186 // Get the ThreadData for the browser process and send it back.
187 base::DictionaryValue* value = tracked_objects::ThreadData::ToValue();
188 const std::string process_type =
189 ChildProcessInfo::GetTypeNameInEnglish(ChildProcessInfo::BROWSER_PROCESS);
190 value->SetString("process_type", process_type);
191 value->SetInteger("process_id", base::GetCurrentProcId());
192 DCHECK_GE(request->ui_processes_pending_, 1);
193 DecrementPendingProcessesAndSendDataOnUI(sequence_number, value);
194
195 return sequence_number;
196 }
197
198 void TrackingSynchronizer::NotifyAllRendererProcesses(RequestContext* request) {
199 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
200 DCHECK_EQ(request->ui_processes_pending_, 1);
201
202 const std::string render_process_type =
203 ChildProcessInfo::GetTypeNameInEnglish(ChildProcessInfo::RENDER_PROCESS);
204
178 for (content::RenderProcessHost::iterator it( 205 for (content::RenderProcessHost::iterator it(
179 content::RenderProcessHost::AllHostsIterator()); 206 content::RenderProcessHost::AllHostsIterator());
180 !it.IsAtEnd(); it.Advance()) { 207 !it.IsAtEnd(); it.Advance()) {
181 content::RenderProcessHost* render_process_host = it.GetCurrentValue(); 208 content::RenderProcessHost* render_process_host = it.GetCurrentValue();
182 DCHECK(render_process_host); 209 DCHECK(render_process_host);
183 // Ignore processes that don't have a connection, such as crashed tabs. 210 // Ignore processes that don't have a connection, such as crashed tabs.
184 if (!render_process_host->HasConnection()) 211 if (!render_process_host->HasConnection())
185 continue; 212 continue;
186 213
187 ++request->processes_pending_; 214 ++request->ui_processes_pending_;
188 if (!render_process_host->Send( 215 if (!render_process_host->Send(new ChromeViewMsg_GetRendererProfilerData(
189 new ChromeViewMsg_GetRendererTrackedData(sequence_number))) { 216 request->sequence_number_, render_process_type))) {
190 DecrementPendingProcesses(sequence_number); 217 DecrementPendingProcessesAndSendDataOnUI(request->sequence_number_, NULL);
218 }
219 }
220 DCHECK_GE(request->ui_processes_pending_, 1);
221 }
222
223 void TrackingSynchronizer::NotifyAllChildProcesses(RequestContext* request) {
224 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
225 DCHECK_EQ(1, request->io_processes_pending_);
226
227 // Default constr references a singleton.
jam 2011/11/19 23:36:25 nit: this comment, and below, seem unnecessary. i.
ramant (doing other things) 2011/11/25 23:59:48 Done.
228 for (BrowserChildProcessHost::Iterator child_process_host;
229 !child_process_host.Done(); ++child_process_host) {
230 const std::string process_type =
231 ChildProcessInfo::GetTypeNameInEnglish(child_process_host->type());
232
233 ++request->io_processes_pending_;
234 if (!child_process_host->Send(new ChildProcessMsg_GetChildProfilerData(
235 request->sequence_number_, process_type))) {
236 DecrementPendingProcessesAndSendDataOnIO(request->sequence_number_, NULL);
191 } 237 }
192 } 238 }
193 239
194 // Get the ThreadData for the browser process and send it back. 240 DCHECK_GE(request->io_processes_pending_, 1);
195 base::DictionaryValue* value = tracked_objects::ThreadData::ToValue(); 241 if (--request->io_processes_pending_ == 0) {
196 const std::string process_type = 242 // We are done because we are not waiting for any browser child processes.
197 ChildProcessInfo::GetTypeNameInEnglish(ChildProcessInfo::BROWSER_PROCESS); 243 BrowserThread::PostTask(
198 value->SetString("process_type", process_type); 244 BrowserThread::UI, FROM_HERE,
199 value->SetInteger("process_id", base::GetCurrentProcId()); 245 base::Bind(&TrackingSynchronizer::DeleteIfAllDone,
200 DCHECK_GT(request->processes_pending_, 0); 246 base::Unretained(this), request));
201 DecrementPendingProcessesAndSendData(sequence_number, value); 247 }
248 }
202 249
203 return sequence_number; 250 // static
251 void TrackingSynchronizer::OnRendererProfilerDatatCollectedOnUI(
252 int sequence_number,
253 const std::string& profiler_data) {
254 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
255
256 TrackingSynchronizer* current_synchronizer = CurrentSynchronizer();
257 if (current_synchronizer == NULL)
258 return;
259
260 base::Value* value =
261 base::JSONReader().JsonToValue(profiler_data, false, true);
262 DCHECK(value->GetType() == base::Value::TYPE_DICTIONARY);
263 base::DictionaryValue* dictionary_value =
264 static_cast<DictionaryValue*>(value);
265
266 current_synchronizer->DecrementPendingProcessesAndSendDataOnUI(
267 sequence_number, dictionary_value);
268 }
269
270 void TrackingSynchronizer::DecrementPendingProcessesAndSendDataOnUI(
271 int sequence_number,
272 base::DictionaryValue* value) {
273 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
274
275 DecrementProcessesCallback decrement_pending_process_cb =
276 base::Bind(&TrackingSynchronizer::DecrementUIProcesses,
277 base::Unretained(this));
278
279 DecrementPendingProcessesAndSendData(sequence_number,
280 value,
281 MessageLoop::current(),
282 decrement_pending_process_cb);
283 }
284
285 void TrackingSynchronizer::DecrementPendingProcessesAndSendDataOnIO(
286 int sequence_number,
287 base::DictionaryValue* value) {
288 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
289
290 DecrementProcessesCallback decrement_pending_process_cb =
291 base::Bind(&TrackingSynchronizer::DecrementIOProcesses,
292 base::Unretained(this));
293
294 BrowserThread::PostTask(
295 BrowserThread::UI, FROM_HERE,
296 base::Bind(
297 &TrackingSynchronizer::DecrementPendingProcessesAndSendData,
298 base::Unretained(this),
299 sequence_number,
300 value,
301 MessageLoop::current(),
302 decrement_pending_process_cb));
204 } 303 }
205 304
206 void TrackingSynchronizer::DecrementPendingProcessesAndSendData( 305 void TrackingSynchronizer::DecrementPendingProcessesAndSendData(
207 int sequence_number, 306 int sequence_number,
208 base::DictionaryValue* value) { 307 base::DictionaryValue* value,
308 MessageLoop* callback_thread,
309 const DecrementProcessesCallback& decrement_pending_process_cb) {
209 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 310 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
210 311
211 RequestContextMap::iterator it = 312 RequestContextMap::iterator it =
212 outstanding_requests_.find(sequence_number); 313 outstanding_requests_.find(sequence_number);
213 if (it == outstanding_requests_.end()) { 314 if (it == outstanding_requests_.end()) {
214 delete value; 315 delete value;
215 return; 316 return;
216 } 317 }
217 318
218 RequestContext* request = NULL; 319 RequestContext* request = NULL;
219 request = it->second; 320 request = it->second;
220 DCHECK(sequence_number == request->sequence_number_); 321 DCHECK(sequence_number == request->sequence_number_);
221 322
222 if (value && request->callback_object_) { 323 if (value && request->callback_object_) {
223 // Transfers ownership of |value| to |callback_object_|. 324 // Transfers ownership of |value| to |callback_object_|.
224 request->callback_object_->ReceivedData(value); 325 request->callback_object_->ReceivedData(value);
225 } else { 326 } else {
226 delete value; 327 delete value;
227 } 328 }
228 329
229 if (--request->processes_pending_ <= 0) 330 callback_thread->PostTask(
230 ForceTrackingSynchronizationDoneCallback(sequence_number); 331 FROM_HERE,
332 base::Bind(
333 &TrackingSynchronizer::RunDecrementProcessesCallback,
334 this, decrement_pending_process_cb, request));
231 } 335 }
232 336
233 void TrackingSynchronizer::DecrementPendingProcesses(int sequence_number) { 337 void TrackingSynchronizer::DecrementUIProcesses(RequestContext* request) {
234 DecrementPendingProcessesAndSendData(sequence_number, NULL); 338 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
339 DCHECK_GT(request->ui_processes_pending_, 0);
340 if (--request->ui_processes_pending_ <= 0) {
341 DeleteIfAllDone(request);
342 }
235 } 343 }
236 344
237 void TrackingSynchronizer::ForceTrackingSynchronizationDoneCallback( 345 void TrackingSynchronizer::DecrementIOProcesses(RequestContext* request) {
346 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
347 DCHECK_GT(request->io_processes_pending_, 0);
348 if (--request->io_processes_pending_ <= 0) {
349 BrowserThread::PostTask(
350 BrowserThread::UI, FROM_HERE,
351 base::Bind(&TrackingSynchronizer::DeleteIfAllDone,
352 base::Unretained(this), request));
353 }
354 }
355
356 void TrackingSynchronizer::DeleteIfAllDone(RequestContext* request) {
357 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
358 DCHECK(request);
359 // Return if we still need to hear from other threads.
360 if (--request->threads_pending_)
361 return;
362
363 DCHECK_EQ(0, request->ui_processes_pending_);
364 DCHECK_EQ(0, request->io_processes_pending_);
365 ForceProfilerSynchronizationDoneCallback(request->sequence_number_);
366 }
367
368 void TrackingSynchronizer::ForceProfilerSynchronizationDoneCallback(
238 int sequence_number) { 369 int sequence_number) {
239 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 370 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
240 371
241 int unresponsive_processes;
242 RequestContextMap::iterator it = 372 RequestContextMap::iterator it =
243 outstanding_requests_.find(sequence_number); 373 outstanding_requests_.find(sequence_number);
244 if (it == outstanding_requests_.end()) 374 if (it == outstanding_requests_.end())
245 return; 375 return;
246 376
247 RequestContext* request = it->second; 377 RequestContext* request = it->second;
248 378
249 DCHECK(sequence_number == request->sequence_number_); 379 DCHECK(sequence_number == request->sequence_number_);
250 380
251 unresponsive_processes = request->processes_pending_; 381 int unresponsive_processes = request->ui_processes_pending_;
252 382
253 delete it->second; 383 delete it->second;
254 outstanding_requests_.erase(it); 384 outstanding_requests_.erase(it);
255 385
256 UMA_HISTOGRAM_COUNTS("Tracking.ProcessNotRespondingAsynchronous", 386 UMA_HISTOGRAM_COUNTS("Profiler.ProcessNotRespondingAsynchronous",
257 unresponsive_processes); 387 unresponsive_processes);
258 } 388 }
259 389
260 int TrackingSynchronizer::GetNextAvailableSequenceNumber() { 390 int TrackingSynchronizer::GetNextAvailableSequenceNumber() {
261 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 391 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
262 392
263 ++last_used_sequence_number_; 393 ++last_used_sequence_number_;
264 394
265 // Watch out for wrapping to a negative number. 395 // Watch out for wrapping to a negative number.
266 if (last_used_sequence_number_ < 0) 396 if (last_used_sequence_number_ < 0)
267 last_used_sequence_number_ = 1; 397 last_used_sequence_number_ = 1;
268 return last_used_sequence_number_; 398 return last_used_sequence_number_;
269 } 399 }
270 400
401 void TrackingSynchronizer::RunDecrementProcessesCallback(
402 const DecrementProcessesCallback& decrement_pending_process_cb,
403 RequestContext* request) {
404 decrement_pending_process_cb.Run(request);
405 }
406
407 // static
408 void TrackingSynchronizer::SetProfilerStatusInChildProcesses(bool enable) {
409 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
410
411 // Default constr references a singleton.
412 for (BrowserChildProcessHost::Iterator child_process_host;
413 !child_process_host.Done(); ++child_process_host) {
414 child_process_host->Send(new ChildProcessMsg_SetProfilerStatus(enable));
415 }
416 }
417
418 // static
419 void TrackingSynchronizer::SendRendererSetProfilerStatusOnUI(
420 int renderer_process_id) {
421 // To find the process, or to send messages to the hosts, we need to be on the
422 // UI thread.
423 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
424
425 bool enable = tracked_objects::ThreadData::tracking_status();
426
427 content::RenderProcessHost* process =
428 content::RenderProcessHost::FromID(renderer_process_id);
429 // Ignore processes that don't have a connection, such as crashed tabs.
430 if (!process || !process->HasConnection())
431 return;
432 process->Send(new ChromeViewMsg_SetProfilerStatus(enable));
433 }
434
435 // static
436 void TrackingSynchronizer::SendChildSetProfilerStatusOnIO(
437 base::ProcessId child_process_id) {
438 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
439
440 bool enable = tracked_objects::ThreadData::tracking_status();
441
442 // Default constr references a singleton.
443 for (BrowserChildProcessHost::Iterator child_process_host;
444 !child_process_host.Done(); ++child_process_host) {
445 if (base::GetProcId(child_process_host->handle()) == child_process_id)
446 child_process_host->Send(new ChildProcessMsg_SetProfilerStatus(enable));
447 }
448 }
449
271 // static 450 // static
272 TrackingSynchronizer* TrackingSynchronizer::tracking_synchronizer_ = NULL; 451 TrackingSynchronizer* TrackingSynchronizer::tracking_synchronizer_ = NULL;
273 452
274 } // namespace chrome_browser_metrics 453 } // namespace chrome_browser_metrics
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698