| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 <limits.h> | 7 #include <limits.h> |
| 8 #include <stdlib.h> | 8 #include <stdlib.h> |
| 9 | 9 |
| 10 #include "base/atomicops.h" | 10 #include "base/atomicops.h" |
| 11 #include "base/base_switches.h" | 11 #include "base/base_switches.h" |
| 12 #include "base/command_line.h" | 12 #include "base/command_line.h" |
| 13 #include "base/compiler_specific.h" | 13 #include "base/compiler_specific.h" |
| 14 #include "base/debug/leak_annotations.h" | 14 #include "base/debug/leak_annotations.h" |
| 15 #include "base/logging.h" | 15 #include "base/logging.h" |
| 16 #include "base/process/process_handle.h" | 16 #include "base/process/process_handle.h" |
| 17 #include "base/profiler/alternate_timer.h" | |
| 18 #include "base/strings/stringprintf.h" | 17 #include "base/strings/stringprintf.h" |
| 19 #include "base/third_party/valgrind/memcheck.h" | 18 #include "base/third_party/valgrind/memcheck.h" |
| 20 #include "base/tracking_info.h" | 19 #include "base/tracking_info.h" |
| 21 #include "build/build_config.h" | 20 #include "build/build_config.h" |
| 22 | 21 |
| 23 using base::TimeDelta; | 22 using base::TimeDelta; |
| 24 | 23 |
| 25 namespace base { | 24 namespace base { |
| 26 class TimeDelta; | 25 class TimeDelta; |
| 27 } | 26 } |
| 28 | 27 |
| 29 namespace tracked_objects { | 28 namespace tracked_objects { |
| 30 | 29 |
| 31 namespace { | 30 namespace { |
| 32 // When ThreadData is first initialized, should we start in an ACTIVE state to | 31 // When ThreadData is first initialized, should we start in an ACTIVE state to |
| 33 // record all of the startup-time tasks, or should we start up DEACTIVATED, so | 32 // record all of the startup-time tasks, or should we start up DEACTIVATED, so |
| 34 // that we only record after parsing the command line flag --enable-tracking. | 33 // that we only record after parsing the command line flag --enable-tracking. |
| 35 // Note that the flag may force either state, so this really controls only the | 34 // Note that the flag may force either state, so this really controls only the |
| 36 // period of time up until that flag is parsed. If there is no flag seen, then | 35 // period of time up until that flag is parsed. If there is no flag seen, then |
| 37 // this state may prevail for much or all of the process lifetime. | 36 // this state may prevail for much or all of the process lifetime. |
| 38 const ThreadData::Status kInitialStartupState = ThreadData::PROFILING_ACTIVE; | 37 const ThreadData::Status kInitialStartupState = ThreadData::PROFILING_ACTIVE; |
| 39 | 38 |
| 40 // Control whether an alternate time source (Now() function) is supported by | |
| 41 // the ThreadData class. This compile time flag should be set to true if we | |
| 42 // want other modules (such as a memory allocator, or a thread-specific CPU time | |
| 43 // clock) to be able to provide a thread-specific Now() function. Without this | |
| 44 // compile-time flag, the code will only support the wall-clock time. This flag | |
| 45 // can be flipped to efficiently disable this path (if there is a performance | |
| 46 // problem with its presence). | |
| 47 static const bool kAllowAlternateTimeSourceHandling = true; | |
| 48 | |
| 49 // Possible states of the profiler timing enabledness. | 39 // Possible states of the profiler timing enabledness. |
| 50 enum { | 40 enum { |
| 51 UNDEFINED_TIMING, | 41 UNDEFINED_TIMING, |
| 52 ENABLED_TIMING, | 42 ENABLED_TIMING, |
| 53 DISABLED_TIMING, | 43 DISABLED_TIMING, |
| 54 }; | 44 }; |
| 55 | 45 |
| 56 // State of the profiler timing enabledness. | 46 // State of the profiler timing enabledness. |
| 57 base::subtle::Atomic32 g_profiler_timing_enabled = UNDEFINED_TIMING; | 47 base::subtle::Atomic32 g_profiler_timing_enabled = UNDEFINED_TIMING; |
| 58 | 48 |
| (...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 278 | 268 |
| 279 //------------------------------------------------------------------------------ | 269 //------------------------------------------------------------------------------ |
| 280 // ThreadData maintains the central data for all births and deaths on a single | 270 // ThreadData maintains the central data for all births and deaths on a single |
| 281 // thread. | 271 // thread. |
| 282 | 272 |
| 283 // TODO(jar): We should pull all these static vars together, into a struct, and | 273 // TODO(jar): We should pull all these static vars together, into a struct, and |
| 284 // optimize layout so that we benefit from locality of reference during accesses | 274 // optimize layout so that we benefit from locality of reference during accesses |
| 285 // to them. | 275 // to them. |
| 286 | 276 |
| 287 // static | 277 // static |
| 288 NowFunction* ThreadData::now_function_ = NULL; | 278 ThreadData::NowFunction* ThreadData::now_function_for_testing_ = NULL; |
| 289 | |
| 290 // static | |
| 291 bool ThreadData::now_function_is_time_ = false; | |
| 292 | 279 |
| 293 // A TLS slot which points to the ThreadData instance for the current thread. | 280 // A TLS slot which points to the ThreadData instance for the current thread. |
| 294 // We do a fake initialization here (zeroing out data), and then the real | 281 // We do a fake initialization here (zeroing out data), and then the real |
| 295 // in-place construction happens when we call tls_index_.Initialize(). | 282 // in-place construction happens when we call tls_index_.Initialize(). |
| 296 // static | 283 // static |
| 297 base::ThreadLocalStorage::StaticSlot ThreadData::tls_index_ = TLS_INITIALIZER; | 284 base::ThreadLocalStorage::StaticSlot ThreadData::tls_index_ = TLS_INITIALIZER; |
| 298 | 285 |
| 299 // static | 286 // static |
| 300 int ThreadData::worker_thread_data_creation_count_ = 0; | 287 int ThreadData::worker_thread_data_creation_count_ = 0; |
| 301 | 288 |
| (...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 509 const TaskStopwatch& stopwatch) { | 496 const TaskStopwatch& stopwatch) { |
| 510 int32_t run_duration = stopwatch.RunDurationMs(); | 497 int32_t run_duration = stopwatch.RunDurationMs(); |
| 511 | 498 |
| 512 // Stir in some randomness, plus add constant in case durations are zero. | 499 // Stir in some randomness, plus add constant in case durations are zero. |
| 513 const uint32_t kSomePrimeNumber = 2147483647; | 500 const uint32_t kSomePrimeNumber = 2147483647; |
| 514 random_number_ += queue_duration + run_duration + kSomePrimeNumber; | 501 random_number_ += queue_duration + run_duration + kSomePrimeNumber; |
| 515 // An address is going to have some randomness to it as well ;-). | 502 // An address is going to have some randomness to it as well ;-). |
| 516 random_number_ ^= | 503 random_number_ ^= |
| 517 static_cast<uint32_t>(&births - reinterpret_cast<Births*>(0)); | 504 static_cast<uint32_t>(&births - reinterpret_cast<Births*>(0)); |
| 518 | 505 |
| 519 // We don't have queue durations without OS timer. OS timer is automatically | |
| 520 // used for task-post-timing, so the use of an alternate timer implies all | |
| 521 // queue times are invalid, unless it was explicitly said that we can trust | |
| 522 // the alternate timer. | |
| 523 if (kAllowAlternateTimeSourceHandling && | |
| 524 now_function_ && | |
| 525 !now_function_is_time_) { | |
| 526 queue_duration = 0; | |
| 527 } | |
| 528 | |
| 529 DeathMap::iterator it = death_map_.find(&births); | 506 DeathMap::iterator it = death_map_.find(&births); |
| 530 DeathData* death_data; | 507 DeathData* death_data; |
| 531 if (it != death_map_.end()) { | 508 if (it != death_map_.end()) { |
| 532 death_data = &it->second; | 509 death_data = &it->second; |
| 533 } else { | 510 } else { |
| 534 base::AutoLock lock(map_lock_); // Lock as the map may get relocated now. | 511 base::AutoLock lock(map_lock_); // Lock as the map may get relocated now. |
| 535 death_data = &death_map_[&births]; | 512 death_data = &death_map_[&births]; |
| 536 } // Release lock ASAP. | 513 } // Release lock ASAP. |
| 537 death_data->RecordDeath(queue_duration, run_duration, random_number_); | 514 death_data->RecordDeath(queue_duration, run_duration, random_number_); |
| 538 } | 515 } |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 685 } | 662 } |
| 686 | 663 |
| 687 void ThreadData::OnProfilingPhaseCompletedOnThread(int profiling_phase) { | 664 void ThreadData::OnProfilingPhaseCompletedOnThread(int profiling_phase) { |
| 688 base::AutoLock lock(map_lock_); | 665 base::AutoLock lock(map_lock_); |
| 689 | 666 |
| 690 for (auto& death : death_map_) { | 667 for (auto& death : death_map_) { |
| 691 death.second.OnProfilingPhaseCompleted(profiling_phase); | 668 death.second.OnProfilingPhaseCompleted(profiling_phase); |
| 692 } | 669 } |
| 693 } | 670 } |
| 694 | 671 |
| 695 static void OptionallyInitializeAlternateTimer() { | |
| 696 NowFunction* alternate_time_source = GetAlternateTimeSource(); | |
| 697 if (alternate_time_source) | |
| 698 ThreadData::SetAlternateTimeSource(alternate_time_source); | |
| 699 } | |
| 700 | |
| 701 void ThreadData::Initialize() { | 672 void ThreadData::Initialize() { |
| 702 if (base::subtle::Acquire_Load(&status_) >= DEACTIVATED) | 673 if (base::subtle::Acquire_Load(&status_) >= DEACTIVATED) |
| 703 return; // Someone else did the initialization. | 674 return; // Someone else did the initialization. |
| 704 // Due to racy lazy initialization in tests, we'll need to recheck status_ | 675 // Due to racy lazy initialization in tests, we'll need to recheck status_ |
| 705 // after we acquire the lock. | 676 // after we acquire the lock. |
| 706 | 677 |
| 707 // Ensure that we don't double initialize tls. We are called when single | 678 // Ensure that we don't double initialize tls. We are called when single |
| 708 // threaded in the product, but some tests may be racy and lazy about our | 679 // threaded in the product, but some tests may be racy and lazy about our |
| 709 // initialization. | 680 // initialization. |
| 710 base::AutoLock lock(*list_lock_.Pointer()); | 681 base::AutoLock lock(*list_lock_.Pointer()); |
| 711 if (base::subtle::Acquire_Load(&status_) >= DEACTIVATED) | 682 if (base::subtle::Acquire_Load(&status_) >= DEACTIVATED) |
| 712 return; // Someone raced in here and beat us. | 683 return; // Someone raced in here and beat us. |
| 713 | 684 |
| 714 // Put an alternate timer in place if the environment calls for it, such as | |
| 715 // for tracking TCMalloc allocations. This insertion is idempotent, so we | |
| 716 // don't mind if there is a race, and we'd prefer not to be in a lock while | |
| 717 // doing this work. | |
| 718 if (kAllowAlternateTimeSourceHandling) | |
| 719 OptionallyInitializeAlternateTimer(); | |
| 720 | |
| 721 // Perform the "real" TLS initialization now, and leave it intact through | 685 // Perform the "real" TLS initialization now, and leave it intact through |
| 722 // process termination. | 686 // process termination. |
| 723 if (!tls_index_.initialized()) { // Testing may have initialized this. | 687 if (!tls_index_.initialized()) { // Testing may have initialized this. |
| 724 DCHECK_EQ(base::subtle::NoBarrier_Load(&status_), UNINITIALIZED); | 688 DCHECK_EQ(base::subtle::NoBarrier_Load(&status_), UNINITIALIZED); |
| 725 tls_index_.Initialize(&ThreadData::OnThreadTermination); | 689 tls_index_.Initialize(&ThreadData::OnThreadTermination); |
| 726 DCHECK(tls_index_.initialized()); | 690 DCHECK(tls_index_.initialized()); |
| 727 } else { | 691 } else { |
| 728 // TLS was initialzed for us earlier. | 692 // TLS was initialzed for us earlier. |
| 729 DCHECK_EQ(base::subtle::NoBarrier_Load(&status_), DORMANT_DURING_TESTS); | 693 DCHECK_EQ(base::subtle::NoBarrier_Load(&status_), DORMANT_DURING_TESTS); |
| 730 } | 694 } |
| (...skipping 25 matching lines...) Expand all Loading... |
| 756 ThreadData::Status ThreadData::status() { | 720 ThreadData::Status ThreadData::status() { |
| 757 return static_cast<ThreadData::Status>(base::subtle::Acquire_Load(&status_)); | 721 return static_cast<ThreadData::Status>(base::subtle::Acquire_Load(&status_)); |
| 758 } | 722 } |
| 759 | 723 |
| 760 // static | 724 // static |
| 761 bool ThreadData::TrackingStatus() { | 725 bool ThreadData::TrackingStatus() { |
| 762 return base::subtle::Acquire_Load(&status_) > DEACTIVATED; | 726 return base::subtle::Acquire_Load(&status_) > DEACTIVATED; |
| 763 } | 727 } |
| 764 | 728 |
| 765 // static | 729 // static |
| 766 void ThreadData::SetAlternateTimeSource(NowFunction* now_function) { | |
| 767 DCHECK(now_function); | |
| 768 if (kAllowAlternateTimeSourceHandling) | |
| 769 now_function_ = now_function; | |
| 770 } | |
| 771 | |
| 772 // static | |
| 773 void ThreadData::EnableProfilerTiming() { | 730 void ThreadData::EnableProfilerTiming() { |
| 774 base::subtle::NoBarrier_Store(&g_profiler_timing_enabled, ENABLED_TIMING); | 731 base::subtle::NoBarrier_Store(&g_profiler_timing_enabled, ENABLED_TIMING); |
| 775 } | 732 } |
| 776 | 733 |
| 777 // static | 734 // static |
| 778 TrackedTime ThreadData::Now() { | 735 TrackedTime ThreadData::Now() { |
| 779 if (kAllowAlternateTimeSourceHandling && now_function_) | 736 if (now_function_for_testing_) |
| 780 return TrackedTime::FromMilliseconds((*now_function_)()); | 737 return TrackedTime::FromMilliseconds((*now_function_for_testing_)()); |
| 781 if (IsProfilerTimingEnabled() && TrackingStatus()) | 738 if (IsProfilerTimingEnabled() && TrackingStatus()) |
| 782 return TrackedTime::Now(); | 739 return TrackedTime::Now(); |
| 783 return TrackedTime(); // Super fast when disabled, or not compiled. | 740 return TrackedTime(); // Super fast when disabled, or not compiled. |
| 784 } | 741 } |
| 785 | 742 |
| 786 // static | 743 // static |
| 787 void ThreadData::EnsureCleanupWasCalled(int major_threads_shutdown_count) { | 744 void ThreadData::EnsureCleanupWasCalled(int major_threads_shutdown_count) { |
| 788 base::AutoLock lock(*list_lock_.Pointer()); | 745 base::AutoLock lock(*list_lock_.Pointer()); |
| 789 if (worker_thread_data_creation_count_ == 0) | 746 if (worker_thread_data_creation_count_ == 0) |
| 790 return; // We haven't really run much, and couldn't have leaked. | 747 return; // We haven't really run much, and couldn't have leaked. |
| (...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1005 : process_id(base::GetCurrentProcId()) { | 962 : process_id(base::GetCurrentProcId()) { |
| 1006 #else | 963 #else |
| 1007 : process_id(base::kNullProcessId) { | 964 : process_id(base::kNullProcessId) { |
| 1008 #endif | 965 #endif |
| 1009 } | 966 } |
| 1010 | 967 |
| 1011 ProcessDataSnapshot::~ProcessDataSnapshot() { | 968 ProcessDataSnapshot::~ProcessDataSnapshot() { |
| 1012 } | 969 } |
| 1013 | 970 |
| 1014 } // namespace tracked_objects | 971 } // namespace tracked_objects |
| OLD | NEW |