OLD | NEW |
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 "base/tracked_objects.h" | 5 #include "base/tracked_objects.h" |
6 | 6 |
7 #include <math.h> | 7 #include <math.h> |
8 | 8 |
9 #include "base/format_macros.h" | 9 #include "base/format_macros.h" |
10 #include "base/message_loop.h" | 10 #include "base/message_loop.h" |
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
204 if (!kTrackAllTaskObjects) | 204 if (!kTrackAllTaskObjects) |
205 return; // Not compiled in. | 205 return; // Not compiled in. |
206 DCHECK(tls_index_.initialized()); | 206 DCHECK(tls_index_.initialized()); |
207 if (!thread_data) | 207 if (!thread_data) |
208 return; | 208 return; |
209 reinterpret_cast<ThreadData*>(thread_data)->OnThreadTerminationCleanup(); | 209 reinterpret_cast<ThreadData*>(thread_data)->OnThreadTerminationCleanup(); |
210 DCHECK_EQ(tls_index_.Get(), reinterpret_cast<ThreadData*>(NULL)); | 210 DCHECK_EQ(tls_index_.Get(), reinterpret_cast<ThreadData*>(NULL)); |
211 } | 211 } |
212 | 212 |
213 void ThreadData::OnThreadTerminationCleanup() const { | 213 void ThreadData::OnThreadTerminationCleanup() const { |
214 tls_index_.Set(NULL); | |
215 if (!is_a_worker_thread_) | 214 if (!is_a_worker_thread_) |
216 return; | 215 return; |
217 base::AutoLock lock(*list_lock_); | 216 base::AutoLock lock(*list_lock_); |
218 unregistered_thread_data_pool_->push(this); | 217 unregistered_thread_data_pool_->push(this); |
219 } | 218 } |
220 | 219 |
221 // static | 220 // static |
222 void ThreadData::WriteHTML(const std::string& query, std::string* output) { | 221 void ThreadData::WriteHTML(const std::string& query, std::string* output) { |
223 if (!ThreadData::tracking_status()) | 222 if (status_ == UNINITIALIZED) |
224 return; // Not yet initialized. | 223 return; // Not yet initialized. |
225 | 224 |
226 DataCollector collected_data; // Gather data. | 225 DataCollector collected_data; // Gather data. |
227 collected_data.AddListOfLivingObjects(); // Add births that are still alive. | 226 collected_data.AddListOfLivingObjects(); // Add births that are still alive. |
228 | 227 |
229 // Data Gathering is complete. Now to sort/process/render. | 228 // Data Gathering is complete. Now to sort/process/render. |
230 DataCollector::Collection* collection = collected_data.collection(); | 229 DataCollector::Collection* collection = collected_data.collection(); |
231 | 230 |
232 // Create filtering and sort comparison object. | 231 // Create filtering and sort comparison object. |
233 Comparator comparator; | 232 Comparator comparator; |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
399 // To avoid conflating our stats with the delay duration in a PostDelayedTask, | 398 // To avoid conflating our stats with the delay duration in a PostDelayedTask, |
400 // we identify such tasks, and replace their post_time with the time they | 399 // we identify such tasks, and replace their post_time with the time they |
401 // were scheduled (requested?) to emerge from the delayed task queue. This | 400 // were scheduled (requested?) to emerge from the delayed task queue. This |
402 // means that queueing delay for such tasks will show how long they went | 401 // means that queueing delay for such tasks will show how long they went |
403 // unserviced, after they *could* be serviced. This is the same stat as we | 402 // unserviced, after they *could* be serviced. This is the same stat as we |
404 // have for non-delayed tasks, and we consistently call it queueing delay. | 403 // have for non-delayed tasks, and we consistently call it queueing delay. |
405 TrackedTime effective_post_time = completed_task.delayed_run_time.is_null() | 404 TrackedTime effective_post_time = completed_task.delayed_run_time.is_null() |
406 ? tracked_objects::TrackedTime(completed_task.time_posted) | 405 ? tracked_objects::TrackedTime(completed_task.time_posted) |
407 : tracked_objects::TrackedTime(completed_task.delayed_run_time); | 406 : tracked_objects::TrackedTime(completed_task.delayed_run_time); |
408 | 407 |
409 Duration queue_duration = start_of_run - effective_post_time; | 408 // Watch out for a race where status_ is changing, and hence one or both |
410 Duration run_duration = end_of_run - start_of_run; | 409 // of start_of_run or end_of_run is zero. IN that case, we didn't bother to |
| 410 // get a time value since we "weren't tracking" and we were trying to be |
| 411 // efficient by not calling for a genuine time value. For simplicity, we'll |
| 412 // use a default zero duration when we can't calculate a true value. |
| 413 Duration queue_duration; |
| 414 Duration run_duration; |
| 415 if (!start_of_run.is_null()) { |
| 416 queue_duration = start_of_run - effective_post_time; |
| 417 if (!end_of_run.is_null()) |
| 418 run_duration = end_of_run - start_of_run; |
| 419 } |
411 current_thread_data->TallyADeath(*birth, queue_duration, run_duration); | 420 current_thread_data->TallyADeath(*birth, queue_duration, run_duration); |
412 } | 421 } |
413 | 422 |
414 // static | 423 // static |
415 void ThreadData::TallyRunOnWorkerThreadIfTracking( | 424 void ThreadData::TallyRunOnWorkerThreadIfTracking( |
416 const Births* birth, | 425 const Births* birth, |
417 const TrackedTime& time_posted, | 426 const TrackedTime& time_posted, |
418 const TrackedTime& start_of_run, | 427 const TrackedTime& start_of_run, |
419 const TrackedTime& end_of_run) { | 428 const TrackedTime& end_of_run) { |
420 if (!kTrackAllTaskObjects) | 429 if (!kTrackAllTaskObjects) |
(...skipping 11 matching lines...) Expand all Loading... |
432 // (since we'll use locks on TallyBirth and TallyDeath). The good news is | 441 // (since we'll use locks on TallyBirth and TallyDeath). The good news is |
433 // that the locks on TallyDeath will be *after* the worker thread has run, and | 442 // that the locks on TallyDeath will be *after* the worker thread has run, and |
434 // hence nothing will be waiting for the completion (... besides some other | 443 // hence nothing will be waiting for the completion (... besides some other |
435 // thread that might like to run). Also, the worker threads tasks are | 444 // thread that might like to run). Also, the worker threads tasks are |
436 // generally longer, and hence the cost of the lock may perchance be amortized | 445 // generally longer, and hence the cost of the lock may perchance be amortized |
437 // over the long task's lifetime. | 446 // over the long task's lifetime. |
438 ThreadData* current_thread_data = Get(); | 447 ThreadData* current_thread_data = Get(); |
439 if (!current_thread_data) | 448 if (!current_thread_data) |
440 return; | 449 return; |
441 | 450 |
442 Duration queue_duration = start_of_run - time_posted; | 451 Duration queue_duration; |
443 Duration run_duration = end_of_run - start_of_run; | 452 Duration run_duration; |
| 453 if (!start_of_run.is_null()) { |
| 454 queue_duration = start_of_run - time_posted; |
| 455 if (!end_of_run.is_null()) |
| 456 run_duration = end_of_run - start_of_run; |
| 457 } |
444 current_thread_data->TallyADeath(*birth, queue_duration, run_duration); | 458 current_thread_data->TallyADeath(*birth, queue_duration, run_duration); |
445 } | 459 } |
446 | 460 |
447 // static | 461 // static |
448 ThreadData* ThreadData::first() { | 462 ThreadData* ThreadData::first() { |
449 base::AutoLock lock(*list_lock_); | 463 base::AutoLock lock(*list_lock_); |
450 return all_thread_data_list_head_; | 464 return all_thread_data_list_head_; |
451 } | 465 } |
452 | 466 |
453 // This may be called from another thread. | 467 // This may be called from another thread. |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
517 return true; | 531 return true; |
518 } | 532 } |
519 | 533 |
520 // static | 534 // static |
521 bool ThreadData::tracking_status() { | 535 bool ThreadData::tracking_status() { |
522 return status_ == ACTIVE; | 536 return status_ == ACTIVE; |
523 } | 537 } |
524 | 538 |
525 // static | 539 // static |
526 TrackedTime ThreadData::Now() { | 540 TrackedTime ThreadData::Now() { |
527 if (!kTrackAllTaskObjects || status_ != ACTIVE) | 541 if (kTrackAllTaskObjects && tracking_status()) |
528 return TrackedTime(); // Super fast when disabled, or not compiled. | 542 return TrackedTime::Now(); |
529 return TrackedTime::Now(); | 543 return TrackedTime(); // Super fast when disabled, or not compiled. |
530 } | 544 } |
531 | 545 |
532 // static | 546 // static |
533 void ThreadData::ShutdownSingleThreadedCleanup() { | 547 void ThreadData::ShutdownSingleThreadedCleanup() { |
534 // This is only called from test code, where we need to cleanup so that | 548 // This is only called from test code, where we need to cleanup so that |
535 // additional tests can be run. | 549 // additional tests can be run. |
536 // We must be single threaded... but be careful anyway. | 550 // We must be single threaded... but be careful anyway. |
537 if (!InitializeAndSetTrackingStatus(false)) | 551 if (!InitializeAndSetTrackingStatus(false)) |
538 return; | 552 return; |
539 ThreadData* thread_data_list; | 553 ThreadData* thread_data_list; |
540 ThreadDataPool* final_pool; | 554 ThreadDataPool* final_pool; |
541 { | 555 { |
542 base::AutoLock lock(*list_lock_); | 556 base::AutoLock lock(*list_lock_); |
543 thread_data_list = all_thread_data_list_head_; | 557 thread_data_list = all_thread_data_list_head_; |
544 all_thread_data_list_head_ = NULL; | 558 all_thread_data_list_head_ = NULL; |
545 final_pool = unregistered_thread_data_pool_; | 559 final_pool = unregistered_thread_data_pool_; |
546 unregistered_thread_data_pool_ = NULL; | 560 unregistered_thread_data_pool_ = NULL; |
547 } | 561 } |
548 | 562 |
| 563 // Put most global static back in pristine shape. |
| 564 thread_number_counter_ = 0; |
| 565 tls_index_.Set(NULL); |
| 566 status_ = UNINITIALIZED; |
| 567 |
| 568 // To avoid any chance of racing in unit tests, which is the only place we |
| 569 // call this function, we will leak all the data structures we recovered. |
| 570 // These structures could plausibly be used by other threads in earlier tests |
| 571 // that are still running. |
| 572 return; |
| 573 |
| 574 // If we wanted to cleanup (on a single thread), here is what we would do. |
| 575 |
549 if (final_pool) { | 576 if (final_pool) { |
550 // The thread_data_list contains *all* the instances, and we'll use it to | 577 // The thread_data_list contains *all* the instances, and we'll use it to |
551 // delete them. This pool has pointers to some instances, and we just | 578 // delete them. This pool has pointers to some instances, and we just |
552 // have to drop those pointers (and not do the deletes here). | 579 // have to drop those pointers (and not do the deletes here). |
553 while (!final_pool->empty()) | 580 while (!final_pool->empty()) |
554 final_pool->pop(); | 581 final_pool->pop(); |
555 delete final_pool; | 582 delete final_pool; |
556 } | 583 } |
557 | 584 |
558 // Do actual recursive delete in all ThreadData instances. | 585 // Do actual recursive delete in all ThreadData instances. |
559 while (thread_data_list) { | 586 while (thread_data_list) { |
560 ThreadData* next_thread_data = thread_data_list; | 587 ThreadData* next_thread_data = thread_data_list; |
561 thread_data_list = thread_data_list->next(); | 588 thread_data_list = thread_data_list->next(); |
562 | 589 |
563 for (BirthMap::iterator it = next_thread_data->birth_map_.begin(); | 590 for (BirthMap::iterator it = next_thread_data->birth_map_.begin(); |
564 next_thread_data->birth_map_.end() != it; ++it) | 591 next_thread_data->birth_map_.end() != it; ++it) |
565 delete it->second; // Delete the Birth Records. | 592 delete it->second; // Delete the Birth Records. |
566 next_thread_data->birth_map_.clear(); | 593 next_thread_data->birth_map_.clear(); |
567 next_thread_data->death_map_.clear(); | 594 next_thread_data->death_map_.clear(); |
568 delete next_thread_data; // Includes all Death Records. | 595 delete next_thread_data; // Includes all Death Records. |
569 } | 596 } |
570 // Put most global static back in pristine shape. | |
571 thread_number_counter_ = 0; | |
572 tls_index_.Set(NULL); | |
573 status_ = UNINITIALIZED; | |
574 } | 597 } |
575 | 598 |
576 //------------------------------------------------------------------------------ | 599 //------------------------------------------------------------------------------ |
577 // Individual 3-tuple of birth (place and thread) along with death thread, and | 600 // Individual 3-tuple of birth (place and thread) along with death thread, and |
578 // the accumulated stats for instances (DeathData). | 601 // the accumulated stats for instances (DeathData). |
579 | 602 |
580 Snapshot::Snapshot(const BirthOnThread& birth_on_thread, | 603 Snapshot::Snapshot(const BirthOnThread& birth_on_thread, |
581 const ThreadData& death_thread, | 604 const ThreadData& death_thread, |
582 const DeathData& death_data) | 605 const DeathData& death_data) |
583 : birth_(&birth_on_thread), | 606 : birth_(&birth_on_thread), |
(...skipping 530 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1114 (combined_selectors_ & BIRTH_THREAD) ? "*" : | 1137 (combined_selectors_ & BIRTH_THREAD) ? "*" : |
1115 sample.birth().birth_thread()->thread_name().c_str(), | 1138 sample.birth().birth_thread()->thread_name().c_str(), |
1116 (combined_selectors_ & DEATH_THREAD) ? "*" : | 1139 (combined_selectors_ & DEATH_THREAD) ? "*" : |
1117 sample.DeathThreadName().c_str()); | 1140 sample.DeathThreadName().c_str()); |
1118 sample.birth().location().Write(!(combined_selectors_ & BIRTH_FILE), | 1141 sample.birth().location().Write(!(combined_selectors_ & BIRTH_FILE), |
1119 !(combined_selectors_ & BIRTH_FUNCTION), | 1142 !(combined_selectors_ & BIRTH_FUNCTION), |
1120 output); | 1143 output); |
1121 } | 1144 } |
1122 | 1145 |
1123 } // namespace tracked_objects | 1146 } // namespace tracked_objects |
OLD | NEW |